Display Items in customer order in a particular order

There is no current built-in solution for this.  I suspect they are displayed in the order they were added to the cart most likely.

Your best hope would be something like the cpjs addon and some magic JS to swap the rows, but it would be...non-trivial at best.

https://github.com/lindseydiloreto/craft-cpjs

You might want to put in a feature request here:
https://github.com/craftcms/commerce/issues


"Not yet" is the short answer. https://github.com/craftcms/commerce/issues/295


How to translate de postdate format for a multilanguage site

Instead of:

{{ entry.postDate.format('d M Y') }}

Use:

{{ entry.postDate | date('d M Y') }}

That should work.


Plugin init check if current page is dashboard

Nope, but you can use the {% includeJsFile %} tag to include the file(s) from your widget template. In whatever template you render in your widget's getBodyHtml() method, add this:

{% includeJsFile "https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY" %}

If you need to queue up several files, you'll need several {% includeJsFile %} tags. There's also a {% includeCssFile %}, if you need to add some external CSS, as well.


paymentMethodID payment method id cannot be blank

Update: it looks like it was an issue with the secure cert on the site.  Once we got that updated, purchases are going through as normal.


You should nest the child's details like so:

{
    "data": [
        {
            "title": "secrets",
            "import_id": "UUID-9-3/4",
            "child": {
                "child_title": "Harry Potter",
                "child_message": "Is in a dream"
            }
        }
    ]
}

Then make sure you you choose data as your Primary Element when mapping your feed and check Create entries if they do not exist for the relational field.


How do I pass a hidden input value to plugin onSaveUser event handler?

I found a solution. Though I am not sure if this is the best way to go about it, but here's what I did:

<input type="hidden" name="userType" value="org">

was added to the register form, and ...

$userType = craft()->request->getPost('userType');

if ($userType == 'org')
{
    // ...

was added to the onSaveUser event handler function.


That's it. mod_security is on by default and a rule is getting triggered. Turned it off and now the entry can be modified and saved. Thank you Brad!


I think you just can't: allowed field types seem to be hardcoded in craft\fields\Table::getSettingsHtml().
See https://github.com/craftcms/cms/blob/develop/src/fields/Table.php#L215 for details.
You might create a CustomTable field that inherits the Table class and overrides its getSettingsHtml() methods to allow you custom field type, but that seems overkill. It may be easier to just use a matrix field instead of a table field.


Allow registered end-user to update entry, but limited only to specific fields (Craft 3)

You can include a custom Behavior like the ContentBehavior/ FieldLayoutBehavior in Craft 3 and handle those by yourself. This way you'll be able to handle permissions by yourself. There are certain Control Panel Hooks to include custom HTML.

Create a custom Behavior that's kind of a wrapper for the usual ContentBehavior
Store "special/extra" fields for those Elements in a custom table
Render those extra fields in a custom panel/tab
store those new values in your custom Table in beforeSave and afterSave funktions

But in general creating a custom Element Type would be easier to achieve, since you'll have more possibilities and more freedom to do what you want


You don't mention if it's Crat 2 or Craft 3, but I'm not seeing anything in either codebase where Craft (or Yii) would limit the amount of memory available in its caching classes.


Error on functions in queue: "Session does not exist in a console request."

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

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

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


Send Password Reset Email to all users at once

I'm not sure if the Sprout Email plugin can do anything to help you or not, but I can think of a few options that would involve simple, custom plugins.

Every user has a "Require a password reset on next login" that an administrator can set from the CP under their settings.  You probably don't want to do that manually for 3,000 users, but a simple plugin (or a simple SQL query) could set the passwordResetRequired column in the craft_users table in the database to 1.

If you wanted to send an email and include a password reset link in that email ahead of time, a plugin would change that column to 1 for all users and follow similar logic in the UsersController for getting the password reset link and include that in the email body that you'd send to every user programatically.


Problem with data hash only storing last entry in loop

For the hash key to be dynamic, you must wrap it in parentheses:

(i): {


Turns out there's a plugin for that. Typography, by nystudio107.
https://nystudio107.com/docs/typogrify/#using-typogrify
===== edit =====
I was never able to get this working with typogrify. It never treated a period immediately surrounded by numbers as a decimal point.
It did inspire me to write a plugin, Fractionalize, to provide a '|fractionalize' filter which does the trick.


Compress Craft Control Panel CSS and JS per environment

I don't think there's anything built into Craft. What I do is

{% if craft.config.devMode %}
  <link rel="stylesheet" href="{{craft.config.environmentVariables['assetURL']}}css/style.css">
{% else %}
  <link rel="stylesheet" href="{{craft.config.environmentVariables['assetURL']}}css/style.min.css">
{% endif %}

I use devMode to control whether or not I want the minified css, and I use grunt's cssmin task to build my minified css.


Upon setup, Craft is installed with a free Solo license. This means that the user generated as part of installation is “the only account you will be able to create.” (From the official User Management documentation)
In order to create more users, you’ll have to upgrade your installation to the Pro version through the control panel’s Plugin Store. Pro is free to test and develop with.


Is it possible to add an entry value to the entry URL Format?

For this a good approach is to use the excellent Dynamic Routing system in Craft.

Solution #1

First create your section "Artists":

After that go to "Settings" -> "Routes" and add this Dynamic Route:

When this is done all URL requests made to "/artists/-whatever-" will be routed to the "artists/_entry" template. Now you can create your link like this:

Artist Name

Your URL might now look like this rendered:

Lady Gaga

In your "_entry" template you can now fetch your entry using this code:

{% set entry = craft.entries.section('artists').slug(craft.request.getSegment(2)).first() %}
Artist Name: {{ entry.title }}

Solution #2

If you instead want the URL to be "/artists/firstname-slug" you can alter the Dynamic Route slightly and use the Twig filter "split" to get the slug from the URL.

First change the Dynamic Route to:

artists/*

Then update your template "_entry" with the following code:

{% set segments = craft.request.getSegment(2)|split('-') %}
{% set entry = craft.entries.section('pages').slug(segments[1]).first() %}
Title: {{ entry.title }}

Your URL can now be "/artists/{{ entry.firstNameField }}-{{ entry.slug }}" and the template code will take care of the rest.


{% paginate craft.entries.section('exhibitions').endingDate('< ' ~ now).limit(8) as pastExhibitions %}
  ...
{% endpaginate %}

This will paginate the entries in section exhibiitions with endingDate < now. That ~ is string concatination operator. The string '< 2014-08-04' queries for entries with endingDate in the past.


You can build the array for your criteria model's relatedTo parameter step for step before adding it:

{# Initial criteria model #}
{% set exhibitions = craft.entries.section('exhibitions').limit(null) %}

{# Compose relatedTo parameter #}
{% set relatedToParam = ['and'] %}

{% if query.art is defined %}
    {% set catIds = craft.categories.group('artCategories').id(query.art).ids() %}
    {% set relatedToParam = relatedToParam|merge([{ targetElement: catIds }]) %}
{% endif %}

{% if query.location is defined %}
    {% set catIds = craft.categories.group('locationCategories').id(query.location).ids() %}
    {% set relatedToParam = relatedToParam|merge([{ targetElement: catIds }]) %}
{% endif %}

{# Add additional criteria. Avoid passing an array with 'and' only #}
{% if relatedToParam|length > 1 %}
    {% set exhibitions = exhibitions.relatedTo(relatedToParam) %}
{% endif %}


Best practice for naming fields shared across entries in CraftCMS

The job of naming something is sometimes the most difficult part of a project! This is pretty subjective, but even though it seems like those three fields would share the same settings and requirements (as mentioned by @Paul Werheul), if it was me I would choose field names like clubName, teamName, and playerName.

This way the field names explicitly state what is expected to be entered or returned in your template.

My very humble two cents!


Could not find a unique URI for this element

The Uri of each element must be unique but if your Uri format is something that might not render a unique string you'll receive the error you are facing with.

As soon as you include some unique identifier like { id } or { slug } into your sections uri it will work again. Right now you can only save an entry if the field value is unique


How do I retrieve tags and tag data for an entry in Element API?

I took a break from this project. Came back, looked at the code, and saw a simple overlooked error - had a ")" instead if "}".  Grrr.  Starring too much at pixels lately. Fixed the code. So it's all working now. The array_map with the Tag Model does work.


How do I use a leading slash with the url() function?

Use the trim filter to automatically remove leading and trailing slashes like so:

{{ url( entry.myField | trim('/') )  }}


Is it possible to use Craft as a webservice when no useragent is sent?

This post may help:
Is it possible to disable `requireUserAgentAndIpForSession` for specific instances?

Take a look at the requireUserAgentAndIpForSession config-setting.

Post from phone, sorry if formatting is a bit off.


Existing contents get deleted on Live Preview when adding new content on a matrix field

Do you have this problem in a multisite-installation? If so, it could be something with your propagation mode on the matrix field.

Please give us some more details to your setup: which version of Craft CMS, which propagation mode, multisite or not.


It's not just Windows / Linux / OSX that have different file system case sensitivities, but even different distributions of Linux can have them.  Or the same distribution, but with different file systems.  Or the same distribution and same file system, but one has been configured to be case sensitive and the case insensitive.

Instead of accounting for all of the different possibilities for a given route (example.com/articles, example.com/Articles, example.com/aRticles, example.com/ArTiClEs), it's going to be much less of a headache to just force lowercase at the web server level.


Pull in images to table rows using craft.assets wilst looping through a table field

Here is what I would do:

First, make an actual array of all the images (using find to make the array):

{% set imageArray = craft.assets.folderId('2').find() %}

Then, loop over the entries:

{% for row in entry.howItWorksTable %}

and in that loop each time you display a row, you can get the corresponding image (using the loop variable index0):

{% set image = imageArray[loop.index0] %}

Putting it all together:

{% set imageArray = craft.assets.folderId('2').find() %}

{% if entry.howItWorksTable | length %}

    {% for row in entry.howItWorksTable %}

        {{ row.stages }}
        {{ row.skillsLearnt }}
        {{ row.classes }}
        {{ row.price }}

    {% endfor %}

{% endif %}


Multiple backends on CraftCMS 3 - Problem with cpresources

Running into the same issue here!

For the uploaded files I have solved it by creating a NFS share on all backends (15 servers). Not ideal but it's working for now. Maybe mounting the cpresources to NFS share would also do the job, but I haven't tested it.


You can find most plugins for Craft here: https://straightupcraft.com/craft-plugins

There's a few different form plugins to choose from, not sure if all of them will have what you're looking for.

I've used Sprout Forms a few times and you should be able to do both of what you're asking for.


Not currently – if you want to, you can add a feature request.

In the meantime, if you're on a Mac I recommend using Sequel Pro for all your importing (and other database related) needs.


You can use this Control Panel CSS plugin to add whatever CSS you'd like.


Hide/show element actions dependent on tab

I've figured out how I can do it, but it doesn't feel like the best way.
What I've done is hooked on to the showActionTrigger event, then hidden the button if the source != 'staged'
showActionTriggers: function() {
    this.base();
    if (this.$source.data('key') != 'staged')
    {
        $('#button-id').hide();
    }
}

I have a feeling the best way is to build the JS on the element action class, under getTriggerHtml, but this will do for now.
Slowly getting my head around the CP js


Can I have a Craft Commerce product with options that change the product’s price?

Absolutely that is possible.  You can see an example of a complex options set up here for example (click Add Prints to get going...):

https://imagescience.com.au/services/fine-art-printing/order-fine-art-printing

Variants are also used for pages like these:
https://imagescience.com.au/products/inkjet-papers/museo-portfolio-rag

In terms of the front end, how you set up the UI is entirely up to you - in the top case, it's a React form at work, and in the second case just a simple table really.

Each of these forms ultimately just POSTs a list of fields to a Commerce controller - purchasableID and qty and optionally notes for each item the user chooses using the form.  These is posted to a Commerce addToCart controller.

The products themselves are all set up in teh back end of Commerce as variations - see https://craftcommerce.com/docs/products for an overview of that.  Basically you define a grid of variant options, each of which gets its own ID (later POSTed, as above) and has its own unique SKU (Stock Keeping Unit).  Each variant can have as many or as few custom fields as you wish (as can the parent product)..and of course each variant can have its own price.

The product & variants system in Commerce is VERY powerful indeed, but does take a little getting used to.  Best way to get started is to download Commerce and have a look through the sample templates to get an idea how it all works, enter some sample products in the back end, then attempt to make a few simple add to cart forms of your own - one that works for jsut products, then one that works for variant products.


How do I hide children of a disabled parent in a nav?

This is an example of our "quick and dirty" menu macro we used in older projects. It's recursive so it can have as many levels as you want and will only fetch enabled entries. For mobile devices the parent entry is rendered in the "child" menu as well because otherwise you won't be able to access parent entries with children.

It looks a bit overwhelming at first, because we had many things to consider but it's relative easy

{% macro menu(menuCategory, currentPage, includeStartpage, level = 1, parent = null, original = null, showParentPage = null) %}
    {% set originalPage = (original)? original : currentPage %}
    {% set activeClass = '' %}
    {% if original is not null and currentPage is not null and original.parent is not null %}
        {% if original.parent.id == currentPage.id %}
            {% set activeClass = "active" %}
        {% endif %}
    {% endif %}

        {% if includeStartpage %}
            {% set startseite = craft.entries.section('homepage').first() %}

                {{ startseite.title|raw }}

        {% endif %}

        {% if showParentPage and parent%}

                {{ parent.title|raw }}

        {% endif %}

        {% switch menuCategory %}
            {% case 'mainmenu' %}
                {% set entries = craft.entries.section('pages') %}
            {% case 'topmenu' %}
                {% set entries = craft.entries.section('pages').showInHeaderMenu('1') %}
            {% case 'footermenu' %}
                {% set entries = craft.entries.section('pages').showInFooterMenu('not 0') %}
            {% case 'descendants' %}
                {% set entries = parent.getChildren() %}
        {% endswitch %}

        {% for page in entries %}

            {% set url = _self.getUrl(page) %}
            {% set target = _self.getTarget(page) %}
            {% set title = page.title %}
            {% set class = "" %}

            {% switch page.type.handle %}
                {% case 'internalLink' %}
                    {% set title = page.linkName %}
                {% case 'externalLink' %}
                    {% set title = page.linkName %}
                {% default %}
            {% endswitch %}

            {% if (originalPage.getUrl == url|trim and not page.hasDescendants)  %}
                {% set class = "active" %}
            {% endif %}

            {# Check if entry has descendants #}
            {% if not page.hasDescendants or (menuCategory == "footermenu" or menuCategory == "topmenu") %}
                {# List navigation item if entry has NO child entries #}

                    {{ title|raw }}

            {% elseif menuCategory == "mainmenu" or menuCategory == "descendants" %}
                {# List navigation item if entry does have children #}

                    {{ title|raw }}
                    {% set includeParent = (page.type.handle != 'pageWithoutContent')? true : false %}
                    {{ _self.menu('descendants', page, false, level+1, page, originalPage, includeParent ) }}

            {% endif %}
        {% endfor %}

{% endmacro %}

Edit

You can use it with

{% import '_macros/menu.twig' as menu %}

    {{ menu.menu('mainmenu', entry, true) }}

You can remove all the entry.getType().handle checks. We have the entry types pageWithoutContent so they will only appear in the menu as "placeholders" to open sub menus, but if the entry type is a page with content the entry must appear in the sub menu as well to make it clickable for mobile devices. These pages need to have an active when they appear as "parents" but not as "children". You can see a working example of this menu here or here


Even thought this is an old thread, I recently ran in to the same problem. It turned out to be a PHP version issue. I was running MAMP with PHP 7.0.0, once I switched that host to 5.6.10 it worked perfectly.


Exclude certain entry types from Entry URL format?

I don't know of good, non-hacky way to do what you're doing.  Every entry in a structure should have some meaning otherwise you're going to fight the system.

Is there a reason why those top level landingPageGroups are just "vestigial" and serve no purpose? That would make them good candidates to break into separate sections. So Major Campaigns would be a new structure section, Major Events would be another new structure section, etc.

You could probably hack your web server to rewrite slugs so that /major-campaigns/moving-office becomes /moving-office but for every section you add, that becomes a nightmare.

Even if you think you'll use one template across the board, it's inevitable that at some point you'll be using different templates for each "section" as well. I don't know your content strategy but if you only use one section, your entry types will likely multiply too.


Sorry about that guys, this issue has been fixed in Videos 1.0.20:

https://dukt.net/craft/videos/updates#v1.0.20


How to add custom options or fields to an Order Adjuster?

Found it, you just need to use:
// `sourceSnapshot` can contain information to explain the adjustment
$adjustment->sourceSnapshot = [ 'data' => 'value' ];


How can I change variant price in Craft Commerce 2 form

It's not possible to send the price to the cart in this way.

You will need to send that price as a custom option on the item and then use a custom module or plugin to update the line item's price.

You can just alter the line item price directly if desired but it may be more appropriate to create an adjuster to do it.

So your add to cart form might look like...

<form method="POST">
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    {{ redirectInput('shop/cart') }}
    {{ csrfInput() }}
    <input type="hidden" name="options[customPrice]" value="HERE NEW PRICE">
    <input type="hidden" name="purchasableId" value="{{ variant.id }}">
    <input type="submit" value="Add to cart">
</form>

Then your custom module would listen for a Commerce event, probably populateLineItem (see events here https://docs.craftcms.com/commerce/v2/events.html#order-related-events)  and update the item's price.

use craft\commerce\events\LineItemEvent;
use craft\commerce\services\LineItems;
use yii\base\Event;

Event::on(LineItems::class, LineItems::EVENT_POPULATE_LINE_ITEM, function(LineItemEvent $e) {
   // update the line item's price with the customPrice option from this line item
   // save the line item
});


How we can set an image as default value in assets field

That's not possible, but the way I handle this is to have a Global called "Missing Image Fallback" inside a "Generic" Global field set, and then when I need to reference an image I use the following twig:

{% set image = entry.myImageField.first ?? generic.missingImageFallback.first %}

That will assign the first myImageField asset to 'image' if it's been filled in, but fall back to the generic global field if not.


Solved - bizarre one this.
Was using a third-party email service via SMTP and it was manipulating the URL somehow. Switching to use a direct SMTP connection with a specific email account has resolved.

Go figure!


I wrote a switch condition in my for loop and everything went well. My bad!


Yes, Craft still has its runtime caches for compiling Twig templates (as seen in your example) and such. Craft's template and partial cache is separate from Twig's own template compilation, if I'm not mistaken.

If storing in local folders won't work, you can change the cacheMethod setting to use a store other than a local directory ('memcache', 'apc', etc.).


You don't need any extra php code to do that.

The search function probably does the job for you.

{% set entries = craft.entries.section('orders').search('2016-04-14') %}
{% for entry in entries %}
  <h1>{{entry.title}} - {{entry.customDateField}}</h1>
{% endfor %}


Craft Commerce - explain transaction types and statuses to me

A transaction can have a single type and status at one time.
A transaction can also have a parent transaction relationship.
There are 4 transaction types:
authorize, capture, purchase, refund.
A transaction type determines what the transactions is and how it is counted when determining the order totals.
authorize is used when the customer is not immediately charged to their card, but an authorization is placed on their card. The authorization will be captured at a later time, and the customers card will then be charged. An authorization can have the status of pending, redirect, processing, success, or failed.
capture transactions are always child transactions of authorize transactions. You can only capture a authorize transaction that had a success status. A capture can have the status of success, or failed.
purchase is used when the customer is getting charged immediately to their card. An purchase can have the status of pending, redirect, processing, success, or failed.
refund is used when the customer was refunded an amount. It can only be the child of a capture or purchase transactions that have the status of success
There are 5 transaction statuses:
pending, redirect, processing, success, failed.
pending status is for when a transaction is first created. It could then be changed to different status once the gateway/customer determines what the transaction should be. For example, changed to the redirect status when the customer is being redirected off-site.
redirect status us when the customer was sent off-site. A redirect status should only be used for authorized and capture transactions as capture and refunds are usually done by an admin from the control panel and not taken off-site to perform those actions.
processing is a semi-successful status introduced due to asynchronous nature of some gateways where knowing if the transaction is successful or failed will happen at a later time. For example, in stripe the customer might be returned from a SCA offsite back to the craft site and we will update the transaction as processing before the webhook comes in with the results of the payment from the bank. When we get a processing status on an authorize or purchase transaction we still
'complete' the cart and turn it into an order. So the only way for a customer to complete a cart is to have a successful purchase or authorization or a successful processing transaction.
success status means the transaction was successful. This covers the authorization, capture, purchase and refund.
failed status means the transaction failed. This covers authorization, capture, purchase and refund.
We will update the docs with the above.


Please read this to get to know how to create a basic ajax request

And change the route to

action: 'utilities/clear-caches-perform-action',
caches: '*'


How can I programmatically change the system's status?

There are two existing console commands you can use, ./craft on and ./craft off (on and off).
If you want/need to implement your own, take a look at the commit.


This is certainly still possible with Commerce 3 and Craft 3.
In a custom plugin or module you can listen for the Transactions::EVENT_AFTER_CREATE_TRANSACTION event and amend the transaction amount at this point in the process.
For example, you could make your own payment form that includes a partPaymentAmount field and posts to the normal commerce/payments/pay controller action.
Then in your event listener to the Transactions::EVENT_AFTER_CREATE_TRANSACTION event, test to see if a value exists for the partPaymentAmount POST variable. If it does, amend the transaction amount accordingly. The payment should proceed with the amended amount, so long as it is still a valid amount to pay against the current order (i.e. it is less than or equal to the total amount of the order).
The nice thing about doing it this way is that it is a very light touch on Commerce and still utilises the existing Commerce workflow for processing the transaction and making sure that everything is updated properly.


How do you programmatically update an asset index?

This is what I ended up with which works great for me.

$ses = craft()->assetIndexing->getIndexingSessionId();
$src = craft()->assetIndexing->getIndexListForSource($ses, 7);

for ($i = 1; $i <= $src['total']; $i++) {
    craft()->assetIndexing->processIndexForSource($ses, $i, 7);
}


Home page won't load without 'index.php'

If I recall, IIS doesn't include index.php as a default document when looking for a page to load in a directory, but only things like index.html, index.htm, deafult.html, etc.

Here's how to change it.


How can I add images to field instructions?

This works with standard markdown code...

![Alt text](/path/to/image.png)

You can use either a full URL, or a local path to the image.


Getting Page Not Found error for my custom subdomain setup

This is now fixed. The dynamic path to the new templates folder was wrong:

define('CRAFT_TEMPLATES_PATH', realpath(dirname(__FILE__) . "/../templates_va").'/');


6 month old site is suddenly throwing 404s

Since files that begin with a dot are hidden by default in Unix-based systems like OS X, Craft ships with a “htaccess” file rather than “.htaccess”. If you are using Apache and want to use this file, you need to rename it to .htaccess when you upload it to your web server.

Not sure why suddenly your site stopped working, but I can tell you that Craft auto-updates will only ever touch files within the craft/app/ folder, so if your .htaccess file was misnamed, it’s definitely not due to a Craft auto-update.


Try out Craft Client and Pro on multiple development URLs?

You can always use this "super-cool feature" with sub-domains of "craft.dev" or "ontherocks.dev"! You can have as many as you want:

"craft.dev"
"pro.craft.dev"
"license.craft.dev"
"testing.craft.dev"
"is.craft.dev"
"super.craft.dev"
"cool.craft.dev"

:D


Entries Related by Category with Filler Entries After

This is probably pretty much the same code you already have, but I can't think of a more elegant solution:

{% set relatedEntriesIds = craft.entries.section('news').relatedTo(entry).limit(8).ids() %}

{% if relatedEntriesIds|length < 8 %}
    {% set moreRelatedEntriesIds = craft.entries.section('news').limit(8 - relatedEntries|length).ids() %}
    {% set relatedEntriesIds = relatedEntriesIds|merge([moreRelatedEntriesIds]) %}
{% endif %}

{% set relatedEntries = craft.entries.id(relatedEntriesIds).fixedOrder(true) %}


ElementCriteriaModel supports 'users' as well as 'entries'.

$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->relatedTo = array(
    'targetElement' => $currentUser,
    'field'         => $employer
);
$employees = craft()->elements->findElements($criteria);


Whilst Doug's answer is useful for knowing the ins and outs of a particular event once you've found it, actually finding which events are available in Craft 3 in the current docs is not straight-forward. After a bit of digging, you'll find that most events are part of Craft's services - so head to the Class Reference and choose the most relevant service from the craft/services menu. The events available to each service are listed at the end. For example: https://docs.craftcms.com/api/v3/craft-services-users.html#events


Here's a tutorial on setting up your first Craft CMS 3 project. I'm a little sad that it didn't come up in any Google searches :(

Setting up a New Craft CMS 3 Project


Pre-fill fields when creating an entry in CP

This functionality could be created in a plugin or module, but why wouldn't you duplicate the entry and change the fields you need to change?


Change markup depending on category of an entry

You're currently fetching an array of categories even if there's only one it, I think. You either need to loop through the array or try replacing this:

{% set categories = craft.categories.relatedTo(entry) %}

with this:

{% set category = craft.categories.relatedTo(entry).first %}

Alternatively, you could scrap the category conditional altogether and use entry types, with different entry types set up for different layouts (that's my preferred method). You could also try testing for the presence of images as well (because that seems to be the only difference in the markup):

{% if entry.images | length %}
    <aside class="newsimages col-xs-12 col-md-6">
        {% for image in entry.images %}
            <img src="{{ image.getUrl('medium') }}" alt="{{ entry.title }}" class="col-xs-12{% if loop.first %}{% else %} col-sm-6{% endif %}" />
        {% endfor %}
    </aside>
{% endif %}

Or have I misunderstood and it's the conditional you're having problems with?


'devMode' enabled on the frontend yet its set to false

Probably you are using SEOmatic; it has its own setting for the local environment you're using; check out this docs here: https://github.com/nystudio107/craft-seomatic/tree/develop#plugin-settings


If you're looking for an "audit trail" of pages a user has visited, then a plugin will be the way to go.

You'd want to track a user by something like their PHP session ID.  And for every request grab that session ID and the URI and save that in a your plugin's dedicated audit table in the database (no need to use entries for this).

When the user goes to their history page, you'll query your audit table and grab any rows with a matching PHP session ID and display them however you want.


How to show flash message for Commerce order when changing status on listing page?

I haven't tried this yet, but I think you can try to use "Server Side Event" with "Control Panel JS plugin for Craft CMS": https://github.com/doublesecretagency/craft-cpjs/blob/v2/README.md

Listen to server and append a custom alert when some event triggered at server side.

Here is some information about SSE.

W3S:
https://www.w3schools.com/html/html5_serversentevents.asp

SSE Browser Support:
https://caniuse.com/#search=Server%20Side%20Event

SSE Polyfill to Support Mobile Android and IE8+
https://github.com/Yaffle/EventSource

Yii2 SSE Server Side Example:
https://www.yiiframework.com/wiki/329/real-time-display-of-server-push-data-using-server-sent-events-sse

Yii2 SSE component:
https://github.com/odannyc/yii2-sse

Hope this helps.


How to remove hidden HTML from Radactor editor in CrafCMS 3

If it's only for you, you can activate/use the source plugin to switch the view. That way no html is generated when you paste something

Maybe this option can help you too. There is also a paste callback you can use to change the inserted html


Tried to duplicate site in local environment but loading blank

I ended it up fixing the issue by replacing the /craft folder with the original installation folder and then just replacing /craft/templates and /craft/plugins from the existing site.


Returning ElementCriteriaModel of entries via plugin

Of course this is the expected behavior because you don't return an ElementCriteriaModel from your plugin.

You do return $criteria->find(); so you'll return an array of entries but not an ElementCriteriaModel if you want to return the object instead of the entries you have to do return $criteria.

As soon as you use the find() method Craft builds a query based on your ElementCriteriaModel, executes it and returns you an array of elements or null.


Based on https://craftcms.com/docs/lightswitch-fields and https://craftcms.stackexchange.com/a/352/5134:

{% if entry.lightswitchFieldHandle %}
    {% if currentUser %}
        Display entry that only logged users can see
    {% endif %}
{% else %}
    Display entry that anyone can see
{% endif %}


Where are all these columns coming from on the Entries in happy-lagger.test project?

On every entry type (or even on the "All entries") you can specify the columns visible in the Panel. Click on the cog at the bottom of the light-grey sidebar. You'll have access to all entry' fields!

The magic of Craft ;)


Solution from Craft:

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

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


Check out the discussion in this SE question: Best way to deploy Craft3 to webserver?


Saving asset programatically, eg via API

Not an answer directly to your question but a general function to upload an asset in PHP. In my case $file is an uploaded file in the $_FILES array. You can download a file per url and insert it's tmp_name and name manually

/**
 * Upload a file
 *
 * @param $file
 * @return int|null|string
 * @throws \Throwable
 * @throws \craft\errors\ElementNotFoundException
 * @throws \yii\base\Exception
 */
public function uploadImage($file)
{
    $assets = Craft::$app->getAssets();
    $folderId = 1; //<- insert your folder id

    /** @var \craft\models\VolumeFolder $folder */
    $folder = $assets->findFolder(['id' => $folderId]);

    $asset = new Asset();
    $asset->tempFilePath = $file['tmp_name'];
    $asset->filename = $file['name'];
    $asset->newFolderId = $folder->id;
    $asset->volumeId = $folder->volumeId;
    $asset->avoidFilenameConflicts = true;
    $asset->setScenario(Asset::SCENARIO_CREATE);

    $result = Craft::$app->getElements()->saveElement($asset);

    // In case of error, let user know about it.
    if ($result === false) {
        throw new Exception('Error while upload asset');
    }

    return $asset->id;
}


Currently no, however the ability to edit completed order details is on the list for 1.1.


Contact Form: Name and Email in Message Body

I figured it out by duplicating the field...

<input id="fromName" type="text" name="fromName"
value="{% if message is defined %}{{ message.fromName }}{% endif %}">
{{ message is defined and message ? errorList(message.getErrors('fromName')) }}
<input type="hidden" id="fullName" name="message[Full Name]" class="fullName">

Then duplicating the single entry to the hidden with some Javascript...

    $('#fromName').bind('keypress keyup blur', function() {
      $('#fullName').val($(this).val());
    });

It parses through to the email message as:

Full Name: First Last


Output Matrix Block with Element API Plugin

you have to call

$block->text->getParsedContent()

or another method of RichTextData Model


Database structure for Craft 3 to import from external source?

I think you have to know what you need and what you want to achieve.
You need to decide if you want to add elements or records because there is a huge difference between those two types of objects and how you need to import and implement them

Elements
Pros:

it does not take a lot of time to make them manageable for clients
they can use all Craft features (relation fields, lists, edit forms....)
they are really flexible

Cons:

you'll need a little bit of time to dig into the concept if you are totally new to Craft
they'll have a record in your elements table so for larger projects you'll have to pay attention at your performance

Records
Pros

easy to handle
it does not require much time to create/import records since they are standalone and have no requirements
Yii's activerecord object is really powerful and intuitive in searching records
they don't create a massive overhead in your db

Cons

If you are going to make your records editable to users/customers in the cp you'll need to create everything on your own (templates/forms....) because they have no field layout and it's a mess to redefine them as elements to use Craft features... I did it once, it was not funny
You are not able to use Craft relations by default and have to create custom relation tables if you are going to do fancy stuff

After you decided what to use, you have to decide how you would like to proceed. You can create a custom element type or use an existing one (entries, categories) and how complex it needs to be. But without more information from your site it's hard to give any further advice.

I suggest everyone to create a custom plugin for imports to handle them. Due to Crafts/Yii2's plugin management and services it's totally trivial to create a data import because everything is really easy to understand and to manage. You can create a custom controller to fetch the data you need, set the values of your elements/records and use their save functions. The rest happens nearly automatically


Delete / change Status from CP via Ajax (trigger event)

Unfortunately, this is a known bug in Craft. Bulk actions do not trigger their respective events.

I'm not sure when (if?) a solution will appear. I'm guessing that it won't be fixed in the 2.x branch, since this bug has existed for quite awhile now. With any luck, it'll be fixed when Craft 3 launches.


How to allow Asset removal in the Control Panel for an Entry

Does everything else seem to be working? Maybe try removing the field from your section and then re-add it?

You might also try clearing the caches: Settings -> Clear Caches.

Craft logs various things to craft/storage/runtime/logs/craft.log If there's an error of some kind, maybe with your database, it'll show up there.

If that doesn't clear it up, shoot P&T a message and have them take a look at your install. You can do that right from the control panel.


How do I check if a product has stock in any of it's variants?

I managed do this with the following:

{% set variants = craft.commerce.variants({
    product: product,
    hasStock: true
}) %}

{% if variants|length <= 0 %}
  Sold out
{% else %}
  Add to basket
{% endif %}

The hasStock criteria takes unlimitedStock into consideration.

if (isset($criteria->hasStock) && $criteria->hasStock === true)
{
  $hasStockCondition = ['or', '(variants.stock > 0 AND variants.unlimitedStock != 1)', 'variants.unlimitedStock = 1'];
  $query->andWhere($hasStockCondition);
}


The trouble is, there's no one way to utilize AWS. You can set up a simple VPS, or get endlessly complicated with load-balancing multiple servers, adding CDN, utilizing cool caching options, and plenty more.

I've been fortunate enough to learn a lot from a siteops team that established all the infrastructure. It's a bit much for getting started, but the result was a combination of Route 53 for DNS, Elastic Beanstalk+Docker+EC2 for server instances, S3 for Asset sources, CloudFront for easy CDN, RDS for MySQL, and Elasticache for Redis session storage. Craft happily worked with all these things out of the box, after some trial and error. The goal wasn't to have a single server running, but discrete components that could be scaled for stability and demand.

But that's a horrendous place to get started. While I need to write a blog post about what I've learned AWS-wise, you can get started more simply by following a tutorial for another LAMP app like WordPress since most of the setup's going to be the same. If you're comfortable with Linux, or comfortable Googling your way through various tweaks, this should be a breeze. Just pretend the AWS control panel isn't hilariously daunting and you'll be fine.

If you're looking to be a Craft-AWS pro, you could experiment in steps:

Level 1: Get Craft running on a single EC2 instance

All the stuff on one box, conceptually identical to Digital Ocean or Linode or whatever. I like Ubuntu 14.04 because I'm most familiar with it, but you can pick a Linux distribution, make sure the requirements are in place, give Craft a poke, and triumphantly point a domain name to your EC2 IP.

Solspace have created a detailed guide for this.

Level 2: Sprinkle in AWS components

This will prove that adding AWS services needn't be hard. You can easily...

Add CDN with CloudFront
Move MySQL off of your VPS and use RDS instead
Use Elasticache for Redis, and store PHP's sessions there by installing an extension and adding two lines to php.ini (session.save_handler = redis and session.save_path = tcp://your-aws-cache-url:6379)
Use Route 53 for DNS, because why not

Level 3: Automate deployments and use multiple server instances

This is where I start to gloss over: set up Docker images and Elastic Beanstalk for automated deployments, and add multiple EC2 server instances with load balancers (and sticky sessions!) that spread out traffic. You've theoretically got many of your pieces in place after level 2, so if you can master level 3 you'll basically have your undergraduate degree in AWS.

Edit May 29, 2020

While it isn’t AWS-specific, there’s a Knowledge Base article with tips for configuring Craft for multi-server environments: https://craftcms.com/knowledge-base/configuring-load-balanced-environments


Is there a quick way to check a server for Craft's minimum requirements?

There is no way of programmatically checking whether a server fulfils the minimum requirements in Craft without uploading all of the Craft files, however I have created a script that performs all of Craft's web server related checks. It does not connect to a database so cannot check the MySQL version or that the InnoDB storage engine is installed and enabled, but this should be relatively easy to find out by asking your web hosting company.

The script is available for download here:

https://github.com/putyourlightson/craft-requirements


Simply using 'RAND()' in the order parameter does the trick.

{% for image in entry.banner.limit(1).order('RAND()') %}
  {{ image.url }}
{% endfor %}


Getting Commerce Products using Element API in Craft 3

You're so close! Just one change (see the elementType key, and the added comment)…

use craft\commerce\elements\Product;

return [
    'endpoints' => [
        'api/search' => [
            'elementType' => Product::class, // This provides Element API the fully qualified Element namespace + class.
            'paginate' => false,
            'pretty' => true,
            'criteria' => [
                'limit' => 15,
                'search' => (Craft::$app->request->getParam('keyName')) ? 'title:'.'*'.Craft::$app->request->getParam('keyName').'*' : ''
            ],
            'transformer' => function(Product $product) {
                return [
                    'title' => $product->title,
                    'url' => $product->url
                ];
            },
        ],
    ]
]

  Note: I'd recommend leaving the use statement as just Product, as I've done above. What you're importing is a class that inherits from the Craft Element class… “Model” has some other specific connotations in Craft + Yii, and even though at a lower level, Elements are still models, I think it's a good idea to leave them named as-is… after all, this is the Element API!


You need to separate your criterias with commas

listinglatitudenumber: 'and, ' ~  '>=' ~ pluginResults.latmin ~ ', <=' ~ pluginResults.latmin,


Is it possible to create a new asset from an image URL?

Download the image into a temp file, then upload it as an asset. You can find $iAssetSourceId by looking at the URL when editing an asset source

$iAssetSourceId = 4;
$iAssetFolderId = (int)craft()->assets->getRootFolderBySourceId($iAssetSourceId)->id;
$sTempFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $sFilename;
$sFileContents = file_get_contents($sImageUrl);
file_put_contents($sTempFilePath, $sFileContents);

// Get craft to copy the temp file into the assets folder
$oAssetOperationResponse = craft()->assets->insertFileByLocalPath(
    $sTempFilePath,
    $sFilename,
    $iAssetFolderId,
    AssetConflictResolution::Replace
);

return (int)$oAssetOperationResponse->responseData["fileId"];


Best practice for adding a title to a channel overview page

If there's only this one page, I'd probably also use a Global Set instead of a Single Section for this.

Add a Global Set with the handle siteInfo and add a Plain Text field title for your title to it, make sure to mark it as translatable. Then in your template access it via {{ siteInfo.title }}.

The good thing with this approach is that you can allow your client to edit the title (for all locales), without having her edit the template or the static translations file. And! You can later add other fields to it, e.g. for other site metadata (description, open graph, etc.) or to change the site's theme.


How can I populate some records after my plugin is installed?

On the main MyPluginPlugin class, there is a method you can override called onAfterInstall(). Which will run after your plugin is installed.

To create those records, you can place the following code into the method:

public function onAfterInstall()
{
    $record = new MyPlugin_ExampleRecord;
    $record->setAttribute('attributeName', 'value');
    $record->save();

    $record2 = new MyPlugin_ExampleRecord;
    $record2->setAttribute('attributeName', 'value2');
    $record2->save();
}


Rich text field adding   and normal space char at random

I've found that this happens when you end a line or string with a space and put nothing after it.

"Text " becomes "Text "

If you then copy "Text " and paste it repeatedly you'd end up with "Text Text Text Text Text Text "

Same for a lone space on a line.

" " becomes ";nbsp"


All of the templates that generate the HTML files for the front-end of your site will live in the templates folder on the server Craft is installed on.

You can edit the HTML there to add <h2> tags anywhere you wish.

The most important thing to note about Craft CMS is it is a platform used to build bespoke solutions for clients. It is light on traditional "out-of-the-box" features and instead provides developers with a modern toolset and content teams with a great author experience. In practice, this means that every Craft site is made specifically for the client which is great and why clients and developers love us.

Here are a bunch of learning resources that should help get you up to speed quickly.

Craft Official Docs & Support:

Craft CMS docs - The official Craft CMS documentation
Support Services - Both free and paid first-party support options.
Craft Discord group - The Craft development team is in Discord every day along with thousands of other Craft developers and users from all over the world.
Craft Stack Exchange - The best place to ask "how do I" type questions. Our development team monitors Craft Stack Exchange on a regular basis.

Learn Craft:

CraftQuest - CraftQuest is our official education and training partner. They have a number of excellent free and paid resources for Craft CMS & Craft Commerce. Ryan Irelan, Mijingo's founder, also offers customized training online or on-site.
Tuts+ Tutorials - Not official but [very good and low cost].
nystudio107 Blog — Andrew Welch is one of the best Craft developers around and the creator of the popular SEOmatic plugin. His regularly posts some excellent developer-oriented posts on Craft and web development.


Issue was not RTFM. :) Basically I didn't include every part of the stripe.js setup


"Your session has ended" modal popping up constantly

Thanks to Brad's help, we discovered that the server was misconfigured with an incorrect value for session.cookie_domain. Fixing that resolved the issue in this case.


Does Craft ActiveRecord require any special table column (dateUpdated, dateCreated,...)?

The only difference between Craft and Yii active records are the columns dateCreated, dateUpdated and uid if you have these columns you should extend Crafts ActiveRecord since it's save function adds compability to those columns otherwise  just use Yii2 ActiveRecord


Set Twig variable with javascript/jquery for displaying entries based on clicked value

The Twig code to fetch entries occurs on page load - Your JS code will run after the page loads and won't be able to update/fetch new entries. Instead, you should look at building a system that uses query strings to add the id's to the Twig variable on page load - then enhance this using AJAX.


Not sure I'm following 100%, but in Craft 2, a structured section has a "Nested Entries" text box in the "Entry URL Format" under a section's settings where you can dynamically access the URI of a parent element in a structure like so:

{parent.uri}/{slug}

In Craft 3, under a section's Settings, that has moved to "Site Settings" and you just have the "Entry URL Format" text box.  You could do something similar like so:

{parent.uri ?? ''}/{slug}

i.e. if there isn't a parent.uri, just use the slug, otherwise use prepend it.

You've got the full power of Twig in those text boxes, so you can adjust however you need.


Erros when using Entry Variable in craft.app.feeds.getFeedItems

Solution is simple, the field type is a select so I need to change

entry.feedLimit

to

entry.feedLimit.value

And then it works


"Error: Unknown package has no name defined" when updating Craft 3

Okay, so this seems to be the incompatibility issue between craftcms/plugin-installer < 1.5.6 and Composer 2: https://github.com/craftcms/plugin-installer/issues/5
The solution is to update in multiple steps:

Do a normal composer update, which will fail for a couple of plugins, but will update craftcms/plugin-installer to 1.5.6.
Delete the vendor folder.
Do a composer install, as the composer.lock file has already been updated in the first step, and craftcms/plugin-installer is locked to 1.5.6 now, so the plugins should install fine.
Deploy to production: because the lock file is backward-compatible, whenever the "internal" Composer of the server will be upgraded to the 2.0-branch, it will be handled, as the composer.lock file is already 2.0-compatible.


Not with Freeform - the fields can only be used once in each form, similar to how fields are used in native Craft elements.
I believe Formie allows you to re-use fields.


How do I get the Settings System email Address?

You can get this in a template like so:

{# returns an array of your email settings #}
{% set settings = craft.systemSettings.email %}

{# returns the email address #}
{{ settings.emailAddress }}

And in a plugin you can do:

craft()->systemSettings->getSetting('email', 'emailAddress')


How do I upload photos into my assets list/library?

Have you created that directory? If not, you need to. Also be sure the directory you create has the correct permissionss (writable by the web server)


How can I restrict assets on a per-file basis?

Why don't you just set up two separate asset sources, one default one with files being freely accessible and one source with access for logged-in users only by making use of that Internal Assets Plugin you mentioned.

Instead of managing the rights with a lightswitch you would upload or move the assets in the right source.

Another option would be to have two asset fields for your entry type, one configured for each source. And you could then always hide one of them with a lightswitch using the brand new Reasons plugin.


You can use slice and merge filters to “insert” that random entry into your array of entries.

In the following example I’m using the id param to query for the selected entries and I’m also setting fixedOrder, as this returns the entries in the same order as the IDs entered into the id param.

{% set selectEntries = craft.entries.id('7, 2, 83, 9, 90').fixedOrder(true) %}
{% set randEntry = craft.entries.section('channelX').order('RAND()').first() %}

{% set navEntries = selectEntries[:2]|merge([randEntry])|merge(selectEntries[2:]) %}


You need to create a custom Field Type or you can use dynamicfields in order to gain dynamic inputs. Or is it just about hiding/showing specific values in Javascript and not really about Craft at all?


Giving the enduser the ability to include scripts is risky way to present social media links. Any errors could protentialy break the entire html page / site If you really want to do it this way you can use twig's raw filter


Create a commerce.php config file in your config folder and set the cartCookieDuration to a time interval. The default is 3 months.

<?php
return [
    'cartCookieDuration' => 'P3M',
    'purgeInactiveCarts' => true,
    'purgeInactiveCartsDuration' => 'P3M',
];


Getting PHP error when trying to bind to onEditionChange event

Because that particular event is raised from AppBehavior (and therefore WebApp), it doesn't follow the same component.eventName syntax that the other Craft events use and you can't use craft->on() to register to listen to it.

You can register to listen to it through the traditional Yii method, though.  This should work for you:

craft()->onEditionChange = function (Event $event) {
    craft()->womb->sendEvent($event);
};


How Do You Add A Form on a Page to Gate the Content?

Depending on your Craft License you could make use of a login form as described inside the docs here.

If you got the loginform working, simply use {% requireLogin %} on the site template (i.e. inside the twig template file) that should have restricted access.

If your goal is to just provide an E-Mail without a password you would need to tinker around a bit and maybe just write up a small plugin. To get startet I suggest reading this and this. Out of the box this is not possible as far as I know.
I would advise not just using an E-Mail for validation as ab@c.de for example is a valid E-Mail, though unlikely that it is real. Some sort of login/auth would provide a more solid experience and enforces that the user is real and has validated their E-Mail with the CMS (as craft can send a validation link to given E-Mail after registering with the site).


How do I create a dynamic field on a front-end form with the Sprout Forms plugin?

Sprout Forms needs to know how a field should render on the front-end. By default it supports several common fields, but you will need to add support for custom fields on your own.  It sounds like you've got your field created and working, so you'll just need to add Sprout Forms front-end field support.

Adding support on the front-end is very similar to how you added support for your field in the Craft control panel. If you want to see several examples of custom fields adding front-end field support for Sprout Forms, take a look at the Sprout Fields plugin.


How to prevent "Failed" errors in job scheduler in Craft CMS 3?

I currently cannot see any way of achieving this as the only appropriate event that exists in the yii\queue\Queue class, afterError, is called before the job is failed in the handleError method of craft\queue\Queue. So your best bet would be to convince P&T that there is a valid use case for adding an extra event that will let you prevent the fail error from appearing.


Fallbacks for assets not avilable in a locale

I think you have to apply locale('en_gb') to the entry and not to the field. So entry.locale('en_gb').assetField.first().url should give you the correct value for the other locale.


Does each MatrixBlockModel in an entry have a unique dateUpdated?

Yes I can confirm, currently the dateUpdated property returns the same datetime object for every block model. It's actually the save date of the entry (entry.dateUpdated) that is saved to the craft_matrixblocks table in the DB.

Can't say if it's intended to work like this though.


Help with understanding how to structurally build a sermon catalogue

There is probably no best answer. There are a number of ways to structure craft to support this, and any answer is going to be highly subjective. A lot will depend on the relationships between the elements, and what the requirements of the different elements are (i.e. how complex, etc).

One option to get the desired uri pattern (i.e. /sermons/series-name/sermon-name) would be to do something like this:

Create a single called sermons that would be the landing page for the sermons section.
In the sermons template you would display the sermons overview content, and retrieve and display the 'series' (perhaps ordered by date, or category, or whatever).
Create a structure to house 'series', with at least 2 levels, with the series collection at the root and the individual series items (a.k.a. sermons), beneath. The series collection and series items would each have a different Entry Type so that fields could be unique for collection vs. items, and you can display a different template depending on the Entry Type.
Set the uri for the 'series' structure to be 'sermons/{slug}' and for nested entries to be {parent.uri}/{slug}.
You could also create additional levels for video, artwork, etc. which would get added to the uri automatically (where each level or type of content might get assigned its own Entry Type based on the type of content your working with) (i.e. /sermons/series-name/sermon-name/videos/video-name).

There are lots of other options and considerations also, but this might be an easier one to deal with, without having to create your own custom routes to get the uri pattern you are looking for.

This assumes of course that an individual series item (or sermon) belongs to only one series. If not, then you may want to consider other options, such as creating a channel for 'series' and a channel for 'sermons' and then relate the two using an entries FieldType.

You can even take the structure concept further and map the whole site using a single structure, with different entry types for the different types of pages. This makes the nav very easy to build and the sections/pages can all be moved around easily. And you can always pull in other content into those pages from other channels as needed. OR create a structure for the rest of the site and structure for the series, where the uri's match up nicely.

Basically. Lot's of options.


AttributeType::Handle Validation and Unique

In addition, is there a way to throw an error when the value isn't unique? Again, the record doesn't save if I use a key that is already in the DB, but there is no error.

If you use 'unique' => true in an attribute on your record, Craft will use Yii's CUniqueValidator class to verify the uniqueness of an attribute in the database.

$record->validate() will fail and you can use $record->getErrors() to get the error message.

return array(
    'key' => array(AttributeType::Handle, 'default' => '', 'required' => true, 'unique' => true),
);


Can you relate entries from more than 1 section?

Yes, you can. When creating an entires field the Sources option is where you select which sections you'd like to be able to select entries from. See Entries Fields in the docs.


Something like this should work:

Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,
        function(ModelEvent $event) {
            $entry = $event->sender;
            $isNew = $event->isNew;

            if ($isNew) {
                $enEntry = Entry::find()->id($entry->id)->site('enSiteHandle')->one();
            }
        }
    );

Just swap out enSiteHandle with your actual English site handle.


Add elements to ElementSelect via Javascript

Do you need something like this (using jQuery):

$('#yourID').append( '<option value="value">text</option>' );


This turned out to be an issue with the mysql server itself, not a Craft CMS issue at all.

It appears that during a previous field addition, the database server crashed and left hanging temporary files that didn't match with the database itself.

Spun up a new database, copied the DB over and everything worked as expected.


Have a look a little further down in the Readme and you will see more information regarding Watermark.

From the Readme...

image: The image that is to be used as watermark. Just as the image parameter in the craft.imager.transformImage method, this can be an AssetFileModel, a string to a previously transformed Imager image, or a string to an external image.

{% set logo = craft.assets({ id: 11 }).first() %}
{% set watermarkedImage = craft.imager.transformImage(image, {
    width: 600,
    watermark: { image: logo, width: 80, height: 80, position: { right: 30, bottom: 30 }, opacity: 0.8, blendMode: 'multiply' }
}) %}

Also a link to a Watermark demo https://imager.vaersaagod.no/?img=6&demo=watermarks


Choose not to save an element on EVENT_BEFORE_SAVE_ELEMENT

This functionality or behavior is a bit confusing. The Elements Service has its own Events for saving Elements, specifically... but because ultimately Elements are just Yii Models, they have a discrete EVENT_BEFORE_SAVE event that uses a ModelEvent, which has the isValid property.

This is the point in the life-cycle where saving the Element can be prevented. The beforeSave method is called on the Element being saved (usually overridden in the actual Element implementation, but called + returned at the end of the subclass's method, like parent::beforeSave($isNew)), and the resulting boolean ($event->isValid) determines whether or not the saving continues.

So, in short: You can listen directly to the Entry's EVENT_BEFORE_SAVE event to prevent it from saving:

use craft\elements\Entry;
use craft\events\ModelEvent;

use yii\base\Event;

Event::on(
    Entry::class,
    Entry::EVENT_BEFORE_SAVE,
    function(ModelEvent $event) {
            $entry = $event->sender;
            if ($entry->sectionId == 5) {
                $event->isValid = false;
            }
        }
    });


Handoff to Paypal Express with Craft Commerce

There is most likely some error in your configuration, or what you're sending to the cart.

The following code (when in devMode) will show you any errors that are coming back from Commerce/Paypal when you're redirected back to the cart:

   {# SHOW ANY ERRORS IF THERE ARE ANY! #}

{% if craft.config.devMode and (craft.session.hasFlash('commerce') or craft.session.hasFlash('notice') or craft.session.hasFlash('error')) %}

    {% set isErrors = true %}
    {% set commerceFlash = craft.session.getFlash('commerce')|join('|') %}
    {% set noticeFlash = craft.session.getFlash('notice')|join('|') %}
    {% set errorFlash = craft.session.getFlash('error')|join('|') %}

    Commerce: [{{  commerceFlash }}]
    Notice: [{{  noticeFlash }}]
    Error: [{{  errorFlash }}]

{% endif %}


How can I push a result of entries/products from a loop into an array?

This line doesn't return an array of items; it returns an ElementCriteriaModel:

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

That's probably why you're having problems with the |merge.

Changing it to the following should do the trick:

{% set entries = craft.entries.relatedTo(category).find() %}


How can I get only those entries with non-empty assets field

Craft 2.5 introduced a new feature for this.

  It’s now possible to find elements where a relational field does/doesn’t have any related elements, by passing ':notempty:' or ':empty:' onto the field’s ElementCriteriaModel parameter (e.g. craft.entries.myEntriesField(':notempty:')).

So in this case you can use:

{% set entries = craft.entries.myAssetField(':notempty:') %}


New Project: Wait for Craft 3 or start now with Craft 2?

My recommendation would be to go with Craft 2:

  A bird in the hand is worth two in the bush

There is no doubt that Pixel & Tonic has turned their focus to Craft 3, but software projects are complex and often take longer than expected and Craft 3 currently only has speculative release dates. It has also had speculative release dates in the past.

If you've made the decision to go with Craft it's likely your additional costs based on the Craft 3 transition will either be to deal with uncertainty and moving targets while developing on Craft 3 for the next several months or to go with the stability of Craft 2 and deal with some extra costs of upgrading to Craft 3 when the transition is well documented and Craft 3 is stable.


How can I 'Parse' { entry.belongsTo } to array with users?

You should be able to use the full Twig tag for what you want to do.  Perhaps something like the following (which assumes you have an email field you are trying to output for each user and want to separate your emails by a comma):

{% for person in object.belongsTo %}{{ person.email }}{% if not loop.last %},{% endif %}{% endfor %}

renderObjectTemplate should parse both the abbreviated syntax with a single curly brace or complete Twig tags.  To take a close look, the abbreviated syntax:

{ belongsTo.first.fullName }

Is being interpreted by Craft as the following:

{{ object.belongsTo.first.fullName }}


I absolutely agree with "build locally and then upload it".

Deploybot can deploy with ftp, and makes it quite painless to keep local and remote and git repo all in sync.

I make debugging sorts of changes directly on the server (tweak the config, tweak .htaccess, that sort of thing), but any change I want to keep I make sure to get into git.


You can pull data from entries by specifying a locale.

{% craft.entries.section('yourSection').locale('en_us') %}

Determine the locale you need by the custom segment.

{% set locales = {  'wetter': 'de', 'weather' : 'en_us' } %}
{% set segment = craft.request.firstSegment() %}
{% set entries = craft.entries.section('yourSection').locale(locales[segment]) %}

The big issue you will have is translating strings for each language.  If you are not at domain.com/de, I believe, you won't receive the benefits of the translation files in Craft/Translations. You will need to build in your own mechanism to translate strings depending on the segment.


As of this commit, there is a Craft::$app->getVolumes()->getVolumeByHandle($handle) method you can call.


Link Popup Modal to correct script in loop

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

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

Hope that helps with the logic.


Not currently, but feel free to make a feature request!

https://github.com/craftcms/cms/issues


Make sure you're running the latest version of Craft.  using key didn't come until Craft 2.2.


When the order is completed, duplicates of the the shipping and billing addresses that were used during checkout are created, and then related only to the Order. This means that editing the address from the order edit screen does not edit the address in the customer address book.

The address IDs that the customer selected (before address duplication) when checking out are the ones saved as the lastBillingAddress and lastShippingAddress on the customer. This enables you to set them as defaults for the next time the user checks out.

The lastBillingAddress and lastShippingAddress have no use for guest checkouts as a new customer will be created for the guest.


What are best practices for using Matrix fields to establish a grid layout

Easiest way I can think of is just to use some math. If your grid columns need to add to 12, keep a current column count while iterating over the matrix blocks.

I'd imagine you'd want your content blocks have some sort of built-in "column" width to begin with... a text content block might be 8 columns and an image would be 4. Or 6 and 6.

If the current block + the previous block adds to over 12, close the current row and start a new row.  Practically speaking, the actual column count doesn't really matter to a user, it's creating a specific layout... whether that's 8 + 4 or 6 + 6, etc. The grid is kind of a formality, really, to keep everything sane.

You'd probably have to look ahead and see what the next block or 2 look like to get an idea of your column count or to adjust it to make sure the user isn't putting in 2 images or 2 half blocks, for example. If they are, then the image could automatically start its own row or something. If you're feeling ambitious, the last one in the row could take up more or less space, depending on how you want the layout to look.  IIRC I think that's how the Happy Lager site does it, if you put two images next to each other, they adjust a bit.

I've experimented a bit with this as well. If you're trying to save the user from himself, it's pretty rare you want to have an arbitrary sized text block... like 2 columns or whatever. I can see where you might want to have a pull quote or something that might take up that size, so define that instead.


Getting total rows from current Super Table within Matrix Block (too many rows)

In this case it was pulling through 19 rows only when 'Static Field' was selected. Everything was fine otherwise, possibly a way that the data was being pulled.


Group entries by category than by month based on Date/Time field

In your code, within the {% for eventDate, entries in eventEntries | group("dayStart|date('F Y')") %} loop, in the sub-loop, you are looping over eventEntries.relatedTo(category).find() rather than restricting the entries in that loop to the ones you have already grouped to the date, i.e. in the entries array. That is why you are getting all the entries related to the category under each date heading, instead of just the ones falling under that date.

This should work:

{% set eventCategories = craft.categories.group('events').find() %}
{% set eventEntries = craft.entries.section('event').order('dayStart asc').limit(null) %}
{% for category in eventCategories %}

{{ category.title }}

        {% for eventDate, entries in eventEntries | group("dayStart|date('F Y')") %}

{{ eventDate }}

                {% for entry in entries if (category.id in entry.categoriesField.ids()) %}

{{ entry.title }}

                {% endfor %}

        {% endfor %}
{% endfor %}


Printmaker fails to render images under SSL

UPDATE 2/Resolution

I don't really have an explanation for what was happening. Hopefully this will help others if they experience the same. I'm happy to update the answer however if anyone has suggestions.

I am forcing https on my site via .htaccess.

The pdf would render 100% of the time in every browser when the request was made using http. When the pdf was requested using https In Chrome I would always get "Failed to load PDF document". Firefox would always work and Safari would give me a grey screen. For others, it would work sporadically.

All of my images are being served from an S3 source (all https) so all of my assets were secure.

I ended up making my .htaccess file force https for everything except the request to the pdf.

RewriteCond %{HTTP:X-Forwarded-Proto} !^https
RewriteCond %{QUERY_STRING} !(^|&)entryId=(.*?)(&|$) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]

RewriteCond %{HTTP:X-Forwarded-Proto} ^https
RewriteCond %{QUERY_STRING} entryId=(.*?)(&|$) [NC]
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [NC,R=301,L]

The url to my pdf looks like this:

https://mysite.com/entry/pdf?entryId=123

When a user makes a request to that url, they are redirected (301) to a non-https version.

http://mysite.com/entry/pdf?entryId=123

Hope this helps someone else!


Need a little help with basic understanding of how categories work

Your code is only listing entries in the structure that are nested inside 2 parent entries. Try this:

{% for entry in craft.entries.section('structure').relatedTo(cat) %}

Also, your
 is inside your for loop, it should be:

    {% for entry in craft.entries.section('structure').relatedTo(cat) %}`

{{ entry.title }}

    {% endfor%}


Show dev mode and Yii toolbar on secondary site

devMode is a general config setting and it applies to the whole Craft installation (regardless of the site if you're running a multi-site Craft installation.

The Craft debug toolbar is a user account preference to enable and it should work across all sites in a multi-site installation as well.


Does CSRF protection for controller actions require POST?

According to https://craftcms.com/support/csrf-protection CSRF does require POST requests

  With CSRF protection enabled, all of your site’s visitors will get a “CRAFT_CSRF_TOKEN” cookie set on their browser, and all POST requests must be accompanied by a POST parameter with a matching name and value (the CSRF Token).

On top of that, you'll need to (manually) enable it in your config:

  You will need to enable it to take advantage of it. You can do that by setting the enableCsrfProtection config setting in your craft/config/general.php file.


Craft 3 RC Upgrade killed the WYSIWYG Editor

With RC1 the rich text editor was moved to a plugin. You can find the Redactor editor (the previous richtext field) in the plugin store along with a new CKEditor editor as well.

You can read about this in the docs, too: https://docs.craftcms.com/v3/changes-in-craft-3.html#rich-text-fields


Building a filtering system using both OR and AND relations

I've looked at it further and arrived at a solution.

The relations array needed to be in the form ['and', {element: [22, 33]}, {element: [42, 43, 44]}, {element: 65}].

So that could be done using the following:

{% set relations = relations|merge([{element:filterValues}]) %}


Recipients as dropdown with Contact Form Plugin

A custom dropdown that allows you to trigger emails to different departments is possible using Sprout Forms and the Sprout Fields Email Select field.


I’m not sure if those Tumblr URLs are just an incrementing ID (so each new post is +1 greater than the last one), or if it’s a randomly-generated string of numbers.

If you just want yours to be the entry ID, all you’d have to do is go into your section’s settings, and set the following:

Do entries in this section have their own URLs? [check]
Entry URL Format: post/{id}

If you want it to be random, that’s a little more difficult. You would need to create a custom text field that stores the random number, attach it to your section, and start entering random numbers into it when creating new entries (or you could write a custom field type that handles this for you). Then your Entry URL Format would get set to post/{customFieldHandle} instead of post/{id}.

As for the image URL, if you have an Assets field that’s responsible for storing the entry’s main image, you can set it to restrict uploads to a single directory, and give it a subfolder based on the entry’s ID/random number custom field handle. (See http://buildwithcraft.com/docs/assets-fields#restricting-uploads-to-a-single-folder)


You can get to any of your config variables (including custom ones) like this:

{{ craft.config.xyz }}

The environmentVariables array is no different:

{{ craft.config.environmentVariables.baseUrl }}

See the craft.config documentation.


This should work:

$section = craft()->sections->getSectionByHandle('sectionHandle');
$sectionId = section->id;


Using the custom styled Stripe button with Craft Commerce

Here is my working solution, basically all you need to do is grab the token from stripe and then submit it with the form.

<form method="POST" id="payment-form">
  <input type="hidden" name="action" value="commerce/payments/pay">
  <input type="hidden" name="cancelUrl" value="/checkout/payment">
  <input type="hidden" name="redirect" value="/orders/order?number={number}">
  <input type="hidden" name="token" id="stripe-token" value="">
  {{ getCsrfInput() }}

  <button id="paymentButton" class="button is-primary">

        Purchase

  </button>

</form>


This isn't possible using Craft's Categories since Categories are a hierarchical structure and will always keep the order they are set in the Category Group when they are added to a category field.

One way around this limitation is to use a channel of entries in place of categories, since it is possible to drag and drop the order of related entries in an entries field.


The 400 error you’re getting is coming from BaseController::requirePostRequest(). It’s happening because this line:

type: "post",

should be:

method: "POST",


Found the answer. When creating the where clauses for the query, there's a line that checks empty($str), so passing a false boolean value, PHP interprets it as an empty string, so the where clause doesn't get created. So I fixed it by changing the query param to hideInEurope: 'false'.


Is there an easy/quick way to do this without using an external service?

Nothing easy I can think of.

For Craft 2 (which only supports MySQL), Craft turns those search queries into a MySQL query that can take advantage of MySQL's Full Text Search indexes on the craft_searchindex table, using full text wildcards as necessary for fuzzy searching the beginning and ending of a string.

It looks like the closest thing that MySQL has that might do what you're looking for is SOUNDEX(), but 1) Craft doesn't use that and 2) it doesn't appear that SOUNDEX can be used against full text indexes.

Keep in mind (just like Search Plus) any solution you find is only going to affect front-end searches (not in the CP).

You should add a thumbs-up/comment to this feature request if you'd like to see that change: https://github.com/craftcms/cms/issues/833


How can I use operators within Twig hashes?

That's what you are after:

startDateTime : 'and', '>= ' ~ now, '<= ' ~ now | date_modify('+5 days')


How can I repopulate my dropdown on a front-end form?

You could dump the account variable to see why the conditional doesn't work as you're expecting. I don't really see the reason to why you'd need the in containment test, but I'd just use dump for debugging.


Environmental variable coming back as literal braces

Your config/general.php file code has some problem with it.

You're missing a closing ) for an array, which I suspect is a typo, but the issue to your real problem is probably the fact you're missing the required '*' key for multi-environment configs to work properly.

See the first warning note on this page: https://craftcms.com/docs/multi-environment-configs


The problem was that I used this code within an entry, so I had to use the tag of that entry (offer) instead of entry.

The code that works now is:

{% for option in offer.offerMinimumPrice.options %}
  {% if option.selected %}
    {{ option }}
  {% endif %}
{% endfor %}


The {% cache %} tag will only write to the database.

You don't provide many details, so all I can do is offer some general advice.

I'd double check how you're using the {% cache %} and make sure that you're not over-caching your data or caching lots of static data that might not need it.

You can always through something like Varnish/Fastly in front of Craft to help with template caching.

You can tell Craft to use things like memcache with the cacheMethod config setting, but that only affects Craft's non-template data caches.


Sprout SEO Re-saving Entries and metadata CPU 100%

Sprout SEO is running the Craft provided ResaveElements task when you save the field. The same ResaveElements task will run if you resave your Section as Craft needs to make sure that if you updated the URL of a section that it saves the right URLs to the database for all entries. (Sprout SEO is doing something similar making sure it has saved metadata needed for output). We have seen sites with a large number of locales experience load when resaving all elements and have seen similar with the resaving of Sections. In all cases where we've seen this, increasing server resources has solved the problem.

In the case this is just caused by a series of one-off changes where things were resaved several times in a row, you could delete the tasks from the craft_tasks table and retrigger the events so they are not triggered multiple times and see if that helps.

The best long-term solution will probably be to increase the resources on your server to ensure things go smoothly.


How to skip fragments of code in Matrix?

Your question is rather vaguely but if I'm right:

You could put an "if" statement around your "h1" element like,

{% if loop.first %}
This text will only be used if the lightswitch is active
{% endif %}

Or add a field to the block. Preferably a lightswitch. Which if enabled will show the H1 tag and wont if you dont activate it.

{% if block.lightSwitch %}
This text will only be used in the first loop
{% endif %}


Adding Google Analytics to an RSS feed via server-side tracking?

I don't know of any off-the-shelf plugins that do it, but it seems like it'd be simple enough to set up, based on existing code.

Craft includes Guzzle which will make calling GA (or any web service) pretty easy. Trevor Davis' craft-guzzle has some code you could use as a starting point.  Just perusing the GA docs, you'll need to do use POST instead of GET but some of plumbing is already done.


Dynamic Asset Sub Folder Paths based on section and. if/else or turnery operators

So this was a simple fix and not to use {% %} tags but instead to use {{ }} tags. Changing the above logic in the subdirectories filed like so seems to have resolved the issue.

{{ section == 'Company' ? slug : company.one|kebab }}/{section|kebab}


Craft 2 uses PHPMailer for its email sending library.

It does have a public CharSet property that Craft explicitly sets to UTF-8 when sending emails.

The problem is, they have logic that overwrites our UTF-8 value in certain circumstances... namely when no 8-bit characters are involved in the body setting it to us-ascii: https://github.com/PHPMailer/PHPMailer/blob/master/src/PHPMailer.php#L2453-L2458

Not sure of a good resolution as this seems like undesired behavior in the PHPMailer library to me.

FWIW, the upcoming Craft 3 has ditched PHPMailer in favor of Swift Mailer where it is much more customizable.


Fetch entries filtered by array within custom field

That plugin doesn't provide a custom element type, so there's no way for it to have a chance to modify the main elements query when fetching the data.

In its existing form, you'll have to do the filtering on the Twig side like you're doing to grab the one you're looking for.


Is it possible to listen for Yii events?

Yii fires the onBeginRequest event before Craft has had a chance to do any of the plugin bootstrapping / initialization, which is why it's not firing in your plugin.


Seomatic - disable tag manager from inside template

This code will let you disable the inclusion of the tag:

{% do seomatic.script.get('googleTagManager').include(false) %}

For more, check out the SEOmatic Twig Templating documentation

If you're changing the inclusion of the tag or not based on some other variable such that the tag may be included or not for the exact same URI, you'll want to bust the cache, too (which is URI-based):

{% do seomatic.script.container().clearCache(true) %}

Also check out the Advanced SEOmatic Tips article for some deeper reading.


I don't think you need to add any composer.json in your module folders
You have to update the project composer.json file only to let the craft know about custom module so that it can load on each boot.
Folder Structure might be like  (inside module folder at the root)

wruxmodule
└── src
    ├── controllers
    │   └── DefaultController.php
    ├── models
    │   └── WruxModuleModel.php
    ├── variables
    │   └── WruxModuleVariable.php
    └── WruxModule.php

Copy below line to config/app.php

 return [
    'modules' => [
        'wrux-module' => [
            'class' => \modules\wruxmodule\WruxModule::class,
        ],
    ],
    'bootstrap' => ['wrux-module'],
];

Now update the project composer.json file

"autoload": {
    "psr-4": {
      "modules\\wruxmodule\\": "modules/wruxmodule/src/"
    }
},

Finally run

composer dump-autoload ( at project root)


It looks like I can do:

{% set myGlobalSet = craft.globals.getSetByHandle( 'setName', 'zh' ) %}
{{ myGlobalSet.myGlobalVar }}

If anyone has a better way to do it, please let me know... my plan is just to put this into a base template so that all of the pages can access the localization easily.


Limitation of adding a Category from the CP field modal within an entry

The easiest solution is to simply hide that DOM element using Control Panel CSS.


Why are gif transform file sizes very large?

No Current Good Solution

Having liaised directly with Craft Support on this issue, the outcome after a bit of research was that there is not currently any good solution.

Apparently, Imagick is really, really bad at animated GIFs, but there's no other option.

My workaround was to edit the templating for gif images, so a super-simplified version would look something like the following:

{% set src = image.getUrl('someTransform') %}

{# No transform used for gifs #}
{% if image.getMimeType() == 'image/gif' %}
    {% set src = image.getUrl() %}
{% endif %}

<img src="{{ src }}">

Whilst this did result in larger than ideal file sizes for gifs (because the original file was being used rather than smaller transforms), it prevents the issues detailed above. Not great, but better than the enormous file sizes we were seeing and the tasks getting stuck!

Possibilities in Craft 3

Apparently, Craft 3 allows for further image optimisation after transforms, and there's a plugin that capitalises on this already, so hopefully, we'll see some improvement in Craft 3.


It looks like the sizes attribute needs to be tweaked. Absolute image sizes need to be specified in px units, not w.

<img src="{{ craft.imager.base64Pixel(16, 9) }}"
     sizes="(min-width:641px) 400px, 100vw"
     srcset="{{ craft.imager.srcset(transformedImages) }}"
     class="{{ imageClass }}">

The way the browser reads sizes is left to right and picks the first match. So the assumption would be that if the viewport width isn't greater or equal to 641px, then it must be smaller than 641px. So there's no need for (max-width: 640px). The last value is the default size.

Alternately, this could be expressed by declaring the smallest viewport size to largest like this:

sizes="(max-width:640px) 100vw, 400px"

Also, instead of saying "when the viewport is smaller than 640px, use the 640px image", e.g. (max-width: 640px) 640px, what you probably want is 100vw. I'm assuming the image doesn't always stay 640px even when the screen gets smaller. If your design is responsive, the image will scale down with the screen width.

Using 100vw means that when your viewport is 400px wide or smaller, the browser can now choose to download the 400px wide image version. Or if the viewport is 640px wide, the 640px wide image is a better match.

Here's an example on Codepen: https://codepen.io/alexroper/pen/VxGgLj

Another possible reason you're not seeing the 400px size is if you're using a hi-dpi, "Retina" display or similar 4k monitor. The browser picks the best image to display from the available ones in srcset. If you specified the target image size as 400px (CSS reference pixels), but you're display is 2x "Retina" display, the browser will favor using the higher resolution image. The high pixel density of a 2x display can fit 800 pixels in a 400-pixel space. 640px isn't as large as 800px, but it's better than 400px so the browser would choose that image.

So even tho an iPhone 5 has a screen size of 320 × 568 in css reference pixels, the physical pixels are double that (640×1136). Safari will prefer to download the higher res 640px image over the 400px one in the img tag example above.


How to display the parent category on an entry page?

Assuming your categories are accessible from a Categories field called 'productCategory', and you only have 1 category assigned to each product, you can display the name of the parent category with:

{{ entry.productCategory.one() }}

Or you can loop through multiple Categories with:

{% for category in entry.productCategory.all() %}
    {{ category.title }}
{% endfor %}

And to get the category link for your breadcrumb, you could use something like:

{{ entry.productCategory.one().slug }}


How do I get the data from a relation field?

If you already know the custom field name then it is pretty straight forward:

$currentEntry = craft()->entries->getEntryById($id);
$relatedEntries = $currentEntry->customFieldName;

Then you could either loop through each one:

foreach ($relatedEntries as $entry) {
    echo $entry->title;
}

Or simply get the data from the first one:

echo $relatedEntries->first()->title;

Remember that all related entries come back as an array even if you have specified that the user can only select 1.

Hope this helps


Eager-Loading child elements in a multi-level structure section

To use eager-loading for the child elements add 'children' to the with parameter.

{% set mice = craft.entries({
    section: 'experiments',
    level: 3,
    descendantOf: entry.id,
    with: ['children', {order: 'postDate asc'}],
}) %}


I had the same issue on my mac and struggled for hours.

Having the right .htaccess file in place was key, but if you are not getting Craft's error messages, that's a sign your .htaccess file is not having any effect (you can verify this by placing some random text in there and see if you get an internal server error or not).

Making the following changes to httpd.conf made .htaccess work and solved this issue for me:

Change from "AllowOverride None" to AllowOverride All" in the
document root directory block
Uncomment LoadModule rewrite_module...

I hope this helps someone solve this quicker than I did.


Close bootstrap row and start a new row Matrix

You could track the total used columns in a var and check if its less than 12.

{% set col_count = 0 %}
{% for item in items %}
    {% switch item.type %}
        {% case "value1" %}
            {% set col_size = 4 %}
        {% case "value2" %}
            {% set col_size = 6 %}
    {% endswitch %}

    {% if not loop.first and (col_count + col_size) > 12 %}

        {% set col_count = 0 %}
    {% endif %}

    {% if col_count == 0 %}

    {% endif %}

    {% set col_count = col_count + col_size %}

        {{ item.title }}

    {% if loop.last %}

    {% endif %}

{% endfor %}


How to handle license when duplicating entire website

I think it would be enough to delete the license.key file under

craft/config

and purchase a new license. The key file will be re-generated.

Some more info in this answer, and here is how Craft decides if it is running on a public domain


getPrev and getNext stop working after 100+ entries

In your criteria, you need to set the limit to null as by default Craft only returns up to 100 entries.

See: Default Craft entry limit


Managing a large number of Variants in Craft Commerce

I'll go ahead and add this as an answer with a bit more detial....we have a large number of variants in total - about 50 different box sizes for about 110 types of product (each product has ~ 10 sizes associated with it).  In addition, we do services and there are about 50 variants there, for each of about 12 products.

In all, the simplest solution if things are relatively static is a bit of data entry...people, in my experience, worry far too much about programmatically generating things that then become hard to maintain (ecommerce tends to have al ot of exceptions and unusual scenarios and programmatic things soon get out of hand) - sometimes a tedious hour or two of data entry is actually a much more effective long term solution to the problem.  (And they invented student/interns for this right?!).

That said, Craft's excellent relations system can help a lot here - if your variation sizes are standard things, you can create a section to store your 'standard boxes' or 'standard variants' or whatever, and then relate these to your variants using an entries field on your variants for that product type.

Then, in your templates and/or shipping plugin etc, you simply refer to these standardised entries - rather than the variant itself - to get the data you need for your width, height, depth, and weight.  This can dramatically reduce your data entry work and keep things MUCH more DRY - there's one standardised place to add/change/remove data for your variants.  It's very effective...but it does mean you do need to have your own shipping plugin as you're sort of over-ruling Commerce's default behaviour here.

(One great thing Commerce could do to help and avoid the need for a plugin here would be to make it an option to specify a bit of twig for these standard fields so you could do things like specify a default value for height of  {standardBox.first().height} -  where standardBox is a field on the variant and that would then be parsed into the product when it is saved...)


By disabling a locale for an entry you are removing the automatically created route for this entry and locale (→ docs for routing).

But what you can do, is to diable the automatic routing (uncheck "Entries in this section have their own URLs" in the section settings) and add the same routes as custom dynamic routes manually.

news/{slug} →  news/_entry

Those manual routes won't 404 for disabled entries and you can have some logic in your _entry.html template.

{% set entry = craft.entries.section('news').slug(slug).first() %}

{% if not entry %}
    {% set entry = craft.entries.section('news').slug(slug).locale('en').first() %}
    {% set duplicateContent = true %}
{% endif %}

{% if not entry %}
    {% exit 404 %}
{% endif %}

I would also recommend to set your meta tags accordingly and make search engines aware of the duplicated content. I updated the code with a new variable definition, test if it is defined in your _layout main template.


Craft CMS with local and flywheel setup?

The .dev connection gives me an error

Don't know if it'll solve all of your problems, but .dev is no longer a valid TLD you can use for local testing since Google made it public: https://domains.google/tld/dev/

Change it over to something like .test instead.


Output entry title in subject line of notification when sprout form is submitted

This is now possible with Sprout Forms 2.0 and Sprout Fields 1.0 Hidden or Invisible Field.

You'll need to make your entry available to the Hidden of Invisible field using the addFieldVariables tag, and then in your field settings you can reference the Entry ID using single curly braces: {entry.id}

{# Make the Entry available to your Hidden or Invisible field settings #}
{% do craft.sproutForms.addFieldVariables({ entry: entry }) %}

{# Output your form as normal #}
{{ craft.sproutForms.displayForm('contact') }}

See Setting a dynamic value (outside the global scope).

Legacy Answer (pre Sprout Forms 2.0)

When a form is submitted, the form notification has access to the variables in the SproutForms_EntryModel which include all the custom fields submitted with the form and anything in the global scope such as {{ currentUser.email }}.

To make the Subject Line of the page that the form was submitted from available to your notification, you will need to make it a field on your form.

This may be a little tricky to do with dynamic forms right now, but we are working on a way to make this easier in the future using a Hidden Field field type.

A couple approaches to consider right now:

Write a Hidden Field custom field type that behaves like you need it to
Build your form with custom HTML and populate a hidden field on your form with the {{ entry.title }} value.
Create a "Page Title" Plain Text field on your form, style it to display:none so the user never sees the field there, and populate the field with the entry title using javascript.