Craft Request Filter Query Matching Drop Down Fields and Checkbox Fields I have a front end form that allows users check checkboxes to find entries that have matching field values. I've pieced together a query reading other posts here and my limited knowledge of Craft and Twig.

My entries have multiple dropdown fields that are getting matched (1 match per field) and one checkbox field (1 or more matches per field). My query works when I only have dropdown fields but I'm struggling getting it to work to match the checkbox fields.

Here's my paired down query:

    {% set params = {
    section: 'entriesSection',
    limit: null
    } %}

    {% set relatedParams = ['and'] %}

 {# dropdown field match #}
    {% set brand = craft.request.getParam('brand') %}
       {% if getBrand %}
           {% set params = params|merge({'brand':getBrand}) %}
       {% endif %}

 {# checkbox field match #}
    {% set getLocation = craft.request.getParam('location') %}
    {% if getLocation %}
          {% for eachLocation in getLocation %}
              {% set params = params|merge({'eachLocation'}):getLocation}) %}
          {% endfor %}
    {% endif %}

 {# merge related params and params #}
    {% if relatedParams|length > 1 %}
         {% set params = params|merge({'relatedTo':relatedParams}) %}
    {% endif %}

 {# search #}
    {% set entries = craft.entries(params).search(searchParams|trim) %}

Here's my paired down front-end form:

 <form>

<!-- brand matches dropdown fields-->

    <label>
       <input type="checkbox" name="brand[]" value ="brandX" />
    Brand X
    </label>
    <label>
       <input type="checkbox" name="brand[]" value ="brandY" />
    Brand Y
    </label>

 <!-- location matches checkbox fields -->

    <label>
       <input type="checkbox" name="location[]" value ="locationA" />
    Location A
    </label>

    <label>
       <input type="checkbox" name="location[]" value ="locationB" />
    Location B
    </label>
 </form>

I'm probably late to answer this, but I've recentry encountered same problem and here's the solution I came to:

use params for dropdown fields and search for checkbox fields

So my code looks similar to this:

{% set orderParams = {} %}

{% for key, val in craft.request.query %}
    {% if val is not empty %}
        {% if key=='orderFinance' %}
            {% set orderParams = orderParams|merge({orderFinance:val}) %}
        {% elseif key=='orderStatus' %}
            {% set orderParams = orderParams|merge({orderStatus:val}) %}
        {% endif %}
    {% endif %}
{% endfor %}

{% set flagSearchQuery = [] %}
{% for flag in craft.request.query.orderFlag %}
    {% if flag is not empty %}
        {% set flagSearchQuery = flagSearchQuery|merge({query: 'orderFlag:'~flag}) %}
    {% endif %}
{% endfor %}

{% set orders = craft.commerce.orders(orderParams).search(flagSearchQuery).limit(100) %}


With Craft Commerce, how can I call getAllStates from my own plugin via ajax? I am trying to call $states = craft()->commerce_states->getAllStates(); from within my own plugin, via an ajax request.

MyPlugin.php

if (craft()->request->isAjaxRequest()) {
    return $this->returnJson(['states' => craft()->commerce_states->getAllStates()]);
}

The above will return this:

Object {states: Array[72]}

However, as I'm walking myself through it, I can see that the original call:

var states = {{ craft.commerce.statesArray|json_encode|raw }};

Gives me these objects:

Object {13: Object, 38: Object, 233: Object}
Object {13: Object, 38: Object, 233: Object}

So it's pretty obvious i'm not calling the correct method. I am using requirejs within my project and having the javascript right in the template is returning errors - it can't access jquery.

Thank you for any suggestions!

Instead of calling getAllStates() to get the same data back as the twig call:

var states = {{ craft.commerce.statesArray|json_encode|raw }};

Within your plugin you need to call getStatesGroupedByCountries()

MyPlugin.php

if (craft()->request->isAjaxRequest()) {
    return $this->returnJson(['states' => craft()->commerce_states->getStatesGroupedByCountries()]);
}


Error on functions in queue: "Session does not exist in a console request." I get the following error on multiple order mails from Craft Commerce. The error points out to the lines where a macro is called:
Email template parse error for email “New order”. Order: “e35f244”. Template error: “An exception has been thrown during the rendering of a template ("Session does not exist in a console request.")

I've also seen this same error on other custom functions in the queue, but this got solved by performing a DB command instead of setting the field values directly on the element followed by the saveElement function, so the error does not only happen in this specific situation.
The mail template:
{% import "_macros/commerce" as macroCommerce %}

{% block content %}

    {% set language = "nl" %}

    {% set lineItemsList = {} %}
    {% for lineItem in order.lineItems %}
        {% set lineItemsListItem = {} %}
        {% set lineItemsListItem = lineItemsListItem|merge(["#{lineItem.qty} x #{lineItem.description}"]) %}
        {% if lineItem.purchasable.product.type.hasVariants %}
            {% set variantLabel = macroCommerce.getVariantLabel(lineItem.purchasable, true)|trim|striptags %}
            {% if variantLabel %}
                {% set lineItemsListItem = lineItemsListItem|merge([variantLabel]) %}
            {% endif %}
        {% endif %}

        {% set lineItemsList = lineItemsList|merge([lineItemsListItem|join(" - ")]) %}
    {% endfor %}

    {% set body = "#{"orders_new_products"|t("app", null, language = language)}
        #{lineItemsList}"
    %}

    {% include "_emails/template" %}

{% endblock %}

The getVariantLabel macro function in _macros/commerce.twig:
{% macro getVariantLabel(variant, showPrice = false) %}
    {% set variantLabel = {} %}
    {% set variantFields = variant.variantFields.one() %}

    {% if variantFields %}
        {% if variantFields.potSize %}
            {% set variantLabel = variantLabel|merge([variantFields.potSize]) %}
        {% endif %}

        {% if variantFields.color %}
            {% set variantLabel = variantLabel|merge([variantFields.color]) %}
        {% endif %}
    {% endif %}

    {% if showPrice %}
        {% set variantLabel = variantLabel|merge([variant.salePrice|commerceCurrency(craft.commerce.carts.cart.currency)]) %}
    {% endif %}

    {{ variantLabel|join(" - ") }}
{% endmacro %}

When the mails are sent manually from the order detailpage it does succeed. There is a cronjob set on the server that keeps the queue running automatically to keep all the functions running in the queue, so I guess that it has something to do with this.
Any solution or tips that could point me in the right direction are much appreciated!

This is a gotcha with the recent move to emails being sent by the queue and not during the actual checkout process.
Your problem is this line (and other lines you might have like it...):
variant.salePrice|commerceCurrency(craft.commerce.carts.cart.currency)

...when the queue runs, there is no current cart for the commerce carts service to retrieve, so therefore you also can't retrieve the currency from it.
If you change this to something direct, i.e. using the Craft currency filter, it will not raise this error.
https://docs.craftcms.com/v3/dev/filters.html#currency
variant.salePrice|currency('AUD')

...for example.
This is fine if your store only uses one currency.
If you are using multi currency, then I think you would need to retrieve the order.paymentCurrency in this case.
https://docs.craftcms.com/commerce/v3/payment-currencies.html#order-currency-fields
...in short, the one thing you can't do is call on the current cart....because there isn't one for console (queue) requests.


How to add HTML, CSS, JavaScript on the front-end using a template hook in a plugin? I'm trying to render my HTML, CSS, JavaScript with the use of template hooks from a plugin.

{% hook 'video.slider' %}

Is it possible? If it is, can you give some snippet?

In your plugin's main file init method setup your template hook. In this hook you can call a service method to return your rendered HTML.

public function init()
    {
        craft()->templates->hook('video.slider', function(&$context)
        {
            $response = craft()->pluginname_service->serviceMethod();
            return $response;
        });
    }

In your plugin's service file create a method to return your rendered HTML.

function serviceMethod()
    {

        $oldPath = craft()->path->getTemplatesPath();

        $newPath = craft()->path->getPluginsPath().'path/templates/folder';
        craft()->path->setTemplatesPath($newPath);

        $templateName = '_templatename';

        //If you need to get data from somewhere else to pass to the template
        $htmlData = craft()->plugin_service->serviceMethod();

        $htmlResponse = craft()->templates->render($templateName, array("variableName" => $htmlData));

        //reset path
        craft()->path->setTemplatesPath($oldPath);

        return $htmlResponse;
    }


Preserve ICC color profile on image transformations Is it possible to configure Craft to preserve the ICC color profile?

I did test JPG images saved in "sRGB IEC61966-2.1" profile and the files returned from Craft transformations are always saved in plain "RGB", oversaturated and just not as nice.

Imagick is installed.

Not currently, but this is already on our list.

The image processing library we're using only recently (within the last 6 months or so) added ICC profile support.

Update:

Great news for all photographers and image lovers! Things changed with Craft 2.3, ICC profiles are now preserved if Imagick is installed and used for the transformation.


Get a defined image-transform's width and height in front-end template Is it possible to retrieve a control panel defined imagetransform’s dimensions in a front-end template without having to retrieve an asset? Because when there is no asset provided, I can't seem to find a (dynamic) way to get the width and height of the transform in order to calculate dimensions for a placeholder div

Craft does not provide the assetTransformService in the craft.variable but you can include it by yourself.
Create a function in your PluginVariable.php that does

public function getTransformationByHandle($handle){
    return craft()->assetTransforms->getTransformByHandle($handle);
}

and in your twig template
{% set transformation = craft.pluginHandle.getTransformationByHandle('yourHandle') %}

Edit: if you don't have a custom plugin then visit this page Pluginfactory fill out the inputs and select the lightswitch for "variable" paste my function into the /variables/pluginHandleVariable.php file and create a folder with the same name as your pluginhandle (the one you inserted in the input at the page) in /app/plugins/ then go to the control panel, install the plugin.


What's the most efficient way to handle a redirect of the home page? I dont't currently need a home page on the personal site I'm working on but I want to be able to keep the option open in the future. I currently have

{% redirect 'portfolio' %}

as the only code on the index page but Craft seems to take a while before it redirects to the portfolio page.

I tried a rewrite rule and while it worked it doesn't change the URL and I didn't see much difference in the time it took to load the page. In fact, it seemed to take longer on my local machine running MAMP Pro 3 then the redirect tag did.

I also looked into Reroute plug-in by Trevor Davis which seemed to work about as well as the redirect tag, maybe slightly better.

Any thoughts as to which is a better approach and why a simple index page with a redirect tag on it would take so long to process?

.htaccess should always be faster because it doesn't involve PHP or Craft at all.

But on top of that the {% redirect %} tag should be pretty darn quick.

Upon hitting it, Craft immediately calls Yii's CHttpRequest->redirect(), which sets the redirect header and terminates the current request.


Don't output specific category on entry page With

{% for category in entry.categories.all() %}
    {{ category.title }} {{ not loop.last ? '| ' }}
{% endfor %}

How do I exclude a specific category from displaying?

I might be mistaken, but you can just insert an if block into your loop:

{% set excludedId = 1234 %}

{% for category in entry.categories.all() %}
  {% if category.id != excludedId %}
    {{ category.title }}
    {{ not loop.last ? '|' }}
  {% endif %}
{% endfor %}

That said, this will no longer know whether the "last" item in the loop was excluded. A better solution might be to trim down the collection before beginning the iteration:

{% set excludedId = 1234 %}

{% for category in entry.categories.all() | filter((c) => c.id != excludedId) %}
  {{ category.title }}
  {{ not loop.last ? '|' }}
{% endfor %}

This makes use of the filter filter, which you can pass a "function" of sorts to compare each ID to your excluded one. If the comparison is false, it'll remove it from the collection before the loop starts.

One last option (and possibly the best one) is to adjust the query itself, before it's run:

{% set excludedId = 1234 %}
{% set onlyDesiredCategories = entry.categories.id("not #{excludedId}").all() %}

{% for category in onlyDesiredCategories %}
  {{ category.title }}
  {{ not loop.last ? '|' }}
{% endfor %}

Instead of filtering down from the natural relations, this method attempts to adjust the ElementQuery instance provided by the relation field (entry.categories) by setting the id param to not 1234, meaning that ID will be excluded when the query is executed. I haven't actually tried this lat method, myself, so your mileage may vary.


Element API — Endpoint has an invalid elementType I'm trying the Element API for the first time and getting this error message {"error":{"code":404,"message":"Endpoint has an invalid elementType"}}

I cannot for the life of me figure out what I'm missing... I've read the docs, followed the Mijingo "Creating an Element API video", read Andrew Welch's post (https://nystudio107.com/blog/lazy-loading-with-the-element-api-vuejs) and hunted through Stack Exchange but haven't came across any fixes.

This is from my current element-api.php file:

<?php
namespace Craft;

return [
    'endpoints' => [
        'api/news.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'news'],
            'transformer' => function(EntryModel $entry) {
                return [
                    'title' => $entry->title,
                    'body' => (string) $entry->newsText
                ];
            }
        ],
    ]
];

Previously, I tried changing the code slightly to:

<?php

use craft\elements\Entry;
use craft\helpers\UrlHelper;

return [
    'endpoints' => [
        'news.json' => function() {
            return [
                'elementType' => Entry::class,
                'criteria' => ['section' => 'news'],
                'transformer' => function(Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'jsonUrl' => UrlHelper::url("news/{$entry->id}.json"),
                        'newsTitle' => $entry->newsTitle,
                    ];
                },
            ];
        },
    ]
];

but still no luck. With the second block of code the error message I get is Template not found: api/news.json

Apologies if I'm missing something completely obvious, this is the first time using the plugin, and I don't know PHP, but following along with the Mijingo video helped me understand what was going on.

If anyone has any suggestions to fix this that would be greatly appreciated!

Cheers

Your second example has the correct elementType value (Entry::class with a corresponding Entry import at the top of the file). Alternatively you could do

'elementType' => 'craft\elements\Entry',

The error you’re getting in that example is because you changed the endpoint to just news.json rather than api/news.json. So the request isn’t getting routed to this endpoint in the first place.


Many To Many Plugin Template Help I am using the Many to Many plugin and wondering if the below is possible.

I have a channel called Model ID. Model ID is then related to two other sections, Memory and SSD. I want to be able to link entries from Memory to entries in SSD via the Many To Many Field within Model ID.

Below is a picture, edited, to show the field layout and the information I have within the Model ID entry. The information within the entry is what I need to pull in to my Memory and SSD section but can not figure it out.

I feel like I am missing something very simple that might not be in the read me document for the plugin.

Any help would be appreciated.

Thanks John

So, if I understand you correctly, you're trying to use the Model IDs channel as a middle man? If so, I think you would just need two steps:

To get all SSDs from a Memory Entry

{% set modelIDs = craft.entries.section('MODEL ID SECTION HANDLE').relatedTo(entry).ids() %}
{% set ssds     = craft.entries.section('SSDS SECTION HANDLE').relatedTo(modelIDs).all() %}

To get all Memory from an SSD Entry

{% set modelIDs = craft.entries.section('MODEL ID SECTION HANDLE').relatedTo(entry).ids() %}
{% set memory   = craft.entries.section('MEMORY SECTION HANDLE').relatedTo(modelIDs).all() %}


Calling a setter via craft.app in Twig apologies if this has been asked, I don’t seem to be able to find the solution.
What is the correct way to call craft.app.session.set in a Twig template (or any other setter function for that matter)? I can’t find a working example in the docs for anything other than getters.
To expand, this causes an error:
{# grab initial value, it is empty #}
{% set mySession = craft.app.session.get("mySession") %}
{{ "mySession = #{mySession}" }}

{# set value to 'someValue' - this will cause the error #}
{% craft.app.session.set("mySession", "someValue") %}

{# grab value again, it should now be 'someValue' #}
{% set mySession = craft.app.session.get("mySession") %}
{{ "mySession = #{mySession}" }}

However this works as expected:
{# grab initial value, it is empty #}
{% set mySession = craft.app.session.get("mySession") %}
{{ "mySession = #{mySession}" }}

{# set value to 'someValue' #}
{% set somePointlessVariable = craft.app.session.set("mySession", "someValue") %}

{# grab value again, it’s now 'someValue' #}
{% set mySession = craft.app.session.get("mySession") %}
{{ "mySession = #{mySession}" }}

Surely I don’t need to create some pointless variable just to use the setter function?

I'm curious to know your use case for this, but have you tried using Twig's do tag?
https://twig.symfony.com/doc/2.x/tags/do.html
i.e. {% do craft.app.session.set("mySession", "someValue") %}


Query entries by matrix date fields for event calendar I have a section Events with a matrix field (let's call it dates). The matrix features a single block type with a single date field. One Event can have multiple dates. Think theatre plays with multiple show dates.

Now I'd like to create a list of all events, ordered by the date field. This means that the same entry could show multiple times in the list (once for each date in the matrix field). I want to query all future dates in the matrix, fetch related entries, limit the number of items displayed and support pagination.

Ideally there is something like craft.entries but for matrix fields.

Example

The following example shows three different Event entries, ordered by their dates. Notice how the same entry can appear multiple times.

14/12/01 @8pm - The Great Gatsby (ID #1)
14/12/01 @8pm - Moby Dick (ID #2)
14/12/02 @3pm - Snow White (ID #3)
14/12/02 @5pm - Snow White (ID #3)
15/12/05 @7pm - The Great Gatsby (ID #1)

Can anyone point me in the right direction? I'm not afraid to dive into plugin development (already created a simple "Address" field type with geocoding support) but is there an easier way? Thanks for your time!

I think that in order to do this you are going to need to loop through all events; find eventTimes (within the blocks) that are after the selected date; merge those into an array;  and then return the sorted array. However, by doing so you will loose the ability to easily use pagination.

Perhaps another solution would be to not use matrix blocks at all and instead create two channels: 1 for 'Shows' and 1 for 'Showtimes' (using your theatre analogy), where 'Showtimes' would be related to 'Shows' using an Entries field-type with limit set to 1. Then finding showtimes would be trivial, and would support pagination, etc. (You could even set the showtimes title to be auto-generated from 'related show title + datetime'.)

And if you wanted to display all the showtimes collected nicely on the Shows entry (for the sake of the client), you can use a nice plugin called 'introvert' to show reverse related entries.


Is it possible to get a tweet image when using Twitter plugin I'm using Dukt's very nice Twitter plugin and it's working nicely returning the most recent tweet as I want, however I cannot seem to access the tweet's image. Is this possible?

{% set tweets = craft.twitter.get("statuses/user_timeline.json?screen_name=#{twitterHandle}&count=1&exclude_replies=true&include_rts=true&include_entities=true") %}

I've tried adding &include_entities=true

When I print out the json, I can't seem to see any media URLs. Has anyone else had any joy here? Thanks

There should actually be a entities.media property available in the JSON, when there are images attached to the tweet.

This is what works for me:

{% set tweets = craft.twitter.get('statuses/user_timeline') %}

{% for tweet in tweets %}

{{ tweet.text }}

        {% if tweet.entities.media is defined %}
            {% for item in tweet.entities.media if item.type == 'photo' %}

            {% endfor %}
        {% endif %}

{% endfor %}


Changing the "homepage" url for logged-in users I know I can set  postLoginRedirect in config/general.php to send the user to a specific page after login. Is there a way to grab that value in the template? This came up because I noticed that the {{siteUrl}} href in the default _layout.html template was sending the user to the homepage (index.html), but I'd like to conditionally replace that link for a logged-in user.

Sure, something like this should work (untested):

Home

The above should create an absolute URL to whatever's in your postLoginRedirect config setting, relative to your siteUrl.

Note that if you want an URL relative to your Control Panel (e.g. "dashboard"), you'll want to use cpUrl() instead, i.e.

Home


Craft Commerce not outputting € symbol Within Settings, the cart currency is set to Euros. But when I use:

{{ product.defaultVariant.price | currency(cart.currency) }}

The output is:

¤150.49

Anyone encountered this before?

What does cart.currency return?

The Twig currency filter ultimately uses Yii's CNumberFormatter class. This uses the symbol you are seeing as a default placeholder for the currency symbol if one cannot be determined from the value of the $currency parameter passed to it. This would indicate that the value of cart.currency is not as expected. You'll need to make sure that the cart variable is being set correctly in your template, then this should work.


Form select entries by year For example have the following code:

<form action="">
       <select>
               <option>2015</option>
               <option>2014</option>
               <option>2013</option>
               <option>2012</option>
      </select>

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

how to get a entries of the selected year?

First thing I recommend is to read through the Search Form guide from the Craft documentation.
To explain the rest I'll add some comments to the example code.

form.html

{# Use the `group` filter to get the years, entries were posted in #}
{% set entries = craft.entries.section('news') %}
{% set entriesByYear = entries|group('postDate|date("Y")') %}

<select name="year">

    {# Go through the `year` groups #}
    {% for year, entries in entriesByYear %}
        <option value="{{ year }}">{{ year }}</option>
    {% endfor %}

</select>

results.html

{# Get the params #}
{% set year = craft.request.getParam('year') %}

{# Compose a param in this format: 'and, >= 2014-01-01, < 2015-01-01' #}
{% set dateParam = 'and, >= ' ~ year ~ '-01-01, < ' ~ (year + 1) ~ '-01-01' %}

{# Query and loop through the entries #}
{% set entries = craft.entries.section('news').postDate(dateParam) %}

{% if entries|length %}
    ...
{% endif %}


How to control the format of an asset's Title Is there any way to control the formatting of an asset's title that is created from the filename on upload?

At the moment, if you uploaded a file called Craft-CMS.pdf it would create the title as Craft Cms - where in most cases I you would expect the uppercase of CMS to remain intact.

I see there is a config setting for filenameWordSeparator, but nothing related to the pattern used to created the title - is there anyway I'm not seeing to configure this?

For Craft 2, You can write a plugin that listens to the onBeforeSaveAsset event, and changes the title from the asset parameter to whatever you want. Something like:

if ($event->params['isNewAsset])
{
    $asset = $event->params['asset']
    $asset->getContent()->title = 'My New Title';
}

For Craft 3, you can write a plugin that listens to the BEFORE_HANDLE_FILE event like so:

Event::on(Asset::class, Asset::EVENT_BEFORE_HANDLE_FILE, function(AssetEvent $event) {
    $asset = $event->asset;
    $asset->title = 'My New Title';
}


How to get entries with or it is possible to do like this:

$users = Entry::find()
  ->userLevel('>3')
  ->or group('admin')

So in database level,the sql will go like this:

select * from users
  where users.userLevel > 3 or users.group='admin'

Many many thanks!!

Yes but not like you tried it. You have to work on Yii2 level and not with Crafts Query

// prefix for content column tables
// if you want to select fields in the field layout do
// $prefix . 'fieldHandle'
$prefix = Craft::$app->getContent()->contentTable . '.' . Craft::$app->getFields()->oldFieldColumnPrefix;

$user = User::find()
    ->andWhere(
        new OrCondition(
            ['>','users.userLevel', 3],
            ['=', 'users.group', 'admin']
        )
    )
    ->all();

However: keep in mind this SQL will likely produce errors because there is neither a users.group column nor a users.userLevel column in the database

Just as an example for more complex search:

$prefix = Craft::$app->getContent()->contentTable . '.' . Craft::$app->getFields()->oldFieldColumnPrefix;
$criteria = [
    'where'     => new OrCondition(
        [
            [
                'between',
                $prefix . 'startDate',
                Db::prepareDateForDb($startDateDb),
                Db::prepareDateForDb($endDate)
            ],
            new AndCondition(
                [

                    ['=', $prefix . 'recurring', 1],
                    ['<=', $prefix . 'startDate', $startDateDb->format('Y-m-d H:i:s')]
                ]
            )
        ]
    ),
    'orderBy'   => ['startDate' => SORT_ASC],
    'sectionId' => 10,
];

$query = Entry::find();
\Craft::configure($query, $criteria);


Charge plugin not showing errors on payment fail I am using the Charge plugin.  They payment process happens in a modal.  If I enter in a bad number from one of the stripe test numbers and submit, when the payment fails the modal goes away and no errors are shown.  The errors are not getting loaded into the div set for payment errors.  I do get the errors before form submit but that doesn't help with a bad card or something.

I am getting the error in the cp and can see it but I cannot find anything in their documentation to log this to the view.

I have read here quite a bit and also viewed thier example and I am not doing anything different.  But for some reason I cannot get the declined error to show on the entry page once it returns.

this is the script

<script>
  (function () {
    Stripe.setPublishableKey('{{ craft.charge.getPublicKey() }}');
    $(this).charge('#charge-form', '#payment-errors', '.charge-indicator');
  })();
</script>

Form is almost exactly the same as their example except that I have a few custom fields (those are not the fields with errors in them).

If anyone has any experience with this plugin that can shed some light on how to return a declined card error or any errors that occur after form submission it would be greatly appreciated.

I see this in the cp

This is how I got the errors to show:

{% if charge is defined and (charge.getErrors or charge.user) %}

        {% if charge.getErrors %}
            {% for error in charge.getErrors('general') %}
                {{ error }}
            {% endfor %}
            {% for key, error in charge.getErrors %}
                {% if key != 'general' %}
                    {{ error[0] }}
                {% endif %}
            {% endfor %}
        {% endif %}
        {% if charge.user %}
            {% for key, error in charge.user.getErrors %}
                {% if key != 'general' %}
                    {{ error[0] }}
                {% endif %}
            {% endfor %}
        {% endif %}

{% endif %}

And then included:

Before the submit button (as they are loaded using JS)


Div being removed from Rich Text Field I have a Rich Text Field within a Matrix block. I need to add a div around a section of content but can't do this in the template because it's within multiple Matrix blocks.  Solution would be to add it directly into the Rich Text field in code view but it strips out the div and replaces with p tags on save?

I've tried this suggestion but it didn't work.

As with most questions and problems with Redactor, the answer to this should probably be: don't do it in Redactor.

You could just add a new block type to your Matrix field that does just one thing: add the div tag (or close it, if there's an open one). Another possibility is to do this all programatically, check if it is the first or the last block of a specific type and conditionally add the markup to wrap them in your div.

Have a look at the discussion here, to read more about these solutions:
Solution for Matrix-within-Matrix (or More Robust Table Fields)

And if that's still not flexible enough, you could also have a Super Table within you Matrix (within a Super Table, within...).


Select distinct entries? Here is my situation: I have a bunch of different series (which are each stored in a channel), and there are a bunch of sermons related to each series.

What I need to do is display the most recent entry of each series. Typically I would do this in a SELECT DISTINCT SQL query; How should I go about doing it in Craft?

If I understand your question and structure correctly, then this might work.

{% entries = craft.entries.section('series').limit(null) %}
{% mostRecentSermons = [] %}

{% for entry in entries %}

    {# retrieve most recent sermon related to series #}
    {% set sermon = craft.entries.section('sermons').relatedTo(entry).order('postDate desc').first %}

    {# merge sermon into mostRecentSermons array #}
    {% set mostRecentSermons = mostRecentSermons|merge([sermon]) %}

{% endfor %}

If you need to worry about duplicates then you can use {% if not sermon in mostRecentSermons %} before merging.

You may also want to wrap this in {% cache %}{% endcache %} tags to improve performance.


Entry template category loop repeats URI when HTML added My entry template looks for the category of the entry

{% for category in entry.productCategory %}
      {{ category.uri }}
{% endfor %}

This will output products/[category slug] as I intended. There is only one value in the loop.

As soon as I wrap the category URI in HTML like this:

{% for category in entry.productCategory %}
     view
{% endfor %}

The URI doubles: eg the output is repeated so the template renders {{ category.uri }} as

products/[category slug]/products/[category slug]

Am I missing something in the loop / or Twig behaviour?

Using {{category.uri}} is likely just appending to the page's URL. You can use either {{category.url}} or {{siteUrl~category.uri}} to get the full URL.


Trying to create a new field returns "General Error: 1030 Got error 1 from storage engine" I recently updated the site to 3.5.5, so not sure if this has anything to do with it. It's been a while since the last field we created, so can not say for sure if this is correlated. Database on this site is fairly large, but my host dashboard shows no issue with DB memory or storage.

I restarted my DB server and it fixed the issue. Sorry for the false alarm, but I've never seen something like that before. Should have tried the DB restart before.


Delete Stale Template Caches tasks much larger in Production than Staging I've been running into issues where the Delete Stale Template Caches tasks on my Production environment are running up to 20x longer than on my identical Staging environment. The config/environment settings are the same across both (including devMode being disabled on Stage) but they use separate databases. So I imported my Prod database into my Stage environment just to get complete parity across both environments to try and diagnose the problem.

I edited the same entry on Prod/Staging and hit save, both kick off the DSTC task, but I got ~10,000 steps on Production as opposed to ~500 on Staging.

I copied the SQL row on each database and this is what I get:

Stage:

14  14  1   2   0   263 555 running DeleteStaleTemplateCaches   NULL    {"elementId":["3282","3342","3343","3341","3548","3549","3550","3547","3382","3383","3381","9171","9172","3395","3391","14629","14630","14628","3281"]} 2016-07-14 18:38:46 2016-07-14 18:38:52 d39e2b0f-e6d6-446d-9d2b-30d35ecca378

Production:

16042   16042   1   2   0   439 9864    running DeleteStaleTemplateCaches   NULL    {"elementId":["3282","3342","3343","3341","3548","3549","3550","3547","3382","3383","3381","9171","9172","3395","3391","14629","14630","14628","3281"]} 2016-07-14 18:36:46 2016-07-14 18:37:07 b152c337-2316-45c9-8b29-4716faf41897

The settings of the tasks are the exact same as far as the ElementIds that it involves, but the Stage task is 555 steps while the Production task is 9864. I'm seeing this pretty consistently across all entries - the number of steps in the Production environment is around 20x the Staging on identical entries.

I'm a bit stumped as to why this is happening -- what determines the number of steps involved in any given DSTC task?

EDIT: Another odd thing is that it's kicking off the tasks on entries that don't have any cache tags inside the templates. Again this is only happening in Production, it seems that the Staging site seems to recognize that these templates shouldn't be getting cached in the first place.

First, this is perfectly normal. :)

Have a look at Brandons explanation here on how the cache tag works.

  If the element was added or modified, it queues up a new “Delete Stale
  Template Caches” task, which cycles through the templatecachecriteria
  table to see if there are any cached element queries which (if not
  cached) would have started showing the just-saved element. If the
  query returns the element, its corresponding cache will be deleted.

So, the number of steps corresponds to the number of rows in the templatecachecriteria table in the database.

Why would this be different between staging and production? Probably because you're getting different kind of traffic on the production site than the staging site.

It's important to understand that the cache is tied to the url, so mydomain.com/news and mydomain.com/news?id=212 will result in two different caches being created in the database, and a number of rows in the templatecachecriteria table being created based on the number of criterias created inside the cached code (which can be alot).

The example given above is an example that we encounter a lot, where when an old site is replaced by a new one, there will still be a lot of links pointing to the new one. If these aren't handled correctly by either rewriting them to new url's, or returning 404's, this could result in many old urls generating new caches for the same page.

The recommended way to avoid this is to use the globally keyword, and using the request path as the key, see the example in the "using key" section of the docs for {% cache %}.

Another common caveat is that there are caches on the 404 page that is not declared as globally, for instance a menu that needs a selected state or something. Then all urls that results in a 404 not found page, will create new caches with new criterias in templatecachecriteria. I've seen examples where this will eventually just kill the server because of the number of criterias that are rerun when an entry is saved.

If I were you I'd have a look in the templatecaches table, and look at the path column to identify the paths of the created caches. This will often reveal groups of urls which generates more caches than they ideally should, and you could work from there to reduce the number.


Pass custom variable to view Coming from a Yii2 background, I am accustomed to doing things in an MVC way.

I have set up a demo Craft CMS application to have a play around with. I've created a "singles" page (homepage) and got it displaying data. What I want to know is, how do I pass custom variables to the view?

For example I have a function that fetches tweets from my Twitter account, I would like this data to be displayed on the homepage. In Yii2 I would normally do the following:

<?php

namespace app\controllers;

use yii\web\Controller;
use app\services\TwitterFeedService;

class SiteController extends Controller
{
    public function index()
    {
        $twitterFeed = TwitterFeedService::getTweets();

        return $this->render('index', [
            'twitterFeed' => $twitterFeed,
        ]);
    }
}

But since there is no controller or action for my homepage at the moment, I am not sure how I would go about doing this in Craft CMS.

Try reading this.

return $this->render('index', ['twitterFeed' => $twitterFeed]); is correct in craft 3 you just need to do some custom routing in order to reroute the homepage to your controller/action.


Image Transforms not happening Apologies if this has come up before. I did check but the previous post referred to version 2.x and was regarding a bug.

I have set up 2 image transforms for images but nothing works. The assets folder is writable. Files upload without issues and I can crop them, rotate them, etc. but Image Transforms don't work.

Anyone know what the issue could be?

What Mike Pierce said in the comments above is your answer; Craft doesn't create the image transforms until you ask for them.

So for instance, in a index.twig file you might do something like:

...which would output the image. If instead you wanted to output the image transformed based on one of the transforms you made in the AdminCP, you'd do:

...where someTransform is the handle to the transform you created in the AdminCP backend. Craft will then perform the image transform, and it'll output the transformed image on the frontend.

The next time that the same transform on the same image is requested, rather than doing the transform all over again, it'll just use the already transformed image that it's saved to disk.


Free shipping discount on whole order doesn't appear as adjustment TL;DR : Free shipping on order discounts don't appear as a discount (or any type of) adjuster. So how do I check if a free shipping discount has been applied?
Sorry for the long post - hopefully it explains what I'm trying to achieve!
I have a custom module that shows and hides shipping options depending on a few factors.
At the moment the client has a discount that allows Free Shipping on all orders over $200. They have set this up and ticked the "Remove all shipping costs from the order"

This is working well and no shipping is being applied correctly at the right time. However the only thing that shows you have free shipping is that the shipping price is 0.
To make it clearer to the user I'd like to display a notice to show they are getting free shipping. I can't do this using the shipping total as that may be zero simply because they haven't selected anything yet.
So my idea was that I could use the adjusters to check if the discount was being applied, but this type of discount doesn't seem to appear in the list of adjusters. Here are a couple of scenarios where I have listed all adjusters:
1.) Order with normal shipping applied: - shipping and tax adjusters applied.

2.) Order over $200 (free shipping) - only tax adjuster applied.

3.) Order over $200 (free shipping) and 10% discount applied.

So my question is how do I detect that a free shipping discount has been applied to an order? Should the discount appear as an adjuster? Is there a different way to detect what discounts have been applied?
Thanks

For anyone else viewing this question - until there is a zero value adjuster as mentioned by Luke, my solution has been to simply do the discount checks in my custom module.
A little messy but it'll do the job for now.


How can I query for entries that have one of two Lightswitch fields enabled? I have two Lightswitch fields – lightswitchA and lightswitchB – and I need to pull all entries in a certain section, that have one or both of these fields enabled.

Is it possible to execute such a query with a standard ElementCriteriaModel, or do I need to construct a custom query? If I need to construct a custom query, how would that look (in a template, not a plugin)?

I also need to paginate the results, using the {% paginate %} tag.

Craft 3

Thanks to the where() function this has become easy in Craft 3.

{% set query = craft.entries.where([
    'or',
    {'field_lightswitchA': 1},
    {'field_lightswitchB': 1},
]) %}

Craft 2

Custom field parameters are being added with and-logic, so you'd indeed have to
do it from PHP with custom dbCommands.

You could either approach it with converting a criteria model to a dbCommand object using the buildElementsQuery method, or you listen for elements.buildElementsQuery events and modify the dbCommand if the criteria model meets certain conditions.

craft()->on('elements.buildElementsQuery', function(Event $event) {
    $criteria = $event->params['criteria'];
    $dbCommand = $event->params['query'];

    if (isset($criteria->or_lightswitchA) && isset($criteria->or_lightswitchB)) {
        $params = array(
            ':lightswitchA_value' => $criteria->or_lightswitchA,
            ':lightswitchB_value' => $criteria->or_lightswitchB,
        );

        $conditions = array('or',
            'content.field_lightswitchA=:lightswitchA_value',
            'content.field_lightswitchB=:lightswitchB_value',
        );

        $dbCommand->andWhere($conditions, $params);
    }
});

Here's how you'd trigger that listener from your criteria model in Twig.

{% set entries = craft.entries({
    or_lightswitchA: 1,
    or_lightswitchB: 1,
}) %}

Here's example code for the buildElementsQuery approach, the problem with this is that
once you've converted to dbCommands you can't go back to a criteria model (which would be
necessary to use the result with Craft's paginate tag for example).

public function myCustomCriteria($criteria, $lightswitchA_value, $lightswitchB_value)
{
    $dbCommand = craft()->elements->buildElementsQuery($criteria);

    $params = array(
        ':lightswitchA_value' => $lightswitchA_value,
        ':lightswitchB_value' => $lightswitchB_value,
    );

    $conditions = array('or',
        'content.field_lightswitchA=:lightswitchA_value',
        'content.field_lightswitchB=:lightswitchB_value',
    );

    $dbCommand->andWhere($conditions, $params);

    $results = $dbCommand->queryAll();

    return EntryModel::populateModels($results);
}


Import a large number of assets via feedme I have 224,559 assets (images) I need to import and assign to entries. Assets are currently stored in folders that match their original asset id. Imported assets will be stored on s3. I'm using feedme for the import so far.

I have json for both the assets and entries. A typical record for assets looks like:

{
    "title": "Ceiling decor at The Atomic Tiki in Memphis, TN",
    "import": {
        "key": "asset-1197-16772",
        "source": "TikiTime",
        "sourceUrl": "https://tikitime.com/images/locations/1197/16772_jumbo.JPG",
        "outputPath": "/Volumes/Sites/Personal/mytiki.life/web/uploads/master-assets/tiki-bars/1197/16772.jpg",
        "date": "2020-04-23T08:09:01+00:00"
    }
},

A typical entry json entry looks like:

{
    "title": "Sun Hung Heung Green Bucket",
    "originalId": 2,
    "assets": [
        {
            "title": "Sun Hung Heung Green Bucket - 2-153663",
            "key": "ooga-mooga-asset-2-153663",
            "outputPath": "/Volumes/Sites/Personal/mytiki.life/web/uploads/master-assets/tiki-mugs/2/153663.jpg"
        },
        {
            "title": "Sun Hung Heung Green Bucket - 2-153664",
            "key": "ooga-mooga-asset-2-153664",
            "outputPath": "/Volumes/Sites/Personal/mytiki.life/web/uploads/master-assets/tiki-mugs/2/153664.jpg"
        }
    ]
}

The import.sourceUrl property is the local file path of the file. All the images are broken up into folders that match their original entry ids.

I've setup a field in the entry channel for the asset relationship that's restricted to a single folder with a subdirectory pattern: {section.handle|kebab}/{id} -> tiki-mugs/875

Obviously the new (imported) entry id doesn't match the old entry id so… I could export all the new entry ids and then rename all the folders to match but that would be painful.

I'm having trouble figuring out how to relate the assets with the entries and get them in the correct directories.

I thought I could possibly leave the files in their current location and run the asset index command. That would create the records. Then somehow assign them in feedme. If I did that would the assets be moved when the entry gets saved?

Any other ideas?

I ended up writing my own command line importer rather than using feedme. This meant I could be much more flexible with my import.

I also had to break up the sub folders into groups given the Assets admin panel cannot deal with 1000's of sub folders. See: https://github.com/craftcms/cms/issues/2547#issuecomment-537934580


Override an event's param array? I'm having problems setting up an event. It gets triggered and I can access the event's params array, but I can't override the value like I can with Craft's default events.

MyPlugin_myServiceService.php

public function setTest()
{
    $test = true;

    $event = new Event($this, array(
        'test' => $test
    ));

    $this->onAfterSetTest($event);

    return $test;
}

public function onAfterSetTest(Event $event)
{
    $this->raiseEvent('onAfterSetTest', $event);
}

MyOtherPluginPlugin.php

craft()->on('myPlugin_myService.afterSetTest', function(Event $event)
{
    $event->params['test'] = false;
});

Not sure what I'm doing wrong but
craft()->myPlugin_myService->setTest() returns true.

It looks like it doesn't updated the variables passed to the event directly (referenced) and you have to access the value from the $event object.

public function setTest()
{
    // ...

    $test = $event->params['test']

    return $test;
}


Craft task send mails at specific date I already learned how to create a task from this page but I would like to know how to run this task?
I'm creating a portal where users are allowed to give their votes and discuss several projects. Backend users can create different phases and declare a start and an end date and a few days before these phases end all members/participants of this phase should receive an email.
I know how to send the mail, I know how to create the task but I don't know how to start the task 1, 3 and 7 days before a specific date.
Do those steps run every single second?
public function runStep($step)
{
    $criteria = craft()->elements->getCriteria(ElementType::Category);
    $criteria->group = 'phase';
    if($criteria->count()){
        $phases =  $criteria->find();
        foreach ($phases as $phase){
            $now = time();
            $threeDaysBefore = $now - (60 * 60 * 24 * 3); //Seconds * Minutes * Hours * Days
            $OneDaysBefore   = $now - (60 * 60 * 24 * 1); //Seconds * Minutes * Hours * Days
            $endTime = $phase->phaseEndDate->getTimestamp();
            if($endTime == $OneDaysBefore || $endTime == $threeDaysBefore){
                 craft()->myplugin->sendMailToUser();
            }
        }
    }
}

Where do I activate the task? Do I run craft()->tasks->createTask(/*parameter*/) in my plugin init() function?
And my last question: how can I debug my function? In my chrome network tap I receive a taskInfo every second but I can't var_dump() something from my runstep function.
Thank you very much

Might I suggest that a Craft task might not be the best way to pull off what you're trying to achieve.

By default, they will be triggered by the next control panel request, no matter when that occurs.

Sure you could build in some timing logic in your plugin, or set the runTasksAutomatically config setting to false and have a cron job hit the task at your set schedule, but that all seems overly complicated.

Just setup an independent cron job to fire when you need your logic to run and have it hit a custom plugin's controller's action and run your logic directly outside of Craft's task implementation.


Edit a table field type from the front end Similar to this question, I'm trying to make a table field type editable from a front end form.

When I update from the CP, the changes are reflected on the front end, but the following code doesn't allow updating from the front end form itself.

Is there anything I'm missing?

(perhaps adding how each field type can be edited from a front end form should be added to the docs)

    {% for row in currentUser.providerCredentials %}

        Institution
        <input type="text" id="accreditingInstitution" name="fields[accreditingInstitution][]" value="{{ row.accreditingInstitution }}">

    {% endfor %}

Each input name needs to have the following format:

fields[FieldHandle][RowId][ColId]

It doesn’t matter what you set RowId to, as long as it’s the same for all of the columns in that row. (Table fields in the CP just get incrementing row IDs - 0, 1, 2, etc.)

ColId, on the other hand, needs to be based on your actual column IDs. The only way to get those would be to inspect a Table field’s HTML on your Edit Entry page:

Each column will have an ID in the format of colN. “N” won’t necessarily be nth column in the table though; it will be the nth column you’ve created in the table since the field was first created, regardless of how they are ordered or whether any columns had ever been deleted. Which is why it’s best to just inspect the table HTML rather than trying to guess what the column ID will be.

So in your case, that  line should look something like this:

<input type="text" id="accreditingInstitution" name="fields[providerCredentials][0][col1]" value="{{ row.accreditingInstitution }}">


White Screen of Death Our users were getting a blank white screen on our homepage yesterday. Inspecting revealed it was just an empty page. All other pages on the site worked fine. I ended up clearing the cache and it resolved the issue.

Any idea why the cache would have been serving an empty page instead of the home page?

Honestly, that's pretty much impossible to say, it could be pretty much anything – though a white screen is often due to PHP errors, in which case you might find a clue in your log files (located at /craft/storage/runtime/logs (search for [error]). Your web server's error logs might hold some clues as well.


How do I add Alt Image Tags to my photos? I am trying to figure out how to add alt image tags to my photos. I was under the impression that the "file name" served as the alt image tag in Craft CMS, but no such alt tags are populating...and furthermore...I really have no idea where I can add them. Can I do this from the assets field?

Out of the box, you can use the image "Title" as alt text.  Since it is already configured - you don't need to add any additional fields.  Then you can output this in your twig template as:

{% set image = image.yourImageField.one() %}

For semantics, you may not want to use the "Title" field.  Or, you may be using "Title" for something else.  In that case, you can add a new text field to your asset called "Alt Text".  It will then appear right below "Title" in your image/asset editing dialogue.

{% set image = image.yourImageField.one() %}


Problem setting security key when installing Craft 3 I'm new to Composer and am using a Mac along with MAMP as a local web server. I've installed Composer but it's referencing an old PHP 5 version that must be the default on my Mac.

I was able to install Craft 3 via Composer by adding the --ignore-platform-reqs flag as per https://docs.craftcms.com/v3/installation.html#downloading-with-composer

The Craft 3 starter project files were all added successfully. However, at the end of the install output in terminal was the following:

@php craft setup/welcome
Craft requires PHP 7.0 or later.

If I navigate to the project install directory and try running ./craft setup I get the same message "Craft requires PHP 7.0 or later".

The installation docs did say you could alternatively edit the .env file directly, so I entered the database details in there instead. But when I went to access the browser install wizard, I got errors about the security key being missing.

Now I worked around that by just generating a random 32 character string myself and entering this for the SECURITY_KEY setting in the .env file & was then able to complete the install wizard.

However, I'm wondering if that is OK to do? I'm concerned that there may be a particular format needed etc and that just pasting in my own key could cause issues down the line.

Ideally I'd prefer to be able to just complete the standard setup via terminal instead and have the key config automatically set there. Is there a way I can get the craft setup command to use the newer PHP 7+ available from MAMP? Or is there an easy way to update the default PHP version Composer references without disturbing the rest of my Mac?

Add this line to your ~/.bash_profile file

export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php/php7.0.0/bin:${PATH}"

Assuming your php7 version in mamp is 7.0.0 of course.

Here is a link with a few more steps if you aren't sure how to edit that file - https://gist.github.com/irazasyed/5987693


FTP Plugin Not Showing Up I am working on a client site and trying to upload the following plugin:

https://github.com/craftcms/guest-entries

The directions instructed me to install the app via composer in my project folderj via composer.

Can I use composer to install the plugin into a random folder, then FTP upload the same into my client's craft plugins folder?

Thanks,

If you FTP up the entire vendor folder, all of the same libraries should be available. Make sure it is properly installed locally, first.


Returning entries based on Relationships across different category groups using 'and' I'm trying to figure out how to set up my relatedTo paramaters to do a category search. Normally it's not a problem but in this case I need something more complex than normal.

I have multiple category groups. Within each group I need to use an "or" condition. So entries are returned if they match any categories in that group.

But across the different groups I need to apply an "and" condition.

i.e. Group 1 is "colours", Group 2 is "size"

So if someone selects:
Group 1: black, blue
Group 2: small

I want to return any entries that are (black OR blue) AND (small)

Setting the 'or' condition within a group is no problem but I'm stumped on how I can merge the different sets of parameters together to get the desired results.

This is a truncated version of what I have so far, just showing 2 of my groups.

{# clear everything #}
{% set colourQuery = '' %}
{% set sizeQuery = '' %}

{# get all the search query parameters #}
{% set colour = craft.request.getParam('colour') %}
{% set size = craft.request.getParam('size') %}

{% set colourQuery = colour | join(',') %}
{% set sizeQuery = size | join(',') %}

{# colour #}
{% set colourParams = ['or'] %}
{% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
{% endfor %}

{# size #}
{% set sizeParams = ['or'] %}
{% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
{% endfor %}

Then I build the criteria... I'm sure this is where I'm going wrong

{# build criteria #}
{% set relatedParams = [] %}

{% set relatedParams = relatedParams | merge(colourParams) %}
{% set relatedParams = relatedParams | merge(sizeParams) %}

I've also tried

{# build criteria #}
{% set relatedParams = [
        ['and', colourParams],
        ['and', sizeParams],
    ]
%}

I'm using relatedParams like so:

{% set products = craft.commerce.products('products').relatedTo(relatedParams).order(sortString).limit(numPerPage) %}

So, my question is how should I join those different paramater arrays in order to get what I need?

After some help from @RobinSchambach on the Craft Slack and a bit of trial and error I got to this, truncated for brevity.

{# clear everything #}
    {% set colourQuery = '' %}
    {% set sizeQuery = '' %}

    {# get all the search query parameters #}
    {% set colour = craft.request.getParam('colour') %}
    {% set size = craft.request.getParam('size') %}

    {% set colourQuery = colour | join(',') %}
    {% set sizeQuery = size | join(',') %}

    {# colour #}
    {% set colourParams = ['or'] %}
    {% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# size #}
    {% set sizeParams = ['or'] %}
    {% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# build criteria #}
    {% set relatedParams = ['and'] %}
    {% if colourQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : colourQuery}]) %}
    {% endif %}

    {% if sizeQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : sizeQuery}]) %}
    {% endif %}

The key difference is that I'm using the Category IDs rather than their slugs. I'm then passing them as comma delimited strings into the array to build up the criteria.

I'm working on refining this a bit more but it's now working as expected.


How do I migrate a Wordpress project to Craft CMS? How do I migrate my Wordpress project to Craft CMS?

What would be the best way?

At this point in time, you have a few options:

Import Plugins

As of this post, there are a few partial import plugins available and rumors that a few others might be on their way.

Sprout Import - Sprout Import supports over 40 data types such as Entries, Users, Assets, Products, Orders, Forms, Email, and Redirects; and more can be added as needed via plugin integrations.
Feed Me - Feed Me is a Craft plugin for super-simple importing of content, either once-off or at regular intervals. With support for XML, RSS, ATOM or JSON feeds, you'll be able to import your content as Entries, Categories, Craft Commerce Products (and variants), and more.
Import - Handles Entries and allows you to map them to fields in
your Entries Sections
EE/Craft Import - While this plugin has EE
in it's title, it looks like it's framed more around XML imports in
general and promotes itself as being a starting point if you have
other custom import needs.

Import Service

Full disclosure, my company offers a migration service to help folks migrate to Craft.  We use a combination of a private plugin, custom scripts, and manual processes when necessary.  We find, in most cases, many things about your data architecture can be improved when migrating to Craft.  So, while an import plugin can help with some heavy lifting, being able to make architecture decisions on how to import certain types of content outside of what a plugin would allow is useful for improving user experience and getting the most of of Craft.  For example, content that fits nicely in Singles and Matrix Fields don't always have equivalents in other CMSs, yet frequently other CMSs have content that fits these use cases.

The Great Migration

Do It Yourself

If you want to roll up your sleeves, you can create a utility plugin or script for your own needs.  If you need to go this route, you probably want to import your data using Craft's Service Layer and the save methods for each of the individual Elements you are importing.

You can see some examples of this in the plugins available on GitHub above, or read up more on the service layer in the Craft docs.  A good place to start may be the Entries Service.

You will need to get your data into a format that matches the EntryModel and then you can pass that information to the saveEntry method:

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

That's a fairly simple explanation, but the gist of where to start. All of the other Elements are going to have similar Models and save methods you can use to import your data.


Nested IA Structure - What's the best way to get it set up? I'm beginning to work on my first Craft CMS website. (I'm really excited!) I've read a ton of documentation and am getting my head around setting up a structure within the system.

The website will be fairly large, and the site structure a few levels deep.

For the IA, say I have:

/ (Home)
/about  (About Overview Page, contains information from all subpages)
/about/team (bios of team members)
/about/history (content page)
/about/contact (contact form)
/industries (overview of all industries, contains content from subpages)
/industries/medical (industry overview page, contains contact from about, featured documents, featured case study, etc)
/industries/medical/about (content)
/industries/medical/history (content)
/industries/medical/documents (content + documents)
/industries/medical/case-studies (content + case studies)
/industries/medical/portfolio
/industries/financial
/industries/financial/about
/industries/financial/history
/industries/financial/documents
/industries/financial/case-studies
/industries/financial/portfolio
...(etc)

You get the point.

So, I believe that for the majority of the data (documents, case studies, portfolio items) I will set up channels to house that data. (Is that the way it should be done? Set up channels and then have a "Industry" select field where the admin can choose what industry the entry belongs to?)

How do I get this structure set up? Is it just a matter of adding templates into the corresponding /templates/ folders in the system?

I've gone into Admin > Sections and created an "Industries" section, and then I created entry types for: Content, Documents, Case Studies, Portfolio Items, Forms, etc.  Will I basically use that index.html template in /templates/industries/index to route ALL of the requests across all subpages in that section? i.e. get the one part of the slug to determine the active industry, and then the second segment to determine what page and what template to show?

If so, then what role would the Entry Template have?

Am I going about this all wrong?

I think once I understand this piece of it, everything is going to click.

Thank you in advance for your help! Happy to clarify anything to help me get clarity ;)

UPDATE: Upon further reading, I think I'm getting it. The entries are really just containers for the data, the sections are a way of organizing that data. I just use routes to handle the site structure. Is that correct?

Lots of question so I'll describe how I would do it more or less. Ask if you want more info.

/ - single page type.

/about - single page type.

/industries - single page type.

/about/{slug} - structure page type (structure offers nested entries)

/industries/{slug} - structure page type

You cannot create /about entry within structure with slug like /about/{slug} - thats why /about is a seperate single page type page.
Of course you can create single structure with {slug} as url - then /about and /industries could be created within structure section. Note: with many entries it is harder to handle in CP.

About structure would have following entry types:

bios
contentPage
contactForm

CP Section edit screen

CP Entries:

about/_entry template would look like this:

{% extends "base_template" %}
{% block body %}
    {% switch entry.type %}
        {% case "bios" %}
            {% include "about/bios" %}
        {% case "contentPage" %}
            {% include "about/content_page" %}
        {% case "contactForm" %}
            {% include "about/contact_form" %}
    {% endswitch %}
{% endblock %}

or it could be (but I prefer first approach)

{% extends "base_template" %}
{% block body %}
    {% include "about/" ~ entry.type %} (filename == entry type)
{% endblock %}

Channel/structure sections can have multiple entry types. All of them use template defined by Entry Template - thats why we include other templates based on entry type.

/about, /industries single page template:

To fetch data from all subpages you can either hardcode it to fetch entries from section like this:

{%- set entries = craft.entries({
    section: 'aboutSection',
    order: 'postDate desc',
    limit: 20
}) -%}

{%- for entry in entries -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

Or you can add entry field (lets call it subpages) to the page and display it like this:

{%- for entry in entry.subpages -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

With field approach you can change content without changing the code.

Here is hybrid - use query when no entries assigned to entry field:

{%- set entries = entry.subpages %}

{% if entries.total() < 1 %}
    {%- set entries = craft.entries({
        section: 'aboutSection',
        order: 'postDate desc',
        limit: 20
    }) -%}
{% endif %}

{%- for entry in entries -%}

{{ entry.title }}

    //use switch to display data specific to entry type
{%- endfor -%}

Similar industries section:

CP Section create page

CP Entries:

UPDATE

Industries Overview entry type template

Here you could query items like so:

{%- set entries = entry.chrildren -%}
{%- set entries = entry.chrildren.descendantDist(n) -%} n levels below entry
{%- set entries = entry.chrildren.type('content') -%} specific type of children
{%- set entries = entry.chrildren.type('content').with(['field', 'field']) -%} .with() helps reduce SQL queries

.children returns ElementCriteriaModel same as craft.entries so all methods here apply.

Or again you can add entry field and display specific children.

UPDATE 2

Q: In the case of the Medical > Portfolio being a single entry type WITHIN a structure, I'm assuming individual Portfolio Items would be housed within a Channel of their own?

Yes, that is one approach. To achieve this you would create a new section with URLs disabled (unless you want portfolio items to be accessible via URL - ex. separate page) like so:

Then you just query those items. Oh, I used Stucture instead of Channel - in addition to nested entries, Structure allows to reorder entries.

{% switch entry.type %}
    {% case "medicalPortfolio" %}
        {%- set entries = craft.entries.section('medicalPortfolioItemsSection') -%}
        {% include "industries/portfolio" with {"entries": entries} %}
        ...
{% endswitch %}

Important thing here is to create additional entry type per industry so you can query proper portfolio items. Also new section per industry. It is not good solution here because we duplicate things.

Another way is to use Matrix field to define portfolio item. This way you just use Portfolio entry type with Matrix field within Industries structure.


How to Check All Users against UserGroup How can i check if ANY users exist in a particular User Group? I know how to check the current user but not ALL users.

Got it all sorted:

{% if craft.users.group('myusergroup').total() > 0 %}


Asset Changes in v3.0 This is primarily directed to P&T, but I'm working on a project which is heavily using/extending Craft Assets.  I noticed in the Asset Service there is a reference to breaking changes in Craft 3.0.  I don't want to get too far down the road with this to realize it will have to be refactored.

I'm sure you're not willing to give a 3.0 release date, but any indication to what these change will look like or when they will happen is helpful.

Craft’s assets functionality is getting refactored in Craft 3, so anything you do with those APIs today will need to be updated when 3.0 comes out.

The silver lining for you is, literally every plugin will need to be updated for Craft 3 (due to us moving to Yii 2), so we are planning on having a several month-long beta period where we will work with plugin developers to get their plugins updated, before the official public release. So we will be happy to work with you on updating your plugin during that period.

As far as an ETA, I couldn’t say. Craft 2 still has a lot of shelf life ahead of it.


New entries not appearing on template page My client has been adding some new entries in a channel called Products. These are using different templates that are selected when creating the entry.

The entries on a few different template types are no longer appearing in the last few days. I have checked that the templates have all the correct field handles and there doesn't seem to be anything missing. I have also tried clearing the cache.

Does anyone have any idea why new entries may not be appearing?

Are there more than 100 entries in the products channel? If so, you'll need to specify the limit. All Craft requests are limited to 100 by default.

{% for entry in craft.entries.products.limit(null) %}

If not, please post your template code :)


Randomly listing entries in more then one section I have created 12 sponsorship ads for my website using a “sponsor” category.

On my home page I have four sponsorship sections, each holding three sponsorship ads.

How can I randomly distribute those 12 sponsorship ads among the four sponsorship areas with each homepage load?

I would just slice the randomized array of categories:

{% set ads = craft.categories({
    group: 'ads',
    order: 'RAND()'
}) %}

{% for ad in ads|slice(0, 2) %}
    {{ ad.externalUrl }}
{% endfor %}

{% for ad in ads|slice(2, 4) %}
    {{ ad.externalUrl }}
{% endfor %}


Have the country in craft.commerce.countriesList default Is there a way I can have the array from craft.commerce.countriesList automatically default to the country my store is in?

Not particularly proud of this code, but if you want to do it from Twig, something like this:

{% set countryList = ['United Kingdom', 'United States'] %}

{% for country in craft.commerce.countriesList() %}
    {% if country != 'United Kingdom' and country != 'United States' %}
        {% set countryList = countryList|merge([country]) %}
    {% endif %}
{% endfor %}

    {% for country in countryList %}

{{ country }}

    {% endfor %}


How do you wrap text with HTML within a Plain Text field? I have a Plain Text field used for product names. Some of these product names have a Registration Mark or a Trademark, which needs to be formatted within a superscript.

Here is code within my template:

{{ product.name | replace({'®': '®' }) }}

Which publishes this:

Acme ABC Widget®

When what I really want to achieve is this:

Acme ABC Widget®

Does Craft persistently render Plain Text fields as raw text? I was hoping Twig filters could extend the use of Craft's Plain Text field.

My preference is to continue using the Plain Text field to avoid additional formatting breaking the layout.

You can use the raw Twig filter. Try this:

{{ product.name | replace({'®': '<sup>®</sup>' })|raw }}


How can I get custom user registration field parameters I am allowing users to register on my site. I want to have the field "full name" on the registration page which, from there I will eventually split that value to populate the first name & last name fields for each user within the CP.

I have the actual in put in place:

twig

Full Name

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

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

I have created a plugin to grab the value of the fullName input. I am using the init() method to listen for the saveUser event which is working perfectly.

MyPlugin.php

public function init()
{
    craft()->on('users.saveUser', function (Event $event) {
        error_log('-- saveUser event called --');
        error_log(print_r($event, true));

        if ($event->params['isNewUser']) {
            error_log('-- creating a new user --');

            error_log($event->params['fullName']);

            // split the fullname into firstname & lastname

            // populate first name

            // populate last name

            // save the new user
        } else {
            error_log('-- updating an existing user --');
        }
    });
}

I can see the data come through in the logs, but I'm not sure how to get to it.

error_log

...
[_attributes:Craft\BaseModel:private] => Array
                            (
                                [locale] => en_us
                                [elementId] => 123
                                [fullName] => aaa bbb
                                [id] => 123
                            )
...

The "fullName" parameter is getting populated, but when I log the out put:

MyPlugin.php

error_log($event->params['fullName']);

I am getting the error Undefined index: fullName. The user is getting created.

I can get to the data using this:

craft()->request->getPost('fields.fullName');

But then I'm not sure how to get that back into the user model so it gets saved.

EDIT

Sigh, well if it isn't obvious I don't give up too easily. I am able to capture the data like this. Is this the correct way? I will have a large number of registrations, so I'm trying to do things the correct way as much as possible.

MyPlugin.php

$event->params['fullName'] = craft()->request->getPost('fields.fullName');
error_log($event->params['fullName']);  // aaa bbb

Here is is in the CP:

The trick I'm seeing now is how to inject (for lack of better words) the values from fullName into firstName and lastName.

Here is what I am using to try to do that (without much success)

$name = explode(' ', craft()->request->getPost('fields.fullName'));
$lastName = array_pop($name);
$firstName = implode(' ', $name);

$event->params['fullName'] = craft()->request->getPost('fields.fullName');
$event->params['firstName'] = $firstName;
$event->params['lastName'] = $lastName;

"Full Name" (as you can see in the attachment) is getting populated, but "First Name" and "Last Name" are not. In the logs I can see it:

 [isNewUser] => 1
 [fullName] => aaa bbb
 [firstName] => aaa
 [lastName] => bbb

But the First Name & Last Name fields in the user account tab are not getting populated.

From the onSaveUser event docs, there are two parameters that are passed to everyone listening.  One is isNewUser, which you're accessing correctly: $event->params['isNewUser'].  But the other is user, which is a full-blown UserModel object that you can access the properties of.

But onSaveUser isn't the event you want, since you want to make changes to the user before they've been saved.  You want onBeforeSaveUser, which has the exact same parameters.

Having said that, names are tricky things around the globe.  I highly recommend reading this article on falsehoods that programmers believe about names.

Here is some code that should work for the most basic use cases.

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

    // Only do this for new users.
    if ($event->params['isNewUser'])
    {
        $fullName = craft()->request->getPost('fields.fullName');

        // Make sure this isn't a user being saved from the control panel.
        if ($fullName)
        {
            $name = explode(' ', $fullName);

            // No spaces, it could be Madonna or Cher.
            if (count($name) == 1)
            {
                $firstName = $name[0];
                $lastName = '';
            }
            // It's a "normal" first and last name.
            else if ($count($name) == 2)
            {
                $firstName = $name[0];
                $lastName = $name[1];
            }
            else
            {
                // The first element is the first name. Combine the rest into a last name separated by spaces.
                $firstName = array_pop($name);
                $lastName = implode(' ', $name);
            }

            // Grab the user.
            $user = $event->params['user'];

            $user->firstName = $firstName;
            $user->lastName = $lastName;
        }
    }
}

Note that UserModel already has a getFullName method that does some basic logic combining the firstName and lastName properties.


Craft Internal Server Error I am getting the following error:

Internal Server Error
CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #34 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'pottings_website.sources1.sortOrder' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

I have no idea how to fix it.

Its Craft 2.6.2911
PHP 5.6

I have tried the methods answered in this similar question:

Getting this SQL Error: GROUP BY incompatible with sql_mode=only_full_group_by

To fix my issue all I did was edit this file:

nano /etc/my.cnf

with the following line:

sql_mode="NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES"

The website was back up and running instantly.


How to disable the Javascript "actions/queue/run" on frontend? After upgraded our Craft from 3.3 to 3.4.14 we have noticed that there is a new Javascript on the footer of the homepage (frontend) that runs "index.php?p=actions/queue/run".

We run the tasks via crontab and there is no need for that.

How can we disable it on the frontend?

Thank you

If you set runQueueAutomatically to false in your config/general.php file, that will disable that behavior.


Install instructions I'm having difficulties following the install instructions found at https://docs.craftcms.com/v3/installation.html. I've ssh'd into my server, and I'm running composer to install Craft, as directed in step 1.

Because I've run Composer, the instructions say I can probably safely skip steps 2 and 3. Awesome.

Step 4: Create a database... now wait, when installing Craft via Composer, it gave me the option of running setup from the terminal - which I did. And during this, it asked for database driver, server or IP name, database name, etc. All stuff I needed to know way before I got to step 4.

Step 5. Setup a webserver. Guessing these instructions are specific for local installs? Perhaps this should be made clearer?

Step 6. Run the Setup Wizard. Again... didn't I do this in step one?

After running setup from Step 1, it finished with this:

> save the first user ... done
> save the email settings ... done
*** installed Craft successfully (time: 3.718s)

Looks to me as if everything is as should be. According to the instructions, I should be able to access my new Craft site from my web browser.

Not so much.

I've been having a lot of issues getting Craft 3 to run (if you look at my post history, I've asked like 3 or 4 questions over the last few days related to installation). I don't think I'm that stupid (but I've been proven wrong before!), so I'm not sure why this has been so challenging to me.

Can anyone possibly explain where I'm going wrong?

If that's what you see when you go to the URL, then you probably don't have the server root set properly. It should point to the web/ directory, not the project root.

Some more helpful Craft setup info can be found here: Setting up a New Craft CMS 3 Project

Typically you do the install in local dev, and then have some kind of a deployment process to deploy it to your staging/production servers.


How do I setup my fields for a tumblr-like blog My blog has different post types, e.g. full blog post, quick status, quote, image post, how would I go about it? Is the logical way to setup a single Matrix Field with each block representing a different post type? Is there a better way of doing it?

Stating the obvious for clarity. A full blog post would have the usual stuff (title, body, image). Status has just content without a title, it's just a quick note. Quote has text and quote author and link, again no title.

I definitely would avoid using a Matrix field to add each of these types, as they'd all belong to a single entry, which isn't what you want to do (it’d get really unwieldy, really fast!).

What you're looking to do is use different entry types in your blog settings. Each entry type can have a different field layout, so you could then switch between each.

Here’s a blog article that covers the exact thing you’re trying to do.


Save out Backup Database to local file I've inherited a Craft 2 site to do maintenance. I don't yet have access to production server. I need to grab the production server DB to run locally on my machine. When I click "Backup Database" from the sites cms back-end, it doesn't appear to download a local .sql file. I assume it's backing up as a file on the actual server. How can I download that backup locally?

If you're in the Craft 2 control panel, and you click on Backup Database, it should always store a .sql file in craft/storage/backups.

If you have the Download Backup box checked, then also your browser should download a .zip file containing that .sql file.

Other notes:
It appears to work the same in Craft 3
If you do Clear Caches first, you may get a significantly smaller file.


Title of the current parent structure I want to display the current title of the parent structure inside the child template.

How would I do that?

Parent (Title: Bla)

Child (Here I want to display Bla)

Parent (Title: Blablu)

Child (Here I want to display Blablu)

I tried something like (in the child template):

{% set parentTitle = craft.entries.section('structure').level(1).title %}
<h1>{{ parentTitle }}</h1>

But that doesn't even result in an error

If you are trying to get the top most parent entry of a child entry in a structure, you can use ancestorOf.

{% set parent = craft.entries.ancestorOf(entry).level(1).first() %}
<h1>{{parent.title}}</h1


Commerce - Email users on new product input Good Afternoon,
Is it possible to have Craft email a list of users (based on a category) when a new product is added to the shop?
Is there a pluigin that would do this, or is it a matter of a small script?

There is this plugin https://plugins.craftcms.com/craft-commerce-back-in-stock
Although I haven't used it, it sounds like it will do what you need.
Always worth having a look for things at https://plugins.craftcms.com


Class '...SiteModuleService' not found when used inside scout.php I have a custom SiteModule that is used inside scout.php to deliver indexing data to Algolia.
I have followed CraftQuest's tutorial on creating a custom SiteModule for handling the indicies.
The setup works when running locally. But when I run it on my host (Hyperlane), I get the error:
Class 'modules\sitemodule\services\SiteModuleService' not found
I reference the SiteModule in scout.php thus:
'indices'       => (new \modules\sitemodule\services\SiteModuleService)->getIndicies()

App.php contains:
return [
    '*' => [
        'modules' => [
            'site-module' => [
                'class' => \modules\sitemodule\SiteModule::class,
            ],
        ],
        'bootstrap' => ['site-module'],
    ]
];

Composer version (local/prod): 2.0.12
PHP version local/prod: 7.3.12/7.3.3

What am I doing wrong?

Worked when I added a use-statement to the top of scout.php:
<?php
use modules\sitemodule\services\SitemoduleService as SitemoduleService;

And then:
'indices'       => (new SitemoduleService)->getIndicies()


Syntax for using 'not'? I want to show a list of entries that excludes two or more specifically by id.

This works:

{% for entry in craft.entries.section('boardOfDirectors').id('not 12') %}

This does not:

{% for entry in craft.entries.section('boardOfDirectors').id('not 12,18') %}

Is this possible?
Anyone know the correct syntax?

You need to start with and, and put not in front of each ID...

{% for entry in craft.entries.section('boardOfDirectors').id('and, not 12, not 18') %}


Why won't the values of an editableTableField show up in my template? I'm still trying to process my csv data as mentioned in a former question. But I'm struggling with another part of this right now.

I decided to implement a custom field type which should display the data from my csv in a table to make it further editable for editors. The problem is that I don't even get something shown in this table even without processing a csv file before.

I tried something really simple, at least I thought it was...

public function getInputHtml($name, $value)
{
    $id = 'test';
    $cols = array(
        'Sample' => array(
            'heading' => 'Heading',
            'type'    => 'singleline'
        )
    );

    return craft()->templates->render('csvImport/csvimport', array(
        'name'  => $name,
        'value' => $value,
        'id'    => $id,
        'cols'  => $cols,
    ));
}

This works until the point of saving the data. Craft stores everything into database as a string. No matter how many cols I use, it will always result in a string which looks like this:

"{"1":"Sample":"The entered string"}}"

This is what craft stores in the database, so at least the data is processed. But how the pencil do I get this stuff to show up in the table of my template?

If you have any other idea how I could solve my problem, please let me know!

UPDATE:

        {% for col in cols %}
            {{ col.heading ? col.heading : ' ' }}
        {% endfor %}
        {% if not static %}

        {% endif %}

    {% for rowId, row in rows %}

            {% for colId, col in cols %}
                {% set cellName = name~'['~rowId~']['~colId~']' %}
                {% set value = (row[colId] is defined ? row[colId] : null) %}
                {% set textual = (col.type in ['singleline','multiline','number']) %}

                    {%- if col.type == 'select' -%}
                        {% include "_includes/forms/select" with {
                            class:    'small',
                            name:     cellName,
                            options:  col.options,
                            value:    value,
                            disabled: static
                        } only %}
                    {%- elseif col.type == 'file' -%}
                        {% include "_includes/forms/file" with {
                            class:    'small',
                            name:     cellName,
                            value:    value
                        } only %}
                    {%- elseif col.type == 'checkbox' -%}
                        <input type="hidden" name="{{ cellName }}">
                        <input type="checkbox" name="{{ cellName }}" value="1"{% if value %} checked{% endif %}{% if static %} disabled{% endif %}>
                    {%- else -%}
                        <textarea name="{{ cellName }}" rows="1"{% if static %} disabled{% endif %}>{{ dump(value) }}</textarea>
                    {%- endif -%}

            {% endfor %}
            {% if not static %}

            {% endif %}

    {% endfor %}

I guess this is the relevant part for the ouput of my values.

That string that Craft stores is just JSON. When you try to save an array, Craft will automatically JSON-encode it, since MySQL doesn’t have an array-based data type.

To get that string to be automatically decoded back into an array for you, you need to give your field type a defineContentAttribute() method that returns AttributeType::Mixed:

public function defineContentAttribute()
{
    return AttributeType::Mixed;
}

To get the values to actually output, you will need to make sure you’re passing the old value with the correct name. Your csvimport.html template is looping through a variable called rows, which is meant to represent the existing value, but in getInputHtml() you are sending $value to the template as a variable called value.

So if you change this line in your template:

{% for rowId, row in rows %}

to:

{% for rowId, row in value %}

the template will probably start outputting data.

If you’re not actually making any changes to the table HTML, you should probably just include the actual _includes/forms/editableTable.html template, though. Using your own HTML puts you at a little risk, if you also intend to keep using the Craft.EditableTable JavaScript class, since those two are very much tied together. We aren’t concerned about making breaking changes to the way the HTML is supposed to look, as long as we haven’t broken the way the actual editableTable.html template is supposed to be included.

So from csvimport.html, you should just replace your entire <table>...</table> HTML with this:

{% from "_includes/forms" import editableTable %}

{{ editableTable({
    id: id,
    name: name,
    cols: cols,
    rows: value
}) }}

(In this case I’m using the editableTable() macro in _includes/forms.html instead of including the actual _includes/forms/editableTable.html template, mainly because I think using the macro looks nicer.)


Categories within matrix for relatedTo I have a matrix field with a category field. I need to group these matrix items by category and give them headings which I'll use for tabs.

This is how I'd do it for entries but is it possible for matrix?

    {% nav category in craft.categories.group('otherAppliances') %}

    {% set itemCount = craft.entries.relatedTo(category).total() %}
        {% if itemCount %}

{{ category.title }}

        {% endif %}
    {% endnav %}

I think my question may be similar to How to query with relatedTo of a Relationship Field in a Matrix Field block but I can't get my head around it.

Matrix setup:

Just answering this for anyone that may come across this in the future as I have...

Could you reuse the group tag?

{% for block in entry.myMatrixField.group(<catgegory here>) %}
    ...
{% endfor %}

You have probably resolved it due to the age, but your answer would be helpful.


Misconfiguration error when accessing URL without file name When accessing www.myurl.com/services, I get this error below the content of my page:

The server encountered an internal error or misconfiguration and was unable to complete your request.

I don't get this error if I access www.myurl.com/index.php/services. I'm new to Craft, but am particularly confused, because nothing else on my site is broken, I just keep getting this error appended to the end of my html. Additionally, I have followed the directions to include an .htaccess file in the web root. This error does not occur locally. Thoughts?

On some servers you might need to add in general.php

'omitScriptNameInUrls' => true

See https://craftcms.com/docs/config-settings

Hope that helps


Loop through entries taking far too long to finish I am attempting to loop through my "journalEntries" in order to find duplicates. For some reason, it is taking a very long time to finish and return a response to me. Last time I tested it, it took 12 seconds to finish.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'journalArticles';
$criteria->limit = 10;
$copies = array();

for($a = 0; $a < count($criteria); $a++) {
  for($b = $a + 1; $b < count($criteria); $b++) {
    if($criteria[$a]->title === $criteria[$b]->title) {
      array_push($copies, $criteria[$a]->title);
    }
  }
}

$this->returnJson($copies);

I think it is something I am doing incorrectly within the two for loops. As you can see, I limit the amount of articles to only 10, so something seriously funky must be going on. Any help?

Something like this should work and be faster.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'journalArticles';
$criteria->limit = 10;
$entries = $criteria->find();

$titles = array();
$copies = array();

foreach ($entries as $entry)
{
    $titles[] = $entry->title;
}

foreach (array_count_values($titles) as $val => $count)
{
    if ($count > 1)
    {
        $copies[] = $val;
    }
}

$this->returnJson($copies);


How to create an entry with MySQL? I'm trying to create a new entry from within the database. The section is defined in craft_sections, and the entries for craft_elements, and craft_entries seem correct after the script is run, but no entries are displayed in the UI.

If you really, really want to create an entry from within the database (you must have a VERY good reason to do so), then you should create a row in:

entries
elements
elements_sites
content

If you'd like the easier path, use Content migrations. Create a migration, and then add something like:

// Create the entry
$myNewEntry = new craft\elements\Entry();
$myNewEntry->setFieldValues([
    'title' => 'My new entry',
    'myCustomFieldHandle' => 'Look, I can even set a custom field!',
    'myCustomCategoryFieldHandle' => [$categoryILookedUp->id],
]);

// Save the entry. Everything else will be handled for you by Craft's API.
Craft::$app->getElements()->saveElement($myNewEntry);


Environmental variables for Scout plugin in scout.php file I was wondering if it was possible to add .env variable for the indices area in the scout.php file?

I added this to my .env file

SCOUT_INDICES = "search_SCOUT_DEV"

Then this to my scout.php

\rias\scout\ScoutIndex::create('getenv(varname:’SCOUT_INDICES’)”)

To replace

\rias\scout\ScoutIndex::create('search_SCOUT')

Which is my Prod indices. It did not work.

If you use this, it should work:

\rias\scout\ScoutIndex::create(getenv('SCOUT_INDICES'))


Correct IAM settings for Amazon S3 bucket I'm trying to setup an Asset source on S3, but i'm having trouble getting the correct permissions.

This is my current policy file:

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

This gives me "Permission denied" when trying to list the buckets.

You need to allow to list bucket location. Also, I'm not confident if you'd be able to upload and delete objects from the bucket with that policy.

I'd go with:

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


Craft install via composer: install to public_html? When I do composer create-project craftcms/craft, it will create a web folder. My webroot is called public_html though. Can I change this somehow, or should I make a symlink?

Or simply don't use composer to install in that case?

You can just rename web/ to public_html/, or move all the files inside web/ into public_html/. (Don’t forget to move the .htaccess and .env files, if the latter.)

As long as the location of the public_html/ folder is in the same place as the web/ folder was, you don’t need to change anything else.

my-project.test/
├── config/
├── ...
└── public_html/
    ├── index.php
    └── ...

If you need to change the location to something like this:

my-project.test/
├── craft/
│   ├── config/
│   └── ...
└── public_html/
    ├── index.php
    └── ...

Then just make sure that your CRAFT_BASE_PATH constant points to the right base path (craft/).

// old:
define('CRAFT_BASE_PATH', dirname(__DIR__));

// new:
define('CRAFT_BASE_PATH', dirname(__DIR__) . '/craft');


MVC - Should these be seperate controllers/models etc I hope this is the right place to post this, it's more a question on MVC for plugin development.

I'm developing a plugin to extend SproutForms to add users to Campaign Monitor lists. So far I've got the interface where the user can submit their API key and List ID. I then use these to pull in information about the list and add it to the db in pluginname_forms.

Now, I also want to pull in the custom fields for that list and store them in the pluginname_formFields table.

From an MVC point of view, should I keep this in the service that deals with the list data or create a new service which deals with the custom fields data?

Well, it looks like Sprout Forms itself prefers separate services for everything (they'd be some big services if they weren't,) but Craft does bundle closely-related things together sometimes - FieldsService deals with both fields and groups, TagsService with both tags and tag groups for example.

Personally I just look at how much code there is, if I start getting lost/sick of scrolling and there's more than one 'thing' I'm dealing with, or if the existing service is already pretty big, then I break it out into separate services.