xero-php icon indicating copy to clipboard operation
xero-php copied to clipboard

Automatically retrieve nested object data

Open tkav opened this issue 5 years ago • 2 comments

I'm trying to automatically get nested object data of any PROPERTY_TYPE_OBJECT returned. I'm saving all data to MySQL, with each model having their own table. Any nested objects-tables will have a column for the parent object (eg. BankAccounts table will have an EmployeeId column).

I have the tables auto-creating based on the defined models but am having trouble getting the nested object data as it's not returned with the initial call.

Example:

Get Employee data: $dataset = $application->load(\XeroPHP\Models\PayrollAU\Employee::class)->execute();

Process values:

foreach ($dataset as $datarecord) {
    $properties = $datarecord->getProperties();

    //refreshId used for nested objects
    $refreshId = md5(uniqid(rand(), true));

    $recordColumns = array();
    $formattedRecordColumns = array();

    //define each record
    foreach ($properties as $key => $value) {

      switch ($properties[$key][1]) {
        case 'object':

          //build values for nested object table
          $nestedFormattedColumns = array();
          $nestedColumns = array();
          $nestedValues = array();

          $NestedEntitiesName = $key;
          $NestedXeroTblPrefix = $xeroTblPrefix.'_'.$entitiesName;
          $NestedEntitiesTbl = $NestedXeroTblPrefix.'_'.$NestedEntitiesName;

          $object = $properties[$key][2];
          echo '<hr>';
          echo '<br>OBJECT Model Location for '.$key.':'. $object;

          $classLocation = '\\XeroPHP\\Models\\'.$object;
          $objectProps = $classLocation::getProperties();

          echo '<hr>';
          echo '<br>Nested Objects: '.$key;
          echo '<br>--------------------------------<br>';
          echo '<pre>';
          print_r($objectProps);
          echo '</pre>';

          //if array is empty, nested object values were not included
          if (empty($value)) {
            echo 'Nested values included';
            $nesteddataset = $datarecord[$key][$entitiesName];
          } else {
            echo 'Nested values not included';

            //attempt to get nested object data
            $getFunction = 'get'.$NestedEntitiesName.'';
            $nesteddataset = $classLocation::{$getFunction}();
            $nesteddataDestination = $classLocation;
            $nesteddataset = $application->load($nesteddataDestination)->{$getFunction}();
          }

          foreach ($objectProps as $objectKey => $objectName) {
              $nestedFormattedColumns[] = "`".$key.'_'.$objectKey."`";
              $nestedColumns[] = $key.'_'.$objectKey;
              $nestedValues[] = $nesteddataset[$key][$objectKey];
          }

          echo '<hr>';
          echo '<br>Nested Values: '.$key;
          echo '<br>--------------------------------<br>';
          echo '<pre>';
          print_r($nestedValues);
          echo '</pre>';

          //insert nested data
          $save = XeroSync::insertNested($mysqli, $tenantGuid, $database, $NestedEntitiesTbl, $primaryKeyField, $primarykeyvalue, $nestedFormattedColumns, $nestedColumns, $nestedValues, $refreshId);

          //for each nested object table updated, delete where $refreshId doesn't match
          $del_data_qry = "DELETE FROM `$NestedEntitiesTbl`
          WHERE tenantGuid = '$tenantGuid' AND $primaryKeyField = '$primarykeyvalue' AND refreshId <> '$refreshId'";
          //echo $del_data_qry;
          $del_data_query = mysqli_query($mysqli, $del_data_qry);


          break;
        case 'date':
          //$formattedDate = $dateobject->format('Y-m-d H:i:s');
          $recordValues[] = "'date'";
          break;
        case 'timestamp':
          $recordValues[] = "'timestamp'";
          break;
        default:
          ${$key} = $key;
          $recordColumns[] = $entitiesName.'_'.$key;
          $formattedRecordColumns[] = "`".$entitiesName.'_'.$key."`";
          ${$key} = $datarecord[$key];
          $recordValues[] = "'".${$key}."'";
          break;
      }

    }


  $primarykeyvalue = ${$primaryKeyFieldName};

  //Save or update data
  $save = XeroSync::saveOrUpdate($mysqli, $tenantGuid, $database, $tablename, $primaryKeyField, $primarykeyvalue, $formattedRecordColumns, $recordColumns, $recordValues);


}

Issue:

The nested object values (including HomeAddress and BankAccounts) are not included in the employee data. Is there a way to retrieve the nested object data using the info supplied by the object's getProperties() function?

//attempt to get nested object data
$getFunction = 'get'.$NestedEntitiesName.'';
$nesteddataset = $classLocation::{$getFunction}();
$nesteddataDestination = $classLocation;
$nesteddataset = $application->load($nesteddataDestination)->{$getFunction}();

Returns:

Fatal error: Uncaught Error: Call to undefined method XeroPHP\Models\PayrollAU\Employee\HomeAddress::getHomeAddress()

I'm hoping to repeat this for all end points - automatically retrieve any nested object data, create a table if required and sync the records.

tkav avatar Feb 13 '20 23:02 tkav

I wish it could do this but you have to make separate requests. You'll probably run into a rate limit so you'll need internal records, rate limiting methods, and a way to resume your progress if the script has to be restarted.

cproetti avatar Feb 14 '20 03:02 cproetti

Thanks @cproetti. At this stage I can't even make a separate request to get the nested objects. Is this is the correct way to call getBankAccounts()?

$employees= $application->load(\XeroPHP\Models\PayrollAU\Employee::class)->execute();
$bankAccounts = $employees[0]->getBankAccounts();
print_r($bankAccounts);

tkav avatar Feb 16 '20 21:02 tkav