Nginx Vhost Config - Get page based on translated URI and without parameters in url I have a localized site, localization works fine for homepage (/en/), however the links to other page does not work (/en/rooms) where /chambres works fine for default language.

The English 'chambres' page is accessible with /en/?p=rooms

I would like the english page being accessible with /en/rooms

It's definitely an Nginx vhost config issue. The config listed in Locales sub directories on Nginx didn't solve my problem.

This is my english index.php:

// Tell Craft to serve the English content
define('CRAFT_LOCALE', 'en');

This is in my general config file:

'quartiergeneral.craft.dev' => array(
        'devMode' => true,
        'usePathInfo' => true,
        'omitScriptNameInUrls' => true,
        'environmentVariables' => array(
            'basePath' => '/home/vagrant/Code/quartiergeneral/craft/public/',
            'baseUrl'  => 'http://quartiergeneral.craft.dev:8000/',
        ),
        'siteUrl' => array(
            'fr' => 'http://quartiergeneral.craft.dev:8000/',
            'nl' => 'http://quartiergeneral.craft.dev:8000/nl/',
            'en' => 'http://quartiergeneral.craft.dev:8000/en/',
        ),
    ),

This is my nginx config vhost:

server {
    listen 80;
    server_name quartiergeneral.craft.dev;
    root /home/vagrant/Code/quartiergeneral/craft/public;

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ @rewrites;
    }

    location @rewrites {
        rewrite ^(.*) /index.php?p=$1 last;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/quartiergeneral.craft.dev-error.log error;

    error_page 404 /index.php;

    sendfile off;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

Ok, I got it working with:

nginx vhost config:

location /en/ {
    try_files $uri $uri/ @enrewrites;
}

location /nl/ {
    try_files $uri $uri/ @nlrewrites;
}

location / {
    try_files $uri $uri/ @rewrites;
}

location @enrewrites {
    rewrite ^/en/(.*)$ /en/index.php?p=$1 last;
}

location @nlrewrites {
    rewrite ^/nl/(.*)$ /nl/index.php?p=$1 last;
}

location @rewrites {
    rewrite ^(.*) /index.php?p=$1 last;
}

And in general craft config:

'omitScriptNameInUrls' => true,


Output first matching matrix block model if condition is true I've run into situation, where I have to loop only once, if condition has met the requirements. The condition is controlled by matrix block field ligthswitch which is the field in finish.

Matrix structure:

Actually, I've ended up doing this:

{% for block in entry.productSettings.type('finish') %}
   {% if block.inStock %}
      {{ block.amazonUri }}
   {% endif %}
{% endfor %}

which outputs cluster of characters: 123456.
Bear in mind, that total count of characters is count of loops. Desire output is 1.

Can't something like this help you?

{% for block in entry.myMatrixField.type('fruits').ligthswitchField(params) %}


How do I clear deprecation errors for looping through element queries? I am getting this depreciation messages.

  Looping through element queries directly has been deprecated. Use the all() function to fetch the query results before looping over them.

In the example below, the depreciation message refers to the 2nd loop for flag in country.  The message appears anytime I have a loop within a loop.

How do I template this to avoid the deprecation message?

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

{% for first in entries[0:1] %}

{% set country = first.countryName %}

{% for flag in country %}

{% endfor %}

{{ first.title }}

 {% endfor %}

What about using the all() function as well? Your field doesn't contain an array, it contains the same type of object like craft.entries provides.

{% for flag in country.all() %}

It doesn't appear because you have a loop in a loop it appears because you treat and object as an array


Multiple Category Sources Field I want to utilise the Category field type but with the ability to choose from multiple category sources (as with Entries).

I noted in cms/src/fields/Categories.php that $this->allowMultipleSources is set to false. What is the simplest way of changing this to true without changing the source file?

Can I create a custom field that essentially just extends the original Category field but with $this->allowMultipleSources set to true?

Isnt this possible with the modifyCategorySources hook?

-> https://docs.craftcms.com/v3/extend/updating-plugins.html#modifyentrysources-modifycategorysources-modifyassetsources-modifyusersources

I'm assuming you are using C3 by the namespace you mentioned. Correct me if this is wrong :).


Sort by Matrix Field I was using this code in the past and it worked well

        {% set assets = craft.assets.limit(null) %}
        {% set entries = craft.entries.section('menu').limit(3).order('RAND()').relatedTo({
            targetElement: assets,
            field: 'assets'
        }) %}

        {% for item in entries %}
                {% set i = item.assets.first() %}

                <img width="{{ i.getWidth('medium') }}" height="{{ i.getHeight('medium') }}" src="{{ i.getUrl('medium') }}" alt="{{ recipe.title }}" />

        {% endfor %}

However, in the new version the standalone "assets" field became a part of the matrix field so this piece of code doesn't work anymore. Please advise :)

You can access the assets field by referencing the matrix field first. myMatrixFieldHandle.assets.  So your entries code would be something like this.

{% set entries = craft.entries.section('menu').limit(3).order('RAND()').relatedTo({
       targetElement: assets,
       field: 'myMatrixFieldHandle.assets'
}) %}


How to redirect a url with a query to one that does not have a query I'm using Redirect Manager (https://github.com/rkingon/Craft-Plugin--Redirect-Manager) and I"m trying to redirect:
www.website.com/?post_type=testimonials

To:
www.website.com/about-us

I've tried the following regex rules with no success (hashes are needed for regex in redirect manager):

#^\?post_type=testimonials#

#^\?post_type=testimonials$#

#post_type=testimonials$#

All of them just stay on the homepage with the query appended when accessing the url. Any ideas on how to fix it or better ways of achieving this would be appreciated.

You could add this to the homepage template.

{% if craft.request.getParam('post_type') == "testimonials" %}
   {% redirect "/about-us" %}
{% endif %}


Eager loading on entry not reducing queries Using this snippet returns me 38 queries on my homepage without the Eager Beaver plugin.

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['headerImage', 'image1', 'image2']
) %}

Without the above loading all three images with .one() gives me 33 queries.

Is this expected behavior or am I doing something wrong?

I don't think eager loading will help in this case because you're trying to eager load fields with only a single relationship (asset). It's not the n+1 query problem eager loading is meant to solve.

If you had an asset field with multiple assets selected, you would see some benefit. But even then, if there are only a few assets, the small penalty of eager loading might not outweigh the small cost of queries for a few assets.

Bigger gains would come from nested relationships. For example, a set of related entries each with an asset for a thumbnail image.

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['entriesField.image1']
) %}

{% for item in entry.entriesField %}
    {% set image = item.image1[0] ?? null %}
    {% if image %}
        {{ image.url }}
    {% endif %}
{% endfor %}

Also, it might be worth noting that in your testing, it matters what data you actually use.

In my test, this produced 19 queries:

{% set asset = entry.headerImage.one() %}
{{ asset.title }}

But this produced 23 queries:

{% set asset = entry.headerImage.one() %}
{{ asset.url }}


Applying project config changes with post-receive git hook I site I'm working on uses a post-receive git hook for deploying changes to the server.

At the moment, it looks like this:

#!/bin/sh

# default cpanel stuff
branch=$(/usr/local/cpanel/3rdparty/bin/git branch | awk '$1 == "*"{print $2}')
while read oldrev newrev ref
do
  if [ "x$ref" == "xrefs/heads/$branch" ]
  then
    echo "Recieved update on checked-out branch, queueing deployment."
    (cd .. ; /usr/bin/uapi VersionControlDeployment create repository_root=$PWD)
  fi

  branch=`echo $ref | cut -d/ -f3`

  cd ../
  # run from dir outside of .git
  # unset git dir because git ugh https://stackoverflow.com/a/10513684
  unset GIT_DIR

  if [ "master" == "$branch" ]; then
    # echo this is master
    # create new working tree in the desired directory
    git --work-tree=../prod-test checkout -f $branch
  fi

  if [ "develop" == "$branch" ]; then
    # echo this is develop
    git --work-tree=../staging checkout -f $branch
  fi

done < /dev/stdin

That works fine. I push from my local and the changes get deployed to staging.

But I want project config and plugin update changes to be automatically applied rather than having to visit the CP and click the sync changes button.

I've seen elsewhere that the way to do that is to run

  ./craft project-config/sync
  ./craft clear-caches/all
  composer update

so I thought I could add it to the hook, just above done < /dev/stdin but it doesn't work, I still have to manually update.

Has anyone else done something like this before?

Based on your comment that you get an error saying Craft is not installed, to me that suggests the bash script does not have access to your environment variables, (this can also be a problem when running cron jobs).

To remedy this, create an env text file to export all the same values as those in your production env variables. For this example name it something like .env_cli.txt and save it in your site in the same place as .env-example if you have one. Add it to your .gitignore too. Syntax should look something like this:

export ENVIRONMENT="live"
export SITE_URL="https://www.example.com"
export DB_DRIVER="mysql"
export DB_SERVER="123.456.789.10"
export DB_USER="aaa"
export DB_PASSWORD="bbb"
export DB_DATABASE="ccc"
export SECURITY_KEY="ddd"
export DB_TABLE_PREFIX="craft_"
export SOME_CUSTOM_VAR_YOU_MIGHT_HAVE="something"

Then in your git hook, you can use a leading . to "source" that env file (basically meaning to suck in and consume all those exported vars), and then run your command(s) afterwards like this:

. /path/to/your/env-file/.env_cli.txt && /path/to/craft/./craft project-config/sync && /path/to/craft/./craft clear-caches/all && /path/to/craft/composer update

You could of course stick with relative paths to make it shorter, I just tend to use absolute paths for more certainty.


How do I target the second item in an array with Twig? I would like to select the second position in the array below. The problem is that this number is automatically changed. So I try to do this with .index function from Twig but I can not figure it out. Can someone help me?

array (
  7296680 =>
  array (
    ...
  ),
  7296635 =>
  array (
     ...
    'url' => 'vesten',
    'title' => 'Vesten',
  ),
)

You can use the slice filter but it will return an array, so you either have to loop the result or access the first index

{% for item in array|slice(1, 1) %}
    {{ dump(item) }}
{% endfor %}


Setting the Homepage URL in Craft 3 This seems like an odd question, but I've looked through the documentation, Slack, and the StackExchange and it's weird that I'm not seeing anything... so I feel like I'm overcomplicating it.

How do you set a Single (or anything for that matter) to be the homepage of a Craft 3 site? In Craft 2 there was the "This is for the homepage" option, but I don't see that in Craft 3. Is that because it hasn't been implemented yet or is there a new best practice for doing this? Is this going to be something added into Setting > Sites section?

So it seems the way to do this is actually by leaving the slug blank. If you happen to look down on the section setup screen prior to naming your section you'll see it clearly: Leave blank if this is the homepage. However since that field is automatically filled in with details from the Name/Handle fields I never actually saw the text by the time I was down there unless I completely cleared the field out.

Both fields need to remain empty from what I can tell, not just the slug.


Localization - How do we manage multilingual, multi-environment on multiple domains? I read this KB article about localization though, the examples are for sub-folders.

I'm wondering how to handle the same concept but, for different language based domains e.g.

example.com
example.mx
example.es

Currently I'm not sure if the different sites will be based on language or country though, let's assume country for this question. For example we'll have Mexico and Spain sites, both will be in Spanish but, will have different content which relates to each country.

I asked CraftCMS about this on twitter and this was their reply.

Am I right to think that each site will have an install of craft, with the config/ general.php setup accordingly (in this case using domains instead of sub-folders?)

And then we'll just link to the db in it's settings on each copy of config/db.php

With that said, I'm hoping for some elaboration on this topic. Bonus points for including a multilingual, multi-domain and multi-environment for git workflow/setup in your answer ;)

You have one Craft install and one DB. Do everything described in that article, just replace the subfolder paths with the different domains:

return array(
    // ...
    'siteUrl' => array(
        'en' => 'http://example.com/',
        'es' => 'http://example.es/',
    ),
);

Then all you have to do is to configure your webhost so that it routes those domains to different index.php files. It should contain the info about the locale and point to Craft folder:

// Path to your craft/ folder
$craftPath = '../../craft';

// Tell Craft to serve the Spanish site
define('CRAFT_LOCALE', 'es');


How do set multiple entry relations using checkboxes on a front end form? I want to set up a form on the front-end of a site to allow logged in users to choose items from a list which represent entries in a channel using checkboxes, then save those entries as relations to an entry that the user is editing.

Using the docs and various questions here I have got setting a relationship to one entry working. However, I want to allow up to 5 relationships to be set and I can't figure out how to add further relationships.

The entry field containing the related choices is called choices.

Here's the template code I've got at the moment (simplified):

{# Get current list of choices to pre-set checkboxes #}
{% set choices = entry.choices %}
{% set choiceList = '' %}

{% for choice in choices %}
    {% set choiceList = choiceList ~ choice.id ~ "," %}
{% endfor %}

<form id="entry-edit-form" method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="choices-saved">
    <input type="hidden" name="sectionId" value="8">
    <input type="hidden" name="enabled" value="1">
    <input type="hidden" name="entryId" value="{{ entry.id }}">
    <input type="hidden" id="choicesList" name="fields[choices][]" value="">

    {% for choice in choices %}

            <input class="choice-checkbox" type="checkbox" id="choice{{ loop.index }}" data-id="{{ choice.id }}" {% if choice.id in (choiceList|split(',')) %}checked="checked"{% endif %} />
            {{ choice.title }}

    {% endfor %}

    <input type="submit" class="button" value="Save choices">
</form>

Then I've got some javascript that runs on form submit to loop through the checkboxes and grab the ids of the checked boxes. What format do these need to be saved in as a value to the hidden choicesList field so that an array of related ids is saved to the correct field in the edited entry?

Or is there another, simpler, way of doing this?

I'm pretty sure you can do this much simpler and without javascript. I've setup a front-end form using the doc's example and added checkboxes to choose entries that will be stored in a relational field simply by using name="fields[fieldName][]" in the input type="checkbox". For example:

<input id="" class="" type="checkbox" name="fields[kitIcons][]" value="{{ entry.id }}" checked>{{ entry.title }}<br/>

In the above example, "kitIcons" is the name of my relationship field, and I have this going through a loop to populate the entry.id and entry.title. Seems to be working without any glitches in my system.


What would be the best way to track downloads by user? Is anybody familiar with a plugin (similar to EE's Link Vault) that tracks all downloads, by user?

You can track the number of times a file has been downloaded using the Asset Count plugin by Verbb.

As the readme shows, rather than linking directly to your files, you’d point the link to the plugin’s controller action:


Problem using "set" with Sprout SEO I usually use {% block %}{% endblock %} to build my template but for the SEO plugin I'll be needing {% set %}{% endset %}. However my pages don't seem to render. If I change it to {% block %}{% endblock %} it works fine.

Anyone know what is causing this?

This is my base file _master.html (partly):

<body class="boxed bg-cover" style="background-image: url(img/backgrounds/street.jpg)">
 <div class="global-wrap">
     {% set header %}
     {% endset %}

this is my index.html (partly):

{% extends "_master" %}
 {% set header %}
   {% include 'header.html' %}
 {% endset %}

I think that's just the way they have set up the templates in the example, so what you're doing is just fine (using {% block %}), if that's how your templates are set up.

The difference is by using {% set %} you are just setting your content to a variable which would be {{ echoed }} into the layout file that you extend. Whereas using {% block %} you are telling twig what block of content should be inherited into the layout you are extending.

The twig docs probably explain it better:

http://twig.sensiolabs.org/doc/tags/extends.html
http://twig.sensiolabs.org/doc/tags/set.html

From the looks of it with the plugin in question, providing you add {{ craft.sproutSeo.optimize() }} into your layout template you should be all good to go.

Example with {% set %}

_layout.html

<body>
  {{ content }}
</body>

index.html

{% extends '_layout' %}

{% set content %}
 Some content
{% endset %}

Example with {% block %}

_layout.html

<body>
  {% block content %}{% endblock %}
</body>

index.html

{% extends '_layout' %}

{% block content %}
 Some content
{% endblock %}


Cannot enable Craft plugin in control panel I'm attempting to enable a plugin from within the Craft control panel but I am unable to do so. It shows Disabled and when I click "Enable" it shows "Plugin Enabled" at the top but still shows disabled below and will not enable.

I'm not getting any errors reported and it seems to work on other environments just will not work now?

My guess is it's a case sensitivity issue with the main plugin class/file name (some operating systems have case sensitive filesystems and some don't).

You can review the requirements for how things should be named here: https://craftcms.com/docs/plugins/setting-things-up

Or better yet, use a site like https://pluginfactory.io/ to generate the boilerplate plugin code for you and compare it to what you have.


How can you crop an image and output from a Matrix field? Trying to output a matrix field image so that it crops the thumbnail. However, I can't seem to get it to work.

Here's what I have:

{% for block in entry.servicesItems.type('images') %}

        {% if block.image|length %}

            {% set thumb = {
                mode: 'crop',
                width: 229,
                height: 172,
                quality: 75,
                position: 'center-center'
            } %}

{{ block.imageTitle }}

{{ block.imageContent }}

        {% endif %}

{% endfor %}

When you call .first on an Asset field, that's going to return an AssetFileModel.

Change the relevant part of your code to this:

{# grab the first image #}
{% set image = block.image.first() %}

{# link to the full sized version #}

    {# generated the transformed thumbnail version #}

{{ block.imageTitle }}

{{ block.imageContent }}


Is it possible to have different fields associated with users in different groups? We're developing a client site in CraftCMS that has 2 different frontend user groups. I know it's possible to set up custom fields for users but I'd like to set up different additional profile fields for each Group i.e. Group A has one set of custom fields and Group B has another. Is that possible?

Currently, this is not possible in Craft via the the Control Panel.

If you are managing user profiles from the front-end, you can manage different fields for different user groups manually.

A few considerations:

You can't set a field to required in Craft if it will be optional for one of the user groups on the front-end and not the other.  You may have to manage required fields in another way.
An admin with direct access to Users in the CP will have no signal in the UI as to which fields belong to which User Groups.


How do you display entries in a specific (custom) order? I want to display entries in a specific custom order in Craft. For example entry Id 1, then Id 5, then Id 3.  How can I do that?

Try using a structure. You can reorder them in the CP.

{% for entry in craft.entries.section('your_structure') %}
  {{ entry.title }}
{% endfor %}


Find related entries from section entry Matrix entry field In my projects section, each project entry has a Entry field in a Matrix. The Entry field references a tool. On the tool entry page I am trying to display all the projects that use that tool in their Matrix entry field. How do I do that? Currently I use this code but it doesn't display anything. I'm guessing I need to reference the Matrix handle and Entry field handle somehow but I haven't seen it done yet.

{% set relatedProjects = craft.entries.section('projects').relatedTo(entry) %}

{% for project in relatedProjects %}
    {{ project.title }}
{% endfor %}

I wasn't able to relate the entries back based on another entry using it in a field. I believe there would be a way to do this if you cycled through all of those relating entries and that field and filtered out the ones that matched to current entry. We ended up using categories instead and relations work much better in there!


How do I pass existing template variables on to an action controller? In a plugin I am using registerSiteRoutes to route URL requests to a controller to handle some user validation before rendering the appropriate template. For example:

public function registerSiteRoutes()
{
    return array(
        'some-path-to/(?P<template>template-name)/(?P<entryId>\d+)' => array('action' => 'myPlugin/handleRequest'),
    );
}

The handleRequest controller looks something like this:

public function actionHandleRequest(array $variables = array())
{
    if (!craft()->request->isSiteRequest())
    {
        throw new HttpException(404);
    }

    // Do some conditional checks

    // If everything is OK, load requested template
    if (craft()->myPlugin->doChecks($userId, $entry))
    {
        $variables['entry'] = $entry;
        $this->renderTemplate('statement/_'.$variables['template'], $variables);
    }
}

The rendered template includes a form that submits to another action controller in the plugin to handle creation of a number of entries based on the submitted values.

How can I pass the error messages (if any) back to the submitted form (that is accessed via the site route set in the plugin)?

I've tried removing the site route and accessing the template directly and this works. However, it also means that I need to add in a load of conditional logic to control access to the template in the template itself. I'd rather extract the logic into a plugin controller as I did before as it makes the templates a lot cleaner and separates out the logic.

Not really a direct answer to your question, but you could also perhaps remove the additional controller routing business and move your conditional logic into a plugin variable (or service method called from your variable).

{% if craft.myPlugin.everythingsOk(entry) %}
    // everything's ok, render template
{% endif %}

Your variable:

public function everythingsOk($entry)
{
    // Do some conditional checks

    if (craft()->myPlugin->doChecks($userId, $entry))
    {
        return true;
    }
    return false;
}


Superscript in entry title We launched a site for a scientific publication and they use subscript and superscript in lots of their content. Now they'd like to use in entry titles too..

I know I can set the entry title to be a custom field, but that field would be a rich text field in this case, which is far far far from ideal for a title.

I'm using this plugin to add sub/superscript https://github.com/elliotlewis/Redactor-Extras

Looking to fix this without having to use a rich text field.

Any pointers are greatly appreciated!

You can create different Redactor Fields with different settings/plugins. The easiest solution would be to create a redactor field only with your sub/superscript options so users can only insert those 2 things and no other html elements (bold, italic and so on).

You can search for an existing plugin or create your own to disable line breaks as well


How can I copy an entry? How can I create a plugin that will let me copy entry?

I found this question but don't have a good answer.

You’d start by creating a new EntryModel and copying over the normal properties:

$oldEntry = craft()->entries->getEntryById(100);

$newEntry = new EntryModel();

// core element attributes
$newEntry->enabled = $oldEntry->enabled;
$newEntry->locale = $oldEntry->locale;
$newEntry->localeEnabled = $oldEntry->localeEnabled;
$newEntry->slug = $oldEntry->slug;
$newEntry->uri = $oldEntry->uri;
$newEntry->getContent()->title = $oldEntry->getContent()->title;

// entry attributes
$newEntry->sectionId = $oldEntry->sectionId;
$newEntry->typeId = $oldEntry->typeId;
$newEntry->authorId = $oldEntry->authorId;
$newEntry->postDate = $oldEntry->postDate;
$newEntry->expiryDate = $oldEntry->expiryDate;

// do this if it's in a Structure section
if (($parent = $oldEntry->getParent()) !== null)
{
    $newEntry->parentId = $parent->id;
}

Where things get tricky is copying all of the content. That's tough because many field types expect their values to be in one format when saving, but they return their values in another format when you call $entry->myFieldHandle. For example relationship fields (Entries, Assets, Users, Categories, and Tags) each expect you to set their values as an array of related elements’ IDs when saving an entry, but when you call $entry->myRelationalField (or entry.myRelationalField from a template) you’re getting an ElementCriteriaModel back. So for those, you’d have to do this:

$newEntry->setContentFromPost(array(
    'myAssetsField' => $oldEntry->myAssetsField->ids()
));

There are some other posts that touch on how to format the various field types’ values (i.e. Duplicating Matrix fields with content from another locale), but nothing comprehensive.


twig for loop put every 2 elements in a new container I have this loop:

{% for div in myHandleHere %}

 {{ block.text }}

{% endfor %}

That actually outputs something like:

 one

 two

 three

 ...

What I want is, every 2 div, put them in a new container, like:

 one

 two

 three

 ...

Please help

I usually do this like so:

{% for block in blocks %}
  {% if loop.index0 % 2 == 0 %}

  {% endif %}
   {# other stuff #}
  {% if loop.index0 % 2 == 1 or loop.last %}

  {% endif %}
{% endfor %}

Or, more generally,

{% set cols = 2 %}
{% for block in blocks %}
  {% if loop.index0 % cols == 0 %}

  {% endif %}
   {# other stuff #}
  {% if (loop.index0 % cols == cols - 1 or loop.last) %}

  {% endif %}
{% endfor %}


RegEx Redirects for Legacy URLs My legacy URLs have this structure:

/teachings/tag/13721/omnipotent/ or
/teachings/series/17764/fearless/

For both the tag and the series they are always followed by a string of digits and then slug I want to capture and redirect to the new formats:

/teachings/topics/omnipotent and
/teachings/series/fearless

I've tried various ways using https://regexr.com/ to capture the slug and target each legacy URL but I can't seem to figure it out. I've seen the basic instructions here but I can't seem to find a way to target the unique legacy formats of these strings.

Any help you can provide would be greatly appreciated.

Here's the regex I think you'll need:

\/teachings\/tag\/\d+\/(\w+)\/? → \/teachings\/topics\/$1
\/teachings\/series\/\d+\/(\w+)\/? → \/teachings\/series\/$1

A couple explanations:

\/ is an escaped / character
\d+ means one or more digit (0-9)
\w+ means one or more alphanumeric/underscore character (A-Z, a-z, 0-9, _)
surrounding something in parentheses makes it a capturing group, which can then be referenced when you're doing the "replace"

So in our regex we're matching the current url structures, capturing the slug, and then using that in the new url structures. Hopefully that helps!


Relations and Categories What's given:

Channel: Nutrition
Entries Fieldtype: restaurant
Category Fieldtype : menu

Category: Menu

Channel: Menus that also use relations using restaurant field.

Each item in the nutrition channel has restaurant and menu category selected.

On a restaurant's menu page I'm trying to list menu items from the nutrition channel grouped by categories.

Currently I use the following snippet

            {% for category in craft.categories.group('menu').all() %}

{{ category.title }}

                    {% for entry in craft.entries.section('nutrition').relatedTo(category).orderBy('title').all() %}

{{ entry.title }}

                    {% endfor %}

            {% endfor %}

Which works fine. However if I add more nutrition items and assign them to another restaurant they'll be listed as well.

I assume we need to define restaurant first

{% set restaurant = craft.entries.section('restaurant').one() %}

but what are my next steps?

The next step is that you would need to chain .relatedTo(restaurant) to your existing craft.entries() call


Can I translate locale names? I've read all posts about localization and translation here and at Craft's documentation, but I still haven't found the answer.

What I want achieve here is having let's say UK instead of British English.

I found paragraph in documentation:

{{ "Welcome, {name}"|t({ name: user.friendlyName }) }}

that says: If your text contains dynamic variables, add tokens to the string where they should go, and pass an object to the t filter that contains their values

Could anything like that work by passing object to _locale.php in /translations folder and set other value? Tried, without effect.
Theoretically it could work, craft would pass the object of an active locale to our translation's file.

Any advice, so I don't waste time on something that can't be done.

Can't be done, don't waste your time.

Only thing that could work is via a static translations file, but the CP gets locale name data directly from that yii language file, so this is your only chance (see dupe question). Other things can be overwritten though, e.g 'Users' => 'Members'.


Enable line breaks in plain text fields When you create a Plain Text field it asks if you want to allow line breaks, but they are ignored when output in the template.

I don't want to have to use a rich text field just to enable editors to add a simple line break, but is that my only option?

You can still use plain text, you just need to use a filter after

{{ entry.text | nl2br  }}


Custom Aliases not working I'm trying to setup aliases following the instructions in the docs, but I can't get them to work (for example they don't appear when setting paths for Assets).
I copied and pasted the code exactly as the example in the docs, and the env variable ROOT_URL shows up in the CP, but the alias @rootUrl does not. Is there another step? I tried clearing caches and logging out/in, but that didn't help.
In the config/general.php file I pasted the code last, right below Dev environment settings. Here is that last portion of the config:
    // Dev environment settings
        'dev' => [
            // existing settings ...
            'backupCommand' => getenv('BACKUP_COMMAND'),
            'restoreCommand' => getenv('RESTORE_COMMAND'),
        ],

    // -- config/general.php Code example from docs --
        'aliases' => [
            '@rootUrl' => getenv('ROOT_URL'),
        ],
];

Also, the 3.6 upgrade documentation states (emphasis mine):

The siteName and siteUrl config settings have been deprecated. We strongly recommend you set your sites’ names and URLs using environment variables instead.

So, does this mean I shouldn't even be bothering with aliases? Should everything be an environment variable only?

Try to add your alias array within one of your environment array such as:
<?php

return [
    // Global settings
    '*' => [
        'aliases' => [
            '@rootUrl' => getenv('ROOT_URL'),
        ],
    ],

    // Dev environment settings
    'dev' => [
        // ...
    ],

    // Staging environment settings
    'staging' => [
        // ...
    ],

    // Production environment settings
    'production' => [
        // ...
    ],
];


Is there a way to create a "sticky" asset I have a list of images that are loaded directly from the content of a specific asset folder.

{% for image in craft.assets.find({ folderId: 18, limit: 240, order: filename }) %}

What I want to achieve is that one (or more) images from that assets folder are listed first (second etc.) before the actual ordering by filename starts place.
Much in the same way as sticky entries (EE).

Based on adding a lightswicht ("sticky") as suggested by @carlcs I think you should be able to solve this by just using two order fields.

{% set images = craft.assets.folderId(18).order('sticky desc, filename asc').limit(240); %}

You should be able to save some twig code, maybe even requests. Haven't tested this though.


How long does the share link on the entry edit screen last? We're noticing that links to hidden entries that are shared via token (share button) eventually expire.

How long do these links last? Is there a setting to adjust how long the token will last?

24 hours by default, but it can be configured via the defaultTokenDuration config setting.

v2 documentation
v3 documentation


How do I setup the Login Page to work with requireLogin? I want to create a login page.  It would be a Single.

The URI is set to login.  So how do I name and map the twig file?

I tried:

creating a login folder under templates.
naming the twig file either login.twig or index.twig
setting the template location to login/login.twig or login/index

Neither approach worked.

How do I setup a login page so that when I use requireLogin the login page is in the right location for loginPath.  At the bare minimum, where is the easiest location to place the login path?

You didn't specify Craft 2 or 3, but I'm pretty sure this answer applies to both.

The template should live at templates/login/index.twig or templates/login.twig. Craft will resolve to both of them.

I tested this on a fresh Craft Pro install and created a Single with a template path of login.  There is a templates/login.twig with the login example here: https://docs.craftcms.com/v3/dev/examples/login-form.html and a templates/test.twig that only has {% requireLogin %} in it.

I logged out of Craft, then went to mysite.com/test in a browser and was successfully redirected to mysite.com/login that rendered the example login template.


Craft 3 Multi Site - Have a related entries field relate to another site, but respect localization I am trying build a hub of sorts using Craft 3. I want the main site to be the hub which manages most of the data, and then subsequent sites are built on top of that, relating where necessary so as to normalize the core data. I do NOT want the entries to propagate from the core site to the sub sites. I want them to only exist in the Core Site and be related to.

Here is the basic site structure:

Core Site En (coresite.com)
Core Site Fr (coresite.com/fr)
Sub Site En (subsite.coresite.com)
Sub Site Fr (subsite.coresite.com/fr)

I then have an entry on Sub Site with a related Entries field. Since the entries do not propagate, when you try to select an entry, the list of options is empty. To fix this I check "Relate entries from a specific site?". The problem is I can only choose one site, forcing me to choose either the EN or FR version of the Core Site.

If I choose EN that works fine, but when I'm on Sub Site FR and access the related entry, it's in English and doesn't respect the translated version of it on Core Site FR.

This seems to be a big trade off in the decision to treat languages as sites.

Is there something I'm missing?

You can use a matrix field with a block and entries field for each sub-site.


Cannot grant user group plugin permission without hasCpSection A user group cannot be given access to a plugin without the plugin having hasCpSection.

I don't want to give anonymous access to the plugin's methods; is there not an option to have a plugin listed for user group permission allocation without it having an cp tab? Too many cp tabs cause a JS error - but that's another issue...

The only point of those permissions is to determine whether the user has access to the plugins’ sections, so it would be pretty pointless to show the permissions for plugins that don’t have sections.

The confusion here is probably just in the wording of the permissions. “Access [Plugin]” isn’t very clear on which aspect of the plugin you’re granting access to. So maybe we should change that to “Access [Plugin]’s CP section” or something.

If you have a plugin that offers functionality that warrants user permissions, register your own custom user permissions using the registerUserPermissions hook, and verify that the user has those permissions using craft()->userSession->checkPermission().


Craft 3 - Programatically get all the values contained in a field of type category I want to programmatically get all the values contained in a field of type category.

I am doing this on Elements::EVENT_AFTER_SAVE_ELEMENT.

If I dump $event->element->getFieldValue('productTheme') I get the field but I did't find how to go from there.

My final goal is to have the categories from the category field in an array (not all the categories in the category group, but only those selected in the field).

Your field contains an object of type ElementQuery in order to get all Categories you'll need to execute it.

$categories = $element->getfieldValue('productTheme')->all();
$categoryTitles = [];
for($categories as $category){
    $categoryTitles[] = $category->title;
}

Please read the documentation


Updating an entry record programatically? I need to update the value of an entry attribute programatically. I've tried a couple things, but the record is not updated. The code I am using is below.

      $criteria = craft()->elements->getCriteria(ElementType::Entry);
      $criteria->section = 'affiliates';
      $criteria->limit = null;
      $criteria -> search ='email:'.$email;
      $criteria = $criteria -> first();

      $criteria->getContent()->setAttribute("optOut", "true");

      craft()->entries->saveEntry($criteria);
      return $criteria->title;

After you call $criteria->first(), you no longer have an ElementCriteriaModel, but an actual EntryModel, so probably more semantic to change to:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->limit = null;
$criteria -> search ='email:'.$email;
$entry = $criteria->first();

$entry->getContent()->setAttribute("optOut", "true");

craft()->entries->saveEntry($entry);
return $entry->title;

But my guess about your actual problem is you're getting a validation error.  You can verify and guard against that in your code by doing something like:

if (craft()->entries->saveEntry($entry))
{
    return $entry->title;
}
else
{
    $errors = $entry->getErrors();
}


Query entries by custom date field (for a particular year) So I'm trying to get all entries that have a particular year assigned to a custom date field. (Could be any day/month in that year).

The custom field is startDate and my attempt at a query - which doesn't work - is below...

PS. year is a 4 digit variable set via the last segment of the url and pulled into the template as a variable, and giving you 2018, 2019 or whatever...

{% set query = {
  section: 'programme',
  isOngoing: 0
} %}
{% set programmeEntries = craft.entries(query).search('startDate:' ~ year|date('Y-m-d')) %}

PS. I think it's more like this but I can't get the syntax right...

{% set query = {
  section: 'programme',
  isOngoing: 0,
  startDate: ( ['and', '>=' ~ (year~'-01-01')|date('Y')|atom, '<=' ~ (year~'-01-01')|date('Y')|date_modify('+12 months')|atom])
} %}

I think your problem is you're converting the date to a year string then converting that to an atom value. Just convert the date straight to an atom value:

{% set yearStart = "#{year}-01-01"|atom %}
{% set yearEnd = "#{year}-12-31"|atom %}

{% set entries = craft.entries({
    section: "programme",
    isOngoing: 0,
    startDate: ["and", ">= #{yearStart}", "< #{yearEnd}"]
}).all %}


How to load a different template for parent page So, I'm newer to Craft, and so I need to figure out the best way to set up a portfolio page with child entries. I've set up a structure, but I need the parent page to load a different template than _entry.html. I still haven't been able to figure out a good solution for this, so any help would be great.

Thanks!

First, I'd recommend that you have a total of 3 templates: _child.html for your child entries, _parent.html for your parent entries, and finally _entry.html which will basically work as a "controller" template (the only code contained in _entry.html should be the code that includes either the child or parent templates). You can, of course, name the templates whatever you want, but make sure that the Section's entry template is pointing to _entry.html.

Then, put this in your _entry.html file:

{% switch entry.level %}
    {% case 1 %}
        {% include '_parent.html' %}
    {% default %}
        {% include '_child.html' %}
{% endswitch %}

What the above does, is simply to look at the entry.level attribute, which returns the level your Structure entry is at. Top level entries are level 1, so for a simple 2-level Structure, this may work.

If you need something more flexible, where a "parent" template should be loaded unrelated to levels but based on whether an entry has children or not, you could do something like this (also in entry.html):

{% if entry.children|length %}
    {% include '_parent.html' %}
{% else %}
    {% include '_child.html' %}
{% endif %}

Another option is to test for an entry's parent property instead (i.e. if an entry has a parent entry, it should load the child template):

{% if entry.parent %}
    {% include '_child.html' %}
{% else %}
    {% include '_parent.html' %}
{% endif %}

Note: You may need to correct the paths to your templates for the examples above – the {% include %} always works relative to your /templates folder, so if your templates actually live inside /templates/news, you'd have to use {% include 'news/_parent.html' %} (even if _entry.html and _parent.html is inside the same folder).


How do I list the tag groups that are actually in use? I'm developing a masonry photo gallery with some filters (colors, style, manufacturer, etc) and I want to use tags to filter them by. I need some navigation which should look like this:

Tag Group 1

Tag 1

Tag 2

Tag Group 2

Tag 3

tag 4

I read this article https://craftcms.com/support/active-tags but I can't figure out how to get all group tags and for them all the tags that are actualy in use. I think i should use

{% for tag in craft.tags.group('blogTags') %}

but I want to get all the group handles in a loop dynamically.

You could use the group filter to group your tags by tag groups:

{% set entries = craft.entries.section('gallery').limit(null) %}

    {# Get all the tags related to our gallery entries and group them by tag group #}
    {% set allGalleryTags = craft.tags.relatedTo(entries)|group('group') %}

    {# Loop the tag groups #}
    {% for tagGroup, tagsInGroup in allGalleryTags %}

{{ tagGroup }}

                {# Loop the tags of this group #}
                {% for tag in tagsInGroup %}

{{ tag.name }}

                {% endfor %}

    {% endfor %}


Description and logo at the very top of browser? All, After we switched from Wordpress to Craft our site description and logo at the very top of the browser tab have been disappeared as shown in the image. Could you please guide me how can I achieve this?

Site title - This is set with HTML meta tags and not really anything to do with Craft specifically. It depends how you "switched" from wordpress to Craft. Inside your document head, you need to include a title tag, like:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
    <title>Website title goes here</title>
</head>
<body>

You can set this automatically by doing the following:

<title>{{ entry.title }}</title>

Favicon (logo) - Upload your .ico file to the /public_html directory.


Error - Unable to resolve the request I've created a 'controllers' folder within the 'plugins' folder and a php file within that following the documentation

I've also created the following form:

    <form method="POST" accept-charset="UTF-8">
        {{ getCsrfInput() }}
        <input type="hidden" name="action" value="pluginName/controllerName/actionName">

        <input type="submit" value="Start poll">
    </form>

I keep getting the 'Unable to resolve the request' error.

Do you have any idea why this could be happening? Am I missing a step that's not in the documentation, like needing to register the url?

For reference, the action only contains $this->redirect('');

As I thought, I was just being silly. I initially didn't realise that custom controllers need to be encapsulated within a custom plugin

I guess my mistake was going directly to the controllers documentation and missing the line that says:

  To create a controller, first create a new controllers/ subfolder within your plugin’s folder

Hopefully anyone who runs into this (doubtful as I can imagine most, unlike me, will probably read the documentation properly) will find it somewhat useful


Integrate Google reCAPTCHA into Contact Form plugin So I just recently plugged in pixelandtonic/ContactForm plugin into my website and I realized I got about 3 spam emails straight into my inbox on the first day it was up.

Is there a way to integrate the simple "one click" google Recaptcha into this form? Or is there any other/better solution than the Honeypot?

Thanks for the help!

---- EDIT -----
Ever since I've installed the Spam Guard Plugin, I haven't received anymore spam! This is a must with Pixel's Contact form plugin.

There are several anti-SPAM form plugins available for Craft that should work for you (including a Google reCAPTCHA one).


Renaming news section leads to 404 I'm pretty new to Craft, just installed my first one. I've checked the docs, but I couldn't find any useful hints anymore and I think it should work.

I'm trying to rename the default news section to post. I changed everything admin side from news to page, but the path http://site.local/post/2016/we-just-installed-craft leads to a 404 page. The http://site.local/post page lists the entries correctly.

I also renamed the news folder in the templates to post. If I change it back to news, the 404 problem is resolved, but obviously I want to understand why it still wants to access that folder.

Sections page looks like this

I don't have any custom route set up.

Problem solved.

Admin was a bit confusing on the UX side, I didn't realize that edit entry types and clicking the name of the section leads to different pages.


How to use the default HTML email template when sending an email from a plugin? On /admin/settings/email, when the HTML Email Template field is set to a valid template, all system messages are sent using it. They inject the content of the messages inside the {% block main %}{{body}}{% endblock %} variable.

From a custom plugin, setHtmlBody doesn't inject the content inside it. It takes its value as the whole template value instead of only replacing the {{body}} variable.

Example:

<?php

use craft\mail\Message;

$message = new Message();
$message->setTo('john@doe.com');
$message->setSubject("Hello world.");
$message->setHtmlBody("Hello world.");
$message->send();

How can I send this email using the custom HTML email template specified in my CP Email Settings?

I could copy-paste the whole file content of my custom template inside the setHtmlBody, but it doesn't seems to be a clean way...

There are different ways

Extending the E-mail template in your template

This could be your email template emails/_someMail

{% extends 'path/of/your/layout-same-as-you-inserted-in-your-cp' %}

{% block main %}Hello World{% endblock %}

And in your PHP file

use craft\mail\Message;

$message = new Message();
$message->setTo('john@doe.com');
$message->setSubject("Hello world.");
$message->setHtmlBody(Craft::$app->getView()->renderTemplate('emails/_someMail'));
$message->send();

Render the correct template from the beginning

You can do exactly the same as Craft does in it's function - but I would suggest the first way

$systemMessage = Craft::$app->getSystemMessages()->getMessage('test_email', $message->language);
$subjectTemplate = $systemMessage->subject;
$textBodyTemplate = $systemMessage->body;

// Use the site template mode
$view = Craft::$app->getView();
$templateMode = $view->getTemplateMode();
$view->setTemplateMode($view::TEMPLATE_MODE_SITE);

// Use the message language
$language = Craft::$app->language;
if ($message->language !== null) {
    Craft::$app->language = $message->language;
}

$settings = Craft::$app->getSystemSettings()->getEmailSettings();
$variables = ($message->variables ?: []) + [
        'emailKey' => $message->key,
        'fromEmail' => $settings->fromEmail,
        'fromName' => $settings->fromName,
    ];

// Render the subject and textBody
$subject = $view->renderString($subjectTemplate, $variables);
$textBody = $view->renderString($textBodyTemplate, $variables);

// Is there a custom HTML template set?
if (Craft::$app->getEdition() === Craft::Pro && Craft::$app->getMailer()->template) {
    $template = Craft::$app->getMailer()->template;
} else {
    // Default to the _special/email.html template
    $view->setTemplateMode($view::TEMPLATE_MODE_CP);
    $template = '_special/email';
}

$e = null;
try {
    $htmlBody = $view->renderTemplate($template, array_merge($variables, [
        'body' => Template::raw(Markdown::process($textBody)),
    ]));
} catch (TemplateLoaderException $e) {
    // Clean up before throwing
}

// Set things back to normal
Craft::$app->language = $language;
$view->setTemplateMode($templateMode);

if ($e !== null) {
    throw $e;
}

$message
    ->setSubject($subject)
    ->setHtmlBody($htmlBody)
    ->setTextBody($textBody);


Merging Multiple Relations as params I have the following code where I'm pulling entries related to another entry which works fine. However I also want to limit the entries returned on a category page and thus am merging in a relatedTo: category

However on the category page it is returning all entries related to that category, not limited to the category AND the related entry

{% set myStation = getCookie('myStation') %}
{% set relatedStation = craft.entries.id(myStation) %}

{# set pagination/categories #}
{% set params = { section: 'blog', limit: 6, offset: 1, relatedTo: relatedStation } %}
{% if category is defined %}
  {% set params = params | merge({ relatedTo: category }) %}
{% endif %}

{% set entries = craft.entries(params) %}
{% paginate entries as pageInfo, pageEntries %}

I see the docs includes 'and' (bottom of the page) but I'm not sure how to get that in there using merge. Please advise.

Something like this should work:

{% set myStation = getCookie('myStation') %}
{% set relatedStation = craft.entries.id(myStation) %}

{% set params = { section: 'blog', limit: 6, offset: 1, relatedTo: relatedStation } %}

{% if category is defined %}
    {% set params = params|merge({relatedTo: ['and',
        { element: relatedStation },
        { element: category }
    ]}) %}
{% endif %}

{% set entries = craft.entries(params) %}
{% paginate entries as pageInfo, pageEntries %}

The trick with merge is that it will always replace matching keys that it finds.  So you need to tell it to replace it with the proper and syntax.


What is CDbException Error: SQLSTATE[42000]: Syntax error or access violation while moving a site to remote? CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #28 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'site.structureelements.root' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by.

The site is working locally through MAMP, and on a remote apache dev server. I have an nginx server built for shared hosting through Laravel Forge. All of the PHP settings are identical, and I used the database backup from the dev site.

I removed all of the tables and the standard craft install worked fine.

Brad was correct in the comments above. The answer is the sql_mode. This is a duplicate of Getting this SQL Error: GROUP BY incompatible with sql_mode=only_full_group_by


Issue on new craft (craftcms3) setups: vendor Twig can't read system variable After installing craft through composer, setting up the database and running craft setup, I have a craft application ready to go.
When I go to settings/general, I always get a crash with following information:
1. in /vendor/craftcms/cms/src/templates/settings/general/_index.html at line 30
    {{ actionInput('system-settings/save-general-settings') }}
    {{ redirectInput('settings') }}

    {{ forms.autosuggestField({
        first: true,
        label: "System Name"|t('app'),
        id: 'name',
        suggestEnvVars: true,
        name: 'name',
        value: system.name
    }) }}

    {{ forms.lightswitchField({
        label: "System Status"|t('app'),
        warning: (craft.app.config.general.isSystemLive is same as(true) or craft.app.config.general.isSystemLive is same as(false) ? configWarning('isSystemLive')),
        id: 'live',
        name: 'live',
        onLabel: 'Online'|t('app'),
        offLabel: 'Offline'|t('app'),
2. in /vendor/craftcms/cms/src/helpers/Template.php at line 106– twig_get_attribute(craft\web\twig\Environment, Twig\Source, null, 'name', ...)
        // Add deprecated support for the old DateTime methods
        if ($object instanceof \DateTime && ($value = self::_dateTimeAttribute($object, $item, $type)) !== false) {
            return $value;
        }

        try {
            return \twig_get_attribute($env, $source, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
        } catch (UnknownMethodException $e) {
            // Copy twig_get_attribute()'s BadMethodCallException handling
            if ($ignoreStrictCheck || !$env->isStrictVariables()) {
                return null;
            }
            throw new RuntimeError($e->getMessage(), -1, $source);
3. in /vendor/craftcms/cms/src/templates/settings/general/_index.html at line 30– craft\helpers\Template::attribute(craft\web\twig\Environment, Twig\Source, null, 'name', ...)
    {{ forms.autosuggestField({
        first: true,
        label: "System Name"|t('app'),
        id: 'name',
        suggestEnvVars: true,
        name: 'name',
        value: system.name
    }) }}

    {{ forms.lightswitchField({
        label: "System Status"|t('app'),
        warning: (craft.app.config.general.isSystemLive is same as(true) or craft.app.config.general.isSystemLive is same as(false) ? configWarning('isSystemLive')),
        id: 'live',

The errors on the lines correspond to:
line 30: value: system.name
line 106: return \twig_get_attribute($env, $source, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
line 30: value: system.name
As you can see, all is happening in /vendor, so I guess it must be some setup that I have missed or incorrectly executed. Why is the system variable null? Is it because of my local machine is missing some configuration? (Macbook Pro with macOs Big Sur)

I've looked all over for a solution to this but couldn't find anything. I don't know if you've already fixed your problem now, but in case you haven't or someone else has found this error and arrived here, a simple fix for it is to add the missing information into the project.yaml in config/project/.
For my local development build, I used the following:
system:
  edition: solo
  live: true
  name: '{YOUR PROJECT NAME HERE}'
  retryDuration: null
  schemaVersion: 3.5.13
  timeZone: UTC

For the schemaVersion, it will need to match the one specified in the installed version of Craft in your vendor folder. This can also be found in the repo.
I'm not sure what the cause of the missing info is, but I am also on a Mac running Big Sur so it may be related. Once you have added in this information, you should be able to edit it normally from Settings -> General.


How to delete tags in Craft CMS 3 I want to delete some of the tags that are entered in the system.

Since there is no way to do that in Control Panel, and there is not a valid plugin that can do this (know that from my previous question).

The only way to delete tags is in the database. So I found this comment. I think this is for CraftCMS 2, but is it still the same and for CraftCMS 3?

Yes the same still applies. You can either delete it via DB directly in your {{%elements}} column or you can just run

PHP

Craft::$app->getElements()->deleteElementById(x)

Twig

{% do craft.app.getElements().deleteElementById(x) %}


Craft, CSS Frameworks, Bower & Grunt setup suggestions I would like to use a CSS Framework like Zurb Foundation with Craft. I also want to manage my bower dependencies and I want to use Grunt to concat and minify my sass/js as well as compress my images. All this good stuff is happening on my local computer running Mamp Pro. I'll then move it to a Staging server once everything is set up.

I have these folders/files in my directory.

.bowerrc
bower.json
-craft
-dev
 -bower_components
 -scss
  .htaccess
  index.php
  robots.txt
-node_modules
-public
Gruntfile.js
package.json

The idea of my workflow is to work in the "dev" folder (html, scss, js) and when it's time to push to Staging server I use grunt to copy/minify/compress into the "public" folder. That way I can send only the "craft" and "public" folders.

If I'm working in the "dev" folder my templates would need to link to the files in the bower_components folders as well as my unminified code. When I publish to the public folder everything gets the minified/concatenated version.

My question concerns templates.
I know that templates are in the "craft" folder. How would I get craft to choose between 2 base _layouts (one built for dev, one built for speed) based on which folder my index.php file is located? Is there a better workflow solution?

In my humble opinion, this is a task for Grunt / Gulp, not for Craft.

Addy Osmani has an excellent article on Environment-specific builds that would be interesting for you and the kind of use case you mention.

In short, gulp-replace or gulp-processhtml and gulp-preprocess will give you what you need to build such functionality in your build scripts. Similar plugins exist for Grunt as well.

As for file organisation, I generally keep my package.json and gulpfile.js files at the root of the repo / website. I find it a lot easier to manage paths.


A way to save feeds as an entry Was wondering if anyone had looked a a way of saving RSS feed items as an entry into craft.
I imagine this would have to be done through a plugin and a custom field type? Or is there a better way to do this.

This would have to be a plugin to pull in an rss feed and make it an entry -butt there is also the option to use the craft.feeds tag to pull rss feeds directly into your template.

http://buildwithcraft.com/docs/templating/craft.feeds


CSS doesn't load on the live server As I put the CSS files on the public root folder of the live site, the CSS doesn't load on the live site.

I'm guessing that the path is not accurate.

If you're 100% sure that the path is correct, then check your file permissions. Small chance the permissions are locked down too tight.


Creating comments via a related section I've been reading on here about suggestions on implementing commenting systems. I'm aware of disqus integration but I want/need  built in commenting.

I have seen it mentioned a couple of times that one approach would be to create a section (presumably a channel) dedicated to comments and the relate that to an entry via an entries field.

I just can't quite wrap my head around how that works out. Do the entries have to be manually selected in order to relate them?

If anyone's built something like this then I would love to know how they tackled it!

One thing to add is that only registered members will be commenting. And there would be several different sections needing comments.

Thanks!

One approach would be to create a comments channel with an entries fieldtype (with sources checked for any channels that you want to allow commenting; limit set to 1) called 'relatedEntry' (or whatever you like). On your article template, include a for loop to display existing comments relateTo the entry. Check to see if there is a current user, and if yes, include a comments form. In the comments form place a hidden field with the id for the current entry. Something like this:

  {{ entry.title }}
  {{ entry.body }}

{% for comment in craft.entries.section('comments').relatedTo(entry) %}

{{ comment.author.fullName }}
{{ comment.body }}

{% endfor %}

{% if currentuser %}
<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="sectionId" value="2">
    <input type="hidden" name="redirect" value="{{ entry.url }}">
    <input type="hidden" name="fields[relatedEntry][]" value="{{ entry.id }}">

    Comment

    <input type="text" name="comment">
</form>
{% endif %}

name="fields[relatedEntry][] is formated this way because related fields expect an array even if it's only a single related entry.

You could also create threaded comments by creating another related entries fieldtype called parentComment (or whatever you like) and including that as a hidden field in the form as well (you might need ajax or javascript here to help set the hidden field value from the 'comment' link).

To make it a little nicer you could also load the comments form via ajax or reveal it with javascript.

Untested, but hopefully this will point you in the right direction.


Cannot access email section of settings I somehow can't access the email section of settings;
/admin/settings/email

Argument 1 passed to craft\helpers\MailerHelper::createTransportAdapter() must be of the type string, null given, called in ___/vendor/craftcms/cms/src/controllers/SystemSettingsController.php on line 139

Everything is up to date, and I've tried disabling all plugins.

Any tips on how to fix this?

I don't think I previously have added any email settings to the site, so it should have been a clean slate.

Try this in dev or back up first.
Set 'useProjectConfigFile' => true, in your config/general.php and refresh your Control Panel. This will place a project.yaml file in your config/ folder.
Open that file and look for a portion that looks like this:
email:
  fromEmail: your@email.com
  fromName: Sitename
  transportType: craft\mail\transportadapters\Sendmail

If only your transportType is empty, add craft\mail\transportadapters\Sendmail as above (you'll be able to change that later if needed). If more is missing, set at least what you see above and if you have no email section at all, add it.
Save the file then refresh your Control Panel. It should say Changes to project.yaml must be applied to the loaded project config. Hit the Sync changes button.
Next, check if you can access your mail settings again and if so set 'useProjectConfigFile' back to false.


Craft Commerce: Validation on Address Fields Can someone break down how I should validate empty address fields as a plugin for Craft Commerce and take the following answer further?

The Craft Commerce documentation provides the following example for the name field - but I'm not sure what my next steps should be...

public function init()
{
    craft()->on('commerce_addresses.onBeforeSaveAddress', function($event){
            $address = $event->params['address'];
            $address->addError('firstName','Not a cool name man.');
            $event->performAction = false;
    });
}

In Craft3 you can do it like this:

use Craft;
use craft\base\Plugin;
use craft\commerce\models\Address;
use yii\base\Event;

class Custom extends Plugin
{
    public function init()
    {
        parent::init();

        Event::on(Address::class, Address::EVENT_BEFORE_VALIDATE, function (Event $event) {
            $address = $event->sender;
            if (empty($address->address1)) {
                $address->addError('address1', Craft::t('app', 'Address Line 1 is required'));
                $event->handled = true; // stop other handlers for this event
            }
        });
    }
}


Getting an array of ids from an array of eager-loaded elements within Twig I have been using the ids() method on the ElementCriteriaModel returned by a call to an entries field within a Twig template to return an array of ids for further processing.

Now I wish to eager-load these entries, but the entries are returned as an array with no access to the ids() method.

Is there an efficient way to get this array of ids within Twig, or would I be better moving this to a plugin?

You would just loop the entry models to collect the IDs (looks ugly, but it's a simple and efficient for loop). But in case you do not need anything else from the models, I'd actually expect your previous approach using the ids method to have better performance.

{% set ids = [] %}
{% for entry in entry.myEagerLoadedEntries %}
    {% set ids = ids|merge([entry.id]) %}
{% endfor %}


Error: Craft\EntryModel and its behaviors do not have a method or closure named "Case Studies" I'm new to Craft CMS dev and I'm trying to create a template using Twig and I'm getting this error: Craft\EntryModel and its behaviors do not have a method or closure named "Case Studies"

I have a reference in the view file:

{% for entry in entry.caseStudies %}

I'm assuming there's a config file or somewhere I can add this to the EntryModel but I'm not sure where this is in the default Craft installation. Any suggestions are welcome.

Thanks

Welcome Ross! If you have 'Case Studies' as a Section and not a field, try changing your syntax to:

{% for entry in craft.entries.section('caseStudies').find() %}

    {{ entry.title }}
    ...

{% endfor %}

Here's an updated example, showing an additional custom field...

{# Find all Entries in the Case Study section #}
{% for entry in craft.entries.section('caseStudies').find() %}

    {# Display the entry's Title #}

{{ entry.title }}

    {# Display the contents of the Intro Summary (plain text field) #}

{{ entry.introSummary }}

{% endfor %}


DevMode not showing detailed Internal 500 Errors I've noticed lately, maybe after the last Craft update or two, that internal 500 errors no longer show information or error traces. I simply get a message like:

Internal Server Error
Undefined offset: 0

And that's all it will show. I've checked that devmode is set to true, and in dashboard it shows that devmode is on. Is there a particular reason this would be happening? Maybe because the error is coming from a plugin and not twig? Or a general setting I'm not aware of for more detailed errors? It used to show all the information I needed.

I confirmed this was a regression with the Yii 1.1.16/Craft 2.4 update and it's been fixed for the next post 2.4.2670 update.


Uploaded file was empty We've got all the max settings set up OK as per https://craftcms.com/support/upload-troubleshooting, but we are still getting errors. The log file just shows this, nothing more:

  2014/10/24 11:26:35 [error] [application] Uploaded file was empty

What else should we be looking for?

I had the same problem and all PHP settings were set OK. I couldn't upload a 2MB file, but uploading a 20KB file was fine.

The problem was that the /tmp folder was almost completely full (because PHP stores the temporary file in /tmp before moving it to web/user space i.e. your assets folder). Freeing up space in this folder solved the issue.


Update user password I'm trying to update a user password on save via a custom field (on registration via the back-end - the admin needs to specify a password on registering a user). Is this even possible?

Came across this question How do I change a user's password programmatically in a plugin? and tried using the users.onBeforeSaveUser event to update the $user->newPassword but the user cannot login with the details registered/created.

Any thoughts on above appreciated!

You can't use the users.onBeforeSaveUser event to set a user's password as this event happens after the supplied password has been hashed by a private method in the UsersService.

Instead, you could use the users.onSaveUser event, check if a new user has just been saved and if so add the password to the userModel and re-save it. The following is untested, but should do the trick:

    craft()->on('users.saveUser', function(Event $event) {

        // Only fire if new user, this should avoid an infinite loop
        if ($event->params['isNewUser']) {

            // retrieve the userModel from the event
            $user = $event->params['user'];

            // set new password
            $user->newPassword = 'My Super Secret Password';

            // save user
            if (craft()->users->saveUser($user))
            {
                // Password successfully saved!
            }
            else
            {
                // Oops, something went wrong!
            }
        }
    });


Is it possible to achieve lead scoring, personalisation / marketing automation using Craft? Is there a Craft equivalent of this type of marketing automation?

lead scoring
personalisation

For example (4 min): https://www.youtube.com/watch?v=Ck9ywjBTEGM

Is there any plugin or external service that can be used with Craft to achieve this?

There are several ways to do this. The best way will likely depend on your situation. This type of functionality will also require some amount of custom development and implementation time.

A few examples:

Services like Intercom can be integrated into Craft. You would manage marketing automation via Intercom and the custom development necessary would be to tie in the actions of your users on your Craft site with Intercom so you had the data you need to communicate how you wish. Intercom can be integrated into login processes, track user actions, and capture data when users submit Forms (plugins like Sprout Forms and Solspace Freeform are both capable of being customized to integrate with third-party services).
For more generic data capture, Mixpanel can capture a lot of data about your customers. Mixpanel is more of a data analytics platform, so using a service like this will require that you have a larger budget to build out your own marketing automation processes around the data you gather.
For additional control over your transactional email in Craft, Sprout Email can help with dynamic personalization of your email notifications, integration with custom events, and targeting specific lists of users.

In all of these cases, you will want to develop a clear plan around your requirements and budget time for customization to integrate the plugins and services into your sites workflows.


How to change an entry's slug on EVENT_AFTER_SAVE_ELEMENT? My entries' titles are auto-generated from several fields values on first save.

When one of these fields values change, I would like to update the auto-generated slug also:

Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function (Event $event) {
        $entry = Entry::find()
            ->id($event->element->id)
            ->one();

        if ([] !== $entry) {
            $title = craft\helpers\StringHelper::toAscii($entry->id.'-'.$entry->title);
            $title = craft\helpers\StringHelper::toLowerCase($title);
            $title = str_replace(' ', '-', $title);

            //  I tried this below, but none works
            $entry->slug = $title; // ⬅ Not working
            $entry->setFieldValue('slug', $title); // ⬅ Error
            Craft::$app->elements->saveElement($entry); // ⬅ Infinite loop
            $event->element->slug = $event->element->id; // ⬅ Not working
        }
    }
);

Unfortunately, none of these methods works. Any idea how to achieve this?

You can change the value in the DB directly instead of using the Elements service

$entry = $event->element;
$elementId = $entry->id;
$siteId = $entry->siteId;
Craft::$app->getDb()->createCommand()
    ->update(
        '{{%elements_sites}}',
        ['slug' => ElementHelper::createSlug('new-slug')],
        [
            'elementId' => $elementId,
            'siteId'    => $siteId
        ]
    )->execute();

By the way the following condition [] !== $entry won't be any good when you fetch an element with one() because one returns an object of instance ElementInterface or null but never an empty array. You can check !== null instead and if you fetch things via all you can perform an empty check if( empty($entries) === false)


Accessing custom fields from User Model I have a User entries field called 'company'.
I'm writing a bespoke plugin to manage users in the front-end and was wondering how I can access the content of this field in my plugin via the user model?

Any thoughts as struggling a wee bit here!

Response via Slack from Brandon Kelly:

  Accessing custom field values from PHP is the same as in Twig - once you have the UserModel it's just $user->myCustomFieldHandle
  or $user->myEntriesField->first(), etc.

Managed to get via following: $user->company->first()->title


Asset routing issue in combination with slug and date Normally I add images to a post through a field for it, but now I thought I'd just use the uploader in the text/newspost field. However, this gives me the following problem.

When on index.htm for the blog channel the image is shown.

http://inquisimunda.evinwijninga.com/uploads/Facebook-Banner.gif

When I go to the the posts page itself however, the post isn't shown as it can't be found. It also isn't shown in the text editor when I edit the post. (Broken image link).

http://inquisimunda.evinwijninga.com/article/2015/uploads/Facebook-Banner.gif

I have never tried to fix routing issues before as I had never had any issues like this before.

Is there a quick fix for this?

The mistake I made was entering "uploads/" in the url in file management. This should be "/uploads".


Category conditionals I have an entry page that lists out specific info for a product. I am using categories to sort the entries. I'm trying to figure out how to write a conditional that pulls in something specific if the entry belongs to a specific category.

The category field returns an ElementCriteriaModel, which means you can use all the methods that you'd usually use to get a specific category on it.

For instance, if the category field is named entryCategories, and you know the slug of the category you want to test for, you could do:

{% if entry.entryCategories.slug('my-category-slug').total() %}
    Do something
{% endif %}

Or you could use the idthe same way.

Please note, this does not work if the entryCategory field was eager-loaded, since entry.entryCategories would then return an array. In that case you could just loop over the array and have a check inside for loop that checks the category you're looping over is the correct one. A bit dirty, but it does the job.


Craft Install Hangs on Locale Record Installing Craft-2.4.2723 on Centos 6.5 MySql 5.6.27 PHP 5.4.45 gets hung in 'Oops' monkey screen. Minimum requirements are met. Permissions are wide open. Database exists but no tables are created. Collation is set to utf8_unicode_ci. Following is craft.log:

2015/11/13 21:51:08 [warning] [application] Skipping record /var/www/craft/app/records/BaseRecord.php because it’s abstract or an interface.

2015/11/13 21:51:08 [error] [exception.ReflectionException] exception 'ReflectionException' with message 'Class Craft\EntryLocaleRecord does not exist' in /var/www/craft/app/services/InstallService.php:125

Stack trace: 0 /var/www/craft/app/services/InstallService.php(125): ReflectionClass->__construct('Craft\\EntryLoca...')
1 /var/www/craft/app/services/InstallService.php(47): Craft\InstallService->findInstallableRecords()
2 /var/www/craft/app/controllers/InstallController.php(159): Craft\InstallService->run(Array)
3 /var/www/craft/app/framework/web/actions/CInlineAction.php(49): Craft\InstallController->actionInstall()
4 /var/www/craft/app/framework/web/CController.php(308): CInlineAction->runWithParams(Array)
5 /var/www/craft/app/framework/web/CController.php(286): CController->runAction(Object(CInlineAction))
6 /var/www/craft/app/framework/web/CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
7 /var/www/craft/app/framework/web/CWebApplication.php(282): CController->run('install')
8 /var/www/craft/app/etc/web/WebApp.php(805): CWebApplication->runController('install/install')#9 /var/www/craft/app/etc/web/WebApp.php(772): Craft\WebApp->_processActionRequest()
10 /var/www/craft/app/etc/web/WebApp.php(193): Craft\WebApp->_processInstallRequest()
11 /var/www/craft/app/framework/base/CApplication.php(184): Craft\WebApp->processRequest()
12 /var/www/craft/app/index.php(62): CApplication->run()
13 /var/www/html/index.php(19): require_once('/var/www/craft/...')
14 {main}

REQUEST_URI=/index.php/admin/actions/install/install
HTTP_REFERER=http://myserver.com/index.php/admin/install

2015/11/13 21:51:08 [error] [application] Class Craft\EntryLocaleRecord does not exist

It appears that it's not being passed the 'Locale' record. Any ideas on this?

Does EntryLocaleRecord.php exist in craft/app/records?  My guess is that it didn't copy/FTP up to your server properly or its corrupted.

I'd try re-uploading the entire craft/app folder to make sure there aren't others missing.


Help with admin panel errors. Fresh install. Mysql version issue? I get this on the admin panel:
CDbException

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #18 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'craftcms.structureelements.root' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by. The SQL statement executed was: SELECT elements.id, elements.type, elements.enabled, elements.archived, elements.dateCreated, elements.dateUpdated,
.....

There's a long trail in the apache error log. here's a snippet.
2017/04/27 04:46:46 [trace] [system.db.CDbConnection] Opening DB connection
in /var/www/craft/app/etc/behaviors/AppBehavior.php (871)

Env details:
Ubuntu 1.04 (fresh digital ocean vps)
php - PHP 7.0.15-0ubuntu0.16.04.4 (cli) ( NTS )
mysql - 5.7.17-0ubuntu0.16.04.2

You need to tweak your MySQL 5.7.5+ config for it to play nicely with Craft.

MySQL 5.7.5 changed the behaviour of the GROUP_BY statement, affecting some of the core Craft queries.

The preferred solution is to add the following to your /etc/mysql/conf.d/sql_mode.cnf file:

[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

This Craft Cookbook recipe provides additional information about the problem, and the possible solutions.


MultiAdd - Add a related product by checkbox Using the MultiAdd plugin, I'm trying to add a related product using a simple checkbox. It's an add on to the existing product.

Here's a screenshot of what it looks like on the page…

I want the related product to:

be added when the checkbox is ticked and vice versa when not ticked
have the same quantity as the parent product

Here's is the relevant code inside my variant loop:

<form method="POST" id="addToCart">
<input type="hidden" name="action" value="multiAdd/multiAdd">
<input type="hidden" name="redirect" value="shop/cart">
{{ getCsrfInput() }}

{# Code For Related Product #}
{% if relatedProduct | length %}

        {% for product in relatedProduct %}
            {% set variant = product.defaultVariant %}

                <input type="checkbox" name="items[addon][purchasableId]" value="{{ variant.id }}" checked="checked">
                {{ variant.title }}
                +{{ variant.salePrice | commerceCurrency(cart.currency) }}
                {% if variant.onSale %} {{ variant.price | commerceCurrency(cart.currency) }}{% endif %}

            <input type="hidden" name="items[addon][qty]" value="1">
        {% endfor %}

{% endif %}

{# Code For Product #}
<input type="hidden" name="items[product][purchasableId]" value="{{ purchasable.id }}">
<select id="quantity-standard" name="items[product][qty]" class="quantity">
    {% for i in 1..50 %}
        <option value="{{ i }}"{% if loop.first %} selected{% endif %}>{{ i }}</option>
    {% endfor %}
</select>
<input type="submit" class="buy-now" value="{{ "Add to cart"|t }}">

The challenges I'm facing are…

I don't know how to set the related product's quantity to zero when the checkbox isn't checked
I don't know how to set the related product's quantity to match the parent product when the related product is checked

Any help would be appreciated!

From the multiAdd perspective, it only cares that each item you're adding to the cart has some qty - if 0 it will ignore it, if anything positive, it will add that many to the cart, i.e. you only need to see things up such that for each product the minimum info required (for each product that's part of this multiadd process) is:

items[someKey][qty]

items[someKey][purchasableId]

....where of course someKey is the same value for both those inputs.

In terms of how you achieve what you want, that's more of an html form/JS question.  The most obvious approach would be to use some simple JS to listen on the submit event.  If at submit the checkbox is unchecked, you just poke a 0 into the val for that input.  If it is checked, you take the main product's qty valuie and poke that into the input.

To debug this, make sure you check your POST values after the JS is run to check you're submitting what you think you are...in the end what needs to be submitted is super simple as per the above - the only tricky part is the JS to hook it up really.


Best method to handle %20 in tag URLs with multiple words On my page of all tags, it works great except for tags that have more than one word.
The URL is replacing the spaces with %20 as one would expect.

http://www.colorcomputergames.com/tags/

I tried using:

{{ siteUrl }}tags/{{ tag.title | kebab }}

This works great in changing the %20 to hyphens.
However, if I click on a tag with multiple words I go to page not found. Makes sense as the system doesn't see that tag.

  {% extends "_layout" %}
    {% set title = "Tags" %}
    {% block content %}
    {% for tag in craft.tags.order('title') %}

{{ tag.title }}

    {% endfor %}
    {% endblock %}

So next I tried:

{% extends "_layout" %}
{% set title = "Tags" %}
{% block content %}
{% for tag in craft.tags.order('title') %}

{{ tag.title }}

{% endfor %}
{% endblock %}

But that wasn't ideal either.

What is the best way to deal with this issue?

Update.

After looking at the tag model a little more closely, it looks like tags have both a title and slug — so if you use the slug to construct your url then you shouldn't have that problem.

For your tag index:

    {% for tag in craft.tags.order('title') %}

{{ tag.title }}

    {% endfor %}

In your tag index page (assuming you are using the tag token in your custom route):

{% set tagEntry = craft.tags.group('myTagGroup').slug(tag).first %}
{% set entries = craft.entries.relatedTo(tagEntry).order('title').limit(null) %}


Get latest assets added to structure I have a structure which is  basically categories of Downloads.
In each Entry there is an "Files" field where multiple assets can be selected.

On a Summary page I want to display the latest assets added.
How can I pull these?

It's as simple as passing dateCreated into the order parameter, like so:

{% set downloads = entry.files.order( 'dateCreated desc' ) %}

If you're showing these from multiple entries you'd need to get all assets that relate to those entries and then order them as above. Something like:

{% set downloads = craft.assets.relatedTo( entries ).order( 'dateCreated desc' ) %}


DB back-up gives syntax errors on import in new DB I had this issue on two different sites on two different occasions and hosts.
When creating a database back-up through the Craft CMS admin and importing that SQL file into a new database through PhP MyAdmin I get syntax errors and import stops.

I tried backing up the database on both sites through the hosting company itself, which resulted in one backup working and one also giving the syntax error.

I just updated the sites to Craft 2.6.x.

Any ideas what goes wrong or how I can solve this? Do I need to manually go through the whole SQL file and fix the syntax errors manually? :/

When I open the SQL file in PhPStorm, it looks like the character where the error happens, all the SQL statements coming behind it are escaped wrong, they are shown as normal text. Maybe an encoding issue?

As Brad replied as a comment, the issue was indeed PhPMyAdmin. Using NaviCat or updating my PhPMyAdmin resolved the issue.

Answer points go to Brad!


Front End entry form, mapping a hidden field to a plugin? I'm not entirely sure if this is possible, or the right way to go about this, however here goes.

I have a front end entry form that members use to create entries. These entries contain location data. I'm looking at using a maps plugin but nothing out there supports front end directly. I'm currently testing Squarebit Maps. (Smartmap is next!)

Now, from checking out the db, Squarebit Maps stores it's field data in the craft_content table in a format like so:

{"mapLat":"50.89150121867578","mapLng":"-1.4487441291137202","mapZoom":"15","pinLat":"50.89150121867578","pinLng":"-1.4487441291137202","__model__":"Craft\\SquareBitMaps_MapModel"}

I was wondering, if I included a map for users to choose a location within the front end form using something like Geocomplete could I pass through the lat & long in a hidden field to the squarebit field?

Hope that makes sense?

It's probably too late to help the OP (sorry @shorn), but here's how you would pull this off with Smart Map...

Add the Address field on the front-end.

Street Address
<input type="text" name="fields[myAddressField][street1]" value="">

Apartment or Suite
<input type="text" name="fields[myAddressField][street2]" value="">

City
<input type="text" name="fields[myAddressField][city]" value="">

State
<input type="text" name="fields[myAddressField][state]" value="">

Zip Code
<input type="text" name="fields[myAddressField][zip]" value="">

Country
<input type="text" name="fields[myAddressField][country]" value="">

Latitude
<input type="text" name="fields[myAddressField][lat]" value="">

Longitude
<input type="text" name="fields[myAddressField][lng]" value="">

Then, you can inject the lat and lng values using JavaScript. Since you're doing that dynamically, you could even make those inputs hidden.

That's it!


import _self throwing ElementCriteriaModel could not be converted to string {% import _self as mcr_home %}

is throwing

  Object of class Craft\ElementCriteriaModel could not be converted to string

How is this possible and how do I fix it?

In short, those two have nothing to do with each other. What's more likely is that the error is being triggered by the imported script. It's possible that your stack trace is just giving you a red herring by pointing to the import itself.

In your Twig code:

import pulls in a macro (or macros).

_self just means "this template file".

"mcr_home" is just how you're referring to your imported macro(s).

In the error message:

An ElementCriteriaModel is simply a model representing a Craft content search.

"could not be converted to string" is telling you that the model cannot be read as a string.

Obviously there is no correlation there. Take a closer look at the macro(s) you are importing... I'm certain you will find an ElementCriteriaModel which is attempting to be used as a string.


Only execute twig block if a Matrix radio has a certain value I have a scenario where I'm using a Matrix to store and output 'sponsored links' for a page. Each link also has a radio button to select whether to display in a left hand column or a right hand column group.

Filtering like this is simple enough:

LEFT COLUMN TITLE

{% for sponsor in sponsors.sponsors %}
    {% if sponsor.grouping == "Left column" %}

    {% endif %}
{% endfor %}

...

RIGHT COLUMN TITLE

{% for sponsor in sponsors.sponsors %}
    {% if sponsor.grouping == "Right column" %}

    {% endif %}
{% endfor %}

This works, but it will always spit out a wrapping div and section heading, even if there is no content. How do I test to see if there's anything to spit out first?

You can filter Matrix blocks on field values – in your case, the field "grouping":

{% for sponsor in sponsors.sponsors.grouping( 'Left column' ) %}

To conditonally output the whole wrapping div and section heading for the left and right aligned sponsors respectively, you can sort the sponsors into two arrays (left and right) beforehand, and then check the length property of those arrays before outputting the relevant markup.

Full example:

{# Pull all sponsors from the Matrix field #}
{% set sponsors = entry.sponsors.type( 'sponsors' ) %}

{# Filter sponsors into two arrays by "grouping" field value #}
{% set sponsorsLeft = sponsors.grouping( 'Left column' ) %}
{% set sponsorsRight = sponsors.grouping( 'Right column' ) %}

{# I can haz sponsors in the left column? #}
{% if sponsorsLeft | length %}

LEFT COLUMN TITLE

    {% for sponsor in sponsorsLeft %}

            {{ sponsor.sponsorName }}

    {% endfor %}

{% endif %}
...
{# I can haz sponsors in the right column? #}
{% if sponsorsRight | length %}

RIGHT COLUMN TITLE

    {% for sponsor in sponsorsRight %}

            {{ sponsor.sponsorName }}

    {% endfor %}

{% endif %}


Sprout Forms - Possible to reduce available field types in form builder Is it possible to reduce the available field types that can be used in the Sprout form plugin form builder section.

It would be useful to not let my clients be able to select the Matrix or Tags fields amongst others.

Sprout Forms for Craft 3 only displays fields that can be used on the form.

Craft 2 answer:

In Sprout Forms for Craft 2, it is not possible to toggle the visibility of the fields available, it displays all fields that can be received by the form.

Sprout Forms does break out the fields listed into option groups, so with a training-based approach, you could show a client that only the Standard Fields are supported and that all the Custom Fields require a developer to get implemented properly.

Another approach could be to use a plugin like Control Panel CSS and hide the Custom Fields option group:

.sprout-field-modal .fieldtoggle [label="Custom Fields"] {
  display: none;
}


Cached template content not invalidating My understanding of the {% cache %} tag is that if the content between it changes, the cache is invalidated and you see the new content.

I'm having an issue where a new entry is created in section, but it doesn't show up on the front-end unless I manually clear the cache in the control panel.

The content is pulled in via a loop such as:

{%  for entry in craft.entries.section( "news" ).limit(3) %}

Am I not understanding how this tag works or is something going wrong?

Edit: Here is the full code block wrapped by cache tags

{% cache %}
{%  for entry in craft.entries.section( item.nameId ).limit(3) %}

{{ entry.title }}

                    {% if item.type == "video" %}
                        {% set iconType = "icon-video" %}
                    {% elseif item.type == "game" %}
                        {% set iconType = "icon-games" %}
                    {% elseif item.type == "image" or item.type == "imageGallery" %}
                        {% set iconType = "icon-image" %}
                    {% else %}
                        {% set iconType = "icon-paper" %}
                    {% endif %}

{% endfor %}
{% endcache %}

The strange thing that I'm noticing is if I add an entry it never shows up, but if I delete one it does get cleared out. And deleting an entry then causes the new one to show up.

UPDATE: Craft support determined there was a bug and plans to fix it in the next version. Current version is Craft 2.1 build 2563.

When new elements are created, there’s no way for Craft to immediately know which template caches should be cleared. That’s where the Delete Stale Template Caches task comes in. It loops through all of your caches that included element queries, re-runs the queries, and checks to see if the new element is now included in the results.

There are two things to be aware of, though:

Your element query must happen inside the {% cache %} tag pair.

bad:

{% set entries = craft.entries.section('news').limit(3) %}
{% cache %}
    {% for entry in entries %}
        ...
    {% endfor %}
{% endcache %}

good:

{% cache %}
    {% set entries = craft.entries.section('news').limit(3) %}
    {% for entry in entries %}
        ...
    {% endfor %}
{% endcache %}

The cache querying is not immediate. After saving the entry you will see a little progress bar in the CP header. You need to wait until that has completed before your caches will be cleared.


Central Craft CMS management for agencies We have now more than 60 active website running on Craft CMS and have been able to keep our lives somewhat straightforward when it comes to the development side of things (eg. code repository access, deployment, etc).

The main challenge we are still faced with: how to central access or authentication (eg through groups in Google or AD) to the individual sites without having to create/delete users on each and every site when a new team member joins/leaves (too much effort) and without using a single login for all team members (too insecure)

Other challenges
- how to have an overview of CraftCMS version installed on production
- how to know centrally what plugins are used and what versions

I'm sure other agencies also have similar or other needs, what are yours?

To your first problem there is a plugin to handle Single-Sign-On here: https://plugins.craftcms.com/saml-sp I've used it successfully with Azure AD, it will be expensive for 60 sites, but perhaps it's worth talking to flipbox factory

On the updates side, there is a plugin that will notify you by slack or e-mail when something needs updating: https://github.com/lukeyouell/craft-updatechecker


P&T Contact Form plugin: How to display error messages in other languages via Ajax The validations error message get displayed in main language instead of being translated, you can try here (contact form at bottom):
http://lequartiergeneral.be/en/

The form is being displayed and get response via Ajax.

How to display them correctly in each language?

Thanks

Well, the problem was that I was posting my Ajax request to / from all languages, therefore the site replied back with the site main language, which was French in my case.

The following finally works:

// Get the proper url to post to

if ( '{{ craft.i18n.getCurrentLocale() }}' == '{{ craft.i18n.getPrimarySiteLocale() }}' {
     var url = '/';
} else {
     var url = '/{{ craft.i18n.getCurrentLocale() }}/';
}

// Send it to the server

$.post(url, data, function(response) {
     .......
});


entry edit no other content area unless title? I am a newbie of Craft CMS. I installed it on my localhost.

I added a few sections and fields to test it when I go to Entries, create and edit the entry, there is just a title input area?

Is that normal?

Or I need to add code in the backend files? I did not find a way to add it from the online documents.

thanks.

You need to add the fields to the section.
If you go into Sections then over at the right side you can edit the entry type there.
Drag the fields up to the top area to select the fields for that entry.

See https://docs.craftcms.com/v3/sections-and-entries.html#entry-types


Redirect to inferior So how do i redirect to error/inferior template.  I could add my template at the templates folder but thats not really nice.  Is there something like {% exit 404 %} but for the inferior page?

Without knowing if this a channel, structure or single and no provided code I can't give you a detailed answer, but I think you are looking for Craft's redirect tag.

Redirect Tag


Manually passing page number to paginate tag {% paginate %} tag takes current subpapage number from url address. Can this behaviour be bypassed and page number be passed directly into {% paginate %} tag?

If you're looking to display a set of Elements that simulate a paginated query, you might actually be looking for the offset Query parameter.

Here's an example of fetching a “page” of results based on a number of entriesPerPage and the number of pagesToSkip:

{% set customPageOfEntries = craft.entries()
    .offset(entriesPerPage * pagesToSkip)
    .limit(entriesPerPage)
    .all() %}

Of course, this doesn't include the ability to see how many pages of results you have, or to generate links to other pages of results.