TYPO3 Extbase: How to sort child objects
Asked Answered
C

4

6

I have an Extbase Model Article and a 1:n Relation Product. In Article TCA i have an inline field configuered. In my Article Template I want to display all related Products. These are oredered by uid. How can i change the ordering of the child objects to the field sorting to be able to manually sort them. ( In the backend form the sorting is possible, only diplaying them sorted by field sorting is not possible )

thanks, Lukas

Crosspurpose answered 12/9, 2014 at 11:35 Comment(0)
L
0

Here's how I do it, in the repository class:

class ItemRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {

    /**
     * http://www.typo3.net/forum/thematik/zeige/thema/114160/?show=1
     * Returns items of this repository, sorted by sorting
     *
     * @return array An array of objects, empty if no objects found
     * @api
     */

    public function findAll() {
        $orderings = array(
            'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
        );

        $query = $this->createQuery();
        $query->setOrderings($orderings);

        $query->getQuerySettings()->setRespectSysLanguage(FALSE);
        $query->getQuerySettings()->setSysLanguageUid(0);

        $result = $query->execute();
        return $result;
    }

}
Lehr answered 13/9, 2014 at 12:45 Comment(7)
Is the Item Model a Child Object ? Of course this works if i get the items directly from the ItemRepository findAll Method, but not if I get the child objects from the parent object. Or am i wrong ?Crosspurpose
Ah I overread that part completely, sorry. Googling "extbase sort child objects" revealed quite a few results. Also, there seems to be a fedext viewhelper fluidtypo3.org/viewhelpers/fed/Data/SortViewHelper.html that might do it in the viewLehr
Here's the correct URL fluidtypo3.org/viewhelpers/vhs/1.8.3/Iterator/…Lehr
<v:iterator.sort subject="{article.articleProduct}" as="products" sortBy="sorting" order="ASC"> did the job. It's important to have a getter and setter method for the field sorting for (in my case) the articleProduct ModelCrosspurpose
<v:iterator.sort> save my day, thank you so much both of you :)Charmain
Why is this answer marked as "answer"? The question was "How to sort CHILD objects", which is not possible in this way. $article->getProducts() will not be sorted as whished.Vanesavanessa
Edit the answer makes no sense: the answer is correct when you want to sort the parent obejcts. But It does not sort the CHILD objects. See comment from JKB. The correct answer ist 8.Tautog
V
14

The easiest way to sort child elements in a object storage is to manipulate the TCA.

Example:

$TCA['tx_myext_domain_model_ordering'] = array(
...
'columns' => array(
    'services' => array(
        'exclude' => 0,
        'label' => 'LLL:EXT:myext/Resources/Private/Language/locallang_db.xml:tx_myext_domain_model_ordering.services',
        'config' => array(
            'type' => 'inline',
            'foreign_table' => 'tx_myext_domain_model_service',
            'foreign_field' => 'ordering',
            'foreign_sortby' => 'sorting',
            'maxitems'      => 9999,
            'appearance' => array(
                'collapseAll' => 0,
                'levelLinksPosition' => 'top',
                'showSynchronizationLink' => 1,
                'showPossibleLocalizationRecords' => 1,
                'showAllLocalizationLink' => 1
            ),
        ),
    ),
),
...
);

With the filed 'foreign_sortby' => 'sorting', you can easily say on which field the childs should be ordered.

Vegetarian answered 7/12, 2016 at 11:34 Comment(2)
When I add ''foreign_sortby' => 'myField', in the backend, I can no longer see 'myField' when editing the parent object, although I still can see it when editing the child object directly. Any ideas?Sloven
This should be the accepted answer imho. If you use an ObjectStorage for your child records (Model B) in your AggregateRoot (Model A) & you want to let editors sort records of model B but you fetch those via Repository of model A, sorting is ignored. 'foreign_sortby' is the solution & with this, the sorting of the child objects is taken into account.Simonetta
R
2

Using the dot notation you can sort by properties of subobjects:

$query->setOrderings(array(
    'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
    'subobject.sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
));

edit: Caught me off guard, I think I read your question wrong. Yes, this sorts by child objet, but it applies that to the parent object, of course. If you want to sort the child objects themselves, you have to set that sorting in the repository of the child object, as @Urs explained.

Raceme answered 7/12, 2016 at 12:1 Comment(0)
L
0

Here's how I do it, in the repository class:

class ItemRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {

    /**
     * http://www.typo3.net/forum/thematik/zeige/thema/114160/?show=1
     * Returns items of this repository, sorted by sorting
     *
     * @return array An array of objects, empty if no objects found
     * @api
     */

    public function findAll() {
        $orderings = array(
            'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
        );

        $query = $this->createQuery();
        $query->setOrderings($orderings);

        $query->getQuerySettings()->setRespectSysLanguage(FALSE);
        $query->getQuerySettings()->setSysLanguageUid(0);

        $result = $query->execute();
        return $result;
    }

}
Lehr answered 13/9, 2014 at 12:45 Comment(7)
Is the Item Model a Child Object ? Of course this works if i get the items directly from the ItemRepository findAll Method, but not if I get the child objects from the parent object. Or am i wrong ?Crosspurpose
Ah I overread that part completely, sorry. Googling "extbase sort child objects" revealed quite a few results. Also, there seems to be a fedext viewhelper fluidtypo3.org/viewhelpers/fed/Data/SortViewHelper.html that might do it in the viewLehr
Here's the correct URL fluidtypo3.org/viewhelpers/vhs/1.8.3/Iterator/…Lehr
<v:iterator.sort subject="{article.articleProduct}" as="products" sortBy="sorting" order="ASC"> did the job. It's important to have a getter and setter method for the field sorting for (in my case) the articleProduct ModelCrosspurpose
<v:iterator.sort> save my day, thank you so much both of you :)Charmain
Why is this answer marked as "answer"? The question was "How to sort CHILD objects", which is not possible in this way. $article->getProducts() will not be sorted as whished.Vanesavanessa
Edit the answer makes no sense: the answer is correct when you want to sort the parent obejcts. But It does not sort the CHILD objects. See comment from JKB. The correct answer ist 8.Tautog
B
-1

I dont't really like the idea of doing basic sorting inside the view (mvc).

The Downside of most Database abstraction Layers ist, that you are quite often restricted to either mixup mvc or have a (sometimes slightly) lower performance.

I am at the same point right now. I am thinking about retrieving the parents (with their children attached). Then go into every single parent and get children for this parent in a sorted way.

public function findAllSorted() {
    $query = $this->createQuery();
    /* sort parents */
    $query->setOrderings(array('name' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
    $parents = $query->execute();
    foreach($parents as $parent){
        /* get children for every parent */
        $children = $this->getChildrenSorted($parent);
        // add children to parent TBD

    }
    /* Debug output */
    \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($parents);
}

public function getChildrenSorted(\mynamespace\ $parent) {
    /* Generate an object manager and use dependency injection to retrieve children repository */
    $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('\TYPO3\CMS\Extbase\Object\ObjectManager');
    $childrenRepository= $objectManager->get('MYNAME\Extname\Domain\Repository\Repository');
    $children = $versionRepository->findSortedByName($parent);
    return $children;
}

The function findSortedByName inside the children repos is using

$query->matching($query->equals('parent', $parent));

to retrieve only children of this parent and

$query->setOrderings(array('name' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));

to be able to give them back in an ordered way.

Warning: Depending on the size and quantity of all retrieved objects, this way might arise a huge performance issue.

Baun answered 16/12, 2014 at 1:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.