if / elseif from base template I have a hero textbox that I would like to control from the base template using a simple if/elseif.

I have a field called "hero" for the homepage. For pages in the "Small Groups" section, I want the hero to say "Groups." For everything else, I want it to be the entry title.

It seems straightforward, but this isn't working? It is ignoring the elseif.

{% if entry == craft.entries.section('homepage') %}
    {{ entry.hero }}
{% elseif entry == craft.entries.section('smallgroups') %}
    Groups
{% else %}
    {{ entry.title }}
{% endif %}

Your issue is probably that you're actually comparing an EntryModel (entry) to an ElementCriteriaModel (the array-like object used for querying entries, which is returned by the craft.entries call).

Something like this should do it:

{% if entry.section.handle == 'homepage' %}
    {{ entry.hero }}
{% elseif entry.section.handle == 'smallgroups' %}
    Groups
{% else %}
    {{ entry.title }}
{% endif %}

Assuming your section handles are correct, the above should work – although this is a perfect use for using the {% switch %} tag instead of {% if %}, which in my opinion would make your code more readable:

{% switch entry.section.handle %}
    {% case 'homepage' %}
        {{ entry.hero }}
    {% case 'smallgroups' %}
        Groups
    {% default %}
        {{ entry.title }}
{% endswitch %}


display entries inside nav I'm building an overview page that will show a title, thumbnail, etc of the pages inside the structure. I want the nav children to start at the parent page we're currently on. I can get the correct elements to display - they just don't have any entry data like title.  If there's a better way to approach this let me know.

{% set overview = (entry.level == 1) ? entry : entry.getAncestors().level(1).first() %}

{% nav entry in overview %}

{{ cycle(['
', '', '', ''], loop.index0)|raw }}

            {% for block in entry.contents.type('image').limit(1) %}
            {% if block.image | length %}
            {% for image in block.image.limit(1) %}

            {% endfor %}
            {% else %}

            {% endif %}
          {% endfor %}

{{ entry.title }}

        {% ifchildren %}
                {% children %}
        {% endifchildren %}

  {{ cycle(['', '', '', '
'], loop.index0)|raw }}

 {% endnav %}

You don't necessarily need to use the nav tag, you can just spin through the entries in a normal {% for entry in entries %} loop, making use of the level property and the getDescendants method.

There are some good suggestions for more complicated nav code in this answer:

How do you handle complex navigation in Craft?

and there's some good pointers in the answers to this question:

Custom or complex nav tag


How to setup assets in multi site where each site should have its own assets? I have a setup with multi sites that are separate domains.

site-a.com

site-b.com

I would also like to have assets separate for each site, like so:

site-a.com/images/picture1.jpg

site-b.com/images/picture2.jpg

I tried setting up aliases for each site, but just couldn't get it to work.
Managed to get only one set of aliases to work, in the general.php file, under '*'.
But cannot get aliases to be different for each site, like @web for example.

How would i setup the general.php or volumes.php or env.php to have separate assets for each site?

Additional notes:

I am using the latest version of Craft 3 (Craft CMS 3.0.23.1).

PHP 7.2

The setting "Propagate entries across all enabled sites?" in section is enabled.

The setting "Manage relations on a per-site basis" for asset field is enabled.

When you're creating a new local asset volume, you choose a file system path. I use both the site handle and the section handle in the path. For example:

/assets/<SiteHandle>/images/<SectionHandle>

Or, referencing your example (and using 'blog' as a section in your site):

/assets/site1/images/blog

I find that it's important to divide up the assets this way so that if you need to migrate content or backup, it will be much easier to figure out which assets go with which content.

If the sites share images in common (eg. social icons), I usually make a common folder to hold these above the site level in assets:

/assets/common/images

But I ultimately recommend that instead of local storage, you use Amazon S3 Buckets. It's relatively simple to set up and you'll see much better performance from Amazon's CDNs. You can use this same concept outlined for local files on Amazon S3.


Send a custom field by email Is there anyway to send a custom field by email? For example if a customer were to enter a shipping note and submits an order is there a way to send that note to an email address?

Best way to do this would be creating a small plugin (recommended on every Commerce install, to be able to easily extend it). In this plugin's init method, you could listen to the OrderComplete event and send the mail. This is untested, but should get you started:

public function init()
{
    craft()->on('commerce_orders.onOrderComplete', function($event) {
        $order = $event->params['order'];
        $note = $order->getContent()->shippingNoteFieldHandle;

        if ($note) {
            //Send Mail
            $email = new EmailModel();
            $email->toEmail = 'address@tospam.com';
            $email->subject = 'New order completed';
            $email->body    = $note;

            craft()->email->sendEmail($email);
        }
    });
}

You can use pluginfactory.io to quickly create a plugin, then put the init method in the plugin's base class.


Multi-Domain routing We are launching 2 different sites, using the same craft installation on multiple domains.

a.com and b.com

a.com points to the main craft install

b.com should point to a subpage/single in this same craft install.
(So basically could be reached via a.com/subpage

What is the best craft internal way of doing this?

I know there is mod proxy..but we wanna handle it internally. So basically different "start" points for different domains or subdomains.

Thanks in advance.

To do this, copy index.php and .htaccess from a.com’s webroot into b.com’s, and make sure the $craftPath variable is correct.

Then, around where $craftPath is getting defined, override $_GET['p'] to make Craft think that the URI actually started with subpath:

$craftPath = '../craft';

$_GET['p'] = 'subpath/' . (isset($_GET['p']) ? $_GET['p'] : '');

// ...

Now when you go to b.com/*, it will be the same as going to a.com/subpath/*.

If you want traffic going to b.com to stay on b.com, you will also need to make sure a.com/subpath is replaced with b.com in any Craft-generated URLs:

{{ url('foo')|replace('a.com/subpath', 'b.com') }}

That will also affect links on a.com, though. If you still want traffic on a.com/subpath to remain on a.com, then it’s slightly more complicated. In your craft/config/general.php file, add a custom domain config setting that varies depending on the requested domain:

return array(
    '*' => array(
        // ...
    ),
    'a.com' => array(
        // ...
        'domain' => 'a',
    ),
    'b.com' => array(
        // ...
        'domain' => 'b',
    ),
);

Then in your templates, only run that str_replace filter when the domain is b:

{% set url = url('foo') %}
{{ craft.config.domain == 'b' ? url|replace('a.com/subpath', 'b.com') : url }}


Does Craft have a bookmarklet to quickly post/save content from the web? Does Craft have a bookmarklet that allows you to quickly post images, text, videos or any other content from web pages to Craft entry types/fields?

Nothing from P&T and I haven't seen one floating around the web, either.


February always comes out as March - expect /yyyy/mm to be 2018/02 but it's 2018/03 This is a site that was recently updated from Craft 2 to Craft 3 and before the update this issue did not occur.

Here is the code:

{# all entries sorted by year/month #}
 {% set allEntries = craft.entries.section('photoblog').limit(null).orderBy('postDate desc').all() %}

    {% for year, entriesInYear in allEntries | group("postDate|date('Y')") %}

{{ year }}

          {% for month, entries in entriesInYear | group("postDate|date('F')" ) |  reverse %}

{{ month }}&nbsp;({{ entries|length }})

          {% endfor %}

    {% endfor %}

Everything works correctly except for February which always outputs 03 and not 02 as expected.

If you go to https://sean-smith.net/calendar and hover over any February link you'll see that the link is set to March inexplicably.

I think the problem is that you are not being specific enough with the date that you are passing to the date function. You are in effect calling date("February") and the PHP date function has to make an assumption and uses the current day of the month, i.e. February 30 which equates to March. If this is correct you will have even more issues tomorrow being the 31st!

If you make the date being passed more specific i.e. February 1 it should work fine.

A related PHP bug post, that wasn't a bug, explains it https://bugs.php.net/bug.php?id=49115


How to replace a html entity within script tags using Craft replace Apologies if this has been asked before, I can only find questions dealing with the reverse scenario (i.e. replacing special characters with html entities)

I need to output special characters as part of a JavaScript array using Craft. Currently the values are output with all special characters replaced by their html equivalent. (e.g.: ampersands are replaced by &amp )

I have tried restoring the special characters using craft replace but without success.

The following code works to replace text, but does not, for example, replace &amp with &, or rather perhaps it does not distinguish these values as distinct.

<script>

    var myVariable = [{% for value in myArray %}"{{ value|replace('raw-html-entity', 'special-character') }}"{%- if not loop.last -%},{% endif %}{% endfor %}];

</script>

This code is being used for an array which is used for jQuery autocomplete values, so raw html is not appropriate.

Any suggestions appreciated.

I have a Craft Helpers plugin on GitHub, which has a htmlEntityDecode Twig filter.

{{ value|htmlEntityDecode}}


Link Popup Modal to correct script in loop Popup Closed Screenshot

Popup Open Screenshot

I have image that has multiple markers on it that can be clicked to bring up different popups. However, I need to some help refining the code to work properly and to link to the correct id tag.

My template code:

{% set var = craft.entries.section('availablehomes').relatedTo(category).level(2) %}
{% for entry in var %}

{% set plotPopup = 'plotPopup' ~ entry.title|camel %}

....markup.......

{% endfor %}

Which outputs

...

...

...

...

And below is the current script text:

Which is printing out as:

This is just a JavaScript problem. You have to add an event listener to the marker which opens the corresponding popup.

I put together a little example on JSBin here: https://jsbin.com/tigefikalu/edit?html,js,console,output

Hope that helps with the logic.


Cannot call service: "'MyPlugin' not found" error I'm sure this is a trivial mistake but I can't figure it out (first-time plugin dev).

I have my plugin running with all code in the controller and want now follow best practice and move the workhorse code into a service class.

My main plugin code is

namespace ns\yutulic;
use ns\yutulic\models\SettingsModel;
use craft\models\Section;

public function init() {

    parent::init();

    self::$plugin = $this;

    $settings = $this->getSettings();
    $settings->sectionOptions = $this->setSectionOptions();

    // Register services
    $this->setComponents([
        'videoentries' => \ns\yutulic\services\VideoEntriesService::class,
    ]);

    $data = $this->videoentries->scanForVideos(null); // works

}

The relevant controller code is

Class ScanController extends Controller {
    public function actionScanEntries() {
        // Neiter works :-(
        //$data = Yutulic::$plugin->videoentries->scanForVideos($id);
        $data = Yutulic::getInstance()->videoentries->scanForVideos($id); // (*)
    }
}

And my service code:

<?php
namespace ns\yutulic\services;
use ns\yutulic\Yutulic;
use Craft;
use craft\base\Component;

class VideoEntriesService extends Component
{
    public function scanForVideos($sectionId = null) {
        echo "Works!!!";
        return null;
    }
}

Even if I use the example of the docs it fails with the same error message on the line indicated (*) in the controller (but with the 'Foo' class name):

Class 'ns\yutulic\Yutulic' not found

This shouldn't be so hard?

I found the issue. The author of the tutorial I copied my first code from made the unfortunate choice to not use a proper plugin class:

class Plugin extends \craft\base\Plugin { ... }

To fix the problem, I replaced this line with

use Craft;
use craft\base\Plugin;
class Yutulic extends Plugin { ... }

and had to add a reference to the class to my controller and service modules:

use ns\yutulic\Yutulic;


Craft Commerce - Different confirmation email address for different product types or category On a website I will be setting up there will be different ranges/types of products.
Basically purchased from different departments within the organisation.

I can filter the products in different ways - either by a category or product type of whatever.
But is there any way to change where the confirmation email goes to.
E.g. All confirmation emails go to finance@domain.com

But if a item is purchased from Category A/Product Type A the confirmation email also goes to deptA@domain.com

An item purchased from Category B/Product Type B - the confirmation email goes to deptB@domain.com

Is this functionality easily achievable or will some sort of plugin be required?

Should be pretty doable with a small plugin.

You'd want to listen to something like the onOrderComplete event, then loop through the line items making note of which product types the line items belong to, adding email address to an array to send to.

Then at the end, you can loop through your email address sending the appropriate emails out to each of the users.


returning HTML in $event->sender->addErrors doesn't work I have a plugin which is checking if there is a duplicate entry before save. I'm trying to give the user back an anchor to the entry which exists so my client can switch without searching for it in a giant structure.
I have this code
$event->sender->addErrors([
    'expiryDate' => 'cpEditUrl.'>'.$entry[0]->title.''
]);

But somehow I can't render the HTML correctly in the Control Panel, it's getting displayed as plain tekst. Is there any way to achieve this?

Allright, after digging & debugging a bit further into this issue I found it out myself!
$event->sender->addErrors([
    'expiryDate' => Template::raw('cpEditUrl.'>'.$entry[0]->title.'')
]);

PS: don't forget to add this to the top of your php file:
use craft\helpers\Template;


Creating entries loop with nth loops across unordered lists I'm looking for some help with the most efficient and performant way to generate this loop.

| COL 1 | COL 2 | COL 3 |
|   1   |   2   |   3   |
|   4   |   5   |   6   |
|   7   |   8   |   9   |
|   10  |   11  |   12  |

Columns here are unordered lists and I want to ordered by postDate going across each column. It needs to be done this way as specific to the design of the page.

I've tried batch, slice , loop indexes and experimented with range. Tried 3 different craft.entries loops to generate the columns.

What I would really need if it existed was offset and nth if nth didn't terminate.

I'm guessing answer will be something like creating these arrays outside of final entries loop and passing in IDs?

I tried a simple solution using javascript, you can translate the code into twig looping. I hope it helps.

const posts = [1,2,3,4,5,6,7,8,9,10,11,12];
const colNum = 3;
const rowNum = posts.length/colNum;

for (i=0 ; i<rowNum ; i++) {
 const row = [];
 for (j=0; j<colNum; j++) {
   row.push(posts[(i*colNum) + j]);
 }
 console.log(row)
 console.log('----')
}

output :

improve solution using twig

@JohnHenryDonovan ah sorry, I didn't notice the batch filter. Why don't you sort the entries first, then batch them?

I assume you use bootstrap as CSS lib, then you can apply d-flex on each row.

{% set projects = craft.entries()
      .section('project')
      .orderBy('postDate desc')
      .all() %}

{% set grouped = projects|batch(3) %}
{% for row in grouped %}

   {% for column in row %}

   {% endfor %}

{% endfor %}

The output of the code above

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

 ...

jsfiddle HTML output http://jsfiddle.net/30k9ndg6/3/


Exchange Content between Local and Production Often I want to test in my local environment with content other people created on the production site. So it would be great to copy e.g. an entry from production.

I've found:

Smith https://plugins.craftcms.com/smith for copy, pasting, and cloning of matrix blocks, but unfortunately only within one Craft installation.

Is there a smart way to quickly exchange content from production with a local dev environment and vise versa?

You may have a look at this article and the scripts introduced there. It basically gives you a console command that pulls the live database or assets into your local environment.

https://nystudio107.com/blog/database-asset-syncing-between-environments-in-craft-cms

The article was written before the project config feature was a thing as far as I know. So watch out for that.


Using a GraphQL mutation to append a block to a Neo field I know how to update simple fields on an entry using a mutation:
mutation updateRecipe($recipeId: ID, $slug: String) {
  save_recipes_recipe_Entry(id: $recipeId, slug: $slug) {
    id
    title
    slug
  }
}
Variables:
{
  "recipeId": 8614,
  "slug":"new-slug"
}

Is there a way to append a block to a Neo field using mutations? I can retrieve the field data in a GraphQL query but have not found a way to update a Neo field with a mutation.
Does anybody have any experience implementing this?
Thanks ...

So the work around was to convert the Neo field to a Matrix. That worked for this instance since we're not storing anything complex but I'd sure like to figure out if/how Neo supports mutations.
mutation addRecipeReview($recipeId: ID, $blocks: [reviews_MatrixBlockContainerInput] = {review: {authorEmail: "", authorName: "", authorReview: "", reviewDate: "", reviewRating: ""}}, $sortOrder: [QueryArgument] = "") {
  save_recipes_recipe_Entry(id: $recipeId, reviews: {blocks: $blocks, sortOrder: $sortOrder}) {
    id
    reviews {
      ... on reviews_review_BlockType {
        id
        authorEmail
        authorName
        authorReview
        reviewRating
        reviewDate
      }
    }
  }
}

Variables:
{
  id: "1234",
  sortOrder: ["4321", "4322", "new:1"],
  blocks: [
    {
      review: {
        authorName: "Author Name",
        authorEmail: "Author Email",
        authorReview: "Review",
        reviewRating: "Rating",
        reviewDate: "Date Submitted"
      }
    }
  ]
}

The odd/silly part about the above is that you have to pass in an array of all the existing block IDs to sortOrder, and use the idiom "new:1" for your new block. If you skip the "new:1" it won't add the new block, and if you only pass in "new:1" but omit the existing block IDs it deletes all the existing blocks. You can pass an array of new blocks (the code above only has one) in the 'blocks' array, but you'll have to add "new:1", "new:2" ... up to how many blocks you have.


Craft user group permissions I have a group of different regions which would like to have region admins who can't approve content from each other's region but also have a super admin who can approve content from any regions. I will outline below the how this is laid out and would like to know if its possible with Craft.

Super Admin (master admin - approval master)

Region 1 (region admin - approvers)

Location 1 (location admin - drafters)
Location 2 (location admin - drafters)
Location 3 (location admin - drafters)

Region 2 (region admin - approvers)

Location 4 (location admin - drafters)
Location 5 (location admin - drafters)

Region 3 (region admin - approvers)

Location 6 (location admin - drafters)

Super Admin can approve any item created by location admins and region admins.

Region Admins can approve only content created by location admins within their region only

Location Admins can only create drafts

Seems pretty straightforward, unless I'm missing something.

Create the 6 locales; one for each location (settings > locales)
Create user groups (10) and set permissions (settings > users)

Allow location drafters to only 'edit' and 'create', but not 'publish' (for each section)
Restrict location drafters to their respective locale (single locale)
Allow Region Admins to edit, create, and publish (for each section)
Restrict Region Admins to their region locales (more than one locale)
Allow Super Admins to edit, create, and publish (for each section)
Allow Super Admins for all locales

This is assuming of course you have a locale for each location (and not for each region).


Empty relation field validation failed with Guest Entries plugin I am trying to save a entry with the Guest Entries plugin.

The entry has a custom field 'office' thats set to 'entry' a relation to section 'offices'.

<fieldset class="form-fieldset row-spacing-2">
    <select class="form-input form-select" name="fields[office][]">
        <option>Select office</option>
        {% for office in craft.entries.section('offices') %}
            <option value="{{ office.id }}">{{ office.title }}</option>
        {% endfor %}
    </select>
</fieldset>

The field is set to required in the CP. When I save it with the field set it works, but when empty it throws this error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

Can this error be caught or am i doing something wrong here?

Thanks in advance!

It looks like it's doing what it should. When you set a field to 'required', you are basically telling the system to not let the entry be saved if you haven't filled out the field you've set 'required' on. That's what this error saying (albeit at a database level).

Two quick solutions as I see it...

Always make sure you have a default value that can be used for this
field. So you aren't violating the 'required' setting.
Remove the 'required' option from the field in the CP.

EDIT: In the Plugin settings in the CP, have you turned on the Validate Entry lightswitch for the section you are adding to on the front end? Only I've just had a quick play around with the plugin myself, and I get a validation error when I don't submit an entryId for the related section on the front end form. So it looks as though it's working as expected.

I used this to get the errors...

{%for error in guestEntry.getAllErrors %}
    {{ error }}
{% endfor %}

I also just used the default config file guestEntries.php as suggested in the README...

<?php

return array(
    'entryVariable' => 'guestEntry',
);


URL Structure - advise and thoughts of best approach? I am currently building a website for Hot Tubs and within this there will be New Tubs, Used Tubs and Hire Tubs (each will be a top level page on the navigation, and each tub will have a details page). Each tub will only exist in one of the three sections. The templates will be different and so I have decided to go for 3 individual channels.

However, any thoughts from a URL structure/SEO etc on the different approaches to URLS for sections.
I am thinking of either keeping them all separate like so:

www.domain.co.uk/used-hot-tubs/
www.domain.co.uk/used-hot-tubs/name-of-used-tub/

www.domain.co.uk/hot-tubs/
www.domain.co.uk/hot-tubs/name-of-new-tub/

www.domain.co.uk/hot-tubs-for-hire/
www.domain.co.uk/hot-tubs-for-hire/name-of-hire-tub/

Or whether they should all be structure like so?

www.domain.co.uk/hot-tubs/used/
www.domain.co.uk/hot-tubs/used/name-of-used-tub/

www.domain.co.uk/hot-tubs/new/
www.domain.co.uk/hot-tubs/new/name-of-new-tub/

www.domain.co.uk/hot-tubs/hire/
www.domain.co.uk/hot-tubs/hire/name-of-hire-tub/

or

www.domain.co.uk/used/
www.domain.co.uk/used/name-of-used-tub/

www.domain.co.uk/new/
www.domain.co.uk/new/name-of-new-tub/

www.domain.co.uk/hire/
www.domain.co.uk/hire/name-of-hire-tub/

Any input/thoughts appreciated….

EDIT: I should add this is not an eCommerce website, although the structure could lends itself to that and that the top level domain does contain the words hottubs.

I’d go for /hot-tubs/used etc

This way you can also have /accessories/pipes etc


Multiple Entries fields, show empty ones? I am using Entries Field to display related content. I have several Entries Field in an article and i also want to display the fields that are empty, but with their section name.... Is this even possible? I am quite new to Craft, so don't know if I am even in a right direction... Help will be highly appriciated!

{% set assets = craft.entries({
  relatedTo: {
    sourceElement: entry,
      field: ['entry','entry2','entry3']
    },
    order:     "sortOrder",
    limit:     null
  })
%}

{% if assets %}
  {% for asset in assets %}
      {% if asset|title %}
        {{ asset.section.name }}: {{ asset.title }}
      {% else }
        {{ asset.section.name }}: Empty
      {% endif }
  {% endfor %}
{% endif %}

It's probably not possible to get the sections you limited your entries field to from the template and if there's no entry selected that's what you'd need to do.

But what I'd recommend and what's generally a pretty solid approach in such situations is to build an associative array with all the necessary data and loop through that array:

{% set relationsGroups = {
    'entriesField1': 'Heading Relations 1',
    'entriesField2': 'Heading Relations 2',
    'entriesField3': 'Heading Relations 3',
} %}

{% for fieldHandle, heading in relationsGroups %}
    {% set assets = craft.entries({
        relatedTo: {
            sourceElement: entry,
            field: fieldHandle
        }
        order: 'sortOrder',
        limit: null
    }) %}

    {% for asset in assets %}

{{ heading }}: {{ asset.title }}

    {% else %}

{{ heading }}: Empty

    {% endfor %}
{% endfor %}


Entries grouped by Category and then Sub Category Been trying to get this working for a few hours but no joy, hope someone can help.

I'm looking like an post archive of all entries.

Something like

Category1

Sub Category 1

Entry / Entry

Sub Category 2

Entry / Entry

Category 2

Sub Category 3

Entry / Entry

Etc.

Tried with grouping and even tried with a plugin - https://github.com/timkelty/groupby-craft But no luck so far, help greatly appreciated.

You can get the categories to display hierarchically pretty efficiently using the {% nav %} tag:

{% set categories = craft.categories.group('myGroup').find() %}

  {% nav category in categories %}

      {{ category.title }}
      {% ifchildren %}

          {% children %}

      {% endifchildren %}

  {% endnav %}

Then, you can add in the related entries like so:

  ...
  {% endifchildren %}

  {# Are we on the second level of categories? #}
  {% if category.level == 2 %}
    {# Look for any entries that are related to this category #}
    {% set entries = craft.entries.relatedTo({
      targetElement: category,
      field: 'myCategoriesField'
    }) %}
    {# If there are any, then output them in a nested UL #}
    {% if entries|length %}

        {% for entry in entries %}

{{ entry.getLink() }}

        {% endfor %}

    {% endif %}
  {% endif %}

That code suffers from the “N+1” problem though - each 2nd level category is going to need to initiate a new SQL query to fetch the related entries. So rendering this list will require N+1 SQL queries – one query to geth the initial set of categories, plus N, the total number of second-level categories. If you have 100 categories, that’s 101 SQL queries.

To solve this, you’d need to “eager-load” the related entries. Craft doesn’t support that of the box, but Mike Pepper has a nice little plugin called Fetch which makes it possible.  Download and install that, and then you can do the following:

{% set categories = craft.categories.group('myGroup').find() %}
{% do craft.fetch.entries(categories, 'reverse:myCategoriesField') %}

  {% nav category in categories %}

      {{ category.title }}
      {% ifchildren %}

          {% children %}

      {% endifchildren %}

      {# Are we on the second level of categories, and are there any related entries? #}
      {% if category.level == 2 and
            category.fetched('reverse:myCategoriesField')|length %}

          {% for entry in category.fetched('reverse:myCategoriesField') %}

{{ entry.getLink() }}

          {% endfor %}

      {% endif %}

  {% endnav %}


How to check name of a tag Per documentation I am getting a selected tag:

{% set tag = entry.myTagsField.first() %}

How to check if its name is equal to "Flower"?

Your code returns an TagModel and saves it as "tag". You can now get all model properties like this:

{{ tag.property_name }}

In your case it would look like this:

{% if tag.name == 'Flower' %}
    Do stuff
{% endif %}


Filter entries in the CP based on custom permission We started a new project, a website that lists products based on regions (for example US and Europe). We have all products in 1 channel (to make it dynamic to add more regions later on) and have a region field added to those entries (a checkbox field). We now want to hide products for specific users in the CP.

Through this thread I was able to add custom permissions via my plugin and it pointed me towards this event onBeforeBuildElementsQuery that I could use to add my custom filtering.
I think I may need to add a custom param with the value of what the regio field needs to be to the ElementCriteriaModel.

But I have no idea how to build the next steps. I don't really understand what that ElementCriteriaModel returns. It's just a model with all basic attributes, no custom fields or anything. No clear section it targets...

The next steps should be:

Is the event triggered by the CP?
If so, check the logged in user's permissions and decide what regio should be filtered
Add an extra param to the criteria that filters to correct region
Send the changed ElementCriterioModel (or Query) to wherever it needs to go

So, how do I insert a custom parameter into that ElementCriteriaModel and will it alter the entries that are visible in the CP? Am I on the right track here?

After some digging I came up with some answers myself. For future reference, here they are:

Is the event triggered by the CP:

if(craft()->request->isCpRequest()){}

Check the logged in user's permissions:

$userPermissions = craft()->userPermissions->getPermissionsByUserId($user->id);

or use a permission directly:

if($user->can('permissionName')){}

Add an extra param to the criteria that filters to correct region:

$query = $event->params['query'];
$params = array( ':regio' => '["us","eu"]' );
$query->andWhere('content.field_regio LIKE :regio', $params);

Send the changed ElementCriterioModel (or query) to wherever it needs to go:

After setting that query, the function just executes and filters the list.

If you use something like this, make sure you filter out the correct section to check on (because the onBuildElementsQuery is fired on almost everything in the CP). But that's where I stopped my search as eventually, we will not be needing it in this project.


Is it possible to show more entries of the same entry type as the current entry? I'm creating a tumblr-esque blog with a bunch of different entry types.

One of the entry types will be named "Image". When I'm on the entry page for an "Image" entry, I'd like to be able to show 10 more entries with the same "Image" entry type.

Is this possible?

Yes. This is certainly possible.

I'm not sure how you're templating / naming is setup but you can get entries by entry type and you can check an entry's type. To get entries by a specific type:

craft.entries.section('blog').find({type: 'imagePost', limit: 10})

Here's some helpful references for craft.entries:
Entries Cheat Sheet - Craft Docs For the Entry Model

You could structure some kind of comparison, to see if the current entry is a specific type, and if it is query and render the desired additional entries.

{% if entry.type == 'imagePost' %}
  {% for post in craft.entries.section('blog').find({type: 'imagePost'}) %}
...
{% if entry.type == 'textPost' %}
  {% for post in craft.entries.section('blog').find({type: 'textPost'}) %}
...

However there are many ways to do what you want depending on your setup. Please note I used the name imagePost instead of image, to avoid any confusion there might be with a common name like image. I'm not sure if that could cause name conflicts or if it's a reserved keyword / field etc.


Dynamically update line item in Commerce 2 I'm currently trying to adjust the line items in a particular cart/order after an event is triggered.

I've got:

use craft\commerce\Plugin as CommercePlugin;

$this->requirePostRequest();
$request = Craft::$app->getRequest();

$cart = CommercePlugin::getInstance()->getCarts()->getCart(true);

$lineItem = CommercePlugin::getInstance()->getLineItems()->getLineItemById($cart->lineItems[0]->id);

$lineItem->price = 100.0000;
$lineItem->salePrice = 100.0000;
$lineItem->qty = 1;
$lineItem->note = '';

$cart->addLineItem($lineItem);

$cart->email = $request->getParam('orderEmail');

if (!Craft::$app->getElements()->saveElement($cart)) {
   return false;
}

But this seems to not do anything, except update $lineItem and not update the line item when the cart is then saved.

Turns out I just replace:

$cart->addLineItem($lineItem);

With:

CommercePlugin::getInstance()->getLineItems()->saveLineItem($lineItem, false);


Disable activation link email for a specific user group I am developing a website which is having two user groups. The users of first user group will have self activation email with account activation link while second user group will be activated by admin after registration. As there is Users Setting for "Verify email addresses?" but we can't do it for specific user group. Is there any solution for it? Please suggest if possible with plugin.

Off the top of my head, the pseudocode would be something like:

Listen for the EVENT_BEFORE_SAVE_ELEMENT event.
Check if it's a new user registration.
If so, check the user group status.
Apply account activation email logic based on #3.


Filter by multiple categories I need to filter a sections entries by more than one category but only return entries that belong to all category id's passed in a URL parameter.

Now I can get the correct output if the id's are hard coded but not if contained in the URL parameter.

URL: ajax-swatches?cats=171,172,179

{% set catPars = craft.request.getParam('cats') %}

{% set swatches = craft.entries({
    section: 'swatches',
    relatedTo: ['and',catPars]
}) %}

I presume the 'relatedTo' section is treating the 'catPars' variable as a single entry and ignoring the ',' and next values?

Any help would be really appreciated :)

Craft's relatedTo takes a model, an ID, or an array of either of these. So if you're passing '171,172,179' It's probably coming through as a string and only reading the first ID.

Try making it an array and looping through the values:

{% set catPars = craft.request.getParam('cats')|split(',') %}
{% set related = ['and'] %}
{% for catPar in catPars %}
    {% set related = related|merge([{targetElement: catPar}]) %}
{% endfor %}

{% set swatches = craft.entries({ section: 'swatches', relatedTo: related }) %}

Without knowing your setup I don't know if it's actually targetElement or sourceElement. You can also pass in the field name as well if you want to get more specific. See the documentation linked above for the definitions of all of those.


Change asset name on upload public function init()
{
    craft()->on('assets.onBeforeSaveAsset', function(Event $event) {
        $asset = $event->params['asset'];
        $asset->setAttribute('filename', 'new name');
        craft()->assets->storeFile($asset);
    }
    );
}

Here is the code I use in the primary plugin class. This is just a test as i'm learning. I know it should better be in service.
This is supposed to change the filename upon uploading.

Anyway this does nothing, when I upload an asset in the cp, the dialog with progress bars pops up but get stuck.
How should I modify this for it to work ?

First, when you attach event listeners using craft.on, the naming convention for the event name is assets.beforeSaveEntry, not assets.onBeforeSaveEntry (i.e., skip the on part). Both names appear to work, but the former is the one used in the docs and I'd recommend using that.

Second, the reason why your upload "gets stuck" is your call to craft()->assets->storeFile inside the event listener. Basically, that call results in a loop, because craft->assets->storeFile() will fire another beforeSaveAsset event – making your script execute continually before timing out.

As for actually changing the filename on upload; unfortunately, if there's a reliable way to change the asset filename before the asset is saved, I haven't been able to find it.

However, if you can work with the assets.saveAsset event (which is fired after the asset is uploaded and saved on the server), I found a way:

First, set up an event listener for assets.saveAsset. Inside the event listener, you need to check the $event object's isNewAsset property; making sure the filename is only changed the first time the asset is saved and preventing the loop mentioned above.

Concerning the actual filename, there's a couple of issues to consider. For one, the filename needs to be unique (to that particular folder, as least). If you attempt to store an asset with an existing filename, Craft will use the original filename for your upload (I'd expect Craft to either ask if you wanted to replace the existing file, or suffix the filename with a number, but that doesn't appear to be the case). Secondly, the filename needs to include the file's extension (i.e. jpg or pdf). And finally; because this code runs after the asset has been saved and the file is already stored on the server, it isn't enough to set the filename attribute to the AssetFileModel object (i.e. $asset), you'll also need to rename the actual file.

Keeping these issues in mind, here's a working example:

craft()->on('assets.saveAsset', function (Event $event) {

    if ($event->params['isNewAsset']) {

        $asset = $event->params['asset'];

        // Set the filename to a variable, appending the file extension
        $filename = 'filename-'.md5(time()).'.'.$asset->getExtension();

        // Rename the file on the server
        craft()->assets->renameFile($asset, $filename);

        // Set filename attribute and re-save asset
        $asset->setAttribute('filename', $filename);
        craft()->assets->storeFile($asset);

    }
});

Note that in the above example, I'm hashing the current timestamp and adding it to the filename as an easy fix to ensure that it's unique. I don't know how you want your filenames to look or if duplicate filenames would even be an issue in your case, but you could of course implement a solution that tests for duplicate filenames and/or generates unique filenames in a different manner.

To be honest, although the above should work I do feel this solution is a bit convoluted and I wouldn't be surprised if there's a better way – if there is, hopefully you'll have another answer.


Registration email link not being sent I'm using the following form, and occasionally through testing the e-mail activation link will send, however the majority of time it never gets sent. Did I do something wrong with the form?

<form method="post" accept-charset="UTF-8">
        {{ getCsrfInput() }}
        <input type="hidden" name="action" value="users/saveUser">
        <input type="hidden" name="redirect" value="/success/">

        {% macro errorList(errors) %}
            {% if errors %}

                    {% for error in errors %}

{{ error }}

                    {% endfor %}

            {% endif %}
        {% endmacro %}

        {% from _self import errorList %}

Username

        <input id="username" type="text" name="username"
            {%- if account is defined %} value="{{ account.username }}"{% endif -%}>

        {% if account is defined %}
            {{ errorList(account.getErrors('username')) }}
        {% endif %}

Email

        <input id="email" type="text" name="email"
            {%- if account is defined %} value="{{ account.email }}"{% endif %}>

        {% if account is defined %}
            {{ errorList(account.getErrors('email')) }}
        {% endif %}

Password

        <input id="password" type="password" name="password">

        {% if account is defined %}
            {{ errorList(account.getErrors('password')) }}
        {% endif %}

        <input type="submit" value="Register">
    </form>

If you're using phpmail or sendmail under Settings->Email in the control panel, they are notoriously unreliable at delivering emails consistently.

Try using a proper SMTP relay or a transactional email provider like Mandrill.


Get entries that's not already listed I have a bunch of entries in a section called 'artikkel'. The 14 first of these entries are listed out in another section called 'forside'. Now I need to list out the entries that's not already been shown. Printing out the first 14 entries looks like this:

{% for entry in entry.artikkelbolk1.limit(14) %}

{% endfor %}

The rest of the articles that I'm loading in with ajax is like this:

{% for entry in craft.entries.section('artikkel').order('dateCreated desc') %}

{% endfor %}

Of course the last one now prints all the articles that's already been printed before. PS: This is the first time I'm working with Craft.

This is how you're getting your "Forside" articles:

{% for entry in entry.artikkelbolk1.limit(14) %}
    <!--print out article content-->
{% endfor %}

this let me assume you're using an entries field to "collect" articles from your "artikkelbolk1" section.
The Twig syntax you're using is actually a shortcut for this:

{% for entry in craft.entries({
    relatedTo: { sourceElement: entry, field: 'artikkelbolk1' },
    order:     'sortOrder',
    limit:     14
}) %}
    <!--print out article content-->
{% endfor %}

So it get's you all entries related to your current entry, the preset entry model of your "forside" section.

To get all articles not listed on "Forside" you'd do this. First, grab those "forside" entries again, but you're only interested in the IDs
of the entry models, that's why you now append the ids() method. Then join the IDs into a string with the following syntax (use Twig's join filter for that!):

'and, not 42, not 82, not 20'

So it basically lists all entry IDs prefixed with 'not'; the 'and' at the beginning just makes Craft aware that you're listing multiple values. With this string you can now go ahead and exclude your entries from an ElementCriteriaModel. To do that simply pass the string into the id parameter.

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

{% set forsideEntriesIds = craft.entries({
    relatedTo: { sourceElement: forside, field: 'artikkelbolk1' },
    order:     'dateCreated desc',
    limit:     14
}).ids() %}

{% set idParam = 'and, not ' ~ forsideEntriesIds|join(', not ') %}

{% for entry in craft.entries.section('artikkel').id(idParam).order('dateCreated desc') %}
    <!--print out article content-->
{% endfor %}


Payment currency not allowed Craft 3.3.8

Commerce 2 Lite Version

If I change the base currency from default(USD) to NZD or AU in the setting

CP > Commerce > Store Settings > Payment Currencies

and browse to /shop/ or /shop/[otherpages] the website shows error:

Invalid Configuration – yii\base\InvalidConfigException
Payment currency not allowed.
1. in vendor/craftcms/commerce/src/elements/Order.php at line 1580

And if I switch it back to USD it works fine. It also works fine if I am a public register.

I need to use NZD only, if not, I'm open to other work arounds using USD.

Solution from Craft:

  In your Control Panel, click on Commerce then on the vertical subnav (where you have All Orders, New, Shipped....) you will have Active and Inactive carts, this is what Luke suggested you clear.

Essentially, it looks like existing carts may exist which are still using the old currency. Therefore these must be cleared before changing default currency.


Convert characters to Ascii Is there a twig filter to encode special characters like umlauts:
{{ entry.title | filter }}

  Datensätze & Karten

Which then should result in:

  datensaetze-karten

Basically what 'convertFilenamesToAscii' => true, does but as a filter.

I want to use this as a anchorlink later on so umlauts are not the best to have in anchor links.

I would use a combination of things:

Twig's replace filter to convert ä to ae etc.
Twig's convert_encoding filter to eliminate any remaining non-ascii characters
Craft's kebab filter to do its thing

and of course wrap the thing up in a macro

{% macro ascii_kebab(s) %}
  {{ s
    | replace({
        'ä': 'ae'
      })
    | convert_encoding('ASCII', 'UTF-8')
    | kebab
  }}
{% endmacro %}


Programaticaly create entry with simpleMaps field In a plugin I am writing, I am importing data from a older system and part of it is latitude and longitude data.  One of the fields in Craft is a simpleMap field where that data will go.

I would like to create a new entry that has a simpleMap field as one of the fields.  The github page doesn't have any documentation on how to do this, it mostly covers how to read data and display it in a template.

I have latitude and longitude data and I would like to add it to the simpleMap field.  This code doesn't work but its what I'm looking for.

$entry->setContent([
    'simplemap_field' => [$lat, $long],
    'some_other_field' => 'some text',
]);

I think I probably have to create a simpleMap object first and pass it to the entry field, something like this:

$smap = New SimpleMap([$lat, $long]);
...
    'simplemap_field' => $smap,
...

I actually just had to do this for a project, so I hope this will shed some light on how to set the props:

I started by looking at SimpleMap_MapModel.php and its attributes.

The available properties are: ownerId, fieldId, ownerLocale, lat, lng, zoom, address, and parts. (Don't touch ownerId, fieldId, and ownerLocale—they'll get set automatically when saved!)

So, this means you can set any of the above by simply assigning an associative array to your EntryModel, before saving:

$entry->setContent([
  'simplemap_field' => [
    'lat' => $lat,
    'lng' => $long
  ]
]);

If you have the data already, and want to populate the address "parts", you can json_encode those into the parts attribute:

$entry->setContent([
  'simplemap_field' => [
    'lat' => $lat,
    'lng' => $long,
    'parts' => json_encode([
      'street1' => $address,
      'locality' => $city,
      'administrative_area_level_1' => $state,
      'country' => $country
    ])
  ]
]);

Not a huge fan of the way those "parts" are saved, but it's basically the serialized/cached response from Google.

The address attribute, as far as I could tell, is basically the value that ends up in the search bar, when you're using the field in the front-end. During our import, we were able to build a meaningful string here, from other data (i.e. a venue name and city), so if any records didn't have a complete set of information, admin didn't have to reconstruct the search, manually.

Unfortunately, SimpleMap will not geocode (or reverse-geocode) your information to fill in gaps… you'll need to manually save each entry. This was something we struggled with when building out import scripts, but fortunately only the more recent location-sensitive content really needed to be updated.


GraphQL - Get related entries based on tags field I'm trying to retrieve entries related to the current entry, based on a tag field called topics. Simple stuff.

Now, I use Craft's native GraphQL implementation so I'm bound to the possibilities this interface gives me. In twig, it would be quite easily solved as described in the following topic: Search for related entries based on tags

It seems like the relatedTo property of the entries() query only supports a single ID, without the ability to scope my results based on a certain field. I would expect to be able to do something like the following:

entries(
    section: "article",
    limit: 2,
    relatedTo: {
        sourceElement: 123, // ID of the current entry
        field: 'topics'
    }
) {
    id,
    title
}

This just gives me the following error: Expected type [Int], found {sourceElement: 123, field: \"topics\"}.

Now, if I resort to the documentation it indeed describes that only an entry's ID can be used as the value of relatedTo, like this:

query QueryName {
  entries(
      section: "article",
      limit: 2,
      relatedTo: 123 // Current article ID
  ) {
      id,
      title
  }
}

This does work (it doesn't error), but results in an empty entries array. Even though there's entries that have the same topics (tags) assigned to them.

I'm kinda lost on how to actually retrieve related entries. Should I just revert to using the search param and feed it a concatenated list of the current post's tags?

Any elegant solutions would be greatly appreciated!

Thanks in advance!

I might be missing something here but wouldn't passing the current entry's tag IDs rather than the entry ID work for you?

query QueryName {
  entries(
      section: "article",
      limit: 2,
      relatedTo: [123,456] // Current article's tag IDs?
  ) {
      id,
      title
  }
}


Output random blocks from a matrix but without the first I have quotes inside a global matrix which i want to output randomly on the homepage but without the first quote-block. this does not work:

{% set quotes = city.cityBlocks.offset(1) %}
{% set randomQuotes = quotes.limit(1).order('RAND()') %}

the offset in 'quotes' works fine but the first block is still in randomQuotes anyway.

That query would basically tell MySQL to do this:

Shuffle the blocks
Return the second one

Since the shuffling happens before the offset/limit params get applied, they can’t be used to exclude the first block, since the first block will already be put in some random position by that point.

Instead you should get the ID of the first block, and exclude it using that:

{% set firstBlockId = city.cityBlocks.limit(1).ids()|first %}

{% if firstBlockId %}
    {% set randomQuotes = city.cityBlocks.id('not '~firstBlockId).order('RAND()') %}
    ...
{% else %}
    There were no blocks...
{% endif %}


Freeform is unable to send emails after changing webhost I have moved a website to a new webhost. Since the freeform ist no able to send any emails for notification reasons or alert reasons. Is there a basic switch or something similar I am missing to enable sending emails?

In that case, it's likely that Sendmail isn't configured on your new host. You could contact them for help in setting that up, though I'd recommend considering a switch to sending via SMTP/API. There's a bunch of different services out there, many of which have free tiers if you're not sending many emails - SendGrid, Mandrill, Amazon SES are a few options available.


What's the difference between setting cache with {% header %} tag and {% cache %} tag? I've came to a cache problem/question on one of my sites when I run a speed test and I failed caching test. I have very little knowledge in this area and I'd like to enhance it.

Documentation for {% header %} tag says that it set a new HTTP header in response and you can tell browser what to do (for example caching a page).

Documentation for {% cache %} tag say that it will cache a portion of your template.

So what's the difference in setting cache in HTTP header using {% header %} tag and {% cache %} tag?

The header tag sets an HTTP response header, which may be used to (among other things) tell the browser that the response content is "cacheable".

The cache tag tells Craft to cache the generated HTML on the server side (as a file).


Commerce 2 Subscription Prices We've currently got Subscriptions setup on a site which works a charm, but my main issue is outputting the price of the subscription, after the user has subscribed.

From the docs/templates I can even see how this is possible?!

You can get it via:

{% set subscriptions = craft.subscriptions.user(currentUser) %}

{% for subscription in subscriptions %}
    {{ subscriptionPlanData.plan.amount }}
{% endfor %}

But if for example, the plan is £300.00 then it outputs as 30000 and when formatted, it comes out like 30,000.00 using {{ subscriptionPlanData.plan.amount|number_format(2, '.', ',') }}

I can't see anyway of showing the user, how much they've paid in a human format without hacking around the number.

Stripe stores the amount in cents. If you want to format it from the subscriptionPlanData.plan.amount variable in your template you would need to divide by 100 first.

{{ (subscriptionPlanData.plan.amount / 100)|currency }}


Imager plugin doesn't generate images in multi-language website I upgraded a website from a single to multi-locale site and found out that the images (generated with the Imager plug-in) won't load in the new locale; I get a 404 for every image that the browser tries to load. However, the images do load in the new locale when the entry has been loaded in the original locale first.

It seems that Imager only generates the images when they're requested in the websites original locale; does anyone have an idea how to solve this? Thanks for your help!

Problem solved: imagerSystemPath was set relatively


What's the best way to create a multiple account architecture? (I have a lot of experience with custom PHP and JS code and multiple frameworks and a few CMS's, but little experience with Craft.)

I'm working on a site and they want to have multiple accounts and admins and users that fit in that paradigm, and I'm not sure the best way to approach it.

So general admins should be able to create new accounts and account admins. Account admins can log in and add products for their account only. And then the regular site is locked behind a login so that "regular" users must log in and be associated with an account and can. Both Account Admins and General Admins should be able to create "regular" users (but the former for their accounts only).

I was maybe thinking of associating extra fields to User Groups and trying to go at it in that route. I see you can edit User Profiles with Pro, but I don't see a way to customize User Groups (maybe we don't fully need that, but maybe just let those general admins create User Groups (can this be renamed "Accounts?").

I realize this is a bit of a vague/open ended question. Maybe this isn't really practical in Craft, or will need a lot of custom work...? Or maybe someone has a plugin with this in mind? Just looking for some general help, and this seemed like the place to start!

Not exactly the fine control you're looking for, or ideal by any means, but one direction might be to create an "Account" channel with a related user field for 'User' (required; limit to 1; from userGroup 'Regular User') — or vice-versa (related "Account" entry in "Users").

You can then restrict your Account Admins to only edit 'Accounts' (and Products) entries that belong to them, with all the custom fields that are required.

The problem here is that you wouldn't also want the Account Admin to be able to edit or assign permissions to users (thus defeating the purpose). And there is no way to automatically assign a new user (created through the CP) to a userGroup (as far as I know). Users can however automatically be assigned through the front-end through "allow public registration" and "default user group" settings. So, an Account Admin could technically create a new user through the front-end. And then (back in the CP) create a new 'Account' entry, and relate that account to the user they just created.

They would still require an admin to edit or delete the user, but maybe that's ok.

You would also need checks in place to ensure that only one account was assigned to any one user, somehow. If you reverse the relationship (i.e. related 'Account' entries field in 'Users'; limit 1), then you could ensure the 1-to-1, but this would require an admin to relate the two together.

Admins, of course, could do all of this through the CP and assign the "Account" to the Account Admin, by just setting the author.

Not ideal of course, but perhaps a step in the right direction.


User registration form add user to User Group? When using the User Registration Form (https://craftcms.com/docs/templating/user-registration-form), how do I make it so the user is added to a predefined User Group?

See the docs here:

https://craftcms.com/docs/users#public-registration

  Public Registration

  Craft Pro has the option of allowing public user registration. It is not enabled by default, though. To enable it, you must go to Settings → Users → Settings, and check the “Allow public registration?” setting. With that checked, you will also be given the ability to choose a default user group that publicly-registered users are assigned to.


Wrap a quote in differently styled quotes depending on locale? I want to show quotes for my french visitors like so:

  « Something intelligent someone said. »

but visitors of my english locale should see the quotes formatted like so:

  “Something intelligent someone said.”

You could do this by adding the locale ID as a class to the body tag and then use a technique like described in this nice CSS-Tricks to add the quotes depending on that body class.

https://css-tricks.com/almanac/properties/q/quotes/

If you want them to be in the HTML you could write a quick Twig macro that adds the quotes depending on the locale ID.

{% macro wrapInQuotes(string) %}
    {%- set quotes = {
        'en': ['“', '”'],
        'de': ['„', '“'],
        'fr': ['« ', ' »'],
    } %}

    {{- quotes[craft.locale][0] }}
    {{- string }}
    {{- quotes[craft.locale][1] -}}
{% endmacro %}

{% import _self as macros %}
{{ macros.wrapInQuotes(entry.quote) }}


List Entries by Author We would like to show a page which lists all Authors, and their respective entries, eg.

Dan Griffey

Entry 1
Entry 2

Joe Blogs

Entry 1
Entry 2

Have tried a few options but alas none working, so would appreciate any help / examples.

I would use the group filter:

{% for author, entries in craft.entries.find() | group('author') %}
    {{ author }}

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


How can I make related entries and globals part of the search considerations? How can I make related entries and globals part of the search considerations?
So I have a website search bar that searches the whole website.
Within some jobs pages there are some global elements that exist, a related entries to pull through some on page related content (a call out bar) and some general text that is used on all jobs pages. The reason these are global, is that they can be updated and applied to multiple pages in one go.

However, doing a search for the phrase 'benefits' does not include any jobs pages at all, even though the call-out bar and the global benefits content are used on each job page/template.

Equally on other pages, there is a related module type that links to related entries ((call out bars) and I would like these to be part of the search considerations too, so this issue stretches further than just one section.

Any thoughts on how to achieve this?

I am going to guess that Search does work on rendered templates, so relatedTo items and globals would not figure into the results.

Is it possible to add something to the query string? If so, you could modify the search results page with a "related to" query.


How to add Facebook pixel code to my website How do I add the html code to the head of my website in Craft CMS?

Do I need to install a plugin, or is there somewhere I can access the code?

Craft makes no assumptions on how your site should be built so it's impossible for us to say exactly where to put the pixel code.

You would add the code to whichever template you needed it in. This depends entirely on how your site is put together.

Oftentimes the <head> portion will be within your main _layout file but that is not necessarily always the case. This file can also be anywhere within your templates directory.

For Craft 2, look in your /craft/templates directory
For Craft 3, look in your /templates directory


How to implement radiobuttons field on frontend registration form? I want to add a question to a frontend registration form.
The radiobuttons are just 'Yes' or 'No'.

I've created a radiobutton field and added that to users > fields.

If I add this option to the form, new registrations are not submitted.
The page reloads and doesn't redirect to the confirmation page.

Any idea what's wrong with my form?

<legend>Are you a Beekeeper?</legend>
<input type="hidden" name="fields[areYouBeekeeper]" value="">
{% for option in entry.areYouBeekeeper.options %}
    <input id="isBeekeeper{{ option.label }}" type="radio" name="fields[areYouBeekeeper][]"
    {%- if account is defined %}value="{{ option.label }}"{% endif -%}>
    {{ option.value }}
{% endfor %}

Here's the complete form template.

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="{{ siteUrl }}registration/confirmation">

    {% macro errorList(errors) %}
        {% if errors %}

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

    Username
        <input id="username" type="text" placeholder="gebruikersnaam" name="username"
        {%- if account is defined %} value="{{ account.username }}"{% endif -%}>

    {% if account is defined %}{{ errorList(account.getErrors('username')) }}{% endif %}

    Email
        <input id="email" type="text" placeholder="somebody@example.com" name="email"
        {%- if account is defined %} value="{{ account.email }}"{% endif %}>

    {% if account is defined %}{{ errorList(account.getErrors('email')) }}{% endif %}

    Password
        <input id="password" type="password" placeholder="password" name="password">

    {% if account is defined %}{{ errorList(account.getErrors('password')) }}{% endif %}

    First name
        <input id="firstName" type="text" placeholder="First name" name="firstName"
        {%- if account is defined %} value="{{ account.firstName }}"{% endif -%}>

    {% if account is defined %}{{ errorList(account.getErrors('firstName')) }}{% endif %}

    Last name
        <input id="lastName" type="text" placeholder="Last name" name="lastName"
        {%- if account is defined %} value="{{ account.lastName }}"{% endif -%}>

    {% if account is defined %}{{ errorList(account.getErrors('lastName')) }}{% endif %}

    <legend>Are you a Beekeeper?</legend>
    <input type="hidden" name="fields[areYouBeekeeper]" value="">
    {% for option in entry.areYouBeekeeper.options %}
        <input id="isBeekeeper{{ option.label }}" type="radio" name="fields[areYouBeekeeper][]"
        {%- if account is defined %}value="{{ option.label }}"{% endif -%}>
        {{ option.value }}
    {% endfor %}

    <input type="submit" class="button expanded" value="Registreer">

</form>

I think the problem is with the for loop. I'm trying to output the radio options with a for loop on an entry, but it's actually not an entry. No idea why I do get the options anyway.
I've managed to get this working with the following code:

<input type="hidden" name="fields[areYouBeekeeper]" value="">

<input type="radio" value="yes" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>Yes
<input type="radio" value="no" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>No

Because radio inputs are a "single value field", meaning that when the form submits, only one value actually goes through, you don't need the extra [] array brackets at the end of each fields[] array.  In fact, you don't even need the hidden field above it.  That setup would work for checkboxes, where any number of values could be submitted. A great reference for how to format HTML form fields correctly to submit to Craft can be found on this StraightUpCraft article.

Your code should look like this:

<label>
    <input type="radio" value="yes" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>Yes
</label>
<label>
    <input type="radio" value="no" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>No
</label>

And the input values yes and no need to be exactly the same (lowercase in this case) as they are in the Values column of the respective custom radio field created in the CMS.


Redactor adding extra paragraph and br tag when entering and exiting HTML source mode I'm currently on the latest version of Craft (2.6.2785). When I edit Redactor content I have no issues, but if I enter HTML mode and exit it I end up with

 prepended to the content.

Here's a GIF of this issue.

I updated from version 2.5.2767 and that version does not have this bug.

In case it helps, here's the JSON config for the Redactor field I'm referring to:

{
  "buttons": ["html", "formatting", "bold", "italic", "unorderedlist", "orderedlist", "link", "file", "image", "video"],
  "plugins": ["fullscreen", "video", "table"],
  "toolbarFixed": true
}

This appears to be an issue with Redactor itself. Their example allowing you to edit the source code of a field has the same bug.


Trouble getting a list of categories that have entries for a specific category group I have a long list of categories in a specific category group, but only want to show a list of the categories from this group that currently have an entry associated with them.

I've been trying to implement the solution that I found at this thread: How can I output a list of categories that are not empty?

Only categories with related entries are showing. However, it's not being narrowed down to specific to a specific category group. Here's my code below:

{% set handshapeCategories = craft.categories.group('handshape').limit(null) %}
{% set entriesWithHandshapeCategories = craft.entries.relatedTo( handshapeCategories ).limit(null) %}
{% set handshapeCategoriesInUse = craft.categories.relatedTo(entriesWithHandshapeCategories) %}

{% for handshapeCategory in handshapeCategoriesInUse %}
    <h3>{{ handshapeCategory }}</h3>
{% endfor %}

Any ideas why the shown categories are not being limited to categories from the 'handshape' category group?

I would reverse your logic:

get all entries in whatever channel
display only categories (from a certain group) that have entries fetched in step 1 attached to them

Something along the lines of:

{% set entries = craft.entries.section('myChannel').limit(null) %}
{% set activeCategories = craft.categories.group('myCatgroup').relatedTo(entries).find() %}

You can then use a simple for loop to display only the active categories


Unix permissions for Craft Quick preface - i'm a new to managing my own servers. I'm on Ubuntu 14.04 running Apache. I ran into some problems setting up Craft which i was hoping someone might be able to shed a bit of light on what i got wrong. I have a user with sudo privileges, lets say 'user1'.

I used a simple PHP script to find out what user PHP is running as:

<?php echo exec('whoami'); ?>

Which came out as 'www-data'. In terminal as 'user1' i created a new group 'craftpermissions' and added 'user1' and 'www-data' to this group. I then set the group 'craftpermissions' as the owner of the following directories:

/craft/app/
/craft/config/
/craft/storage/

I then set permissions on those three folders to 775 using:

sudo chmod -R 775 /var/www/myvirtualhostaddress/craft/app/

However when i visited mydomainname.com/index.php/admin/ i still got the error saying php could not write to the /config folder.

In the end i set permissions on the folder to 777 so i could crack on with installation and it worked fine, but i'd like to do it properly as i think 777 is a bit of a no-no? Or does it not matter too much if craft folder is one directory above my web root?

Any guidance much appreciated.

EDIT

for /craft/app everything is owned by craftpermissions except .. which is owned by the group created when i made user1:

drwxr-xr-x  7 user1 user1 4096 Aug 25 06:44 ..

does this refer to the directory above it? When i run on /craft/storage/ it appears as:

drwxrwxrwx 3 user1 craftpermissions 4096 Aug 25 09:18 .
drwxr-xr-x 7 user1 user1       4096 Aug 25 06:44 ..
drwxr-xr-x 6 www-data   www-data         4096 Aug 25 09:19 runtime.

/craft/config appears as

drwxrwxrwx 3 user1 craftpermissions 4096 Aug 25 09:19 .
drwxr-xr-x 7 user1 user1       4096 Aug 25 06:44 ..
-rwxrwxrwx 1 user1 craftpermissions  671 Aug 25 06:44 db.php
-rwxrwxrwx 1 user1 craftpermissions  220 Aug 25 06:44 general.php
-rw-r--r-- 1 www-data   www-data          255 Aug 25 09:19 license.key
drwxrwxrwx 2 user1 craftpermissions 4096 Aug 25 06:45 redactor
-rwxrwxrwx 1 user1 craftpermissions  844 Aug 25 06:44 routes.php

I'm not sure if this helps, but here is how I (attempt) to manage deployments/installs.

I first create a user so I'm not using the root account. I tie that user to the apache user group. We'll call him 'user1'.

I use beanstalk to deploy, and the deployment credentials are for 'user1'.

Once all of the files have deployed for the first time, I'll log into the server via terminal, and chown the project directory: chown -R user1:apache

Next, I'll make sure everything has the correct permissions: chmod -R 754 mysite.com

Next, I know that Craft needs to be able to write to:

/craft/app
/craft/config
/craft/storage

I will chmod those directories to 774. chmod -R 774. Since 'user1' belongs to apache, it can read/write to the appropriate directories.

Hope this helps!


Dynamic link to same entry but in alternate language I'm working on a multilingual website (Spanish and English, default is Spanish). I'm using the SEOmatic plugin, and I see that it generates this code:

<link rel="alternate" hreflang="es" href="http://localhost:8888/cmml/contacto" />
<link rel="alternate" hreflang="en" href="http://localhost:8888/cmml/en/contact-us" />

And I'm wondering if, instead of linking to the home page in an alternate language is there a way to link to the same resource in the alternate language?

Is there an easy way to achieve this? Thanks folks.

Both SEOmatic for Craft 2 and SEOmatic for Craft 3 have built-in functions to give you these URLs. I'm not sure which you are using so...

For Craft 2: https://github.com/nystudio107/seomatic/wiki/15.-Utility-Filters-&-Functions#getlocalizedurls

For Craft 3: https://github.com/nystudio107/craft-seomatic#helper-functions-seomatichelper


Filtering entires via tag field and checkbox field using a form *** Edited the question
I have a code that used to work fine on Craft 2 and I don't understand what I need to change to make it work on Craft 3.
I am using form to filter through a channel of entries based on two fields - checkbox field with handle blogcategory and tags field with handle blogTags.
Here is the code of the form I am using for the filtering (worked perfectly on craft 2):
{% set blogcategory =  craft.request.getQuery('blogcategory') %}
{% set tags =  craft.request.getQuery('tags') %}

<form action="" method="get">

            category
            <select name="blogcategory">
                <option value="">Any Category</option>
                {% for option in craft.fields.getFieldByHandle('blogcategory').settings.options %}
                    <option value="{{ option.value }}">{{ option.label }}</option>
                {% endfor %}
            </select>

            tags
            <select name="tags">
                <option value="">Any tags</option>
                {% for tag in craft.tags.group('blogTags') %}
                    <option value="{{ tag.title }}">{{ tag.title }}</option>
                {% endfor %}
            </select>

        <input type="submit" value="filter">

</form>

And here is the code for displaying the entries:

    {% set entries = craft.entries.section('blog') %}
    {% set search_terms = '' %}

    {% if blogcategory %}
        {% set search_terms = search_terms ~ ' blogcategory:' ~ blogcategory %}
    {% endif %}

    {% if tags %}
        {% set search_terms = search_terms ~ ' tags:' ~ tags %}
    {% endif %}

    {% if search_terms %}
        {% set entries = entries.search(search_terms) %}
    {% endif %}

    {% for entry in entries %}

            {{ entry.title }}

    {% endfor %}

The problem is that after submitting the form with the desired filtering, none of the entries are showing up at all. It seems like the .serach function is not working...
I am a bit lost how to start understanding what fails under Craft 3...

I'm not sure why your search is not working in this instance (though it might be because you're not executing the query, see my comment). But in general, fulltext search is way less precise, I would only do that if you need to support actual search terms. Since you're only filtering by categories and tags, I wouldn't search by category/tag titles, but instead use IDs to match the selected categories/tags directly. This will be way more precise, avoid edge-cases and will be much faster as well.
First you'll need to adjust your form so the select fields use IDs instead of titles as their value:
{# category filter #}
<option value="{{ option.id }}">{{ option.label }}</option>

{# tag filter #}
<option value="{{ tag.id }}">{{ tag.title }}</option>

Then adjust your query to query your blogcategory and tags field directly by ID:
{% set entries = craft.entries.section('blog') %}
{% set blogcategory =  craft.request.getQuery('blogcategory') %}
{% set tags =  craft.request.getQuery('tags') %}

{% if blogcategory %}
    {% do entries.blogcategory(blogcategory) %}
{% endif %}

{% if tags %}
    {% do entries.tags(tags) %}
{% endif %}

Finally, make sure to actually execute the query:
{% for entry in entries.all() %}
    {# output results #}
{% endfor %}


ERROR 1370 (42000) alter routine command denied to user I am trying to upload my DB using MySQL Workbench but am getting this error:

ERROR 1370 (42000) at line 4534: alter routine command denied to user 'detectalocal'@'%' for routine 'detectalocal.checkLicensesExpiration'

How do I troubleshoot this? My root account has all of the correct permissions.

Most likely your Craft install has some custom stored procedures in it.  I say custom because Craft doesn't use them by default and therefore doesn't require the necessary privileges to use them.

You'd need to make sure the MySQL user account Craft is running as and the one you're using to import the database backup has the
ALTER ROUTINE and CREATE ROUTINE privileges to properly use them.


How do I remove segment 1 in my URL AND get the parent URI? I have a structured group of pages in a static channel that I would like to display without "static" in the URL and show the parent URI. This is my structure:

patients-visitors
---- our-stories
-------- share-your-story
support-groups
---- healing-yoga

All of these entries are in a "static" channel. When I roll over the link in the Control Panel, my link look like this:

https://www.website.com/static/patient-visitors
---- https://www.website.com/static/our-stories
-------- https://www.website.com/static/share-your-story
https://www.website.com/static/support-groups
---- https://www.website.com/static/healing-yoga

However, I want the links to look like this:

https://www.website.com/patients-visitors
---- https://www.website.com/patients-visitors/our-stories
-------- https://www.website.com/patients-visitors/our-stories/share-your-story
https://www.website.com/support-groups
---- https://www.website.com/support-groups/healing-yoga

Edit your section‘s settings (Settings > Sections > [Section Name]), and delete the static/ from the Entry URI Format.


Q: Call to member function on null - Freeform (Solspace) I am running Freeform 1.9.0 and I have a small plugin that is supposed to save user submission id's to a custom user field. The plugin returns error when it runs after a new user submits a form though.

Here is the error

  Call to a member function getContent() on null

Here is the code

craft()->on(
        "freeform_submissions.onAfterSave",
        function (Event $event) {
            $submission = $event->params["model"];
            $isNew    = $event->params["isNew"];

            $submissionId = $submission->id;

            $user = craft()->userSession->getUser();

            $user->getContent()->submissionID = $submission->getId();
            $success = craft()->users->saveUser($user);

            if (!craft()->users->saveUser($user))
            {
                $errors = $user->getErrors();
            }
        }
    );

Please read the article handling errors gracefully in Craft  it will explain to code defensively and what to do in those scenarios. Your $user variable is null and you can't execute functions on null variables


Craft 3 Multi Site - Entries/categories/assets fields aren't translatable? I'm testing out the Craft 3 beta's multi-site capability at the moment to see if it's suitable for an upcoming project.

My sample scenario is a school that runs out of multiple countries. They offer the same courses, but may want to tailor the content for different countries.

If we want different tutors assigned per site (country) to this course, we can't as an entries field (pulling from teachers section) is not translatable/multi site capable.

We run into the same problem with using matrix fields for content. We generally have a general content matrix field that allows the client to build their content with different pre-defined blocks (side by side images, text with image, full width text, video etc. etc.). But matrix fields aren't translatable either.

Same for images etc. There are a few other scenarios where this would raise its head just in this one example.

For this feature to be usable for how we use Craft, we'd need multi site support on those field types. Is this something that's coming or should I start thinking of another solution?

If we want different tutors assigned per site (country) to this course, we can't as an entries field (pulling from teachers section) is not translatable/multi site capable.

  …

  Same for images etc.

All relational field types (Assets, Categories, Entries, Tags, and Users) have a “Manage relations on a per-site basis” setting (under Advanced). If you check it, each site will get its own set of relations.

  But matrix fields aren't translatable either.

Same - Matrix fields have a “Manage blocks on a per-site basis” setting, right below the big Configuration setting.


Restrict Sources on element select field I'm building a module with a form that includes an element select field that I want to restrict to specific volume. So far this is what I have:

{{ forms.elementSelectField({
    label: "Asset"|t('app'),
    id: 'images',
    name: 'images',
    elementType: 'craft\\elements\\Asset',
    selectionLabel: "Choose"|t('app'),
    criteria: {
        kind: ['images']
    },
}) }}

I can see there is a 'sources' attribute, but I don't know how to structure the value. I've tried:

sources:[1] and the handle sources:['images'] without luck.

I am not expert in Craft CMS but this is how it works for me:

Depending on the element type, source is different.

Look at this link how Craft CMS implements this:

https://github.com/craftcms/cms/blob/60881865f1b680c5aa5d4ad8f56d9a1ce3e452b0/src/fields/BaseRelationField.php#L842

Now how assets implement inputsource function:

https://github.com/craftcms/cms/blob/f83815cf28e7ce91edd501fc55ffd10f915a808e/src/fields/Assets.php#L550

so the format of sources for asset is like:

['folder:uid in volumefolders table']

and you can easily limit user to select assets from volumes you want.


Add listener to dynamic html elements I have a field type that I need to initialize. When the page loads I can use code like the following to handle certain behaviors of the field:

$('.myfieldwrapper').each(function() {
  new Craft.MyField(this);
});

Within the Craft.MyField object, I add a couple listeners like so:

this.addListener(this.$element, 'change', 'handleElementChange');
this.addListener(this.$element2, 'click', 'handleElement2Click');

That all works fine.  However, this field doesn't just get added to the page on page load. It exists in the row of a table, and a user can add additional rows to the table which add a new row and field to the DOM.

I've tried to instantiate the newly added field in several ways, and I have been unable to get it right yet. The Craft.MyField seems to be initializing, and I appear to be able to re-initialize the default fields on the page, but my attempts do not have any affect on the dynamic fields that get added.

I don't think the following is the best way to do this, but it's currently the closest I've come and is the simplest example code I can share reflecting my attempts.

After a new field gets added dynamically, I trigger an event:

$('#tableId').trigger('rowAddOrRemove');

And I have additional code watching for that event and attempting to re-initialize all the fields on the page:

$('#tableId').on('rowAddOrRemove', function(event){
  $('.myfieldwrapper').each(function() {
    new Craft.MyField(this);
  });
});

When I do this the initial field on the page still works but none of the dynamically added fields behave as I need them too.

Any ideas on what I'm doing wrong or what concepts I need to understand better to get this right?

You might be looking at a simple race conditions issue, i.e. that the rowAddOrRemove event is triggering before the new .myfieldwrapper elements have been attached to the DOM. To make sure that you don't call new Craft.MyField too early, you can try to wrap the constructor call in an anonymous requestAnimationFrame handler:

$('#tableId').on('rowAddOrRemove', function(event){
    Garnish.requestAnimationFrame(function () {
        $('.myfieldwrapper').each(function() {
            new Craft.MyField(this);
        });
    });
});

Not sure if race conditions is even the issue here, but it's the only thing I can think of, based on the code you provided.

Some other thoughts:

I'm not sure you actually need the rowAddOrRemove event – unless other parts of your application also needs to respond to that event, I'd opt for calling a simple function, rather than triggering a jQuery event, e.g.:

# ... field gets added dynamically

Garnish.requestAnimationFrame(initFields); // Instead of $('#tableId').trigger('rowAddOrRemove');

function initFields()
{
    $('.myfieldwrapper').each(function () {
        new Craft.MyField(this);
    });
}

Sidenote: If you do need to trigger an event, I'd recommend looking at Signals.js, which is a much more robust Event/Promises implementation than $.trigger.

Another thing: I'm not sure if calling Craft.MyField(this) on DOM elements that have previously been initialized is an issue, but if it is, you could add a simple classname to the initialized elements, to prevent them being initialized multiple times:

function initFields()
{
    $('.myfieldwrapper:not(.js-initialized)').each(function () {
        $(this).addClass('js-initialized');
        new Craft.MyField(this);
    });
}

Finally, if you need to destroy instances of Craft.MyField that have previously been initialized but are now removed (to prevent memory leaks or other bugs), you could do something like this (note that this example assumes that your Craft.MyField class has a destroy method that e.g. removes event listeners, deletes variables etc):

var myFieldInstances = [];

function initFields()
{
    // Destroy removed fields
    var currentFieldInstances = myFieldInstances.slice(0);
    myFieldInstances = [];
    for (var i = 0; i < currentFieldInstances.length; ++i) {
        var field = currentFieldInstances[i],
            $el = field.$el;
        if (!$el.closest('#tableId').length) {
            // This field's DOM element is no longer a child of #tableId – kill it with fire
            field.destroy();
        } else {
            myFieldInstances.push(field);
        }
    }
    // Init new fields
    $('.myfieldwrapper:not(.js-initialized)').each(function () {
        $(this).addClass('js-initialized');
        myFieldInstances.push(new Craft.MyField(this));
    });
}


renderTemplate() renders the twig file without any CSS I've set up the routing for a specific URL in my plugin to trigger the actionIndex controller method. I after logging a message to the Craft logs, I want to return the rendered twig file as the view, which is supposed to look just like an empty Control Panel page. Pretty simple in theory.

Everything in the twig file seems to render just fine (text & images) except for the CSS.

Controller: Controller.php

class Controller extends \craft\web\Controller
{
    public function actionIndex(){

        Craft::info("hello!", __METHOD__);

        return Craft::$app->getView()->renderTemplate('plugin/done');
    }
}

Template: done.twig

{% extends "_layouts/cp" %}
{% set title = "Manual Sync"|t('plugin') %}

{% block content %}

Manual Sync Done.

{% endblock %}

I've attached a screenshot of the elements that are rendered on the page.

Hopefully that is enough for someone to help bounce some ideas around with me. Any advice and suggestions would be greatly appreciated!

I sincerely appreciate the responses!
I've since resolved this issue, below is the changed code. My controller was extending the Craft web controller (\craft\web\Controller) which has its own renderTemplate() method that I switched to, which fetches the Control Panel assets I wanted for styling the page.

The template twig file remains identical as is above.

(Modified) Controller: Controller.php

class Controller extends \craft\web\Controller
{
    public function actionIndex(){

        Craft::info("hello!", __METHOD__);

        return $this->renderTemplate('plugin/done');
    }
}

This did the trick for what I wanted. Thanks again!


Error trapping on discount codes based on Cart contents Is there any automatic Error trapping built into Craft for discount codes for the following rules?

Orders over a set Total
Orders over a set Quantity

The codes work/apply, but if the rules don’t match I am not getting any errors/messages back.
Any ideas? Do we have to write checks for every scenario?

There are likely more scenarios than the two I have listed above. It seems a little poor UX to appear to do nothing, no error, no discount applied if the contents of the cart don't qualify.

So this is for coupons?

If a coupon can't be applied during an updateCart, you'll get back the rather unhelpful response in JSON of {"error":"Cart not completely updated."}

We intercept this, and because we know it's a coupon operation just replace the text of that to 'Could not apply coupon'.

But it does not give you a reason or anything, unfortunately.


"Craft is unable to determine if an update is available at this time." I am receiving the following error when I click on Check for Updates ...

  Craft is unable to determine if an update is available at this time.

Do you know what could be causing this?

You'll get this if (for any reason) your local install can't connect to our web service that holds all of our update and release information.

If this happens, your local install will cache that there was a connection error and cache to not try again for 5 minutes, no matter how many times you refresh.

So you can either wait the 5 minutes and try again, or clear your data caches under Settings->Tools->Clear Caches Tool and try again and hopefully the connection problem will have resolved itself.

You can also check your craft/storage/runtime/logs files for any cURL related errors indicating a cURL configuration problem on the box.


Get the section name based on a url segment I'd like to retrieve the name of a section based on a url segment. Normally I would use {{entry.section.name}}, but this doesn't work, since there is no entry available.

I've got this working:

{% set entry = craft.entries.section(craft.request.getSegment(1)).first %}

<h2>{{entry.section.name}}</h2>

This means that I first have to get an entry and then reverse retrieve the section it belongs to.

Is there no direct way to get the section name based on a url?

Do you mean

{% set section = craft.sections.getSectionByHandle(craft.request.getSegment(1)) %}
{{ section.name }}


Set default status in CP admin for queried entries from "All" to "Live" Just wondering if there's a way to set the default status for the entry listing pages in the admin, in my case from "All" to "Live". This would need to account for a page "refresh" and navigation using the sidebar links.

I've tried to amend the toolbar property available in the passed context for the cp.layouts.base hook but this is purely visual and has no effect on the criteria to query for these entries.

I've attached a screenshot to confirm location for anyone who's unsure. Many thanks in advance!

After a little head-scratching, the only way I could get this working was to register an AssetBundle (to load in my own JS), and making use of the Garnish toolkit as follows:

$(document).ready(function() {
    var statusSet = false;

    Craft.elementIndex.on('updateElements selectSource', function(data) {
        if (!statusSet) {
            // Find the option (and make sure it actually exists)
            $option = data.target.statusMenu.$options.filter('a[data-status="live"]:first');

            if ($option.length) {
                data.target.setStatus($option.data('status'))
                statusSet = true;
            }
        }
    });
});

This should only trigger the setStatus() process once, even when navigating between sources (which will also be filtered to to the saved status state of "Live"), but allows the user the freedom to change the status again if they so choose.

I hope this helps :)


How do I combine search for categories and entries into one set of search results? I have a search page. I can search either categories or entries using

{% set entries = craft.entries.search(query).order('score') %}
{% set categories = craft.categories.search(query).order('score') %}

I have added quite a bit of content in each category i.e. what it's all about etc. and I would like this content returned like a standard search result going to the category URL (it works when I search categories only)

I've tried to merge the above two arrays

{% set results = categories | merge (entries) %}

But that's obviously not how you do it because it throws a craft error.

Now, I guess I could return the results of one, and then the other, but I was hoping to have the score create a more sensible order of relevant results.

The reason you're getting an error when trying to merge the two search results is that they are not technically arrays, but elementCriteriaModels. To convert them to actual arrays you would need to use the find() method.

{% set entries = craft.entries.search(query).order('score').find() %}
{% set categories = craft.categories.search(query).order('score').find() %}
{% set results = categories|merge(entries) %}

The problem with this is that the sort order will be wrong (showing all categories and then all entries). Although you could potentially sort the results array using something like the supersort plugin.

The other option to consider is redesigning the database so that there is nothing in categories that needed to be searched for, which might simplify things in the end.


Getting products with Craft 3 and Craft Commerce 2 I've never had success using Craft 3 with Commerce 2 beta. I always get an error that ".find()" is not recognized, and ".all()" doesn't work either.

My latest attempt has given me this error:

  Twig Runtime Error – Twig_Error_Runtime
  Calling unknown method: craft\commerce\services\Products::type()

The line in question is this one:

{% set silentItems = craft.commerce.products.type('silentAuctionItems').find() %}

If I delete

.type('silentAuctionItems').find()

the error doesn't come up, but I don't get any products displaying.

I've searched through the Commerce documentation, and I can't find anything about this problem.

Thanks for any help you can provide!

I figured out the problem. It should be

{% set silentItems = craft.products.type('silentAuctionItems').all() %}

You don't put .commerce between craft and .products.

Thanks!


Structuring site with multiple subsites I have to make a website that has a single craft installation and one database.

Now the site is for a company that owns several garages which should have their own subsite on a subdomain. It should all be multilingual and those subsite/subdomains would have single pages as well as channels for used cars or new cars.

Now what I'm wondering is how to set up those subsites.
Their url structure should be like http://subsite.domain.com/{lang}/{single-page} or http://subsite.domain.com/{lang}/blog/{slug}

I was thinking maybe using a structure per subsite to keep all the content uncluttered in the dashboard and creating a channel for each subsite blog, used cars section and new cars section.

But I'm not really sure what the best way to set this up would be or even how to point the pages/channels to a subdomain.

Would I have to create new multi-environmont configs for each subsite or is there a way to do this automatically or maybe that's not even necessary?

Each subsite will also have users who can only edit that specific subsite. (Maybe something to keep in mind when structuring the site)

Here's a  little diagram that might help show what I'm looking for:

Of course I'll be using craft pro for the languages and users.

Any help and tips would be much appreciated.
(Feel free to ask for more information if necessary)

Thank you very much in advance

As of this comment, Craft 3 is still in beta but you may want to consider it as your challenge sounds like the new Sites functionality may be a good fit.

Sites, allow you to manage multiple websites and multiple languages in one Craft installation. You can find a longer discussion and some examples here:
Managing Multiple Sites in Craft 3 – Sites and Localization

You could create a Site for each combo of Garage and Language that you need to manage. For example:

Garage 1 - French
Garage 1 - German
Garage 2 - French
Garage 2 - German

The blog and other sections for each of these sites could be managed under one channel. Admin users would be able to switch between each subsite just as they switch between locales when editing an entry. User Groups could be created for each subsite as well as the permissions in Craft 3 will allow you to restrict a users access to a specific subsite.

You can read more about how to configure each site in this Localization Guide in the Craft docs. You'll need to configure a couple of files for each site and make sure your DNS is pointing to the right place for each subdomain. But once you get those items setup, you should be able to use the same templates for all of the different sites and languages.


Craft ships with PHPUnit... How can we use it to test our plugins? Since Craft ships with a copy of PHPUnit, is it possible to use that to run tests on a plugin? Or do we need to have a separate copy installed?

Yes it is possible, see this example plugin by Selvin Ortiz: https://github.com/selvinortiz/craft.loath.

You can also check out https://github.com/boboldehampsink/import for some detailed unit tests.


saveEntry() not firing I'm using code I've been using to update existing entries for a while now and it's failing to fire following the 2.5 upgrade. Trying to figure out what might have changed, or if there's something I'm overlooking. I'm consistently getting the "not saved" response and seeing no update in the entry. showInInvestmentAdvisersReference is the new field I'm setting. I've got limit=1 set for testing purposes.

$entries = craft()->elements->getCriteria(ElementType::Entry);
$entries->section = 'referenceMaterials';
$entries->limit = 1;

$existingEntries = $entries->find();

foreach ($existingEntries as $existingEntry) {
    echo 'id: ' . $existingEntry->id . '
';

    $entryToSave = new EntryModel();

    $entryToSave = $existingEntry;

    // Setting these in case they're required to be set for saveEntry()
    $entryToSave->sectionId = 9;
    $entryToSave->typeId = 9;
    $entryToSave->authorId = 1;
    $entryToSave->enabled = true;
    $entryToSave->getContent()->title = $existingEntry->title;

    $entryToSave->getContent()->showInInvestmentAdvisersReference = 1;

    if ( craft()->entries->saveEntry($entryToSave) )
    {
        echo 'saved
';
    }
    else {
        echo 'not saved
';
    }
}

Is it me? Did something change? Happy to file a bug report but thought I'd start here first where code formatting is supported.

Something on the $entryToSave EntryModel is failing validation.  If you
echo out implode(', ', $entryToSave()->getAllErrors());, then you'll see what those errors are and you can correct them.


File input attachment format for Contact Form plugin Is it possible to specify the file formats for an upload field with the Contact Form?

Is it controlled by the extraAllowedFileExtensions setting?

No, currently it will allow all file types and does not take the extraAllowedFileExtensions config setting into account.