Jump to content
Sign in to follow this  
Texan78

Sorting through variable values

Recommended Posts

Hello, I am trying to repurpose some old code and update it to use Bootstrap. This is a two part question so I will try to keep it short. First part. I am parsing an XML URL with simpleXML and setting variables to return values to use in some HTML code. This worked great when it was first written years ago but, I need to sort through the values in this case "event" and only show certain events and then sort those show it shows certain ones first before others. For brevity I am only showing the relevant code.

// get path info & protect for cross-site scripting vulnerability
$sri = ($_SERVER['REQUEST_URI']) ? str_replace('#SA', '', htmlspecialchars(strip_tags($_SERVER['REQUEST_URI']))) : '';

$error = false;

//Set initial output to false
$AlertData = false;
$entries = simplexml_load_file($data);
if(count($entries)):
    //Registering NameSpace
    $entries->registerXPathNamespace('prefix', 'http://www.w3.org/2005/Atom');
    $result = $entries->xpath("//prefix:entry");
if(!$result){
$error = true;
}
    foreach ($result as $entry):
        $updated = $entry->updated;
if($updated == ''){
$error = true;
}
        $Updated = date("D, M d, g:i a", strtotime($updated));
        $summary = $entry->summary;
if($summary == ''){
$error = true;
}

  // Replaces all triple periods with single periods
        $summary = trim(str_replace('...', '.', $summary), '.') . '.';


  //now capitalize every letter after a . ? and ! followed by space
        $Summary = preg_replace_callback('/([.!?*])\s*(\w)/', function ($matches) {
            return strtoupper($matches[1] . ' ' . $matches[2]);
            }, ucfirst(strtolower($summary)));
        $event = $entry->children("cap", true)->event;
if($event == 'Tornado Warning, Severe Thunderstorm Warning, Flash Flood Warning'){
$error = true;
}       $updated = $entry->updated;
        $effective = $entry->children("cap", true)->effective;
        $expires = $entry->children("cap", true)->expires;
        $updated = date("l M jS, g:i A", strtotime($updated));
        $effectiveDate = date("l M jS, g:i A", strtotime($effective));
        $expiresDate = date("l M jS, g:i A", strtotime($expires));
        $status = $entry->children("cap", true)->status;
        $severity = $entry->children("cap", true)->severity;
        $urgency = $entry->children("cap", true)->urgency;
        $area = $entry->children("cap", true)->areaDesc; 

 Take notice to this insert below from the code above where I have defined what events to show. So it should only show those events but, instead it still shows all of them. 

$event = $entry->children("cap", true)->event;
if($event == 'Tornado Warning, Severe Thunderstorm Warning, Flash Flood Warning')

Second part is I need this to show in 4 columns across in one row but, it just displays them down. I have experimented with some but not sure how to currently place the bootstrap code so it displays 4 columns per row then starts a new row. The image below shows the output going down. The yellow and green are hard coded for example of what I am wanting it to do. 

 

bootstrap.png

 

 

Here is the code for the output in red that is going down when it should be going across. 

// If no storms were in the source, set no storm message
if($error) {
     $AlertData .= "<div class='alert alert-danger' style='padding:5px;' role='alert' data-toggle='tooltip' data-placement='top' title='There are currently no active severe weather alerts.'>\n";
     $AlertData .= "{$noStormMessage}\n";
     $AlertData .= "</div>\n";
} else {
    $AlertData .= "<div id='Tornado' class='individualAlert'>\n";
    $AlertData .= "<div class='text_alert'>\n";
    $AlertData .= "<span class='title AlertTornado'><i class='fa fa-exclamation-triangle severe-icon__tornado'></i> {$event}</span>\n";
    $AlertData .= "<span class='state'>TX</span>\n";
    $AlertData .= "<span class='counties'>{$area}</span>\n";
    $AlertData .= "<span class='expires'>Expires: {$expiresDate}</span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "<div class='alert__view'>\n";
    $AlertData .= "<span class='fa fa-eye'></span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
}

       endforeach;
endif;

echo $AlertData;

Then the raw HTML code.

<div class="row">
                      <div class="col-md-3">
                                        <!-- <span>Active Tornado Warnings</span> -->
                                        <?php include ('inc/alerts.php'); ?>
                      </div>
                      <div class="col-md-3">
                                        <!-- <span>Active Severe Thunderstorm Warnings</span> -->
                                        <div id="SevereThunderstorm" class="individualAlert">
                                            <div class="text_alert">
                                                <span class="title AlertSevereThunderstorm"><i class="fa fa-exclamation-triangle severe-icon__thunderstorm"></i> SEVERE THUNDERSTORM WARNING TEST</span>
                                                <span class="state">TX</span>
                                                <span class="counties">DALLAS</span>
                                                <span class="expires">Expires: 12:00 PM CST</span>
                                            </div>
                                            <div class="alert__view">
                                                <span class="fa fa-eye"></span>
                                            </div>
                                        </div>
                      </div>
                      <div class="col-md-3">
                                        <!-- <span>Active Flash Flood Warnings</span> -->
                                       <div id="FlashFlood" class="individualAlert">
                                            <div class="text_alert">
                                                <span class="title AlertFlood"><i class="fa fa-exclamation-triangle severe-icon__flood"></i> FLASH FLOOD WARNING TEST</span>
                                                <span class="state">TX</span>
                                                <span class="counties">DALLAS</span>
                                                <span class="expires">Expires: 12:00 PM CST</span>
                                            </div>
                                            <div class="alert__view">
                                                <span class="fa fa-eye"></span>
                                            </div>
                                       </div>
                      </div>                  
                      <div class="col-md-3">
                                        <!-- <span>Active Flash Flood Warnings</span> -->
                                       <div id="FlashFlood" class="individualAlert">
                                            <div class="text_alert">
                                                <span class="title AlertFlood"><i class="fa fa-exclamation-triangle severe-icon__flood"></i> FLASH FLOOD WARNING TEST</span>
                                                <span class="state">TX</span>
                                                <span class="counties">DALLAS</span>
                                                <span class="expires">Expires: 12:00 PM CST</span>
                                            </div>
                                            <div class="alert__view">
                                                <span class="fa fa-eye"></span>
                                            </div>
                                       </div>
                      </div>                  
                    </div>

I am sure I need to add <div class="row"> <div class="col-md-3"> in my PHP code but I am not sure how and the things I have tried had not worked.

 

-Thanks

Share this post


Link to post
Share on other sites

Quick update since it won't let me edit my original post. If I put the Bootstrap in the PHP like so...

// If no storms were in the source, set no storm message
if($error) {
     $AlertData .= "<div class='alert alert-danger' style='padding:5px;' role='alert' data-toggle='tooltip' data-placement='top' title='There are currently no active severe weather alerts.'>\n";
     $AlertData .= "{$noStormMessage}\n";
     $AlertData .= "</div>\n";
} else {
    $AlertData .= "<div class='row'>\n";
    $AlertData .= "<div class='col-md-3'>\n";
    $AlertData .= "<div id='Tornado' class='individualAlert'>\n";
    $AlertData .= "<div class='text_alert'>\n";
    $AlertData .= "<span class='title AlertTornado'><i class='fa fa-exclamation-triangle severe-icon__tornado'></i> {$event}</span>\n";
    $AlertData .= "<span class='state'>TX</span>\n";
    $AlertData .= "<span class='counties'>{$area}</span>\n";
    $AlertData .= "<span class='expires'>Expires: {$expiresDate}</span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "<div class='alert__view'>\n";
    $AlertData .= "<span class='fa fa-eye'></span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
}

       endforeach;
endif;

echo $AlertData;

With it in the HTML page like so....

                 <div class="panel-body" style="background-color: #878787; padding: 5px;">
                    <?php include ('inc/alerts.php'); ?>
                 </div>

It still prints it out down instead of columns of 4 across. 

Share this post


Link to post
Share on other sites

You only created one column. You need this...

<div class="row">
  <div class="col-md-3">col 1</div>
  <div class="col-md-3">col 2</div>
  <div class="col-md-3">col 3</div>
  <div class="col-md-3">col 4</div>
</div>
Edited by benanamen

Share this post


Link to post
Share on other sites
//Set path to data file
$data = "http://alerts.weather.gov/cap/".$zone.".php?x=0";

$zone is tx

Share this post


Link to post
Share on other sites

Parsing the XML file is not my issue. The specific nodes I am parsing are in my original post within the first code block. I am able to do that just fine and create variables to insert into the HTML. The issues are as follows... 

 

1. Only show certain events and sort them by priority to show certain ones first.

$event = $entry->children("cap", true)->event;
if($event == 'Tornado Warning, Severe Thunderstorm Warning, Flash Flood Warning, Flood Warning') 

2. Dynamically create the Bootstrap columns (4) for each row to display the parsed information. 

Share this post


Link to post
Share on other sites

Ok, got it. Long day in front of the computer.

 

Could you please attach the entire script. 

 

Are these the certain events and is this the order of display?

 

Tornado Warning, Severe Thunderstorm Warning, Flash Flood Warning, Flood Warning

Edited by benanamen

Share this post


Link to post
Share on other sites

Well one brain fart solved. This seems to work for producing 4 columns per row. Will need to keep an eye on it to see if it messes up when there isn't equal number of entries. 

// If no storms were in the source, set no storm message
if($error) {
     $AlertData .= "<div class='alert alert-danger' style='padding:5px;' role='alert' data-toggle='tooltip' data-placement='top' title='There are currently no active severe weather alerts.'>\n";
     $AlertData .= "{$noStormMessage}\n";
     $AlertData .= "</div>\n";
} else {
    $AlertData .= "<div class='col-md-3'>\n";
    $AlertData .= "<div id='{$alertID}' class='individualAlert'>\n";
    $AlertData .= "<div class='text_alert'>\n";
    $AlertData .= "<span class='title {$alertClass}'><i class='fa fa-exclamation-triangle severe-icon__tornado'></i> {$event}</span>\n";
    $AlertData .= "<span class='state'>{$stateShort}</span>\n";
    $AlertData .= "<span class='counties'>{$area}</span>\n";
    $AlertData .= "<span class='expires'>Expires: {$expiresDate}</span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "<div class='alert__view'>\n";
    $AlertData .= "<span class='fa fa-eye'></span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
}
    $AlertData .= "</div>\n";

       endforeach;
endif;

echo $AlertData;
                 <div class="panel-body" style="background-color: #878787; padding: 5px;">
                    <div class='row'>
                       <div id="alerts"></div>
                    </div>
                 </div> 

So last issue is only pulling certain events or in this case "alerts" and prioritizing them so they will show in a certain order. This one seems to be puzzling me.

Share this post


Link to post
Share on other sites
So last issue is only pulling certain events or in this case "alerts" and prioritizing them so they will show in a certain order. This one seems to be puzzling me.

 

 

to do this will require changing how your code works, by separating the different 'concerns'. you need to separate the parsing of the data from the display of the data.

 

in the parsing code, you would store the data into an array of sub-arrays, using the event type as the main array index and only store the types that you went to keep. you would only store the raw data values, without any formatting. you can use print_r() or var_dump() to verify that the data you have stored is what you expect, before going onto the next step of producing the output.

 

in the display code, you would loop over the main array indexes in the order that you want to display them. this will give you any sub-arrays of data for each event type. you would loop over the sub-array and produce the output from the data. all the formatting code would be in this section.

 

lastly, i'm sure in one or more of your threads, it has been suggested (by me) to not write out php logic just to map one value to another. you should use a simple mapping array. see the following - 

// define a map of the event type string, to any other values. the two entries are the alertID and the alertClass
// this defining array is also used in the parsing code to control what event types are kept - if $type[$event] isset(), keep the data
// is it also used when displaying the data. the order of the entries here controls the output order, by looping over the keys (see array_keys() ) from this array to access the parsed data in the same order
$type = array();
$type['Tornado Warning'] = array('Tornado', 'AlertTornado');
$type['Severe Thunderstorm Warning'] = array('SevereThunderstorm','AlertSevereThunderstorm');
$type['Flash Flood Warning'] = array('FlashFlood','AlertFlood');
$type['Flood Warning'] = array('FlashFlood','AlertFlood');

besides the uses listed in the comments, this converts your design into a general purpose 'data driven' design, where any specific data values are pulled out of the program logic, leaving the program logic simplified and general purpose, and by putting the data values all in one place, you eliminate repetition in the code and make it easy to add, remove, or alter any of the data values.

 

edit: by switch'ing (coding pun intended) to a data driven design, all that switch/case logic can be replaced with this -  

$alertID = '';
$alertClass = '';
if(isset($type[$event]))
{
    list($alertID,$alertClass) = $type[$event];
}
Edited by mac_gyver

Share this post


Link to post
Share on other sites

None of that makes any sense to me because I have no idea where that is to be used or how to implement it into my current script. Guess I will have to hire someone for 5 mins to update it. 

Share this post


Link to post
Share on other sites

lastly, i'm sure in one or more of your threads, it has been suggested (by me) to not write out php logic just to map one value to another. you should use a simple mapping array. see the following - 

// define a map of the event type string, to any other values. the two entries are the alertID and the alertClass
// this defining array is also used in the parsing code to control what event types are kept - if $type[$event] isset(), keep the data
// is it also used when displaying the data. the order of the entries here controls the output order, by looping over the keys (see array_keys() ) from this array to access the parsed data in the same order
$type = array();
$type['Tornado Warning'] = array('Tornado', 'AlertTornado');
$type['Severe Thunderstorm Warning'] = array('SevereThunderstorm','AlertSevereThunderstorm');
$type['Flash Flood Warning'] = array('FlashFlood','AlertFlood');
$type['Flood Warning'] = array('FlashFlood','AlertFlood');

 

 

Why on Gods green earth would you ever want to assign your style classes and IDs to the same variable that's outputting data?  

Lastly, the switch is being used in more than just once script on other areas of the site. Which is why it is being used in a included file so I can pull what I need instead of having to write the logic out every single time across multiple scripts. Which BTW, was something that was suggested by a member of this forum several years ago when that script was originally created. As I have mentioned before as well, that is the thing about PHP and online forums. You will get multiple ways to do the same thing and not everyone is going to agree. 

 

Those snippets would probably be useful it you included how to implement it into my current code because this below doesn't work and throws tons of errors. 

// get path info & protect for cross-site scripting vulnerability
$sri = ($_SERVER['REQUEST_URI']) ? str_replace('#SA', '', htmlspecialchars(strip_tags($_SERVER['REQUEST_URI']))) : '';

$error = false;

//Set initial output to false
$AlertData = false;
$entries = simplexml_load_file($data);
if(count($entries)):
    //Registering NameSpace
    $entries->registerXPathNamespace('prefix', 'http://www.w3.org/2005/Atom');
    $result = $entries->xpath("//prefix:entry");
if(!$result){
$error = true;
}
    foreach ($result as $entry):
        $updated = $entry->updated;
if($updated == ''){
$error = true;
}
        $Updated = date("D, M d, g:i a", strtotime($updated));
        $summary = $entry->summary;
if($summary == ''){
$error = true;
}

  // Replaces all triple periods with single periods
        $summary = trim(str_replace('...', '.', $summary), '.') . '.';


  //now capitalize every letter after a . ? and ! followed by space
        $Summary = preg_replace_callback('/([.!?*])\s*(\w)/', function ($matches) {
            return strtoupper($matches[1] . ' ' . $matches[2]);
            }, ucfirst(strtolower($summary)));
        $event = $entry->children("cap", true)->event;
          if($event == ''){
        $error = true;
        }       
        $updated = $entry->updated;
        $link = $entry->link;
        $effective = $entry->children("cap", true)->effective;
        $expires = $entry->children("cap", true)->expires;
        $updated = date("l M jS, g:i A", strtotime($updated));
        $effectiveDate = date("l M jS, g:i A", strtotime($effective));
        $expiresDate = date("D M jS, g:i A", strtotime($expires));
        $status = $entry->children("cap", true)->status;
        $severity = $entry->children("cap", true)->severity;
        $urgency = $entry->children("cap", true)->urgency;
        $area = $entry->children("cap", true)->areaDesc;

        //include ('alertColors.php');
        
        $type = array($event);
          $type['Tornado Warning'] = array('Tornado', 'AlertTornado');
          $type['Severe Thunderstorm Warning'] = array('SevereThunderstorm','AlertSevereThunderstorm');
          $type['Flash Flood Warning'] = array('FlashFlood','AlertFlood');
          $type['Flood Warning'] = array('FlashFlood','AlertFlood');
          
        $alertID = '';
        $alertClass = '';
           if(isset($type[$event]))
       {
           list($alertID,$alertClass) = $type[$event];
       }
        
   // Let's assign the table some styles
     $divNoStorms = "padding:5px; width:50%; margin:auto; margin-top:5px; margin-bottom:5px";

  // If no storms were in the source, set no storm message
if($error) {
     $AlertData .= "<div style='{$divNoStorms}' class='alert alert-danger' role='alert' data-toggle='tooltip' data-placement='top' title='There are currently no active severe weather alerts.'>\n";
     $AlertData .= "{$noStormMessage}\n";
     $AlertData .= "</div>\n";
} else {
    $AlertData .= "<div class='col-md-3'>\n";
    $AlertData .= "<div id='{$alertID}' class='individualAlert'>\n";
    $AlertData .= "<div class='text_alert'>\n";
    $AlertData .= "<span class='title {$alertClass}'><i class='fa fa-exclamation-triangle severe-icon__tornado'></i>{$type}</span>\n";
    $AlertData .= "<span class='state'>{$stateShort}</span>\n";
    $AlertData .= "<span class='counties'>{$area}</span>\n";
    $AlertData .= "<span class='expires'>Expires: {$expiresDate}</span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "<div class='alert__view'>\n";
    $AlertData .= "<span class='fa fa-eye'></span>\n";
    $AlertData .= "</div>\n";
    $AlertData .= "</div>\n";
}
    $AlertData .= "</div>\n";

       endforeach;
endif;

echo $AlertData;

Share this post


Link to post
Share on other sites
Why on Gods green earth would you ever want to assign your style classes and IDs to the same variable that's outputting data?  

 

 

don't know what that is referring to, since nothing posted is doing that.

 

you can require the defining array and the couple of lines of logic anywhere you want. if you do the other things that are needed to accomplish the stated goals of only keeping data of those types and ordering the data in the output by those types, the defining array will need to be required before the point where it is first referenced.

 

the errors you are getting, which you didn't post, but i'll guess anyway, are either due to this - $type = array($event);, which isn't what i posted, that's creating an array with $event as the value in it, or they are due to the fact that the various child values you are getting are SimpleXMLElement objects, not strings, and for the case of using $event as an array index, needs to be cast to a string either implicitly, by adding double-quotes around it where it is used, or explicitly by using (string) when the value is first assigned to $event.

Share this post


Link to post
Share on other sites

don't know what that is referring to, since nothing posted is doing that.

 

This is doing just that. What is set in the array is style classes and IDs. From what I can tell that is assigning it to the same variable $type.  This is the alert or event ['Tornado Warning'] and these are styles array('Tornado', 'AlertTornado');

$type = array();
$type['Tornado Warning'] = array('Tornado', 'AlertTornado');
$type['Severe Thunderstorm Warning'] = array('SevereThunderstorm','AlertSevereThunderstorm');
$type['Flash Flood Warning'] = array('FlashFlood','AlertFlood');
$type['Flood Warning'] = array('FlashFlood','AlertFlood');

 

 

the errors you are getting, which you didn't post, but i'll guess anyway, are either due to this - $type = array($event);, which isn't what i posted, that's creating an array with $event as the value in it

 

 

How else am I going to pass the values to it to filter out what I want? It's not just going to know if you don't pass something to it to filter through. 

 

Like I said, those snippets would probably be useful it you included examples of how to implement it into my current code.

Share this post


Link to post
Share on other sites

yes, $type is one variable, it's an array variable. it has more than one dimension. each array index references a different element of the array variable.

 

there is a posted example showing how to use the $type array, for one of the stated purposes, of replacing the switch/case statement. that example would be this code - 

$alertID = '';
$alertClass = '';
if(isset($type[$event]))
{
    list($alertID,$alertClass) = $type[$event];
}

i'm guessing you don't understand what that is doing?

 

$type is the array that has been defined and has had four elements assigned to it.

 

the 'Tornado Warning', 'Severe Thunderstorm Warning', 'Flash Flood Warning', and 'Flood Warning' are the array indexes.

 

supplying a literal array index name - $type['Flash Flood Warning'] in some code would reference the id and class values that are stored/assigned for the flash flood warning array index value.

 

supplying a variable array index name - $type[$event] (assuming that $event is a string, rather than an simplexmlelement object) in some code would use the value in $event as the array index and would reference the id and class values that are stored/assigned for whatever is in $event.

 

using isset($type[$event]) is testing if the element in the array $type, given by the array index name in $event is set.

 

using list($alertID,$alertClass) = $type[$event]; is referencing the element in the array $type, given by the array index name in $event, and assigning the id and class values that are stored for that array index name to the $alertID and $alertClass variables.

 

note: once your code has parsed and filtered the xml data so that only data having those four types is being processed and displayed, there's no need for the if(...){...} conditional logic or initializing the $alertID and $alertClass to empty strings. the event types in the data being looped over will be in the $type array and you only need the - list($alertID,$alertClass) = $type[$event]; line of code.

Edited by mac_gyver

Share this post


Link to post
Share on other sites

yes, $type is one variable, it's an array variable. it has more than one dimension. each array index references a different element of the array variable.

 

there is a posted example showing how to use the $type array, for one of the stated purposes, of replacing the switch/case statement. that example would be this code - 

$alertID = '';
$alertClass = '';
if(isset($type[$event]))
{
    list($alertID,$alertClass) = $type[$event];
}

i'm guessing you don't understand what that is doing?

 

$type is the array that has been defined and has had four elements assigned to it.

 

the 'Tornado Warning', 'Severe Thunderstorm Warning', 'Flash Flood Warning', and 'Flood Warning' are the array indexes.

 

supplying a literal array index name - $type['Flash Flood Warning'] in some code would reference the id and class values that are stored/assigned for the flash flood warning array index value.

 

supplying a variable array index name - $type[$event] (assuming that $event is a string, rather than an simplexmlelement object) in some code would use the value in $event as the array index and would reference the id and class values that are stored/assigned for whatever is in $event.

 

using isset($type[$event]) is testing if the element in the array $type, given by the array index name in $event is set.

 

using list($alertID,$alertClass) = $type[$event]; is referencing the element in the array $type, given by the array index name in $event, and assigning the id and class values that are stored for that array index name to the $alertID and $alertClass variables.

 

note: once your code has parsed and filtered the xml data so that only data having those four types is being processed and displayed, there's no need for the if(...){...} conditional logic or initializing the $alertID and $alertClass to empty strings. the event types in the data being looped over will be in the $type array and you only need the - list($alertID,$alertClass) = $type[$event]; line of code.

 

 

Should I guess how to implement those snippets or you going to show me an example of how to implement it into my current code since you're not making any sense or listening to anything I am saying. I also can't ditch the IF statement because it is doing two different things as it is suppose to. 

 

Have you ever heard of the KISS method? 

Edited by Texan78

Share this post


Link to post
Share on other sites

Still looking for a solution to this that implements into my current script that will filter certain values and then sort them. 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.