19

The ElementCriteriaModel and the individual element models (like the EntryModel) can be thought of as two different points of time in retrieving data from your database. Essentially, you'll use an ElementCriteriaModel before the database is queried and the element models afterwards. Why do I sometimes have to fetch elements with .first(), .last(), .find()…...


16

Craft 2.5 introduced a new feature for this. It’s now possible to find elements where a relational field does/doesn’t have any related elements, by passing ':notempty:' or ':empty:' onto the field’s ElementCriteriaModel parameter (e.g. craft.entries.myEntriesField(':notempty:')). So in this case you can use: {% set entries = craft.entries.myAssetField(':...


12

Read the article about ElementCriteriaModel in the official Craft docs on how to query elements in general and the craft.entries article about the parameter available to modify the object returned. Example code for your events list: {# Get events from `events` section in desired sort order #} {% set allEvents = craft.entries.section('events').order('...


11

You can do this in a single query using the search parameter: {% set uncategorized = craft.entries.section('news').search('-categories:*') %} More on searching here.


10

Once you've got your ECM, pass it off to the buildElementsQuery method... $query = craft()->elements->buildElementsQuery($criteria); This will convert your ECM into a DbCommand object. From there, you can make further modifications to the query... like adding a join for your 3rd party table. $query->join('myplugintable myplugintable', '...


10

As per the (new) "Working with Elements" guide from the docs, it works the same as from your templates. The actual list of available parameters depends on the element type. They are identical to the parameters available to your templates. So this template example: {% craft.entries.section('news').myPlaintextField('xyz').myLightswitchField(1) %} Works ...


9

For most cases you can find a workaround to combine such conditions by making use of entry IDs. In this example query for each time range condition separately and use the ids() method to "collect" your entries. All matching IDs are then passed to the id parameter of a final ElementCriteriaModel, that you can also use for Pagination etc.: {% set ...


9

The order param sets the ORDER BY part of the MySQL query. You can also pass MySQL functions in it. In your case GREATEST() should do the job: {% set allEntries = craft.entries .section(['publication','text', 'exhibition']) .order('GREATEST(releaseDate, publicationReleaseDate, exhibitionOpeningDate) desc') .limit(null) %}


9

Something like this should work: $criteria = craft()->elements->getCriteria(ElementType::Entry); $criteria->section = 'sectionHandle'; $criteria->postDate = array('and', '> 2014-11-03 23:59:59', '< 2014-11-05 00:00:00'); $results = $criteria->find();


9

It appears that when one or more Entries (or other types of content) are manipulated (in my case, deleted) from the bulk edit view in the Control Panel, the type of events that are triggered are Element events, rather than Entry events. If you refer to the Craft documentation on elements.onPerformAction, you can see that the 2 params you get access to are ...


8

You can do this with the relatedTo param. First get all assets that could possibly be related. (If you only wanted to find entries that related assets from a particular source, this would be the place to add that filter.) {% set assets = craft.assets.limit(null) %} Next up, you would get all the entries that are related to any of those assets: {% set ...


8

Have a look at DbHelper::parseParam docs: If the $value is a string, it will automatically be converted to an array, split on any commas within the string (via ArrayHelper::stringToArray()). If that is not desired behavior, you can escape the comma with a backslash before it. To escape the comma and other characters treated as special in DbHelper::...


7

You can use the a special search format. $criteria-> search = 'fieldHandle:searchstring'; Learn more about searching Hope that helps!


7

I think that you actually want to use 'and' rather than 'or'. 'Or' would return all entries. This is also assuming that you have predefined the 'startDate' and 'endDate' variables. {% set params = { section: 'exhibitions', startDate: 'and, >= ' ~ startDate ~ ', <= ' ~ endDate, order:'startDate desc' } %} {% set startedThisYear = craft....


7

With good help from @carlcs here and on Slack, we found a solution: {% set allEntryIds = craft.entries.limit(null).ids() %} {% set usedAssets = craft.assets({ relatedTo: allEntryIds, limit: null, }).ids() %} {% set unusedAssets = craft.assets({ id: 'and, not ' ~ usedAssets|join(', not '), limit: null }) %}


6

You could do this with a plugin. Create a Variable class with a function called sum(), which accepts an ElementCriteriaModel, passes it to ElementsService::buildElementsQuery(), and then replaces the SELECT value on the resulting DbCommand object: <?php namespace Craft; class FooVariable { public function sum(ElementCriteriaModel $criteria, $column) ...


6

You’re close! You just need to begin the array with "and": $criteria = craft()->elements->getCriteria(ElementType::User); $criteria->customNumberField = array('and', '>=5', '<=10'); $users = $criteria->find(); This same thing could also be accomplished from your templates like this: {% set users = craft.users.customNumberField('and', '&...


6

Your statuses are incorrect. They would be correct for many elements, but the Entry Element overwrites them to the following: EntryModel::LIVE EntryModel::PENDING EntryModel::EXPIRED BaseElementModel::DISABLED


6

You can get your entry's parent entry with getParent(). Use this entry method in a conditional, if your entry has no hero image set. You can nest the code to climb up all of your structure's levels: {# Check if entry has hero image #} {% if entry.hero.first() %} {{ entry.hero.first().url }} {% else %} {# Check the parent entry #} {% if entry....


6

You're very close! Try this: $criteria = craft()->elements->getCriteria(ElementType::Entry); $criteria->section = 'concepts'; $criteria->limit = null; $criteria->relatedTo = array( 'targetElement' => $e, 'field' => $field ); $elements = craft()->elements->findElements($criteria); Keep in mind, in this instance, $...


6

Ok, so I've managed to get an answer to this courtesy of Brandon Kelly. It's much more simple than I thought. Firstly, you do not have to specify a relatedTo parameter the defineCriteriaAttributes(). Craft takes care of this automatically. So in order to retrieve the details of an asset in a table list view you do the following in the ...


6

I'm not sure if there's some other Craft helpers / static variables that you could use, but this technique works. Create a DateTime object without the param set to get the current time, modify it and format it for use in the query like so: $date = new DateTime(); $date->modify('-7 days'); // Format datetime for use in query $timezone = new \DateTimeZone(...


6

This should do the trick: $idList = [1, 2, 3, 4]; $criteria->id = 'and, not ' . implode(', not ', $idList); In plain text, the id property would then look like this: 'and, not 1, not 2, not 3, not 4' The syntax may look a little odd, but it essentially makes Craft compile an SQL query with an AND (elements.id!=$elementId) statement for each ID you ...


6

You would need query for these entries using the first and the last method. {% set criteria = craft.entries.section('blog').order('title asc') %} {% set prevEntry = entry.getPrev(criteria) ?: criteria.last() %} {% set nextEntry = entry.getNext(criteria) ?: criteria.first() %} <a href="{{ prevEntry.url }}">{{ prevEntry.title }}</a> <a href="{...


5

You can do a certain amount of logic in the ElementCriteriaModel syntax. I think this will work: {% set entries = craft.entries.section('equipment').modelYear('and, > 2006, < 2009') %} {% for entry in entries %} ... {% endfor %}


5

I think what you want is to check if a property of the asset is empty, rather than the asset itself, as a concept. The following appears to work, and might be of interest if you think you have empty assets, or in this example, count filled-in ones: {% set entries = craft.assets.filename(':notempty:') %} Filled Count is {{ entries.count() }} You could of ...


5

Another way to do this would be to assemble a list of the entry IDs that you want to look for a hero image in, in order, and then finding the first hero image related to one of those entries. To create that list of entry IDs, we start by creating an array of the current entry’s ID, and merge it with an array of the entry’s ancestors’ IDs in reverse order: {...


5

Untested, but something like this should work: {# set base criteria #} {% set params = { section: 'productsServices', limit: null } %} {# set relationship criteria #} {% set relationParam = ['and'] %} {% for segment in craft.request.segments %} {% if loop.index != 1 and segment != 'all' %} {% set category = craft.categories.slug(segment)...


5

To get all categories that are related to an entry you would do this: {% set allEntries = craft.entries.limit(null) %} {% set categoriesInUse = craft.categories.relatedTo(allEntries) %} If you want to narrow down to a specific category group or any other category property you can do it like so: {% set newsCategories = craft.categories.group('...


5

I fixed this now by using the method buildElementsQuery, like so: $query = craft()->elements->buildElementsQuery($criteria, $contentTable, $fieldColumns); After that, I was able to add custom joins to the query: $query ->addSelect('sport.title sportTitle') ->leftJoin('relations sportRelation', 'sportRelation.sourceId = elements.id ...


Only top voted, non community-wiki answers of a minimum length are eligible