Вопрос

I've got an ItemObject with the field 'Categories'. In this field, the IDs of the related CategoryPages are stored as string. e.g 25,30,8.

Now I want to return only the ItemObjects, where the CategoryPage ID is in the string of the Categories Field.

To achieve this, I created this function

public function getItemsForCategory() {
    $items = Item::get();
    foreach($items as $item) {
        $categories = $item->Categories;
        $explode = explode(',', $categories);
        if( in_array($this->ID, $explode) ) {
            echo $item->ID . '<br>';
        }
    }   
}

It puts the correct IDs of the ItemObject for this one Category in the Page. So it works, but I want to return the ItemObjects for the Category so I replaced the echo $item->ID ...; with return $item; but it seems that this is only returning the first Item for the Category.

Can someone please tell me my mistake?

Thank you in advance!

Это было полезно?

Решение

I will answer your question, why your code is not working,
However, I must warn you, this code is bad and I strongly advise against using it!

What you need to understand is how functions work.
A key rule of a function is that "return" means the end of a function. A return statement means that there will be no more code executed in this function, its the end.
So that's the reason why its not working.

To get it working like this, you need to create an array/list to store the items you want to return.

public function getItemsForCategory() {
    // DO NOT USE - I ADVISE AGAINST USING THIS! THERE IS A MUCH BETTER WAY TO HANDLE IT!
    $matchingItems = ArrayList::create();
    $items = Item::get();
    foreach($items as $item) {
        $ids = explode(',', $item->Categories);
        if(in_array($this->ID, $explode)) {
            $matchingItems->add($item);
        }
    }
    return $matchingItems;
}

Doing it the right way:

Again, I strongly urge against using the above example. See the example below for doing it right:

SilverStripe comes with a ORM and a DataModel capable of managing 1...n (has_many) and n...m (many_many) relations. And some of the FormFields, including CheckboxSetField can save into those relations.
The example contains 2 ways to handle relations, a GridField and a CheckboxSetField:

class CategoryPage extends Page {
    // in template you can then do <% if $Items %> and <% loop $Items %>
    private static $many_many = array(
        'Items' => 'Item',
    );
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->addFieldToTab('Root', Tab::create('Items', 'The Items');
        $config = GridFieldConfig_RelationEditor::create();
        $fields->addFieldToTab('Root.items', GridField::create(
            'Items',
            'Items for this Category',
            $this->Items(),
            $config
        ));
        return $fields;
    }
}

class Item extends DataObject {
    // in template you can do <% if $Categories %> and <% loop $Categories %>
    private static $belongs_many_many = array(
        'Categories' => 'CategoryPage',
    );
    public function getCMSFields() {
        $map = CategoryPage::get()->map();
        return FieldList::create(array(
            TextField::create('Title', 'Item Name'),
            CheckboxSetField::create('Categories', 'Categories for this Item', $map),
        ));
    }
}

This code will store the relation in a relational db. SilverStripe will magically create methods for the relation:

$categoriesForItem = $item->Categories();

and:

$items= $category->Items();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top