Search code examples
phpxmlcodeignitersimplexmlactiveresource

How to get past [@attributes] in SimpleXMLElement?


The goal: Using PHP/CodeIgniter, I need to get a list of users and their custom field names and values in a usable array. If I can just get to the items, I can do what I need. Please see OUTPUT with notes for "// <<< " so you can see where I'm stuck. I just can't get past the dang [@attributes].

I'm using PHP to connect to Redmine using ActiveResource.php and their built in REST API. I want to get a list of all the users and am getting the OUTPUT below.

Models/Employees_model.php:

<?php
require_once ('ActiveResource.php');

class Employees_model extends ActiveResource {
    var $site = 'http://user:password@localhost:8080/redmine/';
    var $element_name = 'user';
    var $request_format = 'xml';

    function __construct() {
        parent::__construct();
    }       
}
?>

controllers/employees.php:

public function employees () {
    $employees = new Employees_model();     
    $data['employeeList'] = $employees->find('all');        
    $this->load->view('customers/ajaxEmployees', $data);
}

view/ajaxEmployees.php:

<?php
//I can get the following with no problem
echo $employee->id . "<br/>";
echo $employee->firstname . "<br/>";
echo $employee->lastname . "<br/>";

//This is where I'm stuck (see OUTPUT for [@attributes] and "// <<<" notes)
echo $employee->custom_fields->custom_field;
?>

OUTPUT:

Array
(
[0] => Employees_model Object
    (
        [id] => 
        [site] => http://user:password@localhost:8080/redmine/
        [element_name] => user
        [request_format] => xml
        [extra_params] => 
        [user] => 
        [password] => 
        [element_name_plural] => users
        [_data] => Array
            (
                [id] => 16
                [login] => jschmoe
                [firstname] => Joe
                [lastname] => Schmoe
                [mail] => joe@example.com
                [created_on] => 2012-08-24T01:58:21Z
                [last_login_on] => SimpleXMLElement Object
                    (
                    )
                [custom_fields] => SimpleXMLElement Object
                    (
                        [@attributes] => Array
                            (
                                [type] => array
                            )

                        [custom_field] => Array
                            (
                                [0] =>     SimpleXMLElement Object
                                    (
                                        [@attributes] => Array
                                            (
                                                [name] => Quality Control //<<< I need this
                                                [id] => 2
                                            )
                                        [value] => 1 //<<< I need this to know that QualityControl = 1
                                    )
                                [1] => SimpleXMLElement Object
                                    (
                                        [@attributes] => Array
                                            (
                                                [name] => Technical Contractor // <<< I need this
                                                [id] => 3
                                            )
                                        [value] => 0  // <<< I need this to know that TechnicalContractor = 0
                                    )
                                [2] => SimpleXMLElement Object
                                    (
                                        [@attributes] => Array
                                            (
                                                [name] => Content //<<< I need this
                                                [id] => 4
                                            )
                                        [value] => 0  // <<< I need this to know Content = 1
                                    )
                            )
                    )
            )
    )
)

Thank you all so much for your help. After wasting many hours searching around, trying everything I came across and everything I could think of - I figured I'd better wave my little white flag. :(


Solution

  • $employee->custom_fields->custom_field; is an array, and you can foreach over it to get each name attribute and its corresponding value using SimpleXMLElement::attributes().

    foreach ($employee->custom_fields->custom_field as $cf) {
      // Loop over the custom field nodes and read the name of each
      switch ($cf->attributes()->name) {
        // Load a variable on each matching name attribute
        // or do whatever you need with them.
        case "Quality Control":
          $quality_control = $cf->value;
          break;
        case "Technical Contractor":
          $technical_contractor = $cf->value;
          break;
        case "Content":
          $content = $cf->value;
          break;
      }
    }
    

    Or if you don't know in advance all the ones you'll need, load them into an array:

    $employee_attrs = array();
    foreach ($employee->custom_fields->custom_field as $cf) {
      // Add an array key of the name, whose value is the value
      $attrs[$cf->attributes()->name] = $cf->value;
    }
    
    var_dump($employee_attrs);