Hot answers tagged

29

The trick is to add and once before the first not {% set entries = craft.entries.search(query).section('and, not this, not that') %}


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

Craft imposes a default limit of 100 for element queries. To disable this you need to specify a limit of null. $criteria->limit = null;


9

I haven't tested this, but it should be a good starting point, at the very least. {# Determine the number of days in the month #} {% set daysInMonth = "now"|date("t") %} {# Determine the date range spanning the month #} {% set firstDayOfMonth = "now"|date("Y-m-01") %} {% set firstDayOfNextMonth = "now"|date_modify("first day of next month")|date("Y-m-01") %...


7

I can't answer your question directly as I never got even close to 300 fields yet. But even with 50 fields I had some serious slowdowns, especially when getting related entries in form of assets and such. I think you should definitely consider using the built in cache function to get good performance. In regards to that field name / instructions problem ...


6

Use craft.request.getQueryStringWithoutPath() like so: products/category?{{craft.request.getQueryStringWithoutPath()}} Returns the query string, except for the p= param (which was probably added by your .htaccess redirect). More complicated logic to avoid the ? when the query string is empty (one of several ways to do this): {# queryString will include ...


6

The ElementCriteraModel description in the docs explains what the find() method does. Essentially, when you use craft.entries you are building an ElementCriteriaModel object that represents the query that you want to make. That query doesn't actually happen until you call the find() method. As the docs state, as soon as you treat craft.entries (or a ...


5

I think you are using the wrong string concatination operator. ~ is the twig string concatination operator (vs . for php and + for javascript). Try this: {% set entries = craft.entries.section('schools').find({ search: 'body:' ~ queryKeyword ~ ' categories:' ~ queryLocation, }) %}


5

Crisis averted, thanks largely in part to the versitile nature of the relatedTo targetElement processing. The relevation came that I could feed an array of category ids (inclusive) into that element, and use a single relatedTo "and" parameter overall to get my intended filtering: {% set params = { section: 'technologies', limit: null } %} {% set ...


5

You are currently performing a SELECTinstead of an UPDATE so no data will be updated. I'm guessing that entryId is the primary key of the record you are trying to update? If so, I would suggest you find the record to make sure it exists, update its attributes (status) and then save it. // PluginController public function actionDeny() { $this->...


5

You can't do this using the craft.entries tag in twig. You'll need to create a new function in your plugin that returns the entries in your custom order. Assuming you can create an array of element ids in your custom order then the following code should allow you to then fetch entries in that order: $criteria = craft()->elements->getCriteria(...


5

By default, Craft sets a limit of 100. Set it to null: limit(null).


4

This happens because you set the parameter on the ElementCriteriaModel to get entries with that specific datetime. If you omit a time when you compose a datetime with strings, you'll still get a time (00:00:00) and even a timezone set on it: {% set myDatetime = '2014-08-12' %} {# Print the datetime in ISO 8601 format / 2014-08-12T00:00:00+02:00 #} {{ ...


4

You would first need to query for the users that match your criteria and than query for the profile entries which are related to one of these users. {% set userIds = craft.users({ year: craft.request.getSegment(3), userOptions: craft.request.getSegment(2), }).ids() %} {% set profiles = craft.entries({ section: 'profiles', relatedTo: { ...


4

Both approaches are valid. In your first example, you could have moved .all() into the for-loop; and in the second example, you could have moved .all() out of the for-loop, and into the {% set entries = ... %} statement. Until you call .all(), you are working with an entry query, and after you call .all(), you’re working with an array of the actual entries (...


3

If you have an EntryModel and know the category field's handle, you don't really need a service: $categories = $entry->categoryFieldHandle; In other cases, you can construct an ElementCriteriaModel to search for related elements (categories, entries, users or assets), using a number of different variables. Easy example to get related categories from an ...


3

Rather than fetching the entries at first, just grab their IDs using ids() instead of find(): {% set featuredBlogId = craft.entries.section('blogs').limit(1).ids() %} {% set featuredArticleId = craft.entries.section('articles').limit(1).ids() %} {% set featuredSpecialReportId = craft.entries.section('specialReports').limit(1).ids() %} {% set ...


3

Please don't laugh, but I thought to myself, let's give this a go in Twig and see where it takes me. It very soon began to become clear, that this will end up in lots of criteria models, db queries and a huge pile of Twig code. So my better answer should be, don't do it in Twig. This is something you should better do in PHP with custom database queries (→ ...


3

The main problem is your URL isn't formatted correctly. You need brackets after each 'size' parameter to make an array of those values. Otherwise, it only picks up the last value. http://domain.com/search/results?size[]=small&size[]=medium Then you can do something like this: {% set sizeQuery = craft.request.getParam('size') %} {% set params = {...


3

In Craft 3 you don't have to iterate through the chidlCategories manually, you could use the column filter instead, like this: {% set queryCatSlugs = childCategories.all() | column('slug') %} {% if slugToCheck in queryCatSlugs %} .... {% endif %}


3

I would construct an array of the category slugs outside of your childCategories loop (using twig's merge filter: {% set queryCatSlugs = [] %} {% for category in query %} {% set queryCatSlugs = queryCatSlugs|merge([category.slug]) %} {% endfor %} Then your childCategories loop can use twig's containment operator (in) for the test: {% for childCategory ...


3

DbCommand represents a SQL statement to execute against a database. ElementCriteriaModel is a model just like any other model in craft/app/models, but it also happens to make it easy to search for Elements in the database. By setting all of the criteria for the elements you're searching for and calling the find() method, that will invoke craft()->...


3

Update: I'll leave the original answer because they're certainly still viable options, this is now probably best solved by using the eager loading features that Craft 2.6 added. A bit difficult to properly debug without seeing things like your content architecture, database profiling information, logs, etc. But using the {% cache %} tag is certainly an ...


3

ElementCriteriaModel parameters always add up to further filter down the results, which means an element has to be truthy for each one of them to be returned. So your params basically look right for what you're trying to achieve. The only thing that might mess with the results is the for me unusual use of the w3c methods on the DateTime objects, which might ...


3

You don't need to use the search parameter in this case. I'd avoid using it where ever possible. {% set tag = craft.tags.slug(slug).first() %}


3

You're using $criteria, but attempting to set the relatedTo property on $this->criteria. Assuming that's not the issue, have you tried using $criteria->setAttribute('relatedTo', ['targetElement' => $category])? I've found setAttribute to be more reliable than the ElementCriteriaModel magic methods.


3

Eager loading only works when your field is a RelationField it does not work with Text fields. If you goal is to reduce the length of the queries and to maximize your performance you could fetch the raw rows instead of populating the elements. $criteria = craft()->elements->getCriteria(ElementType::Category); $criteria->status = null; $criteria->...


3

I was finally able to piece this together using Brad's explanation of MatrixBlocks parameters and this thread Can I get an entry by Matrix Block ID? Seems merge([block.owner.id]) was the piece I was missing to fold the MatrixBlock query back into an entries loop. {# Find Matrix Blocks with field value #} {% set blocks = craft.matrixBlocks.type('variant')....


3

At the same time as you are iterating over your Hero posts, you could populate an array that you could then use in your most popular query. This is just sudo code but hopefully you get the idea: {# This would go before your hero loop #} {# Initiate a heroIds array starting with not #} {% set heroIds = ['not'] %} {% for entry in heroEntries %} {# Add ...


3

You're not misunderstanding anything, and your concerns are perfectly valid. I feel like many developers using Craft do not realise that .one() and .all() are in fact database calls, and pretty expensive ones at that. Do it your way, watch the number of DB queries go down in the debug toolbar and feel all warm and fuzzy. (Also, you don't need parentheses in ...


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