You would use the split filter.

{% set fruits = "Apples; Bananas; Tomatoes" | split('; ') %}


Forgotpassword: wrong url in reset password e-mail

I've found the problem: The test account had control panel privileges and was therefore redirected to the control panel set password page. This behaviour makes absolutely sense.


Just because Google has not indexed your pages doesn't mean there isn't necessarily anything wrong. Have you gone into the group Google search console to see what pages it has actually consumed?

Also, you might consider trying SEOmatic to handle your SEO:  https://github.com/nystudio107/seomatic


Getting image url from globals asset field

Thanks to Andrew Fairlie for pointing out I need to make sure Assets in this volume have public URLs set


Filter entries on a page based on related entry

You can conditionally add parameters to your criteria model. Check if there's a "area" parameter in your query string, e.g. http://example.com/barristers?area=7 before adding the filter.

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

{% set query = craft.request.getQuery() %}

{% if query.area is defined %}
    {% set areaIds = craft.entries.section('practiceAreas').id(query.area).ids() %}
    {% set barristers = barristers.relatedTo({ targetElement: areaIds }) %}
{% endif %}

In case you need to add more than one relatedTo condition, have a look at this discussion:
Dynamic relatedTo queries


Rich Text Field Adding Tags around script

You probably need to set the Redactor allowedTags config setting to allow <script> tags.

You can see how to define custom Redactor configs in Craft here.


Use pure PHP and HTML instead of Templates

You're really fighting against the way Craft CMS does things.

I'd start by having a good read through the Craft Docs first, there really isn't a shortcut. The docs are really great though, and contain everything you're likely to need.

Then, I'd set up a copy of Craft in isolation of your site/framework and just get a feel for how you do things the "Craft way". It is different to just doing HTML & PHP, but not so different that's it going to take you too long to figure it out.

Craft actually uses the Twig tempting language, which is really easy to get going with.

In answer to your specific question...

Does craft allow me to make calls to get the stored data and then I manually handle the inserting of this data?

Yes it does. To output your data, you'd likely use sections/entries in your Twig template. So take a look at the example at the top of this page to see how you'd go about it. You'd input your data via the Control Panel, so have a read here for that.


How can I get tasks to complete when not logged in to the CP?

To reiterate what has been said in the comments above and to present an answer, the best way to ensure that queue jobs are completed even without the CMS being logged into or the site being visited is using a scheduled cron job.

The following will run all jobs in the queue every 10 minutes:

*/10 * * * * /usr/bin/php /path/to/craft queue/run


Do ImageOptimize Volume Variant Transforms replace Craft's default Asset Transforms?

No, they do not replace Craft transforms. They are in addition to. And in fact, Image Optimize uses regular old Craft Transforms under the hood.

Image Optimize will do three major things for you:

Every image transform you do, whether it be via Craft image transforms, or the Optimized Images field will be run through a variety of image optimizers that you have installed, including making .webp variants
An Optimized Images field makes it easy to create an image srcset for doing responsive images
You can entirely replace the transform method from your local server to a service like Imgix or Thumbor

These all operate independent of each other, but they can work together as well.


Table fields, default single empty row, and never returning as empty?

You could test if the first cell is empty

{% if entry.whiskeyTableHandle|length and entry.whiskeyTableHandle[0][0] %}
{% endif %}

Or you simply remove all default rows in the field’s settings.


Fetching Existing Users In Users Field Doesnt Work When entries.saveEntry Event Triggerred From Frontend

Turns out I was inadvertently "emptying" my user field on form post. Essentially I had named one of the form fields "fields[customUserField]" which upon submitting the form, was saving an empty value into the "Users" field. Then my custom event would trigger and fetch the "Users" field thereby retrieving an empty "array".

So nothing is wrong with the code below:

// get entry
$entry = craft()->entries->getEntryById($entryId);

// get ALL users related to entry
$users = craft()->elements->getCriteria(ElementType::User);
$users->status = null;
$users->relatedTo = [$entry];
$userIds = $users->ids();


Your usual setup for blogpost matrix field

Something like this: Creating a Content Builder in Craft CMS


How to handle mock / placeholder assets in a pattern library?

Two ideas come to mind.

First, it would be a lot easier to check if an image exists if you send in null in the include instead of an url to the placeholder image, and then let the cart template know what to do if there isn't an actual image. Something like this:

{% include '_partials/card' with {
  title: 'Something',
  description: 'A bit of text',
  image: null
} %}

And in _partials/card:

{% if image!=null %}

{% else %}

{% endif %}

Second option is to have a dummy image in your Assets library, with a known id, and pass that to the card template. Something like:

{% include '_partials/card' with {
  title: 'Something',
  description: 'A bit of text',
  image: craft.assets({ id: 99 }).first()
} %}

The logic in the card template would be a little bit simpler that way I guess. But maybe you risk that the image is deleted at some point and then everything fails? Depending on the images in your Assets library, maybe you could just pick one at random?

{% include '_partials/card' with {
  title: 'Something',
  description: 'A bit of text',
  image: craft.assets({ order: 'RAND()' }).first()
} %}

Might give some weird results, but.. Depends on your project.


Getting the first category of the deepest level for an entry

Assuming you are only assigning one category (and thus by default all of that categories ancestors), then getting the 'last' returned category should work.

{% set category = entry.categories.last() %}

Otherwise, you will need some logic of some kind. What you have works, or perhaps something where you don't need to know how many levels there are.

{% set level = 0 %}
{% for category in entry.categories %}
    {% set level = category.level > level ? category.level : level %}
{% endfor %}
{% set category = entry.categories.level(level).first %}

However, this will still not retrieve all the categories if there is more than one category set with same level.


Plugin: Tags field for front-end Entry Form

While the full answer to this probably requires some planning, and a plugin that handles various aspects of the tag management, here are a few components to consider:

You can submit tags from the front-end and, on the server side, they will behave like Craft handles them in the Control Panel. The syntax for your front-end form field is as follows:

<select multiple name="fields[fieldHandle][]">
  <option value="13">Tag Name One</option>
  <option value="42">Tag Name Two</option>
  <option value="144">Tag Name Three</option>
</select>

For a more friendly UI, there are a handful of javascript libraries that could help on the front-end. I believe the one that Craft uses in the Control Panel is selectize.js and it could be setup to be used on the front-end as well.

To handle the pre-processing of tag behavior before an Entry is saved, your plugin may need to use the entries.onBeforeSaveEntry Event.


Craft 3.1 Beta - Email settings and categories not working

Cause: Moved the template folder from / to /src/
This also apparently affect the backend / admin templates for some reason.

Solution: Update index.php to use the right path.


Reverse related entry with Solspace Calendar

after reading and re-reading the docs got this working:
{% set relatedDates = craft.calendar.events.relatedTo(entry).all() %}

{% for relatedEventEntry in relatedDates %}
 {{ relatedEventEntry.title }} - {{ relatedEventEntry.startDate.format("l, F j, Y \\a\\t g:ia") }}
      ({{ relatedEventEntry.duration.humanReadable }})
      in {{ relatedEventEntry.calendar.name }} calendar.
      {% if relatedEventEntry.repeating %}
        Repeats {{ relatedEventEntry.readableRepeatRule }}
      {% endif %}
{% endfor %}

this is called from the projects/_entry template


How do I add a value to a tag field type using the entries service saveEntry method?

The Tags field classifiedTags needs an array of tag IDs, not slugs/titles. Also, if this is an existing entry and you want to retain tags already added to the field, you'll need to pull the existing tag IDs using $entry->classifiedTags->ids() and merge with those.

$tag = craft()->elements->getCriteria(ElementType::Tag, [
    'groupId' => 1,
    'slug' => 'tagtest',
])->first();
if ($tag) {
  $existingTags = $entry->classifiedTags->ids();
  $entry->getContent()->setAttribute('classifiedTags', array_merge($existingTags, [$tag->id]));
}

Note that if the tag doesn't already exist, you'll need to create it using the TagsService:

$tag->groupId = 1;
$tag->getContent()->title = 'tagtest';
$success = craft()->tags->saveTag($tag);


How to get related entries from a Matrix block itself related to another section

You access the wrong variable to get to you "compDiscographie" Matrix field. It should be:

{% for block in record.compDiscographie %}

Another thing to change here is to add the type parameter, as you probably have other Matrix block types in that field (if not, why did you choose Matrix?):

{% for block in record.compDiscographie.type('myPerformersBlockTypeName') %}

Then you should be good. Oh, and you better have that <ul> outside your loop!


Sorting categories by the post date of the entries related to them

Alan,

Without having tested this, you might get the desired result by using the group filter.

So, get all you entries ordered by dateCreated, and then group them by category:

{% set sermons = craft.entries.section('sermon').order('dateCreated desc').limit(null) %}
{% for category, catSermons in sermons | group('categoryFieldHandle.first().title') %}
    <li>{{ category }}
        {% for sermon in catSermons %}
            <li>{{ sermon.title }}</li>
        {% endfor %}
    </li>
{% endfor %}

Let me know if that works!


How do I install the FormBuilder 2 plugin in my local Craft project?

I rolled old-school and just downloaded the zip file to my local machine.
When I did that & unzipped the directory the folder is called FormBuilder-2-Craft-CMS-master

You will want to rename that to formbuilder2, copy/paste that folder to /craft/plugins/ and then it should show up in your list of plugins when you navigate to settings->plugins.

Hope this helps!


How to upload asset element on its own, not into an asset field (frontend form)

There is indeed an assets/save-asset controller. You will find it in vendor/craftcms/cms/src/controllers/AssetsController.php, the actionSaveAsset() function.


There are a couple of existing plugins that look like they might do what you're looking for:

https://plugins.craftcms.com/password-policy

https://plugins.craftcms.com/enforce-password

And of course, you could always write a plugin that meets your exact requirements as well.


Is there a way to get a variants stock quantity in commerce?

You can do the following:
{{ variant.stock }}


Sales that select both Product Types and Specific Products in the Conditions

A blank selection of products or product types will match all products.

Both 'product type' and 'product' conditions need to match for the sale to match the product.

If you selected product type A and a single product from product type B in your conditions, then the sale would not apply to the single product from type B even if added to the cart.

Therefore the condition could be thought of as an AND, meaning that all conditions need to match for the sale to apply.

Let me know if you need further clarification.


Fetching & Displaying an API Request using 'Fetch'

So there are two things wrong with your code snippet.

First off, the fetch() method takes four parameters in the following order: client, method, destination, and options. In your example above, you're passing your options object in as the destination (because that is the third parameter), which is not going to work.

So you'll want to do something like the following instead:

{% set client = {
    base_uri : 'https://api.tickets.com',
    timeout : 10
} %}

{% set destination = 'rest/v2/Events/2704/Reviews?order=1&count=30' %}

{% set options = {
    headers: {
        'Content-Type': 'application/json',
        'apiKey': 'aaabbbcccdddeee',
    }
} %}

{% set request = fetch(client, 'GET', destination, options) %}

We've made the client.base_uri actually the Base URI (by removing the segments and query strings) and moved those to a separate variable (which is technically where they belong). This allows us to now have four parameters that we're passing into fetch() in the right order (notice our options object is now the fourth parameter like it should be).

In addition, it should be headers: {, not headers: new Headers({ in your options hash. headers: new Headers({ is not valid Twig. Not sure where you got the new Headers() from but a simple hash should work well (similar to the PHP example in the Guzzle docs).

Your second issue (and this is the bigger one) is this:

{% echo $request->getReasonPhrase(); %}

That is not proper Twig at all. Looks like you grabbed a bit of PHP code from somewhere and popped it inside {% ... %}, which is never going to work.

If you take a look at the Fetch README, it shows you what a response is going to look like:

{
    "statusCode":200,
    "reason":"OK",
    "body": {
        "credits_left":30,
        "test_id":"JDHFbrt7",
        "poll_state_url":"https:\/\/gtmetrix.com\/api\/0.1\/test\/JDHFbrt7"
    }
}

What this snippet means is after you run {% set request = fetch(...) %}, the request variable is now going to equal a Twig object (more properly known as a hash) containing the status code of the response, the reason phrase (which is basically just a description of a status code; so the corresponding reason phrase for a status code of 200 is OK, for a 404 it's going to be Not Found, etc.), and then finally the body of the response returned from the API endpoint.

You'd access these variables no differently than you would any other hash in Twig. To get the status code and/or the reason phrase, do:

{{ request.statusCode }} - {{ request.reason }}

To access any property of the request body, you would do:

{{ request.body.myProperty }}

Depending on the structure of the API response, you might have to dig down into several levels of nested hashes:

{{ request.body.oneHash.subHash.somethingElse.myProperty }}

You get the idea...

If you're not sure what the API response looks like (often times the API you're using will show you an example of what the response body will look like, so I'd look at the API docs first), you can just dump() the whole body property to see what it contains:

{{ dump(request.body) }}

Hopefully that helps!


How to override the Craft forgot password email

The documentation can be found here:
https://craftcms.com/docs/templating/forgot-password-form

Part of the full templating documentation that starts here:
https://craftcms.com/docs/templating/global-variables

The actual HTML side of things is determined by the template you're using, which you can specify in the control panel -> settings -> emails.  I believe these settings are considered 'self documenting' in that there are explanations on that page as to what they do.

One thing worth noting is that IIRC you can't extend a layout template with that template, which is a little unfortunate.  So I have one general layout for all my general emails and duplicate that fully into the system email template.


How do I keep the 2nd  styled inside a  in my Rich Text (Redactor) editor?

Looks like a Redactor bug to me as I can reproduce it on their demo site: http://imperavi.com/redactor/

I've created a support ticket with them reporting the issue.


So looks like i found the answer.  My javascript was submitting the data as json instead of as regular form data.  I reformatted and it works as expected.

Whoops.


Craft has a maxUploadFileSize config setting, but it is set to 16MB by default.  Maybe someone has changed it to 8MB for your install, though.  It would be in craft/config/general.php.


If you explicitly want a Channel of entries, then you should go with a number field. If, however, you'd use a Structure (with 1 level max), you'd be able to drag and drop entries and use that to order 'em.


How can I filter Craft Commerce products by price

Looks like defaultPrice is the property on the Commerce_ProductElementType class you can use for this:

i.e.

{% set queryParams = {
    relatedTo: category,
        defaultPrice: [
            'and',
            '>= ' ~ 200,
            '<= ' ~ 500,
        ]
    }
%}


Loop index inside a switch content builder

I belive you can use {% if loop.index is even %} or {% if loop.index is odd %}


How can I group entries based on a string value?

There’s a lot to unpack here. Before I get to the solution, I’ll step through each of your examples, line-by-line. Hopefully that will help explain the behavior you’re seeing.

First Example

{# Get all entries from the section. #}
{% set entries = craft.entries.section('mySection') %}

Your comment is correct – this will fetch all the entries from section mySection and assign them to a new variable called entries.

{# Loop through the entries and get the user account associated with each. #}
{% for profiles in entries %}

Start a loop on the entries variable. Within the loop, each profile entry will be represented by a profiles variable.

Note: it’s misleading to call your variable “profiles” rather than “profile”, since it will only represent a single profile entry.

    {% set users = profiles.userAccount %}

Fetch all of the user accounts related to the current profile (profiles) via the userAccount field, and assign them to a new variable called users.

    {% if users|length %}

Only do the following if there were any related users…

        {% for year, user in users|group('myYearField') %}

Turn the users (users) that are related to the current profile (profiles) into a multi-dimensional array, grouped by their myYearField field values. Then start a loop on that multi-dimensional array. Within the loop, each myYearField value will be represented by a year variable, and the array of grouped user accounts will be represented by a user variable.

Note: This is where things start really going wrong. You want to group all of your users by year – not just the ones that are related to the current profile. Also, your choice of “user” as a variable name here is misleading since it’s actually an array of grouped users; not a single user.

{{ year }}
 {# 2016 #}

Output the current grouping’s myYearField value, which was assigned to a year variable.

                {% for user in users %}

Start a loop on the same users variable that you’re already in the middle of looping through. users here refers to the same users variable that was defined in the 3rd codeblock.

{{ user.name }}

Output the profile entry’s (profiles) URL, and the current user’s (user) name.

                {% endfor %}

Close out the loop on the user accounts related to the current profile entry (users).

        {% endfor %}

Close out the loop on the multi-dimensional array of year-user groupings based on the user accounts related to the current profile entry (users).

    {% endif %}

Close out the conditional checking if there any users related to the current profile entry.

{% endfor %}

Close out the loop on the profile entries (entries).

Second Example

{% set allProfiles = craft.entries.section('mySection') %}

Fetch all the entries from section mySection and assign them to a new variable called allProfiles.

{% if allProfiles|length %}

Only do the following if there were any profile entries…

    {{ allProfiles|length }} {# 3 #}

Output the total number of profile entries.

    {% for profiles in allProfiles %}

Start a loop on the allProfiles variable. Within the loop, each profile entry will be represented by a profiles variable.

Note: as with the last example, it’s misleading to call your variable “profiles” rather than “profile”, since it will only represent a single profile entry.

        {% for profile in profiles.userAccount %}

Fetch all of the user accounts related to the current profile (profiles) via the userAccount field. Start a loop on the user accounts. Within the loop, each user account will be represented by a profile variable.

Note: it’s misleading to call your variable “profile”, since it is actually the user account, not the profile entry.

            {% for year, user in profile|group('yearFieldHandle') %}

Turn the current user account (profile) into a multi-dimensional array, grouped by its properties’ yearFieldHandle sub-property values (which isn’t a thing). Then start a loop on that multi-dimensional array. Within the loop, each yearFieldHandle value will be represented by a year variable, and the array of grouped user account properties will be represented by a user variable.

Note: Since profile is a single element (the user account) and not an array of elements, nothing about this is likely doing what you expected it to.

{{ year }}
  {# No output #}

Output the current grouping’s yearFieldHandle value, which was assigned to a year variable. (This is the equivalent of doing something like profile.id.yearFieldHandle. It’s expected that you wouldn’t get any output.)

{{ profile.firstName }}
    {# Bob #}

Output the user account’s first name.

{{ profile.myYear }}
 {# 2016 #}

Output the user account’s myYear custom field value.

            {% endfor %}

Close out the loop on the multi-dimensional array of year-user account property groupings based on the current user account defined by the parent loop.

        {% endfor %}

Close out the loop on the user accounts related to the current profile entry.

    {% endfor %}

Close out the loop on the profile entries (allProfiles).

{% endif %}

Close out the conditional checking if there any profile entries.

Solution

To group all of your profiles by their related user accounts’ custom date fields, first let’s load the profiles, eager-loaded with their related user accounts:

{% set profiles = craft.entries({
    section: 'userProfiles',
    with: ['userAccount']
}) %}

Next let’s group the profiles by the myYear custom field on their related user accounts:

{% set profilesByYear = profiles|group('userAccount[0].myYear') %}

Now we can loop through the years, and their corresponding user profiles/accounts:

{% for year, yearProfiles in profilesByYear %}

{{ year }}

    {% for profile in yearProfiles %}
        {% set user = profile.userAccount[0] ?? null %}
        {% if user %}

{{ user.firstName }}

{{ user.myYear }}

        {% endif %}
    {% endfor %}
{% endfor %}


.getUrl() outputting {{ siteUrl }} in address

If your putting the variable in the craft settings input, try wrapping it in single brackets like {siteUrl} instead of {{ siteUrl }}

That should do the trick


Removing "action" from a module's route. Is it possible?

Yep, you can add the route in config/routes.php.

return [
    'custom/route' => 'module/controller/action',
];

(See https://docs.craftcms.com/v3/routing.html#advanced-routing-with-url-rules)


Craft 2.6 Asset Upload 500 Error (EC2 and Amazon S3)

Apparently PHP hadn't installed the XML Parser appropriately. The amazing Craft team provided this link. Which solved my issue.

sudo apt-get install php-xml

https://stackoverflow.com/a/35604148/520520


Normally folders in the /craft/storage/runtime/* directory are just cached files.

Those files are generated by craft, so really they're generated by php/php-fpm/nginx/apache or what ever you've got setup.
Maybe check the user that made those folders are in the www-data group if you do want to look into it further.

The better solution is to completely ignore that folder... Those files do not need to be deployed at all. They're just cached files generated by Craft. So just ignore that directory from your repo completely.


How to build a web page using different sections created in Craft

Actually, not all sections are created equal. Craft actually has three different types of sections:

Singles
Channels
Structures

Well, you need to work with dynamic URLs and Twig to show your sections at Web Page.
Here is the link of official documentation of Craft CMS:
https://craftcms.com/docs/2.x/sections-and-entries.html#sections


{% requireLogin %} not working on extended (layout template) files?

Try inside this in the main template file:
{% block access %}
    {% requireLogin %}
{% endblock %}


You could add a custom asset field for the users' profile images and hide the default one in the CP.

Here's a plugin to do this: Control Panel CSS by Lindsey D


With the supercool table maker you can create dynamic tables. Is this what you are looking for?


This looks like a situation where you might get away with just using Twig's default filter:

{{ entry.metaTitle|default(title|default(siteName)) }}

It works even with undefined or empty strings, and methods that don't exist on objects that might not be defined themselves.


Is there any downside to using localized characters in urls?

There is technically nothing wrong with using them in a URI since they are valid URI characters.  Even multi-byte characters (Chinese, Korean, Japanese, etc.) are valid in the URI (i.e. domain.com/漢字漢字).

However, some people have requested that they not be allowed in the slug, so for the upcoming 2.2 release, we've added a config setting where you can disable the behavior and multi-byte characters are stripped and high-ASCII characters like ó are swapped with their low-ASCII counterparts (o).

I can't speak to any other non-technical reasons why they might not want to be used (SEO, etc.).


Match to Existing Category on FeedMe Entry Import JSON

For the category, you need to pass an array of objects and choose to match on title (or ID if you have them).
For the dropdown, pass in the value, not the label and it will work. Try this:
[
  {
    "title": "Product: A type of Chair",
    "dropdown": "valueNotLabel",
    "category": [
      {
        "id":"1234"
        "title":"Wing Chair"
      },
      {
        "id":"5678"
        "title":"Another category"
      }
    ],
    "description": "Text here"
  }
]

To find your category ID, you can click the small cog (customize) on your Categories page in your control panel and add the ID column to your table.


How do I select a specific product variant by element/field/entry?

You would currently need to loop over all variants and just grab the ones that match the 'if' condition shown below:

{% set colourSlug = craft.request.getSegment(4) %}

{% if not colourSlug %}
    {# Grab first product variant #}
    {% set dressColour = product.defaultVariant %}
{% else %}
    {# Set dress colour #}
    {% for variant in product.variants %}
    {% if variant.colour == colorSlug %}
       {{variant.sku}}
    {% endif %}
    {% endfor %}
{% endif %}

We will look to enable variants to be an element criteria query. If each variant has their own page, would it make sense they are seperate products?


There's no easy twig function available to do this, but the code from this answer should be able to help you.

{% set columns = 3 %}
{% for entry in entries %}
    {% if loop.first or loop.index0 is divisibleby(columns) %}

    {% endif %}

    {{ entry.title }}

    {% if loop.last and loop.index is not divisibleby(columns) %}
        {% for n in range(low=columns - (loop.index % columns), high=1, step=-1) %}
            &nbsp;
        {% endfor %}
    {% endif %}

    {% if loop.last or loop.index is divisibleby(columns) %}

    {% endif %}
{% endfor %}


Search not searching certain words - how to fix?

Try to specify the fields you need to search.
{% set queryParams = {
        search: {
            query: 'title:*' ~ name ~ '* OR description:*' ~ name ~ '* OR previewText:*' ~ name ~ '* OR tag:*' ~ name ~ '*'
        }
    } %}

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


If you want to order by multiple columns that include custom fields, first make sure you're at least on Craft 2.4.2684, then you'll be able to use this syntax:

{% for gallery in craft.entries.section('Gallery').order('postDate desc, available desc').limit(null) %}

Also note that that you should be using limit(null) instead of limit(none) if you want to result all results.


Do the number of Sites in a Multi-Site have a practical limit?

I'd highly discourage this.
We've seen large Craft sites in the half a million to million elements (users, entries, assets, tags, categories, etc.) range. But even those maxed out at 20-30 sites.
Craft's multi-site was designed for sites that share a common information architecture and I'd say even 20-30 sites are pushing what the UI was designed for in the control panel.


Permission for "Send an activation email now?" Option

This feature was added in Craft 3.3.5, see the changelog.

If you update to this version, your users should be able to control whether the activation email is sent.


How to handle a big amount of whitelabel sites (with multi-site)

Craft just isn't set up to handle this many sites, as you said it will likely be a hot mess. One way to circumvent could be to create your own plugin to manage things.

Either way I would get in touch with P+T as depending on your use (if every site is a new client) this may be outside of the license agreement.


Can I change the list of available locales?

You can download the locales you want from https://github.com/yiisoft/yii/tree/master/framework/i18n/data and place in your craft/app/framework/i18n/data folder and they will show up as options.

Since Yii ships with so many locales, we initially stripped a lot of them out to keep the Craft download size to something reasonable.

If there are some locales we stripped that you think should be included in Craft, hit us up at support@buildwithcraft.com and we'll get them in.


Workaround for deprecated regex pattern modifier in PHP 5.5.0 and up (10.10 Yosemite)

Okay, so, thanks to carlcs' answer I managed to solve the camel-case to lower-dash-case conversion. The other direction was a bit trickier, but again, after digging in a bit deeper I was able to figure it out myself:

First off, I'm not using the plugin any longer! Yay! The secret was to create a custom Twig filter that would convert dash-separated strings like so:

{{ 'my-first-car'|dash2camel }}
{# outputs 'myFirstCar' #}

With the help of this guide and some code from this answer I created my own custom Twig filter within Craft. Nothing fancy and hacked together quickly, but I've put it on GitHub if someone runs into the same issues.


Prevent change field in user profile edit

There isn't anything to do this out-of-the-box in Craft.

I believe the proper way you'd want to approach it would be to write a plugin that has it's own field type that takes into account user permissions.

An admin would get a normal text input, for example, and any other user would just see read-only text.


Javascript console logs in devMode not always showing?

All that's required for the logging and profiling information to show up in the browser's console is that devMode is enabled.

If it's not showing up then, then either you're enabling it in the wrong place in a multi-environment config or you've got a plugin that's explicitly removing the logging routes.


Including the category group in nested category URIs?

You would just enter { parent? parent.slug : '' }/{ slug } in the "Category URI Format" Field in the Craft3 CP and it will recognize nested categories


Is there a way to control the order of appearance of shipping methods in Craft Commerce?

I don't think there is any in-built way to do this, no.
A relatively easy hack to achieve it, though, is to loop through your shipping methods (as youare) - but rather than directly outputting them, instead add the data to a twig array (possibly adding some extra data long the way, such as a sortOrder of your choosing, based on the handle) - and then use Twig's sort to sort your options based on your desired criteria (e.g. the aformentioned sortOrder or just by e.g. the price - before then actually outputting those options from the array, rather than the initial direct loop.
It's not awesome/elegant, but it works!


Everything you need to know is in the Relations part of the official documentation.

You essentially want to add an Entries field to your Courses channel and then when you set it up pick Instructors as the source. If you only want to pick one instructor, just set the limit to 1. How you then use this in the templates can be found here.


{{ paginate.nextUrl }}?q={{ query }} did the trick with this setup.


Per their configuration docs, which also link to Craft's docs on the subject, it looks like you'd just need to add "alignment" to the plugins portion of one of your craft/config/redactor/ JSON config files.

i.e.

{
    "plugins": ["alignment"]
}

Then whatever config you end up modifying, you'll want to make sure that config is selected under that field's settings in Craft (Settings->Fields->Your Rich Text Field).


Get Entries within a Category Group with no duplicates in each category

I've tested this with some of my own content and believe it works to your spec. You need to keep a track of all entries that have been displayed so far. You then loop through each categories related entries and if the entry hasn't been shown in a previous category we add it to a new array within that category loop.

    // Set empty array to hold id's of all currently displayed entries
    {% set entries_displayed = [] %}

    // Loop over a category group
    {% for category in craft.categories.group( 'productBrand' ) %}

{{ category.title }}

      // Get related entries to the category
      {% set related_entries = craft.entries.relatedTo( category ) %}

      // Set empty array to hold id's of entries we'll eventually output
      {% set entries_to_display = [] %}

      // Loop through related entries
      {% for entry in related_entries %}

        // If the entry hasn't been displayed
        {% if entry.id not in entries_displayed %}

          // We want to show the entry
          {% set entries_to_display = entries_to_display|merge([entry.id]) %}
        {% endif %}
      {% endfor %}

      // Finally grab the entries to display from the array of id's that haven't already been shown
      {% set entries = craft.entries.id( entries_to_display ).limit( 4 ) %}
      {% for entry in entries %}

        // Add the id to our "already displayed" array
        {% set entries_displayed = entries_displayed|merge([entry.id]) %}

        {{ entry.id }} - {{ entry.title }}

      {% endfor %}
    {% endfor %}

UPDATE:

Erik later discovered an error in my original answer where I was setting entries_displayed in the first for loop before they'd actually been output in the last for loop. I've updated the code to reflect his fix.

  I had to move the entries_displayed array to the last for loop which displayed the entries. That way I knew exactly what entries had been displayed. If I didn't do that, it would assume more than 4 were shown per category.


How do I create an advanced route with an ID that hits a controller method

In your plugin's main class file you'd set the registerCpRoutes method to something like this:

public function registerCpRoutes()
{
    return array(
        'user/update/(?P<userId>\d+)' => array('action' => 'pluginHandleController/updateUserRecordsTest'
        ),
    );
}

The the method in your plugin's controller would look something like this:

public function actionUpdateUserRecordsTest(array $variables = array())

And $variables will be a collection of all of the named regex patterns captured in your route definition.


There's a lot going on here, but a) assuming you're really using Craft 3 and b) you generated your plugin, service and variable scaffolding on https://pluginfactory.io, this should work:

KGVariable.php Variable

<?php

namespace kg\variables;

class KGVariable
{
    public function sayHello()
    {
        return \kg\KG::$plugin->useTR->exampleService();
    }
}

UseTR.php Service

<?php

namespace kg\services;

use craft\base\Component;

class UseTR extends Component
{
    public function exampleService()
    {
        $result = 'hello';
        return $result;
    }
}

Then using this in a template will return hello:

{{ craft.kG.sayHello() }}


Specifying administrators for localized sites?

Yes. you can:

Here I created a User group which has only access to the english part of the content.
As you can see these are checkboxes. So you can grant access to multiple languages at once.


It is hard to answer without additional information, but here are some things you can check:

Did you try it in other browsers/on other computers/in a different network?
Is there enough free disk space on your server?
Did you check the server logs?
Did you ensure the "Assets in this source have public urls" option is on for your volume(s)?
Did you try to clear the cms caches?


How to change the Craft 3 activation email?

Under Settings > Email there is a field called "HTML Email Template" which you can use to point to a single template that handles all of the system emails. It's not very obvious from the Craft UI, but you can use that single template as a routing mechanism for including per-email templates using the variable emailKey which is available in the template. Your routing template could look like this:

{# Craft has four predefined email keys:

    account_activation
    verify_new_email
    forgot_password
    test_email

... route to them here, or fallback to default
#}

{% include [
    '_emails/' ~ emailKey ?? null,
    '_emails/default'
] %}

You'd then have another template called account_activation.twig where you can go wild with whatever modifications you like. Each email also has a link variable available in the template to output the link to whatever it is.


Default limit is 100, try adding .limit(null) to the query


How can you allow users to create products in Craft Commerce

User/User Group permissions don't apply to Product Types in Commerce like they do to Sections in Craft, so I'm not seeing any easy way to pull this off in the Control Panel.

There is a feature request here you might want to comment on if you think this should be the case: https://github.com/craftcms/commerce/issues/174

You could do this from a front-end template/product admin section if you wanted, but not sure if that would be a valid use-case for you.


Unknown Errors when trying to select category

Looks like the server didn't like the .htaccess file we use for Craft 2 - specifically this part:

<IfModule mod_mime.c>
   AddCharset utf-8 .atom \
                    .bbaw \
                    .css \
                    .geojson \
                    .ics \
                    .js \
                    .json \
                    .jsonld \
                    .manifest \
                    .markdown \
                    .md \
                    .mjs \
                    .rdf \
                    .rss \
                    .topojson \
                    .webapp \
                    .webmanifest \
                    .xloc \
                    .xml
</IfModule>

There weren't any errors in Craft but the PHP logs did have some information that helped us track this down.


Using ImageOptimize plugin with Matrix fields

I'm also using ImageOptimize and yes, it does work within Matrix.
Your image has to have the call to the plugin code as specified in the plugin docs. Additionally, your image calls must match the image size you've setup within the plugin preferences panel. Within Matrix, you are calling the assets Field Type.

Here's a sample:

{% if block.type == "graphicCalloutBlock" %}
        {# Full Width Image #}
        {% set image = block.graphicCalloutImage.one() %}

                 {% if image | length %}

                {% endif %}

{% endif %}


How do I remove the index.php from all URLS in Craft 2 CMS?

It sounds like you haven't set up your .htaccess file or have failed to rename it. The file in the default set up doesn't have the . at the start.

Read https://docs.craftcms.com/v2/installing.html carefully. The bit concerning htaccess is just before step 2.

Also ensure you're files are in the right place.


Set email recipient based on value of select in freeform - possible?

FreeForm actually has a Dynamic Recipients field that sounds like it will do what you're wanting. I believe you can choose to have it displayed as a select field, radio buttons, or checkboxes.

Alternatively, you could probably create a little custom Twig and set up dynamic template notifications. I would think you should be able to switch the recipient array there based on the value of your select field for each submission (but it's possible I'm wrong; the Dynamic Recipients field definitely seems like the better option).


Edit

OP updated the question to specify Craft 3, so this is no longer relevant.

You can define a separate value for each locale, as described in the localisation documentation:

<?php

return [
    'flagName' => [
        'de' => 'Bundesflagge',
        'fr' => 'Tricolore',
    ],
];


How do I import existing products into Craft Commerce with the FeedMe or Import plugins?

Feed Me only supports Entries at this stage. Its on the short-term roadmap in allow importing into all Elements, including Commerce Products. This cannot be achieved through hooks at the moment. Keep an eye on the plugin page.

Update: FeedMe 2.0 now supports multiple entry types, including Commerce Products: http://sgroup.com.au/plugins/feedme/getting-started/introduction


How can I correctly set the time of a dateTime field from a front-end form?

Thank you everyone for your suggestions - I need to keep reading/digging more to fully understand, but it seems that it was just a formatting issue.

{{ block.startDateTime|date('H:i:s') }}

Renders the correct time on the template.


Removing index.php causes Not Found error on secondary pages

Thanks to @brad-bell - his comment on another post pointed me in the right direction. I thought that I already checked on mode_rewrite but I didn't.

  The Apache mod_rewrite module wasn't installed, so the  block of Craft's default .htaccess file was being
  skipped not allowing index.php to be rewritten in the URL.

Enabling mod_rewrite solved the issue.


Cannot invalidate template cache (by element) on entries.onDeleteEntry

Ok so here's what did it:
In my plugin, I had to manually call:

        craft()->templateCache->includeElementInTemplateCaches($entry->id);

With that, I didn't need had any of my event listeners in place.

Interesting that things seem to be inserted into craft_templatecachecriteria automatically, but not into craft_templatecacheelements...Perhaps that is bug?


I'm not aware of any way to do this in Redactor II other than going into Source view and manually entering the mailto syntax.


Commerce: How can I save a custom SKU from a plugin?

You should be able to do this the usual way of setting entry fields in a plugin I think:

        $product->setContentFromPost(array(
            'sku' => $sku,
        );
        craft()->commerce_products->saveProduct($product);

(Alternatively, you could listen to onBeforeSaveProduct -  https://craftcommerce.com/docs/events-reference#commerce_products.onbeforesaveproduct - and since the product will be saved after that anyway you could probably leave out the call to saveProduct in that case)

I don't think I've tried it with products but it certainly works with orders for much the same sort of thing.


What's the best way to create public profile and content forms?

User registration works just like front-end entry editing. You build the form on any page you like, and submit it to the action "users/saveUser".

All fields need to be coded by you, and extra profile fields can be filled in by setting the input name to "fields[handle]".

The Craft Documentation has an example registration form. The also have an example for allowing users to update their profile.


Element API endpoint without a resourceKey

Not cleanly... the Fractal library that the Element API plugin uses to serialize that data has 'data' hard-coded as the root element if no other resource key is passed in.


You'll probably want to read up a bit on relations in the Craft docs, but I think something like this should work

{# First get the category elements #}
{% set supportCategory = craft.categories().id(458).one() %}
{% set widgetCategory = craft.categories().id(459).one() %}

{# Now we use those elements in our query #}
{% set entries = craft.entries().section('Post').relatedTo(['and',
  { element: supportCategory },
  { element: widgetCategory }
]).all() %}

{% for entry in entries %}
  {# ... your code #}
{% endfor %}

I believe the relation needs an element, but you might be able to do something like .relatedTo(['and', 458, 459]).


index.php in output HTML - channel pages

I'd suggest starting with the official docs on removing index.php from your URLS:

https://craftcms.com/support/remove-index.php

https://craftcms.com/support/why-index.php

And if that doesn't help, there are lots more environment-specific things here on Craft SE, you can check.


You get the author's username of an entry via it's entry model like so:

{{ entry.author }}


You would need to build the complete URL to your file in order for it to work in your CSS.

See this answer:
Do Remote Assets (ie. S3) have file paths?

If the background-image is handled by something like a single or an entry template you could handle it with an inline style tag:

Regular Loading:
{% set image = entry.backgroundImage.first()%}

Eager-loaded:
{% set image = entry.backgroundImage[0] ?? null%}

Template:
<main style="background-image: url({% if image %}{{image.url}}{% endif %});"></main>


You need to include a hidden field with the value of 0 before the checkbox to ensure that the value is included in the form data if the checkbox is unchecked. See the docs on templating for checkbox fields.

So you'll need to have this in your form:

<input type="hidden" name="enabled" value="0">
<input type="checkbox" name="enabled" id="enabled" value="1"{{ entry.enabled == '1' ? ' checked' }}>

When the checkbox is checked, the value of 1 for enabled will override the value of the earlier hidden field.


Feed Me currently doesn't support this, as sometimes your data is contained in attributes, so it needs to be able to access that. Crucially, the tags are the same value, which is what trips things up.

Have you looked at the Wordpress to Craft guide? https://sgroup.com.au/plugins/feedme/guides/migrating-from-wordpress


Removing /index.php/ from url breaks site

I hope you figured it out however, I just found adding

RewriteBase /

right under RewriteEngine On fixed my issue.


Cannot access plugin controllers when plugin does not have a "cp section"

If you don't want to give the user specific access to your plugin, I think the only solution is to allow anonymous access to the controller action. But of course, this would make the controller accessible to alll anonymous users, also outside the control panel.


There is no current way that I know of that does this, but you can probably do it relatively easy with a custom plugin.

If e-mail validation is turned off in the Users settings, the created user is verified by default. You can hook into the users.onBeforeSaveUser event and set the status as UserStatus::Pending. Then redirect them to a screen saving something like "Blah blah you will be notified once we activate you blah blah".
Hook into the users.onSaveUser event, check if this is a new user (isNewUser) and send off an e-mail to a given e-mail.
Admin logins and activate as normal.
(Optional) In the same users.onSaveUser event, if this isn't a new user and the user status is UserStatus::Active, send out an e-mail to the address given by the user.


You can get the errors from the model by using $model->getErrors().  That will return an array of errors indexed by the attribute name.

Since you submitted over AJAX, you'll want to use $this->returnErrorJson() to return them and have your JavaScript parse the errors out to display them to the user.


Is there a way to re-order states in Craft Commerce?

Not at the moment, you would need to manually put the states at the top of your select box in the front-end. There is no harm if you have a duplicate select option in your form, so you could list the popular ones first, then list all of them.

We will look to add sorting of States in a future release of Craft Commerce. I have added it as a feature request and can follow progress there: https://github.com/craftcms/commerce/issues/1284


Update:

Turns out server side initiated remote calls won't be logged in your browser's Network tab (only client-side ones).  Which now that I type that out, seems very obvious.

If Guzzle actually makes a request, then it will show up in your browser's inspector's "Network" tab.


Possible to re-use one field multiple times in a section?

You can re-use the same text field multiple times in a section on different Entry Types, but if you would like to re-use the same text field multiple times on the same Entry Type (or page) your best bet would be to make it a Matrix Block.

For a quick overview on Matrix Blocks: https://craftcms.com/features/matrix

More info on Matrix Blocks: https://craftcms.com/docs/matrix-fields


Multilingual Dates where date format varies

Craft has extended Twig's date filter so that it translates the output (no documentation for this, but the code is in craft/app/etc/templating/twigextensions/CraftTwigExtension.php around line 152). So {{now|date('F j, Y')}} will give July 13, 2014 on the English site, and luglio 13, 2014 on the Italian site. Which is half way there. In order to get the Italian date to use the Italian format (j F Y), we need a translation for the format string. Add this to craft/translations/it.php. (For more info see Static Translations):

'F j, Y' => 'j F Y',

To output the translated date:

{{now|date('F j, Y'|t)}}


Craft 3.2 introduces Headless Preview which works a treat with SPA's. Essentially Craft exposes tokens which you can forward on to subsequent Element API requests and Craft will do the rest. The interesting thing to note with this release is that Live Preview isn't actually "live" rather draft entries that are saved and accessible by tokens generated to identify the entry version.

Your example outlined above is adequate in configuring Vue Router for these previews to work. But we also need to pass on these preview tokens to Element API. These tokens allow Craft to do away with obfuscating URL's loaded in the Live Preview iframe and now load the actual entry URL as you would access it on the actual website.

For example, previously Live Preview would load /admin/entries/282-project-slug in an iframe, it now loads the entry target URL /projects/project-slug?x-craft-preview=XXX&token=XXX. Fantastic!

Detecting Preview Mode

Live Preview loads the entry URL in an iframe with tokens exposed via a query string. These are x-craft-preview and token. We can extract these from the URL either client-side or server-side. The choice is entirely up to you but we just need to grant easy access to these tokens.

Client-side detection example:

let hashes = window.location.search.slice(window.location.search.indexOf('?') + 1).split('&')
let params = {}
hashes.map(hash => {
  let [key, val] = hash.split('=')
  params[key] = decodeURIComponent(val)
})

// x-craft-preview = params['x-craft-preview']
// token = params['token']

Server-side detection example (Twig):

{% if craft.app.request.isPreview %}
   token = {{ craft.app.request.getQueryParam('token') }}
   x-craft-preview = {{ craft.app.request.getQueryParam('x-craft-preview') }}
{% endif %}

  It's worth noting that Craft 3.2 also deprecates isLivePreview in
  favour of isPreview since Live Preview is no longer programatically
  live rather drafts saved on-the-go and tokenized.

Configuring Vue

For demonstration purposes we will declare the following variables and assume we now have access to the tokens.

const craftPreview = // value of 'x-craft-preview',
const craftToken = // value of 'token'

Set the router mode to mode: 'abstract', for example:

const router = new VueRouter({
  mode: craftPreview ? 'abstract' : 'history',
  ...
})

The router will resolve the preview URL so there's no need to replace the path. If you're still having trouble with this then you can try setting it to see if it resolves your problem...

router.replace({ path: window.location.pathname })

Below is an example of forwarding these params with Axios as our HTTP client.

axios.get('/api/v1/project.json', {
  params: {
    slug: 'project-slug',
    token: craftToken,
    'x-craft-preview': craftPreview
  }
})

Alternatively, you could utilise Axios interceptors and configure params before each request.

axios.interceptors.request.use(
  (config) => {
    // Forward Craft Preview tokens to API
    if (craftPreview) {
      const params = {
        token: craftToken,
        'x-craft-preview': craftPreview
      }
      if (!config.params) {
        config.params = params
      }
      else {
        Object.keys(params).map(key => config.params[key] = params[key])
      }
    }
    return config
  },
  (err) => {
    return Promise.reject(err)
  }
)

Hopefully this steers people in the right direction. As always, huge shout out to the Craft team for making this possible.


Try using this (completely untested):

{% if paginate.prevUrl %}
    Previous Page
{% endif %}

{% if paginate.nextUrl %}
    Next Page
{% endif %}

Update:

The above will only work once Craft 2.3 comes out.

In the meantime, it's a bit sketchy, but you can open up craft/app/variables/HttpRequestVariable.php and add this method:

public function getQueryStringWithoutPath()
{
    return craft()->request->getQueryStringWithoutPath();
}

And it should work.  But please be aware that file could be overwritten by a 2.2 build release at any point during an auto-update and your template would break.


Show time ordered entries from midnight at end of loop

I -think- one of the neatest ways to go about this is to introduce a "Show as last in list" lightswitch-field.

I'm currently working on a similar project (festival line-up) where I also needed this; here's the approach I went with.

Basically, I'll be going for two fields: eventTime (date/time-field) and showAsLastInList (lightswitch-field)

{% set events = craft.entries.section('events').showAsLastInList('NOT 1').orderBy('eventTime ASC').all %}

{% for date, eventsByDate in events|group('eventTime|date("Y-m-d")') %}
    {% set additionalEvents = craft.entries.section('events').eventTime(date).showAsLastInList('1').orderBy('eventTime ASC').all %}

{{ date|date('l j. F')|capitalize }}

    {% for event in eventsByDate|merge(additionalEvents) %}
       {# PRINT YOUR HTML HERE #}
    {% endfor %}
{% endfor %}

It's not exactly pretty, but I can't really think of another way to achieve this without creating a custom plugin for it.


Obtain suspended users in Craft3 Dev Preview

Something like this should work:

$user = User::find()
    ->email($email)
    ->status(null)
    ->one();


There is currently no filter but you can access the units of measurement from your settings, and display the measurement:

{% set weightUnits = craft.commerce.settings.weightUnits %}
{% set dimensionUnits = craft.commerce.settings.dimensionUnits %}

{{ variant.weight }} {{ weightUnits }} // 10 mm


How are you setting permissions? Command prompt? (S)FTP? What user does php run under? Make sure there are no open_basedir restrictions as well.

You can find out the user that php runs under as well as a bunch of other details right inside Craft: http://server/admin/utils/phpinfo and look for user/group and open_basedir.

Make sure you're giving the storage directory recursive permission as well. I would delete everything under /storage manually...

cd /path/cms/craft/storage/ && rm -r * && chmod -R 777 .

... and then let Craft/php recreate the folders underneath.


Error when using if statement in template

It is expecting an {% endpaginate %}.

{% set categoryName = craft.request.lastSegment %}
{% if categoryName == 'all' %}
    {% paginate craft.entries.section('photo').limit(6) as entries %}
    ...
    {% endpaginate %}
{% else %}
    {% set category = craft.categories.slug(categoryName) %}
    {% paginate craft.entries.section('photo').relatedTo(category).limit(6) as entries %}
    ...
    {% endpaginate %}
{% endif %}

Update: if you want to define the paginate block separately to keep your code dry you can assign the element criteria model to a variable first. See carlcs' answer above/below for another way to do the same.

{% set categoryName = craft.request.lastSegment %}
{% if categoryName == 'all' %}
    {% set ecm = craft.entries.section('photo').limit(6) %}
{% else %}
    {% set category = craft.categories.slug(categoryName) %}
    {% set ecm = craft.entries.section('photo').relatedTo(category).limit(6) %}
{% endif %}

{% paginate ecm as entries %}
    ...
{% endpaginate %}


Did a crtitical update now getting errors

Most likely you've got an Assets field inside of a Matrix field somewhere on your site and you're referencing project-images/{slug} in that field's upload location setting when it should be project-images/{owner.slug}.

At some point, those settings were more loosely enforce, but now the error you're getting will be shown if it is incorrect.

See here for more info: https://craftcms.com/docs/assets-fields#dynamic-subfolder-paths


How to trigger updateElements when hide modal?

If the page is rendered from a template that extends _layouts/elementindex, then the Element Index class instance is available at Craft.elementIndex. So all you’d need to do is include this in the settings object when creating your Modal instance:

onHide: function() {
    Craft.elementIndex.updateElements();
}


Thank you Verbb for fixing this up. The answer can be found here.

https://github.com/verbb/feed-me/issues/298


What Damon said is correct.  You'll need to modify Craft's public .htaccess file so that all requests to Moodle URIs go to it's public index.php file and requests to Craft URIs go to Craft's public index.php file.

Alternatively, you could keep them as two separate installations, which simplifies things.


The problem here was the URL in the database was wrong. I had assumed that config was entirely file-based but it seems that the config file is dependent upon the database Site URL. It would be great if this could be avoided as it makes deployment between environments so much easier without paths or URLs in the DB.


Table button missing in Rich Text fields?

Update: since version 2.3.2621 Craft comes with Redactor's table plugin preinstalled again. So there's no need to do anything special, simply add it to your Redactor json config.

Craft 2.3 now comes with a new version of Redactor. With the release of Redactor 10 non-essential functionality was removed from Redactor's core and is now released as separate plugins.

So, to get the Table function back, you have to add the Redactor Table plugin to Craft.

You can download and save the plugin into craft/app/resources/lib/redactor/plugins/ or you can make a little Craft plugin that adds this Redactor plugin to Craft.


Why am I getting "no sources available" when adding/editing a field of type Assets?

I would not consider this to be the best solution, but I was able to fix my issue.

I downloaded a fresh copy of Craft and replaced the craft/app/ directory with the fresh download. This restored all functionality back to normal. Not the most ideal, but it worked.

Hope this helps someone.


Not sure I'm following 100%, but in Craft 3, you can add the code necessary to create the new table in your plugin's Install migration.

That will run every time someone does a fresh installation of your plugin.

For the people that already have your plugin installed, you need to create a migration that also creates the table.  The code for the table creation will be very similar in both places.

For the latter, in order for Craft to know a plugin has a new migration is wants to run, you'll need to bump your plugin's schema version number.


How to apply multiple Twig filters to text - SOLVED

I believe filters are applied in the order they're written. So in your example you're probably applying the new line breaks with nl2br and then removing them again with hacksaw.

Try:

{{ workItem.summary | hacksaw(words='75', append='...') | nl2br }}

Alternatively you could try setting hacksaw to allow line break tags. Something like this (untested):

{{ workItem.summary | nl2br | hacksaw(words='75', append='...', allow='
') }}

I'd go with the first option though.


How to replace a html entity within script tags using Craft replace

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

{{ value|htmlEntityDecode}}


relatedTo - return only entries that have a related entry where a field in the related entry has a value

If your craft_searchindex table (assume your table prefix is "craft_") isn't too big (I think 100k rows is big), and your field in "relatedMerchant" is the 'title' field.

You can do it in one step.

$locationsRelatedToCategories = Entry::find()
   ->section('locations')
   ->limit(100000)
   ->relatedTo([
     'targetElement' => $categoryElement, 'field' => 'locationOffers.category'
   ])
   ->search('-relatedMerchant:*')
   ->all();

Otherwise, I don't think its possible. You will need to query the relatedMerchant entry to get ids().
And relate the id array to locationsRelatedToCategories.

$relatedMerchantQuery = Entry::find()->section('relatedMerchangt');
$relatedMerchantQuery->field = ':notempty:';
$relatedMerchantIds = $relatedMerchantQuery->ids();

$locationsRelatedToCategories = Entry::find()
   ->section('locations')
   ->limit(100000)
   ->relatedTo($relatedMerchantIds)
   ->all();

Craft only store element relations via craft_relations table. The elementQuery->relatedTo() method is the only way to access it, without creating custom query or tables.


First off, the easiest way to fetch the user's entries is to do something like this:

{% set entries = craft.entries.authorId(user.id) %}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

The way this works is you fetch all the entries that were authored by the current user in your main for loop by using authorId(user.id). In my opinion, this is a lot cleaner and more performant over what you were trying to accomplish with the  group filter.

Now, to answer your question; here's how I would solve it.

First, create an empty array:

{% set services = [] %}

Then, inside your user's entries for loop, we'd grab the value of the service field (for each entry) and see if it exists in the services array. If not, we'll merge it in.

{% set dropdown = entry.service.label %}
{% if dropdown not in services %}
     {% set services = services | merge([ dropdown ]) %}
{% endif %}

Then we can use this array to display whatever we want on the frontend:

{% for item in services %}
    {{ item }}
{% endfor %}

So, all together:

{% set users = craft.users.group('influencer').all() %}

{% for user in users %}

    {% if user.getPhoto() %}

    {% else %}

    {% endif %}

{{ user.username }}

    {{ user.location }}

{{ user.richText }}

    {% set entries = craft.entries.authorId(user.id) %}
    {% set services = [] %}
    {% for entry in entries %}
        {% set dropdown = entry.services.label %}
        {% if dropdown not in services %}
            {% set services = services | merge([ dropdown ]) %}
        {% endif %}
    {% endfor %}

    {% for item in services %}
        {{ item }}
    {% endfor %}

{% endfor %}


Can I choose a language for the translate filter?

Yes. You can see all of the arguments the |t filter supports by looking at the docs for Craft::t(), the function that |t maps to. Its $language argument defines the target language translation to use. So in your case you could do this:

{{ "Leer esta página en Español"|t(language="es") }}


Deciding between multiple products and variants

Really it largely comes down to data/content concerns.  E.g. using one product allows you to keep all the data that is shared by those products together, and is very DRY...and changes (be it to content, pricing, shipping etc) - only need to me made in one place, versus say 3 in your example.

But the lack of linking to variants is a definite disadvantage (one expects that will come in due course, but for now..)

If the cost of the gain (one place to edit) is too high, or there isn't much data to worry about, then by all means use 3 products and one level of variants.  It's precisely this flexibility that makes Commerce so....flexible!  (And useful :) )

There's no real right or wrong, and it would be easy to test both approaches - and even put them in front of the final editors for their view.


Duplicate? How do I combine search for categories and entries into one set of search results?

You will have to use something like supersort to sort your array.

{% set classesLocations = craft.entries.section('classes')|merge(craft.categories.group('locations'))|supersort('sortAs', '{ startTime }') %}


Does Craft do joined calls or multiple ones when fetching the related items? [Element API]

As Robin mentioned in a comment, this is exactly what eager loading was designed for... bringing in related elements in a single element query call.

The above link shows how to do it from Twig, but you can do it from PHP as well: https://straightupcraft.com/articles/examples-of-eager-loading-elements-in-twig-and-php


To answer my own question: There may be some plugin incompatibilities when upgrading to Craft 2.5. This is to be expected, given all the variables. In my case the Placid plugin was not yet compatible, as seen when I put Craft into devMode.

So either:

Wait on the upgrade until your plugins are current, or
Disable lagging plugins as necessary if you need the bleeding edge.


You can use Yii2 routing

    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_SITE_URL_RULES,
        function(RegisterUrlRulesEvent $event) {

        $event->rules[] = [
            'pattern' => '/<route:\S+>',
            'route'   => 'controller/to/redirect'
        ];
    }
);

And in your Controller

public function actionRedirect($route){
    if($entry = Entry::find()->oldUrl($route)->one()){ //<- insert your criteria to mach old with new URLs
        return $this->redirect($entry->getUrl());
    }
}


You can create two different Entry Types for your Structure section, and use one Entry Type for parent entries, and a different entry type for child entries. Entry Types have their own field layout, which makes it possible to have different fields for different kinds of entries, within the same Section. Then, it's simply a matter of selecting the right Entry Type when you create/edit your entries.

If that isn't dynamic enough (it isn't possible to assign entry types automatically based on whether an entry has children or not), you could possibly use the CP CSS plugin (perhaps in combination with the CP JS plugin) to hide the relevant fields for the parent entries.

I realize that neither of these solutionals are ideal – however, if you only have a single parent (i.e. "Works") for all your portfolio entries, I think a better approach would be to create a separate "Portfolio" Structure section limited to a single level, to hold all your portfolio entries. Set the URL format for this section to "works/{slug}". Under /templates/works you can add two templates, index.html and _entry.html. The former will render for the URL example.com/works and can be used for your portfolio section's listing page (i.e. it'd replace the current "Works" parent page), and the latter template's path (i.e. works/_entry) should be added to your portfolio section's Entry Template setting.

If you do need some fields for the listing page, you could create a Single called "Works" and set its URL Format and Entry Template path to just "works". A setup like this would circumvent your issue completely (and also avoid the problem with content editors getting your current solution wrong; adding new portfolio entries to the top level).


Multiple category relationship criteria (or)and(or)

I think what you want here is the union of (products related to a or b) and (products related to c, d, or e).

One good way to do these more complicated queries is to construct a set of the ids, and then do your final query based on that.

So, we will get the ids of products related to a or b:

{% set aOrBProductIds = craft.commerce.products({
    relatedTo: aOrBCategories,
    limit: null
  }).ids()
%}

and the ids of products related to c, d, or e:

{% set cOrDorEProductIds = craft.commerce.products({
    relatedTo: cOrDorECategories),
    limit: null
  }).ids()
%}

Now merge those arrays into one array with all of the ids:

{% set productIds = aOrBProductIds | merge(cOrDorEProductIds) %}

Finally, get the products, and paginate:

{% set productsToPaginate = craft.commerce.products.id(productIds) %}
{% paginate productsToPaginate.limit(20) as pageInfo, products %}


Is there a Zendesk plugin to fetch order information from Craft Commerce?

As of today (08/06/2020) there isn't a plugin that does that in the Plugin Store, so you'd need to do some custom plugin development if that's what you're looking for.


How do you format a date for saving with users/saveUser on the front end?

Craft stores dates in the database in the following format:

Y-m-d H:i:s

So submitting the date in this format should work, for example:

2014-06-24 23:30:00

It should also be possible to split the date and time into individual fields as follows:

<input type="text" name="fields[customFieldName][date]" value="2014-06-24" />
<input type="text" name="fields[customFieldName][time]" value="23:30:00" />


Is there a way to import recipients into a list in Sprout Email?

Sprout Email 2.x is not designed to be sending bulk email on it's own (September 2016). The feature is on our list to explore in future releases, and currently, Sprout Email can be used to manage sending bulk email via a third party mailer such as MailChimp or Campaign Monitor.

The current incarnation of "Recipient Lists" in Sprout Email is meant to be for very simple use cases where you may need to send Notification emails to a small list of people.  We will be revisiting the Recipient List feature to handle larger lists and integrations in the future.


{% for type in entry.buildType %}
{{ type }}
{% if not loop.last %}/{% endif %}
{% endfor %}

See: https://twig.symfony.com/doc/2.x/tags/for.html#the-loop-variable


How to target Sub-Category of Sub-Category

I'm not sure, but I think you might need to use level in your loop.

{% set categories = craft.categories.group('groupHandle').level(3) %}

{% for category in categories %}
    // etc
{% endfor %}

Have a look at the docs:

https://craftcms.com/docs/templating/craft.categories#level


Fatal error in StringHelper.php when using cache block around loop

Increase the amount of memory available to PHP through memory_limit is one option.

Another option is to reduce the amount of data (and therefore memory) you're dealing with in one request.

You don't share what craft.locationAPI.fetchAllLocations() is actually doing, but if you're returning results as Craft models, there is a significant overhead (performance and memory-wise) doing that with large data sets in Craft 2.x.  You could look and return more primitive data structures.

Another alternative is to batch the results and retrieve them over multiple AJAX queries.


Adding entries to the top level scope of a variable in Twig

I'm working on solving a similar problem and I've come up with a solution that stores a string of comma-delimited IDs in the session like this:
{% set displayedContentIds = craft.app.session.get('displayedContentIds')|split(',') %}

This code is added to all components on the page that are required to exclude content that's already been shown further up the page. I pass the array of IDs to the entry query for that block, if there are IDs to exclude:
{% set criteria = {
    section: 'mySection',
    limit: 5
} %}

{% if displayedContentIds|length > 0 %}
    {% set criteria = criteria|merge({ id: 'and, ' ~ displayedContentIds|join(', not') }) %}
{% endif %}

{% set entries = craft.entries(criteria) %}

I output my entries as normal with entries.all(), then I update displayedContentIds with the just-displayed entry IDs:
{% set displayedContentIds = "#{displayedContentIds},#{entries.ids()|join(',')}" %}
{% do craft.app.session.set('displayedContentIds', displayedContentIds) %}

This is a bit crude if I'm honest, but it's the only way I can think of to update a variable inside a block and have the updated value available to blocks further down the page.


How can I get the image picker on the WYSIWYG editor?

The simplest method would be to change your Redactor Config to Default in the rich text field settings. Should look something like this:


Date picker field type - quickly select year?

Using carlcs's idea, I put three LJ Dynamic Dropdowns in a SuperTable, here's the code for each dropdown (day, month, year):

{% for day in 1..31 %}
    { "value": "{{ day }}", "label": "{{ day }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

{% for month in 1..12 %}
    { "value": "{{ month }}", "label": "{{ month }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

{% set maxYear = now|date_modify('-15 years')|date('Y') %}
{% for year in maxYear..1925 %}
    { "value": "{{ year }}", "label": "{{ year }}" }
    {% if not loop.last %},{% endif %}
{% endfor %}

Then I added a Preparse field that joins these three dropdowns into a date string on each save (I have this under a User, so adapt to Entry/Asset/etc. if you need to).

{% spaceless %}
{% if user.userDateOfBirth | length %}

    {% set dateString = user.userDateOfBirth[0].year ~ '-' ~ user.userDateOfBirth[0].month ~ '-' ~ user.userDateOfBirth[0].day %}
    {{ dateString }}

{% endif  %}
{% endspaceless %}

To calculate age in my template, I use this little snippet (date("2015-07-06") will return a DateTime object so we can use the diff function on it).

{% set ageString = date(dateString).diff(now).format('%y') %}


So you'll want to update the Super Table Block's content and to do that when in a Matrix field is a little tricky, but it can be done.
$matrixBlocks = $entry->matrixField->all();

foreach ($matrixBlocks as $matrixBlock) {
    $superTableBlocks = $matrixBlock->superTableField->all();

    foreach ($superTableBlocks as $superTableBlock) {
        $superTableBlock->setFieldValues(['lightswitchField' => true]);

        Craft::$app->getElements()->saveElement($superTableBlock);
    }
}


I found the problem, which is pretty ridiculous but something that probably happens to other developers who are using multiple languages.. (I hope).

In

query: 'klantLocation:' ~ searchL,

I had to replace klantLocation with klantLocatie

Pretty dumb mistake but hopefully someone else will find some help in my mistake


Do I need to change the date.timezone in php.ini?

This is from the Craft Documentation about Date/Time Fields:

  Note: Dates and times [...] are displayed in the site’s timezone, however they get stored in UTC like all other dates in Craft.

Additionally you can also use the date filter, which allows you to specify a different timezone for the output (list of supported timezones). If you want to bind a timezone to a specific site locale (multi-lingual sites), there's a dedicated Q/A on how to do that.


How to retrieve the mode of an image transformation from its name?

Not possible out of the box, unfortunately. Asset transforms can be pulled by using the AssetsTransformService, but Craft doesn't expose that service to Twig (unlike the AssetsService, which is what you're working with when you're using craft.assets).

What you could do is to create a simple, custom plugin exposing the AssetsTransformsService to Twig by adding the following to a Variable class in your plugin:

public function assetTransforms()
{
    return craft()->assetTransforms;
}

Then, you'd be able to do something like this in your templates:

{% set transform = craft.myPluginHandle.assetTransforms.getTransformByHandle('myTransformName') %}

The mode is {{ transform.mode }}


Get a brand list of products for Javascript filter

Presumably you already have the code to retrieve the products you're after.

So just loop through your products and merge your brands in to an array.

If the brands are just strings, just make an array of the strings, otherwise if they are relations, grab the ids.

Something along these (untested) lines:

{% set brandStrings = [] %}
{% set brandIDs = [] %}

{% for product in products %}
    {# Either of these... #}
    {% set brandStrings = brandStrings|merge([product.brand]) %}
    {% set brandIDs = brandIDs|merge([product.brand.first().id]) %}
{% endfor %}

{# If strings, you've now got an array #}
{# If Ids, and you need to get the names, you can do something like... #}

{% set brands = craft.entries.id(brandIDs).find() %}

{% for brand in brands %}
    {% set brandStrings = brandStrings|merge([brand.title]) %}
{% endfor %}


You aren't able to pass an import into a macro. So helpers needs to be imported into each macro file that uses it.

You can however pass the cart to your macros. As a side note, it's definitely best to set the cart variable in a global template - this means you're only ever setting it once. All templates that extend this global template then inherit cart. The way macro's work though means they need to have these variables explicitly passed to them. They don't inherit variables in the same way includes do or when you extend templates.

You can then pass cart to your macro like so:

{# Variable set in an extended template or current template #}
{% set cart = craft.commerce.cart %}

{# Variable is passed to the macro #}
{{ teaser(product, imgSize, className, cart) }}

Macro file then edited to take variables:

{% macro teaser(product, imgSize, className, cart) %}
    {# We still need to import our helpers into this macro file #}
    {% import '_macros/_helpers' as helpers %}

    {% set category = product.category.first() %}

        {% set thumbAsset = product.productImage.first() %}
        {% if thumbAsset %}

        {% endif %}

{{ helpers.product_title(product.title) }}

{{ product.defaultPrice|currency(cart.currency) }}

            View Product

            {% if className == "product-teaser--featured" %}
                {{ category.title }} Range
            {% endif %}

{% endmacro %}


Error when trying to test Craft Pro on .dev

I found a solution! I had my local environment setup with homebrew following this article's instructions. After looking at the php error logs, I uncommented always_populate_raw_post_data = -1 in the php.ini file found in /usr/local/etc/php/5.6.

I then restarted the brew services with brew services restart php56 (install brew services by tapping gapple/services with brew tap gapple/services) and restarted apache with apachectl restart.

That did the trick!


Querying across relationships in a template

OK, here is one solution I've come up with, which seems to work and (I think) avoids 1+ queries:

{% set groups = craft.entries({
    section: 'alert',
    with: [
        'country',
    ]
}).orderBy('postDate desc').status('live').all() | group(alert => alert.country[0]) %}

    {% for country, alerts in groups | slice(0, 5) %}

            {{ country }}

                {% for alert in alerts %}

{{ alert.title }}

                {% endfor %}

    {% endfor %}

I would prefer being able to handle this entirely in queries though


If you do this:

{parent.uri}/{slug}

You should get URLs like this:

site.com/parent
site.com/parent/child-1
site.com/parent/child-2

Does that make sense?


The problem was related to the database already having a particular table defined. Was not so easy to find, some type of error would have made my life easier.

Solution: Re-create the database. Re-run the installation process.


You will need to reset your .limit(null) on the second call (the one with your offset) due to the way Element Queries work.


Can Craft easily be hosted across multiple servers?

Entirely possible. There is some discussion of having Craft installed in a load-balanced environment here.

You'll want to have CRAFT_STORAGE_PATH point to a shared file system for all servers.

If you have sticky sessions enabled at a load-balancer level, then PHP sessions won't be a problem.  If not, then you'll want to set overridePhpSessionLocation to true and have the PHP session files saved on the same shared file system.


Implementing Read-Replica (slave) database connections

Craft 3

You can see an example of how to do read/write splitting in Craft 3 here: https://docs.craftcms.com/v3/config/app.html#database-component

Craft 2

Definitely not current possibly natively in Craft since Yii's CDbConnection (which is what Craft uses for database connections) has no concept of master/slave connections.

In theory, something like the Yii DB splitting extension that @RitterKnight mentioned is a start in the right direction, but even then, you'd have to do some pretty significant core hacking to utilize it in Craft 2.

Should be much more feasible in Craft 3 since the ability to swap out core components like that is planned.


Show a list of recently used tags only from the current locale

Brandon at P&T was able to fill in the piece I was missing. He said:

To only get tags that were related from a specific locale, you just need to specify that in your relatedTo param:

    {% set tags = craft.tags.relatedTo({
      sourceElement: entries,
      sourceLocale: craft.locale
    }) %}

With the addition of order('dateCreated desc').limit(10) to put some additional constraints on what I was getting back, this solved it for me.


Commerce is definitely Craft's achilles' heel right now.

Like you, I'd love to switch over completely off WP but picking the best tool for the job means either rolling up your sleeves and writing your own or picking the best available solution and unfortunately that could be WP/Gravity... at least right now.

  We're also hoping to hand off the form creation process to the client afterwards.

Not to go too far off the Craft path here, but from a client services perspective, this part scares the hell of me.

Forms tend to be tricky beasts to begin with—especially so when you add in the commerce part of it.
I don't know what your registration forms look like but I'm guessing a lot of them are going to be very similar. Do you actually need a form builder to put in name, address, etc. Or is the only thing that changes on the form the retreat date, lodging location, etc.

You can do a lot with Craft's custom fields and instead of building up a form like in Gravity or Ninja (like you might do in WP), bake in those fields that won't change in your template and just let the client change a few pieces from the back end—like the date, price, etc.—and compose the rest of the form with Twig and an action handler.

Regardless of whatever technology you pick, this kind of project tends to need ongoing support as well so if you can do it, get the client on some kind of monthly retainer; that'll remove a lot of the uncertainty as you move forward. Sometimes what clients say they need and what they actually end up needing is completely  different. Craft is going to grow as a platform too, so basically you're buying some time as the client grows with it. It's a nice sentiment to think you just "hand it off" but in my experience, it rarely works like that.


I have also found this slightly confusing from time to time. These settings work well for me:

FYI, on the server the path is: .../public_html/uploads/services

Hope it helps


Empty page instead of 404 error when url contains channel slug

As Brad pointed out in the comments on my question I had to take a look in the custom route's defined in the Craft CP. My client tried to make a custom route which looked like this:

This caused for every url containing one "/" to use that template that unfortunately actually was a template that's why it wouldn't give a 404.

Original Comment:

Maybe an .htaccess rewrite rule interfering? Do you have any custom routes defined (in the Craft CP or in config/routes.php)? – Brad Bell


That error is a bug in Craft that's been fixed for the next release.  That line is PHP 5.4 array syntax and your server is still using PHP 5.3 (Craft still supports back to PHP 5.3).

In the meantime, you can go to the line it's complaining about and change:

$serverArray = [];

to:

$serverArray = array();


Purging inactive carts in Craft Commerce

The mistake was not reading the docs properly and putting the config values in general.php. Instead, I needed to create a commerce.php config file and put the values in that. As soon as I did, the orders were purged.


How to attach a plugin license to a CMS license?

To do this, you need to install the plugin on whatever site you want to associate with it - and then enter the license for it under Settings > Plugins.


Twig (and all php) is processed server-side before javascript even gets initiated. And once the page renders in the browser there no way to interact directly with twig. The only two options that you have is to either 1) reload the page or 2) request a page segment via ajax. I would opt for the later in this case.

To do this, you could either listen for an onClick() event on a submit button of some kind, or listen for onChange() events on the drop-down menus themselves; which would trigger an ajax call to the server, and display the results in your placeholder 'div'.

On the craft side you would want to create a separate template that renders just the requested news articles, based on either: variables that you pass to the template via post; or using a custom route that you set up (i.e. '/news/2015/03/').

For an example of creating a page template using custom routes and ajax to load entries based on date, see this example. You will need to adapt it slightly to only use the month and year (vs. month, day, year).

For an ajax example, see this example — which links to additional examples.

If you have a hard time putting the pieces together, leave a comment and I'll try and provide a more specific example.


Date/Time field outputting time with additional minutes

You are using the wrong variables.

The 10 is there because it means October not 10 minutes.

You have to use | date("g:ia”).


Not able to catch exception sending SMS with Twilio in plugin

The exception is thrown before you enter your catch block during this line

 $number = $twilio->lookups->v1->phoneNumbers($user->mobil)->fetch(['countryCode' => 'NO'])->phoneNumber;

That's why it can't be cached. Move it into the same block and handle every single possible exception that can be thrown accordingly or via generic \Exception class


How to get previous and next entry using the native GraphQL API?

So I'm wondering the same thing, I'm using CraftQL as I need to support mutations, and I am close with this - but I get an error if I try to use $id instead of a hard-wired Int (e.g. 99):

query getEntryData($id: [Int]) {
  prevEntry: entry(prevSiblingOf: 99) {
    id
    title
    slug
    uri
  }
  nextEntry: entry(nextSiblingOf: 99) {
    id
    title
    slug
    uri
  }
  entryData: entry(section: investigations, id: $id) {
    id
    title
    slug
    uri
  }
}

I get the following error:

"message": "Variable \"$id\" of type \"[Int]\" used in position expecting type \"Int\".",

BUT then if I pass the $id as Int (and not [Int]) it works. Can't explain the typing difference.

query getEntryData($id: [Int], $sameId: Int) {

   prev:entry(prevSiblingOf: $sameId) {
    id
    title
    slug
    uri
  }
  next: entry(nextSiblingOf: $sameId) {
    id
    title
    slug
    uri
  }
  investigation: entry(section: investigations, id: $id) {
    id
    title
    slug
    uri
  }
}


Multi-Environment Config Database Credentials

Here is what my configuration looks like. Ideally, I'd like to swap out the hard-coded baseUrl with something like I have for basePath. That way the other members on my team can call/put the site wherever they want and it won't break anything.

I don't make any changes to index.php.

Hope this helps!

db.php

return array(
'*' => array(
    'tablePrefix' => ''
),
'.dev' => array(
    'server' => 'localhost',
    'user' => 'username',
    'password' => 'password',
    'database' => 'dbname'
),
'mysite.stagingdomain.com' => array(
    'server' => '12.345.67.890',
    'user' => 'username',
    'password' => 'password',
    'database' => 'dbname'
),
'mysite.com' => array(
    'server' => '12.345.67.890',
    'user' => 'username',
    'password' => 'password',
    'database' => 'dbname'
)

);

general.php

return array(
    '*' => array(
    'cpTrigger' => 'admin',  // whatever you want
    'omitScriptNameInUrls' => true,
    'enableCsrfProtection' => true
),
'.dev' => array(
    'devMode' => true,
    'siteUrl' => 'http://mysite.dev/',
    'environmentVariables' => array(
        'basePath' => $_SERVER['DOCUMENT_ROOT'] . '/',
        'baseUrl' => 'http://mysite.dev/',
    )
),
'mysite.stagingdomain.com' => array(
    'devMode' => true,
    'siteUrl' => 'http://mysite.stagingdomain.com/',
    'environmentVariables' => array(
        'basePath' => $_SERVER['DOCUMENT_ROOT'] . '/',
        'baseUrl' => 'http://mysite.stagingdomain.com/'
    )
),
'mysite.com' => array(
    'siteUrl' => 'http://www.mysite.com/',
    'environmentVariables' => array(
        'basePath' => $_SERVER['DOCUMENT_ROOT'] . '/',
        'baseUrl' => 'http://www.mysite.com/'
        )
    )
);


Element API: Is it possible to ignore/skip an Entry?

Couldn't you modify the criteria to exclude that entry ?

id => "not X"


Yii 2 (which is what Craft 3 is built upon) has similar looking form/model validation:

https://www.yiiframework.com/doc/guide/2.0/en/input-validation

https://www.yiiframework.com/doc/guide/2.0/en/tutorial-core-validators

You can also look at how Craft does it in its own models and controllers.


But this only outputs the pageContent. I guess because booking is a single section and therefore has no level?

In short, yes. It's not super clean but you could fetch everything without worrying about level:

{% set merger = craft.entries.section(['pageContent','booking']).all() %}

Then check for level in your loop ('normal' entries return null as a level)

{% for item in merger %}
    {% if item.level is null or item.level == 1 %}
        {{ item.title }}<br>
    {% endif %}
{% endfor %}


Error when calling an image transform from matrix field

I seem to have worked it out - by specifying

'imageDriver' => 'gd'

in the config. I first tried to specify 'imageDriver' => 'imagick', but I was getting path error messages so I'm guessing it is not installed on the PHP installation I am using.

More info at
Errors with Craft 2.3, Imagine and Imagick


Dynamically load either standard res or hi-res background image

This is actually a difficult problem, and there are many possible solutions, none of which are optimal (until img srcsets are better supported).

The way I would probably go about doing this, depends on a couple of factors.

If it is important to show something on load, you need to include an initial image in the markup, like you have already. If that is not an issue, I would include the two different resolutions in data-attributes on the
, and then add the appropriate one with Javascript.

It would probably go a little like this:

markup:

....

js: (not tested, probably needs tweaking to work)

$(function() {
    var windowWidth = window.innerWidth || $(window).width();
    var threshold = 600;
    $('.js-resp-bg-img').each(function(idx, elem) {
        var bgImageUrl = $(elem).attr('data-low-res');
        if (windowWidth > threshold) {
            bgImageUrl = $(elem).attr('data-high-res');
        }
        $(elem).css({
            backgroundImage: 'url(' + bgImageUrl + ')'
        });
    });
});

If you need something to display on load, you put the low res image in the style tag, and switch it out only when appropriate. Downside with this is you'll load the asset twice.

Also, in my example I'm only testing for window width, if you need to you can do additional tests, for example testing for retina with this method.


Craft Commerce: Upload File Field in Order?

This is definitely possible. First create a file field to attach to your order in the control panel. Then create a file input type with a name attribute that uses the field you created name="fields[fieldName]". This would then get sent in the post request to updateCart.

<form method="POST" enctype="multipart/form-data">
  <input type="hidden" name="action" value="commerce/cart/updateCart">
  {{ getCsrfInput() }}
  <input type="file" name="fields[fieldName][]">
  <button type="submit">Upload file</button>
</form>

Then you could show the image on the cart/order using something like the following:

{% if cart.fieldName|length %}
  <img src="{{ cart.fieldName[0].url }}">
{% endif %}


If you want to do it in a single query, Marion's answer is probably the best.

Otherwise, you could do something like this:

{% set idsHavingCategory = craft.entries.section('news').relatedTo(category).limit(null).ids() %}

{% set omitIds = 'and, not ' ~ idsHavingCategory|join(', not ') %}

{% set entries = craft.entries.section('news').id(omitIds) %}

Inspired by this article, which shows how to (1) grab ids, and (2) query against them:

  http://webstoemp.com/blog/manipulating-craft-elementcriteriamodel-with-twig/

Also references related solutions found in these answers:

https://craftcms.stackexchange.com/a/4930/45
https://craftcms.stackexchange.com/a/4573/45


Special order filter (by language) in CP for Craft Commerce

Not possible with the system by default. Commerce doesn't support multi-store yet (and wont in Commerce 1).

If you want, a plugin could modify the order sources on the left side of the order listing screen using the hook:

https://craftcommerce.com/docs/hooks-reference#commerce_modifyordersources

In this hook you could show/hide sources depending on the user, and add sources for filtering my orderLanguage etc.


413 “Request Entity Too Large” error with uploading a file

413 errors occur when the request body is larger than the server is configured to allow. Here’s how you can fix it, depending on your web server:

Apache: Set the LimitRequestBody directive in either your httpd.conf file or a local .htaccess file. (https://stackoverflow.com/a/3719358/1688568)

Nginx: Set the client_max_body_size directive in nginx.conf (http://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/)

IIS: Set the uploadreadaheadsize config setting (https://web.archive.org/web/20160204040121/http://blogs.msdn.com:80/b/jiruss/archive/2007/04/13/http-413-request-entity-too-large-can-t-upload-large-files-using-iis6.aspx)

You also might want to try increasing PHP’s upload_max_filesize and post_max_size settings in php.ini or using the php_value directive in your .htaccess file if you’re using Apache (http://davidwalsh.name/php-values-htaccess).


How reference "Craft" js object in jquery scope

The "Craft" javascript global object can only be used in the backend, not on the frontend.


How does one get an order confirmation email to fire immediately in Commerce 3?

There are a couple of options here.

Number 1

If you have the config setting runQueueAutomatically set to false you could call the controller action queue/run via ajax from your success page. This would trigger the queue to run.

Number 2

You can use the EVENT_AFTER_COMPLETE_ORDER event to run some custom code, in a module or plugin. In that code you can include Craft::$app->getQueue()->run() this will also trigger the queue to run. e.g.

Event::on(Order::class, Order::EVENT_AFTER_COMPLETE_ORDER, function(Event $e) {
    Craft::$app->getQueue()->run();
});


Trouble running a plugin console command

Sounds like you haven't enabled the plugin from Settings->Plugins.

Once you do that, yiic will register your plugin's custom command.


Would it be possible to create a plugin to warn a user if a page is being edited

Inspired in part by Mats' detailed answer, I've written a plugin that does just this: MN Snitch

Enjoy!


Previous/Next button to next item in Matrix

In order to get previous or next elements in Craft you have to pass the current criteria in the elements getPrev function. In your case

{% set criteria  = craft.entries.id(2).first().projectList.type('project')

{% set prev = collection.getPrev(criteria)  %}


Display related entries on the entry page they are related to

Argh! this code works! I had duplicate entries and looking at the wrong entry! User erroooor!


Custom field plugin: Unable to find template / General custom field plugin information

Where are you storing your mapElement template? - Unless it is stored in the same folder as the templates for the front end of your site, then

Craft::$app->getView()->setTemplateMode(View::TEMPLATE_MODE_SITE);

is telling craft to look in the wrong place.

If you've got it stored in your plugin directory, then you don't need to change the template mode at all, as per : https://docs.craftcms.com/v3/extend/updating-plugins.html#rendering-templates


You can include standard HTML in Twig templates. So something like this would work:

You don't have to use Twig filters to add CSS or CSS files. Although you could create some CSS variables using {% set gray = '#eee' %} or {% set border = 'border: 1px solid black' %} for repeated styles such as colors, borders, etc., and then reference those like this, using the variable name:


In order to do the namespaced trick in Craft 3, you'd do it like this:

Create your folder structure like this for your locale with one file for the Control Panel and one for the front-end of the site:

Contents of files:

Settings for Checkbox field:

Template code:

Front-end results:

Edit entry results:


SQL Error (Feed Me) when matching entries

I believe this has been fixed in the latest version of Feed Me (3.0.2.1 at time of writing). Do feel free to comment if not, or get in touch via the Feed Me support channels