Save multiple locale data via plugin I'm trying to import data from another database using locales, but am having trouble saving the other locale after the primary locale is saved.

foreach($row as $data) {

    $entry = new EntryModel();
    $entry->sectionId   = 1;
    $entry->typeId      = 1;
    $entry->authorId    = 1;
    $entry->enabled     = true;
    $entry->locale      = "en";

    $entry->getContent()->setAttributes(array(
        'description' => $data["description-en"],
    ));

    $success = craft()->entries->saveEntry($entry);

    if ($success)
    {
        ImportPlugin::log('Successfully saved entry "'.$entry->id.'"', LogLevel::Info);

        $entryEs = craft()->entries->getEntryById($entry->id, "es");
        $entryEs->getContent()->setAttributes(array(
            'description'   => $data["description-es"],
        ));

        // **** The following doesn't work for some reason ****

        craft()->entries->saveEntry($entryEs);
    };
}

The primary entry saves fine and if I dump vars I can see that both $entry.id and $entryEs exist and are formatted as expected — but it doesn't save.

Is it perhaps being overwritten (or ignored) as the content from the primary locale is being copied to the other locales in the background? What's the recommended way to save multiple locales?

I just tried this and it works with Craft 2.3.2636. The only difference is this isn't using ContentModel::setAttributes(), but I wouldn't have thought that would affect it.

$entry = new EntryModel();
$entry->sectionId   = 2;
$entry->typeId      = 2;
$entry->authorId    = 1;
$entry->enabled     = true;
$entry->locale      = "en";

$entry->getContent()->title       = "English Title";
$entry->getContent()->description = "English description.";

if (craft()->entries->saveEntry($entry))
{
    $entryEs = craft()->entries->getEntryById($entry->id, "es");

    $entryEs->getContent()->title       = "Spanish Title";
    $entryEs->getContent()->description = "Spanish description.";

    craft()->entries->saveEntry($entryEs);
}


Can't get current entry's ID - Impossible to access an attribute ("id") on a null variable I'm trying to upgrade my website to Craft 3 and can't resolve one issue with this piece of code:

{% for category in craft.categories.group('blogCategories').order('title') %}

{{ category.title }}

{% endfor %}

I get the following error:

  Twig Runtime Error – Twig\Error\RuntimeError
  Impossible to access an attribute ("id") on a null variable.

I can't find any information in Changes in Craft 3, but I bet there's a new way of getting the category ID of the current post and the entry.blogCategory.one().id won't work anymore?

Any ideas?

Ok, so it came out that the post I used for testing wasn't assigned to any category and that was causing the exception.

I added a validation for checking if the category is defined:

{{ (entry.blogCategory.one().id is defined and entry.blogCategory.one().id is not null) and entry.blogCategory.one().id == category.id ? 'light': 'primary' }}">{{ category.title }}


Div into the content of an Entry I have a problem when trying to put a div into a content of an entry.

I'm creating entries, building a HTML hierarchy that helps me to manipulate the content with JS. I'm adding divs an build something like this:

Hi I am a title

this is the introduction

this is the content

When I create this, the hierarchy is right, but when I edit it from the CP, all the divs change to this:

Hi I am a title

this is the introduction

this is the content

What can I do to prevent this from happening? Hope you can help me, thanks.

Assuming you are using the Rich Text field, you'll want to look at the Redactor setting, convertDivs.

  convertDivs (Default setting is true)

  With this option turned on, Redactor will automatically replace divs to paragraphs.

Go in to your field settings:
Craft Admin › Settings › Fields › Rich Text field name

Look at the config settings to determine which config file you are using. Then, go in to your craft/config/redactor/ConfigFile.json file and edit your redactor settings to exclude the convertDivs setting (assuming nothing else in your config file):

{
    convertDivs: false
}


Append custom sitemap to sitemap index I have a custom generated sitemap which I'd like to append to my SEOmatic sitemap.xml file.

Is this possible?

I suppose the simple alternative would be to just add an extra sitemap to Google Search Console?

This is actually pretty simple...

If you navigate to SEOmatic → Site Settings → Miscellaneous, you'll see a table at the bottom of the page where you can input custom sitemap urls.

Once you add a url in here and save it, it will get added to a custom index sitemap that is included at the bottom of your main index sitemap:

/sitemaps/1/sitemap.xml

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  ...
  <sitemap>
    <loc> http://site.test/sitemaps/1/global/custom/1/sitemap.xml </loc>
    <lastmod> 2018-11-16T10:06:31-05:00 </lastmod>
  </sitemap>
</sitemapindex>

/sitemaps/1/global/custom/1/sitemap.xml

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc> http://site.test/custom.xml </loc>
    <lastmod> 2018-12-07T14:26:25-05:00 </lastmod>
    <changefreq> weekly </changefreq>
    <priority> 0.5 </priority>
  </url>
</urlset>

for more info → https://github.com/nystudio107/craft-seomatic#additional-sitemap-urls


Get content of single by slug I'm trying to get the content of a single using a slug from the url.
I'm using the following code:

{% set item = craft.entries.slug(craft.request.getSegment(1)).first() %}

This doesn't work, returns null, if there is a dash in segment 1.

For example if I have the following url: http://craft.dev/this-is-a-segment/segment2
And in craftcms I have a single with title "This is a segment" and url "this-is-a-segment"
I can't get the content of that single.

If I change the slug to camelcase it does work, but I was under the impression that slug and section handle were two different things...

Is this a bug or am I doing something wrong?

I don't think that either the single's uri or the handle is technically considered a slug per se, although in the case of singles craft likely interprets the handle as such. A more appropriate way to access a single would be by using its section handle.

(updated)

{% if craft.request.getSegment(1) == "this-is-a-segment" %}
    {% set item = craft.entries.section('mySectionHandle').first() %}
{% endif %}


How can I Link a category entry to a Subsite? I have a Structure Section:

Home

Sub 1
Sub 2

About

List item
List item

Info

How can I link the «Home»-Entry in a Structured Section to the «Sub 1»-Entry?

Any help is much appreciated. Thanks in advance.

{% set home = craft.entries.section('pages').one() %}
{% set sub1 = home.getChildren().one() %}
link: {{ sub.title }}


Craft Commerce: Detecting & Styling Flash Messages? I'm styling my flash messages in Craft Commerce - I added if statements to detect the type of flash message. I noticed however that the message no longer displays but the styling does get picked up. Any ideas what I might need to do here?

{% if craft.session.getFlash('notice') %}

      {{ craft.session.getFlash('notice') }}
      &times;

{% endif %}

{% if craft.session.getFlash('error') %}

      {{ craft.session.getFlash('error') }}
      &times;

{% endif %}

Getting a flash message also deletes it, so you should set it to a variable first, otherwise, when you try to access it a second time, it will be empty.

So you need to do something like this:

{% set flashNotice = craft.session.getFlash('notice') %}
{% if flashNotice %}

      {{ flashNotice }}
      &times;

{% endif %}

{% set flashError = craft.session.getFlash('error') %}
{% if flashError %}

      {{ flashError }}
      &times;

{% endif %}


Current Section handle I want to build a subnav with all entries from the current Section.

{% set pages = craft.entries.section(getCurrentSection).level(1) %}

I'm looking for the handle "getCurrentSection". I will use this for pages in 5 different sections, so I don't want to select the section by hand, like:

{% set pages = craft.entries.section('Section 1').level(1) %}
{% set pages = craft.entries.section('Section 2').level(1) %}
......

You can get the current section handle from the entry like so

{{ entry.section.handle }}


Filter entries by tags Still very new to Craft but just can't figure this problem out, it's a level above me at the moment.

I have an FAQ page as a 'single' that I would like to display all entries from a channel by default.

But all these entries will have a tag option (either 'red' or 'blue').

How would I sort these entries via a sub nav to display only all, red or blue tagged entries?

Thank you in advance.

You can read about how to use Relations in the docs. All relations such as (Tags) can be fetched via relatedTo parameter in your ElementsQuery

{% set tagId = craft.app.getRequest().getQueryParam('tagId') %}
{% set entries = craft
    .entries
    .section('faq')
    .relatedTo(tagId)
    .all()
%}

This assumes you include the parameter tagId when someone clicks on your Tag, and that represents the ID of your Tag

{% for tag in craft.tags.group(1).all() %}
    {{ tag.title }}
{% endfor %}


How do you delete entries from a frontend form? Part 2 of a 3 part question:

I am creating a proof of concept for a client in Craft where the client's customers can manage projects from the frontend of a Craft install.

I have a frontend form working correctly for creating a new project via it's own section. However the missing piece to the puzzle for full management is being able to delete an entry in the projects channel.

How do you delete entries from a front end form?

It's going to be virtually identical to this answer, with the exception that you're posting to the 'entries/deleteEntry' controller action instead of 'assets/deleteFile' and you're posting the 'entryId' and the 'locale' of the entry you want to delete, instead of 'fileId'.

Note that this requires a logged in user with necessary delete entry permissions.


Craft CMS 3 - Always load "en" translation file I have 2 sites (fr and en), fr is default.

In index.php, I have define('CRAFT_SITE', 'fr') and define('CRAFT_SITE', 'en')

In templates, I'm using {{ 'Texte FR'|t }} tag.

In /craft/translations/en/site.php, I have my translation : 'Texte FR' => 'Text EN'

When I test the English version, it's OK.

When I test the French version, English translations are displayed.

If I remove translations folder, of course, it's OK.

If I add 'fr' folder in translations, Englishis  still displayed.

Is there a way to trace the choice of the translation file by Craft?

I can't find why ...

Thank for help. :)

In Craft 3 the setup works a little bit different from the Craft 2 setup. You don't actually have to make changes to your index.php to switch the languages.

The languages are defined on a Site base. The translation folder now lives in the root of your projects: projectFolder/translations/fr/site.php.

As of Craft 3.1, you can set the Base Url of each site to a variable in your .env file and use that variable in the admin panel with the site setup. @web as your Base URL doesn't work to properly detect what site you are on.

So in your case, make two sites in the admin panel. Make two variables in your .env file:

SITE_URL_FR = '...'fr/'
SITE_URL_EN = '.../en/'

Use those variables to set your Base Url in the sites config. You can target them with $SITE_URL_FR. That should do the trick.


Integrity constraint violation - Not null violation Looking for some help here - I'm working on a site that is using a PostgreSQL db and am running into an issue. When saving a large Matrix field with multiple block types I was receiving the following error:

Integrity constraint violation
SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "id" violates not-null constraint

At first, I thought there was something corrupted with the Matrix so I nuked it and rebuilt it - everything seemed to be working fine until I created a new channel section - when I tried to create an entry there, I got the following error:

Integrity constraint violation
SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "id" violates not-null constraint
The SQL being executed was: INSERT INTO "drafts" ("sourceId", "creatorId", "name", "notes") VALUES (NULL, 5772, 'First draft', NULL)).

Similar to the above, just a new table this time.

Everything I am reading points to an auto-increment issue, though in both cases there does seem to be the appropriate sequence in the db. I've barely used PostgreSQL and never with Craft, though I'm not 100% certain it has to do with the db.

Any thoughts on what could be causing this?

there's a sequence being created for entrydrafts but not for drafts.

That's your issue.

I did a fresh Craft 3.3. install on PostgreSQL and there should be a drafts_id_seq sequence created for the drafts table that you're missing.


Craft 3 plugins - Logging in a separate *.log file In Craft 2, it was possible to have your plugin log to a separate file. For example, it would record items to a myplugin.log file. You would simply be able to do it like this...

MyPlugin::log('Lorem ipsum');

However, I can't seem to figure out how this would be done in Craft 3. I've seen this answer, which demonstrates how to log items in Craft 3 in general. But that just dumps items into the shared web.log file.

How can I log items to myplugin.log in Craft 3?

Edit 2

I came up with a far far far better approach after a little brainstorming. I'll keep my old answer here but you should probably just use the first snipped.

In your main Pluginfile.php

public static function log($message){
    Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'your-plugin-handle');
}

public function init(){
    $fileTarget = new \craft\log\FileTarget([
        'logFile' => __DIR__ . '/pluginName.log', // <--- path of the log file
        'categories' => ['your-plugin-handle'] // <--- categories in the file
    ]);
    // include the new target file target to the dispatcher
    Craft::getLogger()->dispatcher->targets[] = $fileTarget;
    ....
}

Explanation: categories is an array of all categories that should be in the log file. You usually want to allow only categories of your own plugin (you have to use an unique identifier in case certain other developers try to add the same category). Whenever you want to log something with the Craft/Yii log method that match one of your given categories in the array it will be logged in your file as well.

Old answer

Create this file somewhere in your plugin

FileTarget

class FileTarget extends \yii\log\FileTarget{

    // an array of categories that should be logged
    // note: your target receives all `Yii::log()` messages
    // but you can filter them with this array
    // if you want to track all messages of type 'application' as well
    // just include it in the array
    public $categories = ['a-category-that-you-would-like-to-log']; //<- usually your plugin handle or something

    // set the file path
    public function setLogFile($path = __DIR__){
        // I'm lazy so I just use the current location since it's in my 'src/' folder anyway
        // you can use Crafts default folders or whatever you like
        $this->logFile = $path . '/test.log';
        return $this;
    }

    // Optional -> a callback that formats your messages
    // remove this function if there is
    // no formatting needed or if you want to use the default
    public function formatMessage($message)
    {
        list($text, $level, $category, $timestamp) = $message;
        $level = 'Your fancy plugin Name';

        if ($category == 'a-category-that-you-would-like-to-log') {
            return date('Y-m-d H:i:s', $timestamp) . " [$level][$category] $text";
        }
    }
}

In your Plugin main file

public static $_fileTarget;

public static function log($message){
    if(self::$_fileTarget === null){
        /** @var FileTarget _fileTarget */
        self::$_fileTarget = Craft::createObject('namespace\pluginhandle\filetarget');
        // set the path
        self::$_fileTarget->setLogFile();
        // include your target to the current dispatcher targets
        // -> all messages are tracked in your target as well.
        Craft::getLogger()->dispatcher->targets[] = self::$_fileTarget;
    }

    // just use the default Craft/Yii logging method but with your category
    Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
}

Usage

Plugin::log('Lorem ipsum');
Craft::getLogger()->log('Lorem ipsum', \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
Craft::info('Lorem ipsum', 'a-category-that-you-would-like-to-log');

Maybe we could create a feature/pull request in order to create this feature by default. So every Plugin receives it's own category (by plugin handle) and if these categories are recognized the logger logs them in a separate file

Edit (thanks Andrew for mentioning it):

Note with this method I just add an additional target to the dispatcher that creates log files. So you'll insert 2 messages: one in the default storage/logs folder together with all the other requests and one in you custom log folder thus you are still able to use the great Yii2 Debug Toolbar and you can ask clients to hand over their plugin related logs to see what's going on


Is it possible to limit the locales for asset meta fields? I am working on a multi-lingual site that contains a few sections in 5 languages (de, en, es, fr, ja). Most of the content however exists only in two languages (de, en). For regular content sections I can indicate which locales should be available. However, I could not find a way to limit the locales for asset meta fields in a similar way.

Background: Why do I want to limit the number of locales?

My site contains a large number of product descriptions. Each product description can have multiple assets. Each asset has a (non-translatable) type (e.g. image, PDF, audio sample) and a (translatable) caption. The captions exist only in the de and en locales. When I import the assets in craft (with a plugin), a content entry for every locale will be created and this leads to a very bloated content table.

Can I just delete the unwanted entries in the content table?
Should I use a different setup for storing assets (e.g. a special content section with a file field and not asset meta fields)?

Any help is highly appreciated. Thank you.

Can I just delete the unwanted entries in the content table?

No, definitely don’t do that.

If you only want to enter captions in a couple languages, fine. Just ignore the other locales.

Then from your templates you can always have Craft fetch the assets with the DE or EN content, by setting the locale param.

{% set assetLocale = (craft.locale == 'en' ? 'en' : 'de') %}

{% for asset in entry.myAssetsField.locale(assetLocale) %}
    {{ asset.caption }}
{% endfor %}


Footnotes and Endnotes Are there any plugins or best practices for giving authors in Craft the ability to create footnotes within a Rich Text Field? Is anyone doing anything like this?

I don't know of a solution for footnotes within Rich Text fields aside from the plugin referenced in the comments of the question. As an alternative, consider having a read over Craft Your Content With Markdown And Matrix by Stephen Lewis.  He explains how he handles footnotes using Matrix and smartdown.


Check if a table field’s row has a value We have a table field that has the default value of 1 row when a new entry is published.

Unfortunately, we have

{% if entry.tableField | length %} display markup and field content... {% endif %}

and this will always be true of each entry because of the Craft default.

Obviously, we can remove the default row in the future but wondered if there was a way to extend that condition to say, for example

{% if (entry.tableField | length) and (entry.tableField.row | length) %}

Something like this should do what you're looking for and will work for any number of rows:

{% set reallyEmpty = true %}

{% if entry.tableField | length %}
    {# Since you've got a default row set, we're guaranteed that [0] will be set #}
    {% for column in entry.tableField[0] %}
        {% if column|length %}
            {% set reallyEmpty = false %}
        {% endif %}
    {% endfor %}
{% endif %}

{% if reallyEmpty %}
    It's really empty.
{% else %}
    It's not empty.
{% endif %}


CP entries structure tree view folded (not expanded) by default? Is there a simple way to display the CP entries structure tree folded (not expanded) by default ?
Because we have a very complex entries tree whith lots of entries and levels and my users needs to fold everything each time they access it.

The structure of the tree is stored into local storage on the user's browser, so as long as that is not cleared, then the position of each of the nodes should be remembered between requests.


Variable "entry" does not exist Working on my first craft site and I'm setting up a thankyou template for after a form submission, but am getting an error when calling the contact entry (it's a single).

I've tried several code variations with no luck. This is my current template

{#
 # Contact Thank You template
 # ---------------
 #}

{% extends "_layout" %}

{# pass body id to layout template #}
{% set bodyId = 'contact' %}

    {% set entries = craft.entries.section('contact').id(5).find() %}
    {% for entry in entries %}

        {# Top Images/Slider Content Here #}
        {% block headImage %}
        {{ entry.title }}

        {% endblock %}

    {% endfor %}{# end contact entry for loop #}

Please advise.

I'd simplify the entry like so

   {% set entry = craft.entries.id(5) %}
   {{ entry.title }}


Section Single Title Caching I have the following -

{% set press = craft.entries.section('press').first() %}

{{ press.title }}

If I change the section title in the Sections area of the back end from something like "Press" to "Testimonials" - I still see Press when I call press.title. The section is set to a single.

I've tried clearing cache in the back end which doesn't seem to do the trick. Any advice?

For anyone stuck on this -- when changing a Section's name you have to goto the entry under Entries and hit save. This will update the mysql row / title.


office365 onedrive to use with assets A little question , does anybody have or know someone with a plugin for Craft which can show Offie365 files/docs in Craft to use on an intranet/site?
Just like the feature below:

Assets are files managed by Craft. They live in “asset sources”, which represent physical folders on your server. And with Craft Pro, you can also set up Asset Sources that live on Amazon S3, Rackspace Cloud, and Google Cloud.

This will be possible in Craft 3, when the concept of "Assets" will get converted into "Volumes". Unlike Craft 2, it will be possible to create a custom Volume with a plugin.

Be aware though, everything you're describing will require a custom plugin. At this point, no such plugin exists.


How to trigger code once in a thank you page? Here is my scenario;

When a successful transaction occur, payment form page redirects to customer order page which have the orderId in url like /orders?number=1234

In this page i send ecommerce tag into Google Analytics.However this should be send only once, in first visit. So when the customer returns order page and look again, this code should not be fired.

What kind of ways should i follow? Can i do this from server, Craft side?

Thanks.

We do this by setting a flash message server side and then checking for this in the template. Flash messages are only shown once so no need to manually delete/unset. The best way to do this would be using a custom plugin that listens for the commerce_orders.onOrderComplete event:

<?php
namespace Craft;

class FireAnalyticsPlugin extends BasePlugin
{
    function init()
    {
        craft()->on('commerce_orders.onOrderComplete', function($event)
        {
            craft()->userSession->setFlash('successfulOrderPlaced', true);
        }
    }
}

Customer order page template:

{% if craft.session.getFlash('successfulOrderPlaced') %}
// Add Google Analytics here
{% endif %}


Commerce: are Shipping prices always assumed to include tax? A client is asking if the order calculation can show a 20% tax calculation on the shipping price.
From looking through Commerce 3, it seems this isn't possible, eg Shipping prices are always assumed to be inclusive of tax?

We fixed this by doing three things...

On our tax rate, setting "Taxable Subject" to "Order total taxable price (Line item subtotal + Total discounts + Total shipping)"
Also on our tax rate, turning on the "Is this tax is already
included in the taxable subject?" switch.
In our templates, wherever tax is displayed, changing from {{getTotalTax}} to {{getTotalTaxIncluded}} — eg to display the total tax (included) on a basket for both line items and shipping you'd want something like {{ cart.getTotalTaxIncluded('tax')|commerceCurrency(cart.currency) }}


What are «Structures»? I wonder what structures are since everybody writes about it here. But I can only finde one tiny sentence in the official docs:

  «Used when entries do have an inherent relationship with each other,
  unlike Channels. They are both sortable and hierarchical.»

Is there somewhere a bit more of a real world explenation/example on when/why/how to use this «structure» thing?

A structure is a section that allows for a 'tree' like layout with hierarchy. A good example of where Structures might be used for instance is the Craft documentation pages, or building a navigation using a section.


Can I Create a Way for Users to Add Fields from the Dashboard and/or create Fields with Same Handle? I'm trying to create a Matrix field containing plain text blocks of two kinds, one for providing Youtube video embed codes, and one for providing a description. What I want to know is, is there a way to make it so users can add another field of either kind if they want to embed another video and/or provide another description, or do I have to "build" each field option in manually?

For example, the less elegant way I tried to solved this problem involved creating multiple fields, but since the handles all have to be different, I tacked a number onto each (mainYoutubeEmbed, youtubeEmbed2, youtubeEmbed3, and etc.) This just seems so clumsy and is completely non-DRY. The other option I considered to make it slightly better was to create a bunch of generic fields all with the same title and handle (so I could just loop through them), but Craft says that the handles must be unique.

Is there any way around this or a way to make it at least a little better, or is the best approach really to just create a bunch of fields and hope that my users don't need more in the future? Maybe a plug-in or magic incantation of some kind?? :)

PS. I know the titles can be the same, but I changed them to match the handles because if I find that I'm stuck with this janky method, I want it to be as easy as possible to "see" how it's laid-out.

Thank you in advance for all constructive advice.

I might get you wrong but they must have the option to add as many youtube embed videos as they want?

Isn't it an option to let your client make a new block for every embed and just loop over the blocks they made?

So your block would look like:

Youtube Video (block)

Youtube embed link
Youtube Description

So they just have to add a block when they want a new one and you can just loop over them like you would with any matrixblock?


Feedme Fails - logs not helpful I'm trying to import an ExpressionEngine blog into Craft. I've set up an xml feed on the EE site and limited it to two entries for testing purposes. Once it's working will import everything.

The issue I"m having is that when I run the import it fails and the feed me logs aren't helpful.

EE Blog: Finished database backup
EE Blog: Starting database backup

That's all I get.

I've done field mapping and set a unique identify for existing elements (there should be none at this point).

Sent a support email to feedme via the CP two days ago but haven't gotten a response.

Check to make sure your Primary Element field in the initial setup is the entry element and not the top level in your xml file, for example:

<root>

</root>

article should be the Primary Element


How do I create an advanced route with multiple slugs? I'm trying to create a route for an RSS feed which allows for the following routes.

domain/feed
domain/category/feed
domain/category/subcategory/feed

I have the first two routes working and the category fetching logic looks okay to me.

So far in my routes file I have the following

'feed' => 'feed/_index.twig',
'(?P<slug>[^/]+)/feed' => 'feed/_index',

// Additional New route
'(?P<slug>[^/]+)/(?P<slug>[^/]+)/feed' => 'feed/_index',

That last line was added recently as I thought the child category would include the parent category in its route.

I either get a 404 error without that new route, or when I do add that third route I get the following error

preg_match(): Compilation failed: two named subpatterns have the same
name at offset 27 (craft/app/etc/web/UrlManager.php:387)

Any help would be greatly appreciated.

Brad nails the problem in his comment:

  The error is because you've got two named subpatterns with the same name (<slug>)

And the solution is simple... Change the name(s) of your subpattern(s).

The term slug is just a convention of Craft. It doesn't matter what the names are, they can be anything useful to you:

(?P<domain>[^/]+)/(?P<category>[^/]+)/feed

Whatever values match those named patterns are automatically passed into the Twig template as "magic" variables. So your Twig template can now make use of the domain and category values.


Get 404 Error When Going to mydomain.com/news Craft newbie here.  I have been playing with craft now for a few weeks and built out a couple of pages. I am really liking it this CMS.  The one small problem that I just noticed however, is when I tried to go to the news template (for example) by going to http://example.com/news I get a 404 error.  It works fine when going to http://example.com/index.php/news.

Am I missing something or does the index.php always need to be in the address?

When I read the documentations it says either way would work, so I am sure I am doing something wrong or missing something really simple.

I would appreciate it if someone can point me in the right direction.

The .htaccess file was missing the period in the filename when initially installed.


Enable craft.log for console commands I've got devMode enabled and can see the log happening in craft/storage/runtime/logs/craft.log for browser requests... but was wondering if there is a way to enable this level of logging (detailing every sql etc.) for console commands in plugins?

This was a bug in Craft that's been fixed for the next (post 2.4.2696) release.

Once that release is out, devMode output will be written to the craft/storage/runtime/logs files just like a normal web request would with devMode enabled.


What is appropriate for a Global field in terms of site speed? I'm worried that if I put too much in globals, I will impact the speed of my site by a lot.

For example, I was thinking of putting content in there like matrices for team members (text and image), testimonials, award's (text and images), etc.

Is this content better put somewhere else? I know globals are called on every single site load, so I'm not sure if having that type of content in there is a bad idea.

I can't speak on the speed impact of having lots of content in the Globals, but the use cases you have described don't really seem suitable for Globals.

I would instead recommend creating Sections for each of these (Testimonials, Awards, The Team) and have an entry for each item.

We use the Globals section (for example) for setting the clients phone number, contact address, email address etc. Just little pieces of information that can be re-used. Quite considerably different to the large content sections you have described.


Filter entries by month regardless of year using custom Date/Time and paginate them I am looking to filter entries by a given month regardless of year. The filter would be based on a custom Date/Time input.  My last goal would allow them to be paginated.

{% set firstDayOfMonth = year ~ "-" ~ month ~ "-01" %}
{% set daysInThisMonth = firstDayOfMonth|date('t') %}
{% set lastDayOfMonth  = year ~ "-" ~ month ~ "-" ~ daysInThisMonth %}

{% set thisMonthsEntries = craft.entries.section('messages').messageDate('and', '>= ' ~ firstDayOfMonth, '<= ' ~ lastDayOfMonth) %}

{% paginate thisMonthsEntries as entriesOnPage %}
    {% for entry in entriesOnPage %}
        {# ... whatever your code does... #}
    {% endfor %}
{% endpaginate %}

This is my original code. My first guess is I would need to have an array of years and loop through each year applying to the above code, however I am unclear on how to get a unique list of years that my entries are related too. Then I would probably have multiple sets of entries which would then need to be merged some how for output.

I think you are right and there's no chance to do what you want with parameters on a single ElementCriteriaModel.

You could definitely do it with many queries, the first one to get your years array, then one for each year. Merging them is simple with Twig's merge filter. But then you'd end up with a manually composed array of entry models and don't have the convenience of a single ElementCriteriaModel. Methods like getNext() or – important in your case – the {% paginate %} tag won't work with an array of entry models!

Let's skip the paginate problem for now and look at that query flood, you'd produce. Sure, Craft has the {% cache %} tag, but if your entries are modified regularly, there'll always be people who access the uncached version.

But what about another solution, why not do a single query to get all your "messages" entries and filter them in your template with a simple conditional:

{# Get all `messages` entries #}
{% set entries = craft.entries.section('messages') %}

{# Loop through all entries with a `messageDate` month of `myMonth` regardless the year #}
{% for entry in entries if entry.messageDate|date('m') == myMonth %}
    {{ entry.title }}
{% endfor %}

You'd still have no solution yet for your pagination problem, but this should be way less expensive on performance, and it's really easy to implement.


Accessing Multiple Databases in Craft Is there a way to access another database outside of the one Craft uses for its content? I need to able to access data fields from an external source for a project I'm working on.

From your config/app.php file you could do something like this:

return [
    'components' => [
        'otherDb' => [
            'class' => craft\db\Connection::class,
            'driverName' => 'mysql',
            'dsn' => 'mysql:host=localhost;dbname=mydb;port=3306;',
            'username' => 'myuser',
            'password' => 'mypass',
            'charset' => 'utf8',
            'tablePrefix' => '',
            'enableSchemaCache' => !YII_DEBUG,
        ],
    ],
]

You might not need all of those depending on what you're doing.

Then from PHP, could access it like:

Craft::$app->otherDb->createCommand(...);

And from a template:

{{ craft.app.otherDb... }}


Limit text when output richtext I have a rich text output section I want to limit to specific number of characters or words. So user able preview the blog post and link to the full blog. I try  entry.body|slice(0, 100) ~ '...'. But it slice of my html tag and display html code in front end.

No need for a plugin, just use twig's slice filter, combined with the striptags filter.

I've thrown in the default filter for good measure, in case the body is empty for some reason.

{{ entry.body|striptags|slice(0,100)|default('Read more') }}...

slice will simply output the first 100 characters (starting at 0 the first character), including spaces into the template. striptags ensures that no html tags will be output.


Freeform: How do I detect if a form was submitted? I'm need to send a google analytics tracking event when a form is submitted. To do that, I need to know on any page of the site if a user has landed there as a result of a form being submitted.

Given that the client can create their own forms, I can't rely on URL parameters, and it could be any form, so I can't set the form handle manually.

How do I detect if any form was submitted?
Freeform's docs explicitly name a form handle, which isn't a dynamic approach ( https://docs.solspace.com/craft/freeform/v3/template-functions/freeform.submissions.html#usage-in-templates ).

One way you could do this is on the backend via a module and the FreeForm events:

Run composer require ramsey/uuid in the root directory of your project
Add the following lines to the top of modules/Module.php right after the line that says use Craft;

use yii\base\Event;

use GuzzleHttp\Client;
use Ramsey\Uuid\Uuid;
use Solspace\Freeform\Services\FormsService;
use Solspace\Freeform\Events\Forms\AfterSubmitEvent;

Add the following in the Module's init() method, right after the line that says // Custom initialization code goes here...:

Event::on(
    FormsService::class,
    FormsService::EVENT_AFTER_SUBMIT,
    static function(AfterSubmitEvent $event) {
        $form = $event->getForm();
        $submission = $event->getSubmission();

        $uuid4 = Uuid::uuid4();

        $client = new Client();
        $client->post('https://www.google-analytics.com/collect', [
            'headers' => [
                'User-Agent' => Craft::$app->request->getUserAgent(),
            ],
            'query' => [
                'v' => 1,
                'tid' => 'REPLACE-THIS',      // Tracking ID from GA
                'cid' => $uuid4->toString(),
                't'   => 'event',
                'ec'  => 'REPLACE-THIS',      // Event Category
                'ea'  => 'REPLACE-THIS',      // Event Action
                'el'  => 'REPLACE-THIS',      // Event Label
            ]
        ]);
    }
);

Replace the REPLACE-THIS strings with your own Tracking ID and Event options
Uncomment the following line in config/app.php:

//'bootstrap' => ['my-module'],

Tip: You have the form and the submission available to you as $form and $submission respectively in case you want to use any of their values to populate your Event options (i.e. use the form name as the Event Label or something).

Hopefully that helps! (Disclaimer: I just threw this together so it's not really "tested"  - if you do run into issues ping me on Discord and I'll help you get it working.)


Why does the matrix field produce such a massive amount of duplicate information? The matrix field in Craft CMS is producing massive quantities of duplicate data. About 70 database rows per entry. Is there something I'm doing wrong? I don't think this will be sustainable for my database. The image embedded displays a fraction of the entries into the matrix table for a single Craft CMS structure entry.
Using Craft Pro 3.6.12

Per Oli, I ran ./craft gc for garbage collection. The matrix field went from 70+ (sometimes as much as 130) rows to 8. Still a terribly non-normalized database table, but much better than 70 records for one entry.
Thanks to Oli!


help setting up web root to point to /web I'm new to Craft 3 and I need help getting the web root to point to /web.

I can't figure it out. If I use the url "mysite.com/web" everything works fine.

Any help would be gratefully received.

You need to configure your webserver/virtualhost to point to the /web directory.

For apache you have DocumentRoot: your_disk_path/web

For nginx you have root: your_disk_path/web


When image transforming png to jpg, alpha layer become lined I have several png images that when transformed from png to jpg, the alpha layer is transformed to an horizontally lined pattern.

Therefore I have to keep them as png, wich is in my case unnecessary and a drastic data load issue.

The problem appears in production, wich is an ArcusTech server.

Anyone knows what it could be ?

Thanks !

You'll need to have Imagick installed on your box if you want to preserve alpha channels in a PNG during transforms.

If Craft sees it is installed, it will use it by default.


Trouble updating Craft when allowAdminChanges is false I've just updated a multi-environment site from Craft 3.3.5 to 3.4.5. Here's our config/general.php (irrelevant bits removed):

return [
    '*' => [
        'allowAdminChanges' => false,
        'allowUpdates' => false,
        'devMode' => false,
        'useProjectConfigFile' => true,
    ],
    'dev' => [
        'allowAdminChanges' => true,
        'allowUpdates' => true,
        'devMode' => true,
    ],
    'production' => [],
];

The update succeeded in the development environment (localhost) but the production deployment failed*. Here's the post-deployment command:

/path/to/composer install --no-interaction --prefer-dist --optimize-autoloader && ~/user/craft project-config/sync

When the deployment failed, I went to /admin and received the "Finish Up" button. I clicked it. I then received the "Sync" button and clicked it as well. I then received an error. Unfortunately I can't remember what the error said and didn't take a screenshot. It was a nicely-formatted error (not just a PHP dump) and there was a Troubleshoot link under it.*

Anyway, I SSH'd into the server and ran project-config/sync manually. Here's what was returned:

Applying changes from project.yaml ... error: Changes to the project config are not possible while in read-only mode.

I then edited config/general.php and made allowAdminChanges true on production. Reloading /admin worked and I was able to log into Craft.

At long last, here's my question:

We're following the advice per the allowAdminChanges docs. Does this advice only apply to non-update changes? In other words, is it a known thing that allowAdminChanges must be true when pushing a change to project.yaml that will update Craft?

--

*FWIW, we do have a staging deployment but it doesn't apply to this question.

--

EDIT: I ran another test, here's the error:

A fatal error has occurred:

Status: Internal Server Error
Response: {"error":"A server error occurred."}

I think P&T changed the behavior in Craft 3.1.0 and newer. Before 3.1.0 it was necessary to have 'allowAdminChanges' => true with updates in/to project config.

To be 100% safe you can always enable admin changes when you're on the command line by using this config line in production environments:

'allowAdminChanges' => (php_sapi_name() === 'cli'),

In most installations we even go step further and have a second domain available, which also enables admin changes when this domain is used (for emergencies), where www.yourdomain.com would be the normal domain and admin.yourdomain.com could be the one with admin changes enabled:

'allowAdminChanges' => (php_sapi_name() === 'cli' || strpos($_SERVER['HTTP_HOST'], 'admin.') !== false),


Editing entries on multisite Craft CMS implementation We have a Craft CMS implementation with 3 sites enabled (multi-site). When I create an entry, it populates the entry to all 3 sites, which is fine. However, I would like to modify a link or content for only 1 of the sites. If I used the dropdown, select the site, then make my change and save, Craft still saves that change to all 3 mini sites.
Is editing 1 entry per minisite possible or do I have to create a duplicate?
Thanks!

You need to make sure the field you are trying to change is set to be translatable.
Go to Settings → Fields → Your field → Translation Method and pick the suitable method for your site (see documentation).


How to add a user to a Users field from front-end form? Is it possible to update an entry’s Users field from the front-end? If so, how would you go about it?

The situation is this: training events are created and then posted for members to bid on for a limited number of spots. Logged in members review the available events and add their name (would use their ID) to each event of interest. Admins then manually chose a select few from all submissions.

I know I can do this by adding their IDs to a text field in the event section, and then using Split to create an array, but the Users field approach is much more elegant and offers more flexibility.

You would need to do this with a plugin that provides a custom controller, which looks at the post data and modifies the entries’ Users fields accordingly.

The controller action would look something like this:

<?php

$entryIds = craft()->request->getPost('entries');

if ($entryIds && is_array($entryIds))
{
    // Get the current user's ID
    $currentUserId = craft()->userSession->getUser()->id;

    // Fetch the entries
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->id = $entryIds;
    $entries = $criteria->find();

    foreach ($entries as $entry)
    {
        // Update the Users field value with the current user's ID
        $userIds = $entry->myUsersField->ids();
        $userIds[] = $currentUserId;

        $entry->setContentFromPost(array(
            'myUsersField' => $userIds;
        ));

        craft()->entries->saveEntry($entry);
    }
}


Passing Twig Variable into Template from Include? I'm trying to pass a variable value from an include into a template file.  The variable is imageRatio. Within this include file I have the logic which sets the right image ratio. My goal with this is to have one place to set the logic which I can reuse in different templates - I'm trying to keep the code DRY.

When I do the below get an error saying Variable "imageRatio" does not exist. What am I doing wrong?

The Main Template

{# The Image Ratio include #}
{% include '_includes/builders/images/imageVariants' %}

{# Create an Image Variant #}
{% set optimizedImages = block.image.one()[imageRatio] %}
{% include '_includes/builders/images/imageOptimize' %}

Image Ratio Include

{# Define Image Varient #}
{% if block.imageRatio == 'thumb' %}
    {% set imageRatio = 'imageVariantsThumb' %}
{% elseif block.imageRatio == '16by9' %}
    {% set imageRatio = 'imageVariants16by9' %}
{% elseif block.imageRatio == '3by2' %}
    {% set imageRatio = 'imageVariants3by2' %}
{% endif %}

I suggest using macro (and switch tag instead of if).

{% macro ratio(block) %}
{% spaceless %}
    {% switch block.imageRatio %}
        {% case "thumb" %}
            imageVariantsThumb
        {% case "16by9" %}
            imageVariants16by9
        {% case "3by2" %}
            imageVariants3by2
    {% endswitch %}
{% endspaceless %}
{% endmacro %}

Macro would be used like this:

{% import 'macro' as macroRatio %}
{% set imageRatio = macroRatio.ratio(block)|trim %}


Input Tags Template for my Custom FieldType I created a custom FieldType that gathers data from 2 different Models. I was able to successfully display it as a Drop Down. My problem now is that there are tooo many records on my array and I would like to have a search instead similar to what craft already has implemented on the Tags Field.

My current template is:

    {%- set class = [
    'select',
    (class is defined ? class : null)
    ]|filter|join(' ') %}

    {% set selectedValue = (value is defined ? value : null)  %}

    <div class="{{ class }}">
        <select {%- if name is defined %} name="{{ name }}"{% endif %}>
    {% if value is not null %}
    {% set selectedValue = value.id %}
    {% endif %}
    {% else %}
    <option value="0" > </option>
    {% endif %}

    {% for test in tests %}
    {% set optionValue = test.id %}
    <option value="{{test.id}}" {% if optionValue == selectedValue %} selected{% endif %}>Test - {{ test.name }}: {{ test.price }}</option>
            {% endfor %}
        </select>
    </div>

Any way I can make it similar to the craft/app/templates/_components/fieldtypes/Tags/input.html

You could use Select2 to search in a select field

$(document).ready(function() {
    $('.my-custom-awesome-select-class').select2();
});

All you need to do is to include the js file via asset bundle or register it in your view directly and execute the JS code


How do I target the 3rd entry and only that entry? I am trying to build an Index page and assign a specific card template to the 3rd entry and only the 3rd entry.

{% set items = craft.entries.section('posts').all() %}

{% for cardC in items.offset(2).limit(1) %}

Marketing

{{ cardC.title }}

                   {{ cardC.introParagraph }}

                    subject Read Case Study

{% endfor %}

I also tried {% for cardC in items.nth(3 )%}.

I get the following **error message**:

  Impossible to invoke a method ("offset") on an array.

I created the set because I need to apply templates for the other entries, etc.

As soon as you apply .all(), the variable you're working with becomes an array. Which means that the .offset(2) needs to be applied before you convert it into an array.

UPDATE

As @andrew.welch points out in the comments, it's as easy as grabbing the third item in your array...

items[2]

Ultimately, it looks like you want something like this...

{% set cardC = items[2] %}

{% if cardC %}

    {# ... the rest of your code #}

{% endif %}

ORIGINAL ANSWER

Once it's an array, you'll need to use the Twig syntax instead...

items[2:1]

Which translates to: "get third item (0-based index), limit of one".


Craft 3: Enabling Memcache Is there any configuration hint for enabling memcache in Craft 3? I'm on 3-beta-24

I added

'cacheMethod' => 'memcache',

to config/general.php, but this did neither cause any hits on memcache nor any error.

The Craft 2 (sic!) docs say you also need config/memcache.php, which I created

returning an empty array
returning an array containing the properties I found in *app/vendor/craftcms/cms/src/config/MemCacheConfig.php:
returning a 2 dimensional array with the the first array containing the properties from 2. above

Nothing worked, but 2. & 3. throw unknown property exceptions.

This is my memcache.php (according to variant 3. above):

return [
    [        // A memcached server hostname or IP address.
        'host' => 'localhost',
        // Whether or not to use a persistent connection.
        'persistent' => true,
        // The memcached server port.
        'port' => 11211,
        // How often a failed server will be retried (in seconds).
        'retryInterval' => 15,
        // If the server should be flagged as online upon a failure.
        'status' => true,
        // The value in seconds which will be used for connecting to the server.
        'timeout' => 15,
        // Probability of using this server among all servers.
        'weight' => 1,
    ]
];

This is the exception:

Unknown Property – yii\base\UnknownPropertyException
Setting unknown property: craft\config\MemCacheConfig::0
 in .../app/vendor/yiisoft/yii2/base/Object.php at line 161

looks like the config can't handle multiple memcache servers as array.

Here's the stacktrace: https://pastebin.ca/3855627

If you look at the MemCacheConfig.php file, you'll see that it's expecting a single property, "servers", which contains an array of associative arrays with properties. So, try this as your memcache config:

<?php
return [
    'servers' =>
[
  [        // A memcached server hostname or IP address.
             'host' => 'localhost',
             // Whether or not to use a persistent connection.
             'persistent' => true,
             // The memcached server port.
             'port' => 11211,
             // How often a failed server will be retried (in seconds).
             'retryInterval' => 15,
             // If the server should be flagged as online upon a failure.
             'status' => true,
             // The value in seconds which will be used for connecting to the server.
             'timeout' => 15,
             // Probability of using this server among all servers.
             'weight' => 1,
    ]
  ]
];


Config option to disable update capability per environment In our workflow, we run a shared development server. Each developer develops locally but points to the development database. All Craft software updates need to happen while in the local environment and then changes need to immediately be committed to the git repo otherwise things could get really screwed up.

I would the option to disable the update capability using a multi-environment config setting so we could prevent anyone from running those updates on the shared development server.

I know we could set up user permissions to lock this down, but I think it would be much handier to be able to do that at the config level.

Thoughts?

I believe you're looking for the 'allowAutoUpdates' config option combined with multi-environment configs.


Show custom field on Submissions page in CP In A&M Forms, I'd like to show a custom field on the Submissions page in the control panel to make it easier to quickly reference the submissions.

Is this possible?

Thanks]1

You can click on the wheel icon below Volunteer and check if the field is available there, if not you can modify the ElementType and change it's defineAvailableTableAttributes function in order to add the field/fields you want.

I don't know how this plugin was build but I made several custom ElementTypes in Craft 2 with or without a custom layout and it works every time the same.

Here is the function for Craft entries. You can then set these values in the getTableAttributeHtml function


Prevent ALL templates from being rendered directly? I attempted to set the privateTemplateTrigger to an empty string in my config/general.php file, because I don't ever want Craft to serve up a template file on its own just because a visitor happens to put in a URL that matches its name, and I was hoping to avoid prefixing every single file in my /templates directory with an underscore. Unfortunately doing so breaks several CP pages (like Globals and Plugins)...

I'm guessing it's because some CP files are relying on this feature? Surely there must be some way to disable this "direct rendering of template files" thing that doesn't break the CP?

This is very, very simple to do... just put every single template into a specific folder, then prefix the folder with an underscore:

/craft/templates/_everything/

Template files beginning with underscores are hidden, similarly, template folders beginning with an underscore hide everything inside.


Getting info on the currently logged in user Trying to get the currently logged in user's groups. Trying to get at that by using the user ID. I am currently testing as Admin - user number 1.

Craft::$app->getUser()->id

Returns a user ID (11) that does not exist in the Users table. The Users table has ID's of 1, 20, 21.

How do I get user ID or more specifically, the currently logged in user's groups?

Craft::$app->getUser()

returns only the user service/component. You should read the docs about that

What you want is the current Identity

Craft::$app->getUser()->getIdentity()


ElementAPI : Excluding terms from search criteria I am trying to exclude terms in my search when using the element api. I have successfully managed to include terms and search them by fields in my entries. I would now like to be able to exclude different terms in those fields.

In this case 'recipeIngredients' is a matrix field.

Here is my criteria search so far :

//Get search query text
$searchQuery = Craft::$app->request->getQueryParam('searchQuery');
//Search in either title or ingredients
if ($searchQuery) $criteria['search'] = "title:'".$searchQuery."' OR recipeIngredients:'".$searchQuery."'";

//Get excluded ingredients query
$excludedQuery = Craft::$app->request->getQueryParam('xq');
if ($excludedQuery) {
    if (!isset($criteria['search'])) {
        $criteria['search'] = '';
    } else {
        $criteria['search'] = $criteria['search'].' AND ';
    }
    $criteria['search'] = $criteria['search']."recipeIngredients: not '".$excludedQuery."'";
}

//Get result count
$count = Craft::$app->request->getQueryParam( 'count' );
$count = $count ? $count : 10;//Default to ten if no parameter

return [
    'elementType'     => Entry::class,
    'criteria'        => $criteria,
    'elementsPerPage' => $count,
    'transformer'     => function ( Entry $entry ) {
        return [
            'name'      => $entry->title,
            'url'        => $entry->url,
            //'json_url'    => UrlHelper::url( "recipe/{$entry->id}.json" ),
            'picture_url' => $entry->recipeImage->one()->getUrl(),
            'portions'   => (float)$entry->recipePortions,
            'time'       => [
                'total' => (float)$entry->recipeTotalTime
            ]
        ];
    },
];

I can't figure out if I should be trying to append the excluded terms to the search query, and my syntax is wrong, or if there is another criteria property available to exclude results.

Also, the ElementQuery page mentionned in the docs no longer exists. I assume, it's this page, but I'm not certain.

Here is what I ended up changing my code to exclude search items.

//Get excluded ingredients query
$excludedQuery = Craft::$app->request->getQueryParam('xq');
if ($excludedQuery) {
    if (!isset($criteria['search'])) {
        $criteria['search'] = '';
    } else {
        $criteria['search'] = $criteria['search'].' ';
    }
    $criteria['search'] = $criteria['search']."-title:'".$excludedQuery ."' -recipeIngredients:'".$excludedQuery ."' ";
}


Create event before site loads I want to create an event that triggers before the site loads to I grab the variables passed in the http header and send them to a plugin I have made.

I will have a url like http://www.foo.com?username=abc123

I want it immediately trigger a controller method located at: http://www.foo.com/actions/myPlugin/myMethod

Im just not sure how to connect the dots.

Off the top of my head and in no way tested or thought through, you could put some logic in your plugin's init() method:

public function init()
{
    $username = craft()->request->getQuery('username');

    if ($username)
    {
        craft()->urlManager->setRouteVariables(array(
            'username' => $username
        ));

        craft()->runController('myPluginHandle/myPluginActionMethod');
    }
}

Then in your plugins's controller:

class MyPluginController extends BaseController
{
    protected $allowAnonymous = true;

    public function actionDoIt($username)
    {
        // Do your thing.

        $this->redirect('homepage');
    }
}


Is it possible to use a loop variable to target a specific field entry? I'm looping through the rows of a table field and hoping to target a specific field entry based on the loop.index. Here's a simplified example of what that might look like:

{% for row in entry.table %}
   {% set foo = entry.field ~ loop.index %}
{% endfor %}

The doesn't work, but I’m curious if I just have the syntax wrong or if I’m thinking about this the wrong way.

Turns out Twig has a nifty little attribute function that does the trick. Here's how it works:

{% for row in entry.table %}
   {% set foo = attribute(entry, 'fieldHandle' ~ loop.index) %}
{% endfor %}

Big hat tip to Mr. Brad Bell for posting the original answer in Stack Exchange.


Customizing Craft Commerce Template Paths Let me apologize right now that my inexperience with Craft is likely the issue here and that my question might be more general to Craft's routing features and not so specific to Craft Commerce.

I'm playing with a clean Craft/Craft Commerce installation and using the included templates in /templates/commerce. I wanted to customize the path however to /store/. I changed the directory name, adjusted the "commerce" where it was hardcoded in the templates, and changed the Product URL Format and Product Template within the Product Types to use store/ instead. Everything seems to look okay until I try to add/remove/update a product into the cart.

When that happens I get a routing error:

CHttpException
Unable to resolve the request "store/cart/updateCart".
/path/to/craft/app/framework/web/CWebApplication.php(286)

Line 286 is:

throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".'

Should I be leaving these paths alone and adjusting the URL in a different way? Any help and direction would be greatly appreciated. Thank you!

You'll need to keep any action URLs as commerce/, as these point to controller actions inside the Commerce plugin, not templates in your store directory. So if you find:

<input type="hidden" name="action" value="store/cart/updateCart">

That will need to be restored to:

<input type="hidden" name="action" value="commerce/cart/updateCart">


{{ entry.postDate|date }} Variable "entry" does not exist Might be basic, but not sure where I'm doing wrong. I was trying to display the post date of an article using this code
{{ entry.postDate|date('medium') }}.

But getting the error stating "Variable "entry" does not exist."

The entry variable is automatically created for the individual entry pages that you define in your section settings.
For example, if your Section has the following Site Settings:

URI Format: blog/{slug}
Template: blog/_entry

You can expect an entry variable to exist when the blog/_entry is loaded.
blog/_entry.twig
{{ entry.postDate|date('medium') }}

some-other-template.twig
If you are trying to access an entry in some other template, you would need to make sure you define the entry variable on the page.
{% set entry = craft.entries.id(123).one() %}
{{ entry.postDate|date('medium') }}

You don't need to query the entry by ID, it was just an easy example. You can use any element query options and read more about them in the Querying Entries section of the docs.
is defined
If you have a scenario where you don't know if the entry will exist or not, you can check for its existence using is defined:
{% if entry is defined %}
  {{ entry.postDate|date('medium') }}
{% endif %}

debugging
If you are curious what does exist, you can turn on the devMode setting in your config/general.php settings and dump the variable to see more about what the application is seeing:
{{ dump(entry) }}


How to query for multiple relations with SuperTable The relevant sections for this question are:

Event: One relevant field. guestAllocation (SuperTable). Guest allocation is a table which selects a Partner (Entries) and how many people that partner is allowed to invite to an event
GuestList - Two fields. relatedEvent (Entries) and guestNames (table)

Each Partner creates an Entry in the guestList channel. When they want to update the names of who they're inviting, they edit their post instead of creating a new one.

I'm trying to write a conditional which will let me check if there's already an entry in the guestList channel which is both related to that partner AND the event we're currently looking at. I need to check this as I have to update that Entry instead of creating a new one if it exists. The form is displayed on the Event page, so the entry variable is the current event we're dealing with.

I can't get my head round the relations documentation. How do I write this? The following is returning no results:

{% set partnerGuestList = craft.entries.section('guestList').relatedTo(
    { sourceElement: entry }, {# this event #}
    { targetElement: currentUser.partner.first() } {# current partner #}
) %}

It's a little hard to follow your example/description, but I'll take a stab at it.

The way I interpret your question, you need to pull a single guestList entry that is a) related to the current event, and b) shares a relationship with the partner entry set to the current user's partner field, via a guestAllocation SuperTable field owned by the event EntryModel (I'm assuming there's a guestAllocation.partner column, and that the event section has the event handle).

The first part is easy, although you seem to be confused about the targetElement and sourceElement parameters for the relatedTo method, so I'll try to clear that up:

Basically, in a relatedTo query you either specify the target element or the source element (never both) for the relationship – depending on which element owns the field where relation is created.

In your case, the event entry would be the target element, not the source, as the relatedEvent field (where the relation is created) belongs to the guestList entry model, not the event. In other words, the elements you want (the guest lists) should have the entry you have (the event entry) selected in a field (i.e. the guestLists entries "target" the event entry), not the other way around. If possible, you should also provide the field handle for the field where the relation is created, i.e. relatedEvent in your case. So, to pull all guestlists related to the current event entry, the correct relatedTo query would look like this:

{% set guestListsForEvent = craft.entries.section('guestList').relatedTo({
    targetElement: entry,
    field: 'relatedEvent'
}) %}

Obviously, you only want one guestlist – the one that is related to the current user's partner entry (phew!). Trouble is, that relationship doesn't really exist – it's actually more of a condition, where a) the guestList entry needs to be authored by a user with the correct partner relation, and b) the current event needs to have the correct partner entry (i.e. the current user's related partner entry) in its guestAllocations SuperTable field.

The second part is easy – you can set a canCurrentUserCreateGuestList flag inside a loop on the current event entry's guestAllocations field; if the correct partner event is found in the latter, the current user can create a new guestList entry and you should also query for an existing guestList entry:

{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
    {% if row.partner|length and row.partner.first.id == currentPartner.id %}
        {% set currentUserCanCreateGuestList = true %}
    {% endif %}
{% endfor %}

Once you have that flag, you can use it in a conditional:

{% if currentUserCanCreateGuestList %}
   {# Query for existing guest list, create new list etc #}
{% endif %}

For the latter – the actual query to pull the guestList entry – a single relatedTo call obviously won't do the job here, but fortunately the workaround is quite simple – keeping in mind that you need to make sure that a) only 1 guestList entry is returned, and b) that entry is authored by a user with the same partner entry as the current user.

Again, the first part is easy – simply use limit and first to pull a single entry (I like to add a |default(false) filter to suppress errors if no entries are returned).

For the second part, you'll first need a list of user IDs for all the users that are related to the current user's partner entry, and then feed that array to the authorId parameter for the craft.entries call:

{# Get the IDs for all users related to the correct partner #}
{% set partnerUserIds = craft.users.relatedTo({
    targetElement: currentUser.partner.first,
    field: 'partner'
}).ids() %}

{# Get existing partner guest list related to the current event #}
{% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
    targetElement: entry,
    field: 'relatedEvent'
}).authorId(partnerUserIds).limit(1).first|default(false) : false %}

The above code will return either a single guestList EntryModel, or false, if no related guestlist entries authored by a user with the correct partner entry exists. Whether or not the event entry has the current user's partner entry in one of its SuperTable guestAllocation.partner columns is irrelevant to the query itself, once you've established that the current event does indeed include the correct partner entry in its guestAllocations field (the conditional above).

Here's how the whole thing could look in context:

{# Can the current user create a guest list for this event? #}
{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
    {% if row.partner|length and row.partner.first.id == currentPartner.id %}
        {% set currentUserCanCreateGuestList = true %}
    {% endif %}
{% endfor %}

{# Get existing guest list #}
{% set partnerGuestList = false %}
{% if currentUserCanCreateGuestList %}
    {# Get the IDs for all users related to the correct partner #}
    {% set partnerUserIds = craft.users.relatedTo({
        targetElement: currentUser.partner.first,
        field: 'partner'
    }).ids() %}

    {# Get existing partner guest list related to the current event #}
    {% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
        targetElement: entry,
        field: 'relatedEvent'
    }).authorId(partnerUserIds).limit(1).first|default(false) : false %}
{% endif %}

{# Create, edit, etc #}
{% if partnerGuestList %}
    {# Edit existing guest list #}
{% elseif currentUserCanCreateGuestList %}
    {# Create new guest list #}
{% else %}
    {# Do nothing? #}
{% endif %}

Note that the above isn't tested and there's a good chance I misinterpreted your question – but hopefully you'll take something away from it.

Finally, as your question also touches on the correct usage of relatedTo queries with multiple relation criteria: Your original syntax for the relatedTo call is close, but when you have multiple relation criteria, you'll need to include either and or or as the first parameter, specifying if all or any of the criteria should be met, respectively.

In your case, this means the syntactically correct multiple relation query for the partner guestlist should look something like this:

{% set partnerGuestList = craft.entries.section('guestList').relatedTo('and',
    { target: entry, field: 'relatedEvent' },
    { targetElement: currentUser.partner.first(), field: 'guestAllocation.partner' }
) %}

Obviously, for reasons already explained the above query will return nothing. There's also the fact that SuperTable fields (in your case, the guestAllocation.partner field) doesn't actually work with the built-in relations functionality in Craft – meaning that you can never use craft.entries.relatedTo when the relation is created in a SuperTable field. Instead, SuperTable provides its own method for relation queries, which is explained in this answer. Again, I don't believe a single relatedTo call is the correct approach for your particular use case, but just wanted to mention it.

Just for funsies – here's how you could use SuperTable's getRelatedElements method to pull event entries based on guestAllocation.partner relations:

{% set partnerEvents = craft.supertable.getRelatedElements({
    relatedTo: {
        targetElement: currentUser.partner.first,
        field: 'guestAllocation.partner'
    },
    criteria: {
        section: 'event'
    }
}) %}


How to render a macro from a plugin? Im trying to render a site macro from my plugin, i’m getting the following error:

Argument 1 passed to Twig_Template::display() must be of the type array, object given, called in /path/to/file.php on line 51 and defined in "_macros/elements" at line 3

My service contains the following method:

public function renderSiteMacro($template, $macro, array $args)
{
    // Get the current template path
    $originalPath = craft()->path->getTemplatesPath();

    // Point Twig at the site templates
    craft()->path->setTemplatesPath(craft()->path->getSiteTemplatesPath());

    // Render the macro.
    $html = craft()->templates->renderMacro($template, $macro, $args);

    // Restore the original template path
    craft()->path->setTemplatesPath($originalPath);

    return TemplateHelper::getRaw($html);
}

And i'm calling it as follows:

$args = array(
    'entry' => $user,
    'layout' => 'friend'
);

$userHtml = craft()->logic->renderSiteMacro('_macros/elements', 'listing', $args);

The issue appears to be with the include line in my macro template file:

{% macro listing(config) %}
{% include "_macros/elements/listing" with config only %}
{% endmacro %}

Does anyone know what i'm missing?

The format of the include tag is

{% include 'template' with {var1: value1, var2: value2} only %}

What you need after the with is an associative array (an array with keys and values).

In your specific case you want this:

{% include "_macros/elements/listing" with {config: config} only %}


Sprout Form Date/Time field not displaying I'm working on an inherited site where I have a sprout form and am adding additional fields. I have added a date/time field to the form with the settings in this screenshot.

In my template where all other fields are working I have added the following.

{{ craft.sproutForms.displayField('contact.targetProjectDate') }}

This field does not display and there is nothing in the source either.

Please advise

In the end I switched it to a default text field and used jQuery datepicker.


cp panel entry assets element sorting Is it possible to add an element to the existing assets list and make it sortable

i need it because i have made some modifications that allow to group 2 assets together so generally i now have a list of normal assets added to entries and grouped ones that are wrapped in a div with class pair

i can sort the assets within pairs and assets outside any of the pairs but not the pairs themselves.

In the screenshot you can see that there are two pairs with the purple background. Would it be possible to somehow add them to the sorting flow so i could drag them around as well?

Found out how to do this. If anyone else needs something similar then adding the new {{ jsClass }} part of input template into a function and calling it after extra elements are added also makes them sortable.


S3/No buckets showing Done this a couple of times before so not sure what's going on, but I'm trying to hook up S3. I have the bucket/group/policy/user all setup. But when I enter Access key ID and Secret access key in Craft and refresh, no buckets show up. No errors, just no bucket. My policy looks like this:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": [
            "s3:ListAllMyBuckets"
        ],
        "Resource": "arn:aws:s3:::"
    },
    {
        "Effect": "Allow",
        "Action": [
            "s3:*"
        ],
        "Resource": [
            "arn:aws:s3:::bucketname/*"
        ]
    },
    {
        "Effect": "Allow",
        "Action": [
            "s3:GetBucketLocation",
            "s3:ListBucket"
        ],
        "Resource": [
            "arn:aws:s3:::bucketname"
        ]
    }
]

}

If it matters, my bucket resides in London. Any help much appreciated.

This happened to me and London is relatively new and unsupported at one point, try changing the location to Oregon to see if this works


Using a dynamic url with Feed Me I'm trying to import posts using the Feed Me plugin. I'd like to make a dynamic URL so that I can access the feed from a Cron job or from elsewhere in the CP. It says in the docs that I can use environment variables inside the Feed URL, but it isn't working for me. Am I using them the wrong way?

My Feed URL (not working):

http://some-url.com/{{issueNumber}}

Apart from environment variables, is there some other way to pass variables into Feed Me? The client won't have direct access to the Feed Me plugin and therefore won't be able to manually edit the URL each time.

There's currently no method to parse variables into the feed itself through this, or any means. Typically, we approach this as feeds being third-party, or otherwise non-editable. How would you see utilising issueNumber to work in this scenario?

You can use the concept of aliases in your URL if that helps?

Lastly, you could also make use of the (undocumented) Datatype::EVENT_AFTER_FETCH_FEED event to perform any parsing on the feed once its been fetched?


Add '...' to template field I'm using the following code in my template to truncate the body of an entry (coming from a Rich Text field):

{{ entry.body | slice(0, 500) | markdown }}

To this, I'd like to add ... as a string, so that it will output like:

Words words words...

Since the field part I'm using outputs into its own <p> tag, adding the ... into the HTML itself has them sitting in two different tags. I've tried using |join but I must be doing something wrong, its putting the first part into a separate <p> tag than the ...

Thanks for your help!

You might find the Hacksaw plugin useful for this https://github.com/ehousestudio/craft_hacksaw/ this will truncate text for you and has a wealth of options available for doing so, specifically the append parameter, which will do exactly what you want :)


Why do I get Access denied on s3 asset source images? I have created an s3 bucket in aws and added the correct permissions and user group etc. I have added the below policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:ListAllMyBuckets",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetBucketLocation",
                "s3:PutObjectAcl"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::bucketname"
        }
    ]
}

I uploaded the assets from a local folder via ftp to the bucket using transmit ftp client which was fine. I have then set the bucket up on craft cms as an asset source. I can upload files to s3 via the cms fine with no issues and view the image fine but when I try to access an image on the front end that was uploaded via the ftp I get access denied error 403:

<Error>
AccessDenied
<Message>Access Denied</Message>
<RequestId>96E15AB155C47209</RequestId>
<HostId>
our-hist-id-here
</HostId>
</Error>

edit here

So after some research I found out that you needed to add the policy directly to the bucket. You used to have to create a policy away from the bucket page itself in the IAM area but now(I think) it needs to be in the bucket.

Is this a policy issue?

Thanks

I'm not really an AWS expert, but I think if you want to allow public access to an S3 bucket, then it should look something like this:

{
    "Sid": "PublicReadGetObject",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::bucketname/*"
}


Can I disable template caching for local development? Can I disable template caching for local development?
For example: setting a environmentVariable in a config file?
Or is this possible in the future?

As of Craft 2.4, it is now possible to use the enableTemplateCaching config value.

'enableTemplateCaching' => false,

Simply add that to your local environment in config/general.php, and it'll disable the cache tags entirely.


Navigation position in Control Panel Craft CMS 2.5 The new position of the Control Panel navigation on the left side in Craft CMS 2.5 needs so much space and looks kind of wrong to me.

Is there any way to position it on the top like in pre 2.5 versions?

I wouldn't have thought so, it's to facilitate the new Commerce plugin (or at least that was the main driver) and ultimately is far more expandable over time.

The new interface is fluid too, rather than the previous fixed version. It took a little while to get used to but is now much better suited to the content input.


Sort merged array by array value in Twig? I have two Instagram API responses that I want to merge, by the photo's created_time. Is there a way to do that in Twig?

Right now I am just using this

{% set instagram = <data> %}
{% set community = <data> %}
{% set feed = instagram|merge(community) %}

    {% for photo in feed %}

    {% endfor %}

Each photo has a created_time string that I'd like to sort the array by, is that possible without creating a custom Twig extension?

The sortByField plugin looked promising and sort of what I want, but it was directly aimed at Craft entry manipulation. Is there anything hacky that could be done?

The SuperSort Plugin is built for use cases exactly such as this. It allows you to render each object in your array using a Twig object template and sort the array based on the rendered value.

For example, in OP's case, we could sort the combined array by the created_time variable like this:

...
{% set feed = instagram|merge(community) %}
{% set sortedFeed = feed | supersort('sortAs', '{created_time}') %}

(The plugin parses {created_time} — a Craft 'micro-template' — into {{object.created_time}}, which provides the value by which the array is sorted.)

If the property of interest happened to be different between two arrays, we could include a conditional or ternary operator in the micro-template to differentiate them:

{% set sortedFeed = feed | supersort('sortAs', '{{ object.current_time is defined ?: object.someOtherProperty }}') %}


How can I programmatically set the value of an Entries field type? I need to set programmatically the value of an Entries field type when I'm going to create a new entry from the admin form, after the form loads I'm searching for the entry I need to set in the Entries field, so I'm making something like setAttribute('companyField', $companyEntry) but it didn't work.

I need to find a way to set/lookup that value in the Entries field type so the user can see it in the UI.

For relationship fields (Entries, Assets, Users, Tags, etc.) you need to pass in an array of element IDs.

Something like this should work.

$entry->setAttribute('companyField', array($companyEntry->id));


Add attachments with Craft Commerce Suppose I have an assets field in my orders fields, how could I attach those files in the confirmation email?

I suppose you could use the \craft\commerce\services\Emails::EVENT_BEFORE_SEND_MAIL event for that.

use craft\commerce\events\MailEvent;
use craft\commerce\services\Emails;
use yii\base\Event;

Event::on(
    Emails::class,
    Emails::EVENT_BEFORE_SEND_MAIL,
    function (MailEvent $e) {
        // You would be able to access the `\craft\mail\Message` like so
        // $e->craftEmail;

        // And the `\craft\commerce\elements\Order` like so
        // $e->order

        // So adding an asset could be done by accessing the `attach` method.
        // https://www.yiiframework.com/extension/yiisoft/yii2-swiftmailer/doc/api/2.1/yii-swiftmailer-message#attach()-detail
        $e->craftEmail->attach(...);
    }
);


Complicated A-Z problem I am attempting to create an 'a to z' listing on a site with 1000+ entries of people. The catch is that it needs to be indexed by surname unless that person doesn't have a surname, in which case it will use their forename.

I know what I need to end up with — an array of 'a' to 'z' as keys, with the value another array of people, indexed by their name with the entry id as the value. I can then iterate over this and create the relevant sections for styling.

Is this even possible in Twig? If so, how?

I base my example on the assumption that all people are Users (Element type User). If users are entries, you'd have to replace users by entries ;)

I don't think there's a way to do this without iterating through all users first, creating some sort of ordering attribute (if lastName != '' ? lastName : firstName). Then, you'd be able to group your array by your ordering attribute:

{# create a variable to hold all user data you need #}
{% set allUsers = [] %}

{# loop through users ... #}
{% for user in craft.users.find() %}
    {#
        ... and set variable for each user, containing the info you need
        and an 'orderMeBy' attribute, set to the uppercased first character of lastName or firstName
    #}
    {% set thisUser = [{
        fullName : user.fullName,
        orderMeBy : user.lastName != '' ? user.lastName | slice(0,1) | upper : user.firstName | slice(0,1) | upper
    }] %}

    {# merge this user's info with your allUsers variable #}
    {% set allUsers = allUsers | merge (thisUser) %}
{% endfor %}

{# group 'allUsers' variable by 'orderMeBy' attribute #}
{% set groupedUsers = allUsers | group('orderMeBy') %}

{# create an array of all numbers and letters #}
{% set numbers = 0..9 %}
{% set letters = 'A'..'Z' %}
{% set allChars = numbers | merge(letters) %}

{# loop to chars and, if users in groupedUsers[char], display those users #}
{% for char in allChars %}
    {% if groupedUsers[char] is defined %}

{{ char }}

        {% for user in groupedUsers[char] %}

{{ user.fullName }}

        {% endfor %}

    {% endif %}
{% endfor %}

If anyone knows a quicker and/or easier way, tell me :)


PHP error after installation After I install craft, I am getting the following error when trying to load the website including the admin page:

PHP Stack trace:
PHP   1. {main}() \aspace\index.php:0
PHP   2. require_once() \aspace\index.php:14
PHP   3. CApplication->run() \aspace\craft\app\index.php:35
PHP   4. Craft\WebApp->processRequest() \aspace\craft\app\framework\base\CApplication.php:180
PHP   5. Craft\UserSessionService->requireLogin() \aspace\craft\app\etc\web\WebApp.php:272
PHP   6. CHttpRequest->redirect() \aspace\craft\app\services\UserSessionService.php:371
PHP   7. CApplication->end() \aspace\craft\app\framework\web\CHttpRequest.php:805
PHP   8. CApplication->handleError() \aspace\craft\app\framework\base\CApplication.php:0
PHP   9. CErrorHandler->handle() \aspace\craft\app\framework\base\CApplication.php:816
PHP  10. Craft\ErrorHandler->handleError() \aspace\craft\app\framework\base\CErrorHandler.php:131
PHP  11. CErrorHandler->handleError() \aspace\craft\app\etc\errors\ErrorHandler.php:152
PHP  12. CErrorHandler->render() \aspace\craft\app\framework\base\CErrorHandler.php:289
PHP  13. CWebApplication->runController() \aspace\craft\app\framework\base\CErrorHandler.php:331
PHP  14. CController->run() \aspace\craft\app\framework\web\CWebApplication.php:282
PHP  15. CController->runActionWithFilters() \aspace\craft\app\framework\web\CController.php:265
PHP  16. CController->runAction() \aspace\craft\app\framework\web\CController.php:286
PHP  17. CInlineAction->runWithParams() \aspace\craft\app\framework\web\CController.php:308
PHP  18. Craft\TemplatesController->actionRenderError() \aspace\craft\app\framework\web\actions\CInlineAction.php:49
PHP  19. Craft\BaseController->renderTemplate() \aspace\craft\app\controllers\TemplatesController.php:190
PHP  20. Craft\TemplatesService->render() \aspace\craft\app\controllers\BaseController.php:98
PHP  21. Twig_Environment->render() \aspace\craft\app\services\TemplatesService.php:220
PHP  22. Twig_Environment->loadTemplate() \aspace\craft\app\vendor\twig\twig\lib\Twig\Environment.php:292
PHP  23. __TwigTemplate_d77269d0acd17023cd9970dd5812452d2a881ef03373e6e22c0d80eb68481e00->__construct() \aspace\craft\app\vendor\twig\twig\lib\Twig\Environment.php:345
PHP  24. Twig_Environment->loadTemplate() \aspace\craft\storage\runtime\compiled_templates\d7\72\69d0acd17023cd9970dd5812452d2a881ef03373e6e22c0d80eb68481e00.php:10
PHP  25. __TwigTemplate_9fccce442511366b01108e1e704c62f53125ce92b05eb6545ea02e38a06a15b3->__construct() \aspace\craft\app\vendor\twig\twig\lib\Twig\Environment.php:345
PHP  26. Twig_Environment->loadTemplate() \aspace\craft\storage\runtime\compiled_templates\9f\cc\ce442511366b01108e1e704c62f53125ce92b05eb6545ea02e38a06a15b3.php:10
PHP  27. Twig_Environment->getTemplateClass() \aspace\craft\app\vendor\twig\twig\lib\Twig\Environment.php:323
PHP  28. Craft\TemplateLoader->getCacheKey() \aspace\craft\app\vendor\twig\twig\lib\Twig\Environment.php:265
PHP  29. Craft\TemplateLoader->_findTemplate() \aspace\craft\app\etc\templating\twigextensions\TemplateLoader.php:71
PHP  30. Craft\TemplatesService->findTemplate() \aspace\craft\app\etc\templating\twigextensions\TemplateLoader.php:119
PHP  31. Craft\TemplatesService->_validateTemplateName() \aspace\craft\app\services\TemplatesService.php:835
PHP  32. Craft\PathHelper::ensurePathIsContained() \aspace\craft\app\services\TemplatesService.php:1178
PHP  33. Craft\HttpRequestService->decodePathInfo() \aspace\craft\app\helpers\PathHelper.php:29
PHP  34. Craft\StringHelper::convertToUTF8() \aspace\craft\app\services\HttpRequestService.php:1072
PHP  35. Craft\StringHelper::getEncoding() \aspace\craft\app\helpers\StringHelper.php:390
PHP  36. mb_detect_encoding() \aspace\craft\app\helpers\StringHelper.php:460

Can anyone help me with this error?

Problem was being caused because I was trying to access the server through 'localhost' instead of '127.0.0.1'.


Eagerload inverse relation I would like to eagerload inverse relation. Business case:
I have stories, stories are connected to books over relatedBooks field. Now I would like to query those books only which not have any story.

I do not see any easy way to do it, so I thought that to using eagerload the related stories somehow, and filtering out the nulls
What also could help is to just using having count somehow

But I am not able to do it, because I am not able to lead the relatedBooks(inverse) from books perspective, only from stories.

Tried to use the manyToMany plugin, but it is not helping either, just giving a nice interface

Also I know I can query one-by-one but that is silly

(last workaround would be to use hardcoded sql, but I would like to avoid this one:) )

UPDATE:

in this case you should use :empty:, like this:

{% set orphanBooks = craft.entries.section('books').relatedStories(':empty:') %}

ORIGINAL CONTENT

According to the documentation, you can query the entries using your field handle:

  TIP

  Most custom fields support element query parameters as well, named
  after the field handles.

https://docs.craftcms.com/v3/dev/element-queries/#executing-element-queries

You might use :notempty: as a negative selector, just like in this query:

{% set products = craft.entries.section('product').productSale(':notempty:') %}

These SE question and answers might be helpful, too:

Get entries NOT related to categories

Return entries where field is "not empty"


Amazon S3 plugin uploading to different directory I was using Amazon S3 with Craft 2 fine, now after updating and installing the plugin I am having issues.

We use a folder inside our bucket as the root Assets location - e.g. /bucket-name//folder

When specifying /folder/ in the subfolder field existing images display. e.g. /bucket-name//folder/image.jpg.

However, on uploading, new images are being sent to /bucket-name/folder/image.jpg - which means they don't display on templates.

If I then specify the folder as //folder/ in the subfolder field, and remove the trailing slash from the base url, images do not get uploaded to the correct place, and existing images do not load on the site, as it thinks I am calling ///folder/image.jpg.

Any suggestions would be great, as I'm going round in circles!

Also no image resizes are working, which I currently assume is due to the folder discrepancy.

Ah, it looked like it was thanks to the blank folder name - moving it all to a new folder which actually has a name seems to have done the trick!


Exclude Current Entry How can I exclude the current entry when I've structured my syntax like this?

{% set entries = craft.entries({
  section:        'blog',
  order:          'postDate',
  limit:          5,
}) %}

{% set entries = craft.entries({
  section:        'blog',
  order:          'postDate',
  limit:          5,
  id:             'not ' ~ entry.id
}) %}

or

{% set entries = craft.entries({
  section:        'blog',
  order:          'postDate',
  limit:          5,
}).id('not ' ~ entry.id) %}


Can't save entries with dynamic subfolder path in Matrix I have a Matrix field which contains several assets fields. Each has the dynamic subfolder path set to {owner.section.handle}, so I can reuse the Matrix in multiple sections, but keep the assets organized.
When I try to save an entry with an image, i get the error:

Craft\InvalidSubpathException
Could not resolve the subpath “{owner.section.handle}”

I figured it out -- I'll leave the question up in case anyone else runs into the issue.

I had Assets fields in my Matrix, but I also had a SuperTable field in the Matrix which contained an image. That was the one causing the error. Changing the subfolder path to {owner.owner.section.handle} solved the problem.


Crossdomain ajax request to controller with requireAjaxRequest() I make request from my localhost(gulp server) to example domain in to VerifyPassword controller. When i make request without headers: {'X-Requested-With': 'XMLHttpRequest'}, It comes as expected 400 Bad request

$.ajax({
        url: 'http://example/index.php/actions/users/verifyPassword',
        type: 'POST',
        data: $data,
        xhrFields: {
            withCredentials: true
        },
        success(data, response) {
            console.log(data, response);
        },
        error(data, response) {
            console.log(response, data);
        }
});

When i make request with headers: {'X-Requested-With': 'XMLHttpRequest'} comes response XMLHttpRequest cannot load http://example/index.php/actions/users/verifyPassword. Response for preflight is invalid (redirect), and are not sent cookies. Done OPTIONS preflight request without cookies and server comes 302 and redirect to example/login.
How To be?

http://www.yiiframework.com/forum/index.php?/topic/4945-yiiapp-request-isajaxrequest/

Looking further into the problem, I've found that the page tries to do a post request to the other domain. It calls upon the action function in the UsersController.php file (Location: /craft/app/controllers/)

But because the user isn't logged in on the other domain and anonymous access isn't allowed for this action. You get redirected to /login to login on that domain.

https://craftcms.stackexchange.com/a/12268/635

The developers managed to solve this problem? This applies to almost all controllers require session.


How to use the Element API endpoint without wrapping it in data object By default the Element API plugin all endpoints in a data object like this:

{ "data": [ { "key" : "value", "key2": "value2" } ]}

But i don't want to wrap this in the data object but like this:

{ "key" : "value", "key2": "value2" }

Use the config setting 'first' => true and wrap the endpoint in a function

like this:

'api/link' => function() {
    return [
        'elementType' => 'Entry',
        'first' => true,
        'criteria' => ['section' => 'mysecton'],
        'paginate' => false,
        'transformer' => function(EntryModel $entry) {
            return $something;
        }
    ];
}


User events in Craft 3 How do I capture user events in Craft 3? I looked at the documentation but couldn't figure it out. I need to capture after user registration events and after user save events.

Here is what I tried, I know it's not correct but I think I'm pretty close

Event::on(
    Users::class,
    Users::EVENT_AFTER_USER_SAVE,
    function (PluginEvent $event) {
        // do something
    }
);

There aren't specific User element save events in Craft 3, but you can listen to EVENT_AFTER_SAVE_ELEMENT and check if the element is a user like so:

Event::on(\craft\services\Elements::class, \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT, function(Event $event) {
    if ($event->element instanceof \craft\elements\User) {
        // Do your thing.
    }
});

For user activation, there's EVENT_AFTER_VERIFY_EMAIL:

Event::on(\craft\services\Users::class, \craft\services\Users::EVENT_AFTER_VERIFY_EMAIL, function(UserEvent $event) {
    $user = $event->user
});


Include the URL of a related entry field I would like to add the URL of the channel entry I have selected (atm 2 channels are available to choose from), so I would like a url like:

summerhouses/product1

or

greehnouses/product2

how would I modify the code below to achieve this?

The code below just shows: /product1

{% for row in entry.homeFeaturedProducts.order('RAND()')|batch(4) %}
{% for entry in row %}

{{ entry.title }}

    Product Description
    {{ entry.price }}
{% endfor %}
{% endfor %}

Try this - using {{ entry.section }} and {{ entry.slug }}

{% for row in entry.homeFeaturedProducts.order('RAND()')|batch(4) %}
{% for entry in row %}

{{ entry.title }}

    Product Description
    {{ entry.price }}
{% endfor %}
{% endfor %}


Is it possible to create event with multiple date/time (out of box) I have an event that runs from Monday to Sunday from 9am to 6am but on Thursday the time is from 9m to 8pm.

How can I add repeat dates with diffrent time for Thursday?

I know this is a while ago, however you could do something like:

Default Times: 09:00-18:00
Monday Time:
Tuesday Time:
Wedneday Time:
Thursday Time: 09:00-20:00
Friday Time:
Saturday Time:
Sunday Time:

When listing times check if that day has a specific time, otherwise use the default time. Will save you changing 6 times anytime there is a change in opening times.

Not a complex solution but one that can be easily understood by a content manager.