We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Related records - automatically including

This is basically the issue from : https://forum.phalcon.io/discussion/1437/getting-all-children-grandchildren-etc-from-model-with-hasmany-r

Is there an easier and less obtuse way to dump the related records of a resultset?

The first thing that comes to mind is:

$p_Customer = Customer::findFirst($id);
$a_Customer = $p_Customer->toArray();
$a_Customer['orders'] = [];

foreach($p_Customer->orders as $Order){
    $a_Customer['orders'][] = $Order->toArray();
}

echo json_encode($a_Customer);

The toArray() function is useful, but unfortunately I don't believe it goes down into related records.

edited Apr '14

I'm aware that I can just build up new arrays and do it all myself. Your solution necessitates copy pasting boilerplate all over an API whice violates the DRY principles and is exactly what I am trying to avoid. Furthermore if there are results nested past the first level that solution will quickly become unwieldy.

Thanks for your response but the question asks for an easier way to serialize a resultset.

What I gave you was pretty simple, but admittedly not very automatic. The other post has a response outlining what can be done as well.

There's no built-in way to do what you ask, so you're going to have to code something yourself. You might get lucky, but most likely no one is just going to hand you the code. The first response to your linked post explains exactly what you need to do to abstract out my idea to be more general.



26.3k
Accepted
answer

Hi All!

I have the same problem as david-duncan here and matt-sharp at https://forum.phalcon.io/discussion/1437/getting-all-children-grandchildren-etc-from-model-with-hasmany-r

In the original post matt-sharp wrote:

Customer hasMany Order

Order hasMany Product

Product hasMany Part

My solution for now is:

In a controller:


//obtaining the customer object
$customer = Customer::findFirst($id); 

//obtaining the resultset of all parts that belong to the customer
$his_parts = $customer->getParts(); 

In a model:

then in the Customer model I would define the following getParts() method:


public function getParts() {

  //obtain resultset
  $parts = Part::query()
    ->innerJoin('Product')
    ->innerJoin('Order')
    ->innerJoin('Customer')
    ->where("customer_id = :customer_id:")
    ->bind(array("customer_id" => $this->getCustomerId()))
    ->execute(); 

  return $parts;

}

In the above model my id field is customer_id and its getter is getCustomerId() method. I assume that all models has properly defined relations.

Please write what do you think about it? What other solution you are using?

Innerjoins abstracted into the model is what I have been doing. Seeing as Quasipickle says that there is no automatic phalcon way to do this it looks like your answer is the most correct.

I was hoping there was a flag or parameter I was missing somewhere in a relationship or a call like toArray that would actually serialize down the lineage tree.