2

Currently involved with handling the CategoryModel and using this code

return [
    'endpoints' => [
        // Category    
    'category/<slug:{slug}>.json' => function($slug) {
        require craft()->path->getConfigPath().'controllers/CategoryTransformer.php';
        return [
            'elementType' => 'Category',
            'criteria' => ['group' => $slug],
            'transformer' => new CategoryTransformer(),
        ];
    },
];

refering to CategoryTransformer.php

class CategoryTransformer extends CategoryFieldTransformer
{
    var $entry, $typeMedia;
    public function transform(CategoryModel $entry)
    {
        echo $entry['uri']."
        ";
        $child = $entry->getChildren();
    }
}

It works all though I am not having success with been able to build a hierarchical object that would have parent and child nodes for the API to return. I made a modest attempt at building the categories in another area of the API interface but did not return what I was hoping for.

 public function type_categories($mixedArray){
    $categories = array();
    foreach($mixedArray as $rkey => $rvalue){
        $level = $mixedArray[$rkey]->level - 1;
        $argt = array(
            'id' => $mixedArray[$rkey]->id,
            'uri' => $mixedArray[$rkey]->uri,
            'title' => $mixedArray[$rkey]->title,
            'level' => $mixedArray[$rkey]->level,
            'slug' => $mixedArray[$rkey]->slug,
            'groupId' => $mixedArray[$rkey]->groupId,
            'level' => $mixedArray[$rkey]->level
            );
        // Children
        $obg = $mixedArray[$rkey]->children;
        $kids = array();
        foreach($obg as $kid => $kidval){
          $kids[] = array(
            'id' => $obg[$kid]->id,
            'uri' => $obg[$kid]->uri,
            'title' => $obg[$kid]->title,
            'level' => $obg[$kid]->level,
            'slug' => $obg[$kid]->slug,
            'groupId' => $obg[$kid]->groupId,
            'level' => $obg[$kid]->level
            );
        } 
        $argt['children'] = $kids;                                                                    
        $categories[$level][] = $argt;                                        
    }
    return $categories;
}

I as well took a peek at CategoriesController.php in the core and couldn't find anything that could assist me. It ends with Twig handling the object.

Is it possible if anyone has done something similar that I may reference to build a clean object which is intuitive for someone to loop on in JSON format?

Following is an example of the intended hierarchy:

stdClass Object
(
[0] => Array
    (
        [id] => 1
        [uri] => cars
        [title] => Cars
        [children] => Array
            (
                [0] => Array
                    (
                        [id] => 4
                        [uri] => bmw
                        [title] => BMW
                    )

                [1] => Array
                    (
                        [id] => 6
                        [uri] => audi
                        [title] => Audi
                    )

                [2] => Array
                    (
                        [id] => 7
                        [uri] => vw
                        [title] => VW
                        [children] => Array
                            (
                                [0] => Array
                                    (
                                        [id] => 50
                                        [uri] => hatchback
                                        [title] => Hatchback
                                    )

                                [1] => Array
                                    (
                                        [id] => 50
                                        [uri] => sedan
                                        [title] => Sedan
                                    )

                            )

                    )

            )

    )

[1] => Array
    (
        [id] => 1
        [uri] => trucks
        [title] => trucks
    )
)

Thanks

  • What do you mean by "hierarchical object"? Can you update your question with an example of what you're hoping the resulting JSON will look like? – Brandon Kelly May 25 '16 at 17:35
3

Element API doesn’t have any special support for returning nested arrays of element data, but you can hack it by limiting the initial batch of categories to just those at the top level, and within the transformer function, running additional queries to fetch nested elements, and incorporating them into the parent category’s return data.

To limit the initial batch to just the ones at the top level, change your criteria value to:

'criteria' => ['group' => $slug, 'level' => 1],

And then update your transform() method to this:

public function transform(CategoryModel $category)
{
    $data = [
        'id' => $category->id,
        'uri' => $category->uri,
        'title' => $category->title,
    ];

    $children = $category->getChildren();

    if ($children) {
        $data['children'] = [];

        foreach ($children as $child) {
            $data['children'][] = $this->transform($child);
        }
    }

    return $data;
}

The caveat here is that this will require an additional SQL query for each individual category, since we need to check each category to see if it has any children. As of Craft 2.6.2789 you can fix that by eager-loading the categories’ children with the newly-supported children keyword.

To do that, update your criteria value with this:

'criteria' => [
    'group' => $slug,
    'level' => 1,
    'with' => ['children.children.children']
],

(Put as many .children as the number of levels the category group will have. So if it’s limited to two levels, children.children would suffice.)

  • Tried adding this ``` 'with' => ['children.children.children']``` and it didn't seem to have any impact. I'm on 2.6.3000. Does this work with single entry endpoints? – user814584 Dec 14 '17 at 23:53
  • @user814584 Not sure i’m following you - probably worth posting a new question with a complete code example. – Brandon Kelly Jan 20 '18 at 23:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.