3

I've the following situation:


Accommodations (entry)

  • title
  • description (textfield)
  • ...
  • linkedTo (matrix block)
    • Sport (category)
    • targetGroup (category)
    • minimumAge (number)
    • maximumAge (number)

What I'm trying to do is fetch all entries (accommodations) related to a sport and targetGroup for a person of a certain age. E.g.: Entries for children with the age of 11 years in the targetGroup 'men/boys' and the sport 'football'.

Finding elements using relatedTo works for me, except I'm not able to filter the age. I'm pretty sure I'm doing something wrong here. I think it's not possible in craft to find textfield values via the relatedTo method, but the question is: How should I do this?

private function get ()
{
    $sport      = $this->findSelectedBySlug('football');
    $targetGroup    = $this->findSelectedBySlug('men-boys');
    $age            = 11;

    $wheres = [
        "and",
        [
            'targetElement' => $sport,
            'field' => "linkedTo.sport"
        ],
        [
            'targetElement' => $targetGroup,
            'field' => "linkedTo.targetGroup"
        ],
        [
            'targetElement' => "<= {$age}",
            'field' => "linkedTo.minimumAge"
        ],
        [
            'targetElement' => "> {$age}",
            'field' => "linkedTo.maximumAge"
        ]
    ];

    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'accomodations';
    $criteria->relatedTo = $wheres;

    return $criteria->find();
}
private function findSelectedBySlug ($slug)
{
    $criteria = craft()->elements->getCriteria(ElementType::Category);

    $criteria->slug = $slug;

    return $criteria->first();
}   
1

You're right, this isn't possible with setting relatedTo parameters. But you can pass your ElementCriteriaModel (with all other parameters set) to the buildElementsQuery method, to prepare a DbCommand object. You can now modify the query as you need (→ Craft documentation for Database Queries).

Use join to bring in the "matrixblocks" table and also your Matrix field's content table "matrixcontent_mymatrixfield". Then add the min. and max age conditions with andWhere.

private function addAgeCriteria(ElementCriteriaModel $criteria, $age)
{
    $query = craft()->elements->buildElementsQuery($criteria);

    $params = array(
        ':age' => $age
    );

    $conditions = array('and',
        'matrixcontent_mymatrixfield.field_linkedTo_minimumAge <= :age',
        'matrixcontent_mymatrixfield.field_linkedTo_maximumAge >= :age'
    ),

    $query->andWhere($conditions, $params);

    $query->join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
    $query->join('matrixcontent_mymatrixfield matrixcontent_mymatrixfield', 'matrixcontent_mymatrixfield.elementId = matrixblocks.id');

    $results = $query->queryAll();

    return EntryModel::populateModels($results);
}

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.