Getting all children, grandchildren etc from Model with hasMany relationships

Hi. I'm trying to write a json api. I want to send all the children, grandchildren and so on, along with the parent record.

If I use the following code the json output only contains the parent (Customer) record, but I want to include all the customer's orders, all the products on the order, and all the parts needed to make the product. ```php // Customer hasMany Order // Order hasMany Product // Product hasMany Part

$customer = Customer::findFirst($id); echo json_encode($customer);

// Only outputs the parent (Customer) record ``` Is there an easy way to get all the children many levels deep? (without manually building arrays with foreach loops).

Thanks

Hi,

use the http://docs.phalconphp.com/en/latest/api/Phalcon%5Mvc%5Model%5ManagerInterface.html Model Manager and get all relations using the getHasOneAndHasMany() method to have all relations, than loop on this relation and use the $customer->getRelated() method to get value.

Could you please give an example on how to use the getHasOneAndHasMany() in a model or in a controller?



17.1k

I have the same problem as matt-sharp. There is another topic with link to yours here http://forum.phalconphp.com/discussion/2104/related-records-automatically-including

Please write what do you think about the solution I have wrote. Or maybe you have already found the solution? TIA!



1.6k

anyone got a solution they could share for this one?

edited Nov '14

hello,

i've got a method quite heavy in code, but working ;-)

here is a list of relations attached in my model (it's a member data)

    /**
     * Merge array
     *
     * @param string $key key
     * @param array  $in  in
     * @param array  $add add
     *
     * @return array
     */
    protected function mergeArray($key, array $in, array $add)
    {
        return array_merge($in, $add);
    }
    /**
     * Add child
     *
     * @param string $key key
     * @param array  $in  in
     * @param array  $add add
     *
     * @return array
     */
    protected function addChild($key, array $in, array $add)
    {
        $in[$key] = $add;
        return $in;
    }
    /**
     * Add children
     *
     * @param string $key      key
     * @param array  $in       in
     * @param object $objects  object
     * @param array  $arrayKey arrayKey
     *
     * @return array
     */
    protected function addChildren($key, array $in, $objects, $arrayKey = null)
    {
        $in[$key] = array();
        foreach ($objects as $object) {
            if ($arrayKey) {
                $in[$key][$object->$arrayKey] = $object->toArray();
            } else {
                $in[$key][] = $object->toArray();
            }
        }
        return $in;
    }

    /**
     * Model object to json
     *
     * @param array $params params
     *
     * @return array
     */
    public function toJson(array $params = [])
    {
        $modelObject = $this->toArray();
        foreach (static::$toJsonRelations as $related => $relation) {
            $modelRelated = $this->getRelated(\Phalcon\Text::camelize($related));
            if ($modelRelated) {
                $modelObject = $this->$relation($related, $modelObject, $modelRelated->toArray());
            }
        }
        $refClass = new \ReflectionClass($this);
        return [
            strtolower($refClass->getShortName()) => $modelObject
        ];
    }

and initialize your model with this "relations data" :

    /**
     * Relation types
     *
     * @var array
    */
    public static $toJsonRelations = [
        'part' => 'addChildren',
        'product' => 'addChildren',
        'order' => 'addChildren', // can be mergeArray | addChild | addChildren depending on the relation ( 1<->1 | N->1 | 1->N)
    ];

when you'll execute

$customer = Customer::findFirst($id);
echo json_encode($customer->toJson());

you'll have all data you want attached