Jump to content
Plugnz13

While loop to isolate array items help

Recommended Posts

Hi all,

I have a table that shows data from an xml response that has been converted to an array.

I have successfully managed to get that to work but it's showing more items than I want.

I'm trying to isolate the items by state. There are 11 or so different states, of which I only want 7. 

I've tried the following with a while loop but I keep getting the message "undefined index: job_status"  

Here's my code (partial)

$projects = array();    
    
        $xml=simplexml_load_string($response) or die("Error: Cannot create object");
     
    foreach($xml->Jobs->Job as $item) {
     
    $projects[] = array(
                     'job_no'          => (string)$item->ID,
                     'job_name'        => (string)$item->Name,
                     'job_due'         => (string)$item->DueDate,
                     'job_status'      => (string)$item->State,
                     'job_staff'       => (string)$item->Assigned->Staff->Name,
                    );
     }
     
 usort($projects, function($a,$b) {return $a['job_due'] <=> $b['job_due']; } );

$projects = array_reverse($projects);
     
while ($projects['job_status'] == ('Feasibility') 
          && ('Measure Up') 
          && ('Model Drawing') 
          && ('Concept Design') 
          && ('Developed Design') 
          && ('Resource Consent') 
          && ('Construction Documentation')) {
    
foreach ($projects as $proj) {
$formatted = date('d/m/Y', strtotime($proj['job_due'])); 
    $job_no ="{$proj['job_no']}";
    $job_name ="{$proj['job_name']}";
    $job_due ="$formatted";
    $job_status ="{$proj['job_status']}";
    $job_staff ="{$proj['job_staff']}";

Any help would be much appreciated thanks. 

Share this post


Link to post
Share on other sites

Your while() criteria is incorrect and unnecessary. I haven't tested this code, but give it a shot:

$acceptedStates = [
	'Feasibility',
	'Measure Up',
	'Model Drawing',
	'Concept Design',
	'Developed Design',
	'Resource Consent',
	'Construction Documentation',
];

$xml = simplexml_load_string($response);
$xml = usort($xml, function($a, $b){
	return $a['job_due'] <=> $b['job_due'];
});

foreach($xml->Jobs->Job as $item) {

	if(!in_array((string)$item->State, $acceptedStates)){
		continue;
	}

	$projects[] = [
			'job_no'          => (string)$item->ID,
			'job_name'        => (string)$item->Name,
			'job_due'         => date('d/m/Y', strtotime($item->DueDate)),
			'job_status'      => (string)$item->State,
			'job_staff'       => (string)$item->Assigned->Staff->Name,
	];

}

 

Share this post


Link to post
Share on other sites

Use an array to get the ones you want...

$projects = array();

$required = ['Feasibility', 'Measure Up', 'Model Drawing', 'Concept Design', 'Developed Design', 'Resource Consent', 'Construction Documentation' ];

$xml=simplexml_load_string($response) or die("Error: Cannot create object");
 
foreach($xml->Jobs->Job as $item) {
    if (in_array((string)$item->State, $required)) {
        $projects[] = array(
                         'job_no'          => (string)$item->ID,
                         'job_name'        => (string)$item->Name,
                         'job_due'         => (string)$item->DueDate,
                         'job_status'      => (string)$item->State,
                         'job_staff'       => (string)$item->Assigned->Staff->Name,
                        );
    }
}
     
 usort($projects, function($a,$b) {return $b['job_due'] <=> $a['job_due']; } );       // reverse $a and $b for desc sort

// $projects = array_reverse($projects);          // no longer required

This code is just plain wrong...

while ($projects['job_status'] == ('Feasibility') 
          && ('Measure Up') 
          && ('Model Drawing') 
          && ('Concept Design'                ) 
          && ('Developed Design'               ) 
          && ('Resource Consent'               ) 
          && ('Construction Documentation')) {

and this is a waste of time and effort. Why just move a value from one variable to another and why put a single string variable inside quotes?

$formatted = date('d/m/Y', strtotime($proj['job_due'])); 
    $job_no ="{$proj['job_no']}";
    $job_name ="{$proj['job_name']}";
    $job_due ="$formatted";
    $job_status ="{$proj['job_status']}";
    $job_staff ="{$proj['job_staff']}";

 

Share this post


Link to post
Share on other sites

If, for other purposes, you require all records to be in the array then you can filter the records when you process them to gat those with a required status value EG

$status_filter = function ($v) use ($required) { 
                    return in_array($v['job_status'], $required); 
                 };
                
foreach (array_filter($projects, $status_filter) as $proj) {
    // process $proj
}

 

Share this post


Link to post
Share on other sites

Thanks Barand and Maxxd, much appreciated. Really need to get my head around how these arrays work. 

Share this post


Link to post
Share on other sites

Hi again, sorry to be a pain but further to the previous question, I have the added requirement to be able to show the due date of a particular task but only if that task-name is the same as the current job state.

The xml code looks something like this 

<Job>
  <ID></ID>
  <Name>Job 1</Name>
  <State>Concept Design</State>
  <StartDate>2019-02-01</StartDate>
  <DueDate>2019-10-01</DueDate>
  <Tasks>
    <Task>
      <ID></ID>
      <Name>Measure Up</Name>
      <StartDate>2019-07-01</StartDate>
      <DueDate>2019-07-30</DueDate>
    </Task>
    <Task>
      <ID></ID>
      <Name>Concept Design</Name>
      <StartDate>2019-08-01</StartDate>
      <DueDate>2019-08-31</DueDate>
    </Task>
    ....etc

  my somewhat lame attempt looks like this

$projects = array();    

$required = ['Feasibility', 'Measure Up', 'Model Drawing', 'Concept Design', 'Developed Design', 'Resource Consent', 'Construction Documentation' ];

$xml=simplexml_load_string($response) or die("Error: Cannot create object");
     
foreach($xml->Jobs->Job as $item) {
    
    
if (in_array((string)$item->State, $required) ) { 
   
    $projects[] = array(
                     'job_no'          => (string)$item->ID,
                     'job_name'        => (string)$item->Name,
                     'job_due'        => date('d/m/Y', strtotime($item->Tasks->Task->DueDate)),
                     'job_status'      => (string)$item->State,
                     'task_name'       => (string)$item->Tasks->Task->Name,
                     'job_staff'       => (string)$item->Assigned->Staff->Name,
                    );
     }
}  
 usort($projects, function($a,$b) {return $b['job_due'] <=> $a['job_due']; } );
         
foreach ($projects as $proj) {
   
    $job_no =$proj['job_no'];
    $job_name =$proj['job_name'];
    $job_status =$proj['job_status'];
    $job_staff =$proj['job_staff'];
    if (in_array((string)$item->Tasks->Task->Name, $job_status)){
    $job_due =$proj['task_due'];
    }
    $task_name =$proj['task_name'];
    
 

Thanks again for your help. 

Edited by Plugnz13

Share this post


Link to post
Share on other sites

Given that xml extract

$required = ['Feasibility', 'Measure Up', 'Model Drawing', 'Concept Design', 'Developed Design', 'Resource Consent', 'Construction Documentation' ];
$str = <<<XML
<Jobs>
  <Job>
    <ID></ID>
    <Name>Job 1</Name>
    <State>Concept Design</State>
    <StartDate>2019-02-01</StartDate>
    <DueDate>2019-10-01</DueDate>
    <Tasks>
      <Task>
        <ID></ID>
        <Name>Measure Up</Name>
        <StartDate>2019-07-01</StartDate>
        <DueDate>2019-07-30</DueDate>
      </Task>
      <Task>
        <ID></ID>
        <Name>Concept Design</Name>
        <StartDate>2019-08-01</StartDate>
        <DueDate>2019-08-31</DueDate>
      </Task>
    </Tasks>
  </Job>
</Jobs>
XML;
$xml = simplexml_load_string($str);
// echo '<pre>', print_r($xml, 1), '</pre>';
foreach ($xml->Job as $job) {
    $state = (string)$job->State;
    if (!in_array($state, $required)) continue;

    echo "{$job->Name} — $state — ";
    
    foreach ($job->Tasks->Task as $task) {
        if ($task->Name == $state) {
            echo $task->DueDate . '<br>';
        }
    }
    
}

Output

Job 1 — Concept Design — 2019-08-31

EDIT - Alternative method

$xml = simplexml_load_string($str);

foreach ($xml->xpath("//Job") as $job) {
    $state = (string)$job->State;
    if (!in_array($state, $required)) continue;
    
    echo "{$job->Name} &mdash; $state &mdash; ";
    
    $task = $job->xpath("//Task[Name='$state']") ;
    echo $task[0]->DueDate . '<br>';
}

 

Edited by Barand

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.


×
×
  • 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.