Hot answers tagged

10

If you want to run some code when changes are published for an entry, you’re going to want to check !ElementHelper::isDraftOrRevision($entry), which has been the case since Craft 3.2. Those saves only use the essentials scenario because validation has already been run at that point, on the draft that is being applied to the entry. Here’s a full rundown of ...


6

Brandon's answer was a helpful starting point for me but I think the answer goes deeper and has more scenarios to consider. Here's my attempt at clarifying that: Historic Context Before Drafts and Revisions were Elements, this was simple. When a new Element was created before and after save events had an $isNew property and if it was true you could assume an ...


5

Models are classes that contains abstractions of the reality, for example you could have the model car that contains the technical information about it, how many wheels it has and it's brand. Models are usually not supposed to contain any logic. So it's just a "container" with information Components are more like services that contains business logic to ...


3

Ok this was easy. Tried it at first but didn't work and was successful after another go. All it needed was a array of Entry IDs. Working code: $entry = Entry::find()->id($entryId)->one(); $entry->setFieldValue('textField', 20); $entry->setFieldValue('entriesField', [$relatedEntryId1, $relatedEntryId2]); Craft::$app->elements->saveElement(...


3

You can move them like this $asset = Asset::find()->volume('resourceImages')->filename($filename)->one() $folder = Craft::$app->getAssets()->findFolder(['volumeId' => X]); Craft::$app->getAssets()->moveAsset($asset, $folder, $filename); It won't change your relations or anything else in fact all the function does is: /** * Move or ...


3

you can use the instance of twig test here. You want to flip your logic, so test for Query object first else array stuff but this should work I think. To get the specific class just {% dd props.cards %} in the template for ease.


3

Another approach is to use the following event to attach a behavior Event::on(Asset::class, Asset::EVENT_DEFINE_BEHAVIORS, function(DefineBehaviorsEvent $event) { $event->behaviors[] = MyBehavior::class; }); The behavior could look like class MyBehavior extends Behavior { public $downloads; } This way you won't receive an exception and can ...


3

A Tag field is like every other relation field. Just insert an array of ids in the field and save the element $element->setFieldValue('fieldHandle', [1,2,3,4,5,6]); Craft::$app->getElements()->saveElement($element); In order to get the current ids and add one, just do $ids = $element->getFieldValue('fieldHandle')->ids(); $ids[] = '...


2

This is called Eager Loading you have to do $criteria = craft()->elements->getCriteria(ElementType::Entry); $criteria->order('postDate asc'); $criteria->dateUpdated = array('and', '>=' . $this->dateFrom->format(DateTime::MYSQL_DATETIME), '<=' . $this->dateTo->format(DateTime::MYSQL_DATETIME)); $criteria->limit('null'); // =...


2

As per the docs at https://craftcms.com/docs/3.x/extend/element-types.html#saving-custom-field-values When saving values on a custom field, always use the setFieldValue() or setFieldValues() methods rather than directly accessing the field handle as a property on the element object. This ensures the value is normalized and marked as dirty for delta saves. $...


2

Your code is pretty close. You want to make sure it's a new entry and not a draft or a revision so you could use: Event::on( Entry::class, Entry::EVENT_AFTER_SAVE, static function (ModelEvent $event) { /** Entry @entry */ $entry = $event->sender; /** @var User $user */ $user = Craft::$app->getUser(); if ( $event-&...


2

This is because it's a twig feature in Craft. If I remember correctly it's done in the CraftVariable and look something like this under the hood: use Craft; use craft\elements\Entry; $query = Entry::find(); Craft::configure($query, $criteria); return $query; Where the $criteria is the "query config". Edit: Some references for you. Craft Variable ...


2

The Element::find() method does not take any parameters, it just serves as the factory method for the appropriate element query for the given element type (for example, Entry::find() returns an EntryQuery). You can chain additional methods to the query afterwards: use craft\elements\Entry; $query = Entry::find()->id(11)->relatedTo(22); $results = $...


2

Ben's historical explanation is 100% accurate, as is Brandon's technical explanation. Here is a practical explanation... Much of the time, you won't want this event triggered for Drafts and Revisions. If not explicitly listening for Drafts/Revisions, you can simply exclude them based on the example in the docs... if (ElementHelper::isDraftOrRevision($entry)) ...


1

For anyone else who happens to land on this trying to solve your similar challenge: Super simple - the criteria can accept a custom field value, so in my case, the criteria became 'criteria' => [ 'section' => 'caseOfTheMonth', 'type' => 'standard', 'hideFromFeed' => false, ], What was getting in the way, in my case, was that I was ...


1

Have figured it out. Need to: use craft\commerce\elements\Variant; // not Product setFieldValue still does not find variable stock with Variant, but set it using $variantEntry->stock = 20; Need to find() on Variant to return the actual variant, and not find product with variant as that returns the product Following works, changed $productEntry to $...


1

It definitely does sound like a missing foreign key constraint issue. The Craft 2 version of the Fix FKs plugin for Craft 3 still lives here: https://github.com/pixelandtonic/craft-fixfks I'd give that a whirl.


1

If you have a custom module/plugin, you can register a Twig extension, and then your class would look something like this: <?php namespace my\plugin\twigextensions; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; class MyTwigExtension extends AbstractExtension { /** * @inheritdoc */ public function ...


1

A table field contains a simple array, you can serialize and unserialize it as it is. So there is no custom action required by your side. Just use it in PHP like every other textual field


1

I tried eager loading before, and I couldn't figure out how to do it. https://docs.craftcms.com/v3/dev/eager-loading-elements.html Now I just query it using SQL. I know it's a bit hacking, but it gets the job done. The DB structure of craft_content table hasn't change since Craft 2 (when I started using craft), so its unlikely that future updates will ...


1

it seems that first column of table view is special and is called here which calls mentioned hook in question.


1

You would need to join the array into a string, like so: // Begin defining the response data for this entry $data = [ 'title' => $entry->title, 'slug' => $entry->url, 'status' => $entry->status, 'textArea' => implode(' ',$bodyBlocks) ];


1

The first code section looks correct, other than that you're first creating a bodyBlocks array and then assigning a string to it, but that's not really consequential and not the issue behind this failing. Do yourself a favor and set up PHPStorm + xdebug, you'll find the issue very easily. I suspect you might have some mixed up identifiers (field names, ...


1

https://github.com/craftcms/cms/pull/4404 You can now delete objects that implement ElementInterface using this method: craft\services\Elements::mergeElements()


1

The issue was in the modifyElementsQuery function. When you select all columns addSelect('*') to the query your SQL will select the dateCreated and dateUpdated columns of your custom table as well. As soon as you want to order by one of those columns the database does not know which dateCreated should be sorted. You need to select only the unique attribute ...


1

You can't set a property of an element in Craft that does not exists in the field layout, as a behavior or as a public/private attribute in the object. Craft/Yii2 will throw an exception because the property instance_datetime probably does not exist. In order to attach a custom value you have to either create a new element or you have to store this ...


1

You can apply conditions within the same field but you can't create conditions for multiple fields. Here are some great examples $criteria->expiryDate = 'or, :empty:, =' . $yourDateValue; However you can't combine conditions for multiple fields. So you can't say Where (fieldX = 4 OR FieldY = 5) you would have to create an sql object based on your ...


1

The "proper" way to access the element query that gets generated is through a plugin via the ElementQuery's query and subquery properties. It looks like you're doing a Haversine algorithm to calculate distance between a latitude and longitude. There's are some similar plugins that already do this you can use as an example. For example: https://github.com/...


1

Fixed it for now by including a custom enum class in the base plugin file: abstract class CustomElementType extends BaseEnum { const Badges_Badge = 'Badges_Badge'; } and then querying for the custom element in the plugin using craft()->elements->getCriteria(CustomElementType::Badges_Badge);


1

I came across this post while searching for the same answer. Figured it out eventually. For future reference, the correct syntax in a (Craft 2) plugin would be: $criterea->with = [ ["coolImage", ["withTransforms" => ["transform"]]], "otherAssetField", "someCategoryField" ];


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