Load new entry(s) in the same page with ajax as a popup

First: you need to create a Plugin, I suggest you to use Pluginfactory.io to create your boilerplate and read the docs about plugin development

You'll need an ajax Request that could look like

$('#a-button').click(function(){
    var data = {
        entryIds: [1,2,3,4], // <- insert the id(s) of the entries you want to render
        action: 'pluginName/controllerName/renderTemplate', // <-- route to your controller
        templatePath: 'path/to/template'
    };
    $.ajax({
        type: "post",
        url: '',
        data: data,
        success: function (response) {
            if(response.success === true){
                $('#a-container').html(response.html);
            }else{
                alert(response.message);
            }
        },
        error: function (XMLHttpRequest, textStatus) {
            console.log("Status: " + textStatus);
        }
    });
});

Then you'll insert this function in your controller

/**
 * @throws \Craft\Exception
 */
public function actionRenderTemplate()
{
    $success = false;
    $message = Craft::t('Could not find template path');
    $html = '';

    // check for a template path
    if ($templatePath = craft()->request->getParam('templatePath')) {
        // check for entry ids
        if($entryIds = craft()->request->getParam('ids')){
            // fetch all entries with the ids
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->id = $entryIds;
            $elements = $criteria->find();

            // render the template
            $html = craft()->templates->render($templatePath, ['elements' => $elements]);
            $success = true;
        }else{
            $message = Craft::t('Could not find required entry id parameter');
        }
    }

    // return as json
    $this->returnJson(
        [
            'success' => $success,
            'message' => $message,
            'html'    => $html
        ]
    );
}


Can't think of a native way to do this — a few options come to mind, none of which are ideal.

recreate your sites 404 page in your 404 template (should be able to just copy/paste for the most part).
redirect to your site's 404 page from your 404 template (i.e. redirect 'craft/templates/404.html' to 'mydomain.com/404.html'). So in your 404 template you would have:

{%  redirect '/404.html'  %}

Reaching here, but you could also possibly include your 404 page in an iframe in your 404 template.


I guess it depends on what information each Asset needs to contain. As you mentioned, a Matrix within a Matrix is not possible, so you will need a different method to attach additional information to each Asset.

One method that may work is to create Asset Meta Fields for Assets. This way, you can define additional things on each image on the Asset level. For example, you could have custom fields for things like title, description, copyright, etc.

With Asset Meta Fields in place, you could define one "Gallery" Matrix block that allows for multiple files to be selected. The order could be controlled by drag/dropping each of the selected Assets.


Dropdown field value getting outputted multiple times

You don't need the for loop in this case. What's happening is you're looping over each option in your dropdown field, and each time it's checking the value of the dropdown and displaying white or black. Since you have three options, you're going to get the dropdown value displayed three times (which is why you're seeing black black black).

All you need is just the if conditional:

{% if entry.transparentMenu.value == "menuLight" %}

white

{% elseif entry.transparentMenu.value == "menuDark" %}

black

{% endif %}

  Also, fwiw looks like you have a typo in your code  - you use entry.transparentMenu twice and entry.header.transparentMenu once. I'm guessing you want entry.transparentMenu everywhere...

The only time you'd want to use the for loop to get all the dropdown field's options is if you wanted to display those in the template (in a list for example or to create your own dropdown on the frontend):

    {% for option in entry.dropdownFieldHandle.options %}

{{ option }}

    {% endfor %}

But in your case, you just want the current value and not all the options, so just remove the for loop.


Does Craft CMS support 'encryption at rest' / 'data at rest' encryption?

As far as I'm aware, it does not. But this is typically something you'd do at the VPS level; examples of doing it on various platforms:

Google Cloud Platform
Linode
Digital Ocean

You could also do it at the database level as described here: MySQL Data at Rest Encryption


The documentation for adjusters is here:

https://craftcommerce.com/docs/adjusters
and
https://craftcommerce.com/docs/order-adjustment-model

Essentially your plugin creates a class that fulfils the interface at:
plugins/commerce/Commerce/Adjusters/Commerce_AdjusterInterface.php - which is very simple:

interface Commerce_AdjusterInterface
{
    /**
     * The adjust method modifies the order values (like baseShippingCost),
     * and records all adjustments by returning one or more orderAdjusterModels
     * to be saved on the order.
     *
     * @param Commerce_OrderModel $order
     * @param array $lineItems
     *
     * @return \Craft\Commerce_OrderAdjustmentModel[]
     */
    public function adjust(Commerce_OrderModel &$order, array $lineItems = []);
}

Your plugin (in your main plugin .php file) then just registers your new adjuster to hook it up.  I'd suggest storing your actual adjuster classes in files in an Adjusters folder, lime Commerce itself does.

//at the top, to include your class
require_once('Adjusters/BusinessLogic_TestAdjuster.php');

...

//this registers the adjuster with Commerce so it will be applied to carts
public function commerce_registerOrderAdjusters(){
  return [
    new \Commerce\Adjusters\BusinessLogic_TaxRemover
  ];
}

The adjuster (as you can see) has access to the order and line items and you can basically use any code you like to implement your discount offer, e.g. checking if the qty of something is over 3, and then reducing the price.  It builds & returns Commerce_OrderAdjustmentModels which describe the adjustment(s) made by the adjuster.

Here's a super simple example adjuster:

<?php

namespace Commerce\Adjusters;
use Craft\Commerce_LineItemModel;
use Craft\Commerce_OrderAdjustmentModel;
use Craft\Commerce_OrderModel;

class BusinessLogic_TaxRemover implements Commerce_AdjusterInterface {

 public function adjust(Commerce_OrderModel &$order, array $lineItems = []){

    $myAdjuster = new Commerce_OrderAdjustmentModel();

    $order->baseDiscount = $order->baseDiscount - 5;

    $myAdjuster->type = "Test";
    $myAdjuster->name = "Test Adjuster";
    $myAdjuster->description = "Takes $5 off the order";
    $myAdjuster->amount = -5.0;
    $myAdjuster->orderId = $order->id;
    //if your Adjuster affects lineItems rather than the total, you record the ids here
    $myAdjuster->optionsJson = ['lineItemsAffected'=>null];
    $myAdjuster->included = false;

    return [$myAdjuster];

   }

}

My advice is to being it to generate plugin scaffolding using: http://pluginfactory.io/ - to get you started - removes a lot of the pain points in getting started (such as the cursed capitilisation issues which I swear are the hardest part about getting started with plugins!).

Alternatively, you can take the scaffolding from https://github.com/lindseydiloreto/craft-businesslogic - and put in there, which makes good sense as this pretty much the textbook definition of business logic.  Just clone that, add your adjuster class, and do the registration and away you go!

As long as you're comfortable with PHP implementing a discounter like you describe is really quite simple.  If you're not then it's a perfect way to get more comfortable and I'm sure folks will be happy to help along the way!


Ordering entries by custom field (integer)

Craft 2
Either of these should work (they are equivalent):
{% set entries = craft.entries.width('> 0').section('windows').order('width') %}

or
{% set entries = craft.entries({
  section: 'windows',
  order: 'width',
  width: '> 0'
}) %}

The reason you are getting "Array to string conversion" error is that find has turned your ElementCriteriaModel into an array.
Craft 3
order is now orderBy
Craft 3 Docs: Element Queries


Commerce: what is the purpose of a line item's snapshot?

The snapshot is there so that the key details of an order are forever more available on the order record.
Imagine living with Commerce for a long time - you will of course most likely add, change and/or remove products (or variations) as time goes by.
You might simply disable ones you remove, or you might delete them.  If Commerce did not have line item snapshots, old orders would refer only to these now deleted things - thus, for example, when presenting an order history view to your customers, the details would not be available and this would (at least) mean some order details could no longer be displayed accurately.  And at worst, it might well cause serious errors with your templates/page rendering, if you're relying on those details being there.
Another example - prices change over time.  The order snapshot shows the price at the time of the sale, not the price now - which might be substantially different.
It might even be the case that store operators are altering products actually while a customer has them in their cart and is busy making an order.
Thus the snapshot mechanism is an elegant, if perhaps poorly documented, solution to these issues.
Thus - and you're right, this should probably have its own explanation in the docs - the best practise with Commerce is to always use the snapshot details by preference once something is a line item - i.e. when dealing with carts (incomplete orders) at any point, or orders - always use the snapshot data.
Of course the snapshot doesn't have everything in it (like images etc) - so for prettier templates, you often end up with some conditional logic referring to the actual product / variant - but you must check if it is still available first, before using any data from it, and have a fall-back if it is no longer available.


Yes you can. Go to Settings > Users then the Fields tab.

Here you can add fields just like you would for categories or entry types.


How do you display user photo in templates?

Yes, you should see the photo thumbnail in the list of users after you upload the photo. Your exact code works for me, so I think something has gone wrong with the photo upload.


Element API using the entries field to display related content from a separate section

If relatedJobDescription is an Entries field, accessing the field from your jobs entry will not return the selected jobDescriptions entry directly. Instead, you will get an EntryQuery which you can use to get the selected jobDescriptions from the database. See Working with Entries Field Data and Querying Entries.
To get the jobDescriptions entry, you can use ElementQuery::one() (if your field allowed for multiple related jobDescriptions entries, you could use ElementQuery::all() instead).
Regarding the descriptionOverride, that's just a matter of checking if the override field contains some text and if it does, return it instead of the related job description.
Something like this should work:
// get the entry holding the related job description
$relatedJobDescriptionEntry = $entry->relatedJobDescription->one();
// handle an empty relatedJobDescriptions field gracefully
$relatedJobDescription = $relatedJobDescriptionEntry ? $relatedJobDescriptionEntry->description : '';
// get the description override from the current entry
$descriptionOverride = $entry->descriptionOverride;
return array(
    'title' => $entry->title,
    // return either the overridden description or the related job description
    'description' => ((string) $descriptionOverride) ?: $relatedJobDescription,
);

You can optimize this further to only retrieve the related job description if the override is not set.


entry.featuredProjectLink is not an element or an array of elements, it is an object of type MatrixQuery in order to fetch elements you have to use the .one() or .all() function

<a href="{{ entry.featuredProjectLink.one().getUrl() }}">

Element Queries

Relations -> the "Going Through Matrix" part is the thing you want


Got to bottom of this - is down to how the Tax Rules are set-up.
Taxable Subject was set to Line Item but should have been set to Order Total.


Craft CMS does absolutely nothing to your front end code, and there's literally nothing in Craft that would make anchor links – i.e. Click – in your front end markup behave in any other way than normal.

The error is probably somewhere in your front end code (either in your Twig/markup or possibly in your JavaScript).


Set conditional parameter to not output "dateUpdated" field, when entry is first time created

Here's where I'm going to be more help in theory, rather than code. But maybe something like this? I'm happy to revise if someone sees a typo.

{# Date #}

     {{ "published"|t|ucwords }}: {{ entry.dateCreated is empty ? "" : entry.dateCreated|date("d.m.Y") }},

{% if entry.dateCreated != entry.dateUpdated %}

            {{ "updated"|t|ucwords }}: {{ entry.dateUpdated is empty ? "" : entry.dateUpdated|date("d.m.Y") }},

{% endif %}
{% if entry.expiryDate|length %}

            {{ "expire"|t|ucwords }}: {{ entry.expiryDate is empty ? "" : entry.expiryDate|date("d.m.Y") }},

{% endif %}


How can I tell Smart Map to look at Commerce for entries?

You need to tell Craft to look within the Commerce section like this:

{% set entries = craft.commerce.products.address(params).order('distance').find() %}


How would I write this differently to make it compatible with MYSQL 5.7

Turns out this is a bug as of Craft 2.6.2931 with the ColumnType::PK enum
in a record's attribute type definition.

Pretty sure it'd be a bug in < MySQL 5.7 because it's invalid SQL syntax as well unless they're just more forgiving of it there.

This is a non-issue in the upcoming Craft 3 release (the concept of attributes no longer exists and plugins explicitly define their table schema create statements), but the workaround for Craft 2 until the bug is fixed is to not use a record here and manually create the table schema that you need by adding an onBeforeInstall method to your plugin.


Pass value in form using the amforms plugin

I presume the title of the entry is the name of the job. So if that's the case, just add a hidden input in the form and add the entry's title to the value.

<input type="hidden" name="fields[jobTitle]" value="{{ entry.title }}">

Then make sure to create a 'jobTitle' text field in the CMS and attach it to that form.


You can accomplish this with slice and merge, although it's not very pretty:

{% set myArray = ['a', 'b', 'd' ] %}
{% set myArray = myArray|slice(0,2)|merge(['c'])|merge(myArray|slice(2,myArray|length)) %}

{{ myArray|join(', ') }}

To explain what's happening above:

{% set myArray = ['a', 'b', 'd' ] %}

This just sets an array we can work with.

|slice(0,2)

The first slice filter "chops off" and returns the first two items in the original array (namely "a" and "b"). We do this because we want to add a value after the "b" (i.e. the second index).

|merge(['c'])

The first merge filter appends the value we want to add – the letter "c" – to the first two items. As merge is only able to merge arrays, we need to wrap the c in another array.

|merge(myArray|slice(2,myArray|length))

The inner part of this statement – the slice – pulls all the remaining values from the original array after the first two that we chopped off at the beginning, until the end of the array.

These values are then appended to the a, b and c with another merge statement.

{{ myArray|join(', ') }}

This is just a test, and will print a, b, c, d.


Unfortunately, this isn't currently possible.

This feature request is very similar to what you're requesting... however, it would still require that all of your environments use the same type of asset source.


Querying by lightswitch field type in template

You could try looking for an empty string: mdFeatured('') or prefix 1 or true with not: mdFeatured('not 1').


Craft Developer has responded and confirmed that there was an issue and offered a fix, this issue will be resolved in the next release of Craft.  Version 2.5.2767 contains the issue, so any version higher than this will contain the fix.


This isn't documented, so it's subject to change:

When you set a Single to be the homepage, its slug is automatically set to __home__.

If you want your homepage to be part of a Structure, rather than a separate Single, you can set the slug of a Structure entry to __home__, which makes it act as the site's homepage and gives it that little Home icon in place of its slug in the structure view.


Have you tried processing the entire slug directly in your template, without setting a complex route? Check for the presence of the string "-and-", split the slug accordingly, build a Category query.


Using getCriteria with a custom element type

Fixed it for now by including a custom enum class in the base plugin file:

abstract class CustomElementType extends BaseEnum
{
    const Badges_Badge = 'Badges_Badge';
}

and then querying for the custom element in the plugin using craft()->elements->getCriteria(CustomElementType::Badges_Badge);


List authors on front end by total number of entries

You could do something like this:

{# Fetch entries + authors and group by author id #}
{% set entriesByAuthors = craft
    .entries()
    .section('itbuzz')
    .limit(null)
    .with('author')
    .all() | group(e => e.author.id) %}

{# Build an array with authorId and entry count for each that we can sort them #}
{% set leaderBoard = [] %}
{% for author, entries in entriesByAuthors  %}
    {% set leaderBoard = leaderBoard | merge([{'author' : author, 'count' : entries | length}]) %}
{% endfor %}

{# Build an array of user ids only sorted by entry count and extract the top 8 #}
{% set authorIds = [] %}
{% for result in leaderBoard | multisort(e => e.count, direction=SORT_DESC) | slice(0,8) %}
    {% set authorIds = authorIds | merge([result.author]) %}
{% endfor %}

{# Fetch users based on our sorted and sliced array of ids #}
{% for author in craft.users().id(authorIds).all() %}
    {{ author.firstName }} - {{ author.lastName }}<br>
{% endfor %}


Get a key value from a JSON asset in PHP

I assume that $block->tweet->one() returns an Asset element in your matrix block called tweet. I suggest that you use the getContents() method on Craft's Asset element type to retrieve the string content of the actual file. Your code block would look something like this:
case 'tweet':
  $tweetFileContent = $block->tweet->one()->getContents();
  $tweetJson = json_decode($tweetFileContent, true);
  $tweetUrl = $tweetJson['url'];

  if ($tweetUrl) {
    $components[] = [
      'role' => 'tweet',
      'layout' => 'tweetLayout',
      'URL' => $tweetUrl,
    ];
  }
break;

However, I would recommend extending your code as follows to address empty state and potential exception:
case 'tweet':
  if (empty($block->tweet)) {
    // return early or do something else
  }
  try {
    $tweetFileContent = $block->tweet->one()->getContents();
    $tweetJson = json_decode($tweetFileContent, true);
    $tweetUrl = $tweetJson['url'];

    if ($tweetUrl) {
      $components[] = [
        'role' => 'tweet',
        'layout' => 'tweetLayout',
        'URL' => $tweetUrl,
      ];
    }
  } catch ($e) {
    // getContents() throws
    // InvalidConfigException if [[volumeId]] is missing or invalid,
    // AssetException if a stream could not be created
  }
break;


How to prevent inconsistent comments in generated project config YAML files

Comments were added to Project Config files after Craft 3.6.8 referencing GitHub issue 7584.
They shouldn't be appearing and disappearing unless you're committing config files without them over the ones that already do have them in the repo. That being said, from my experience the comments are only applies to NEW fields added after 3.6.8, or at least are not all done at once as soon as you update to 3.6.8. To get around this, I'd do ./craft project-config/rebuild which will regenerate your config files and add comments to EVERYTHING, commit that, then get your developers to pull them.


Fetch values for a single field across all entries in a section

Getting that array is simple. Prepare an empty array, then loop through your entries and merge the "Sleeps" fields value to it.

To get your array with the unique values, you basically do the same but also save the value as the key on each iteration. If a key already exists in the array the key/value pair gets overwritten (→ good for you)!

There's a strange behaviour that setting custom numeric keys doesn't work with Twig, that's why I composed a string out of the value.

{# Prepare variables #}
{% set myArray1 = [] %}
{% set myArray2 = [] %}

{# Loop through entries of the "Hotel Room" section #}
{% for entry in craft.entries.section('hotelRoom') %}

    {% set value = entry.sleeps %}

    {% set myArray1 = myArray1|merge([value]) %}
    {% set myArray2 = myArray2|merge({ ('key' ~ value): value }) %}

{% endfor %}


404 error if folder in public_html has same name as folder in craft/templates

This is because the 'projects' folder exists in both public_html and craft/templates, right?

No this simply means that you have no entry with the slug projects as soon as you create an entry with the given slug it will work.

You can also define a route in a config file

'projects ' => 'projects/index.twig',

Generally your template path structure has nothing to do with your url structure. You should define which template should apply for which url route in your CP in the element settings or via config file or plugin

public function registerSiteRoutes()
{
    return array(
        'projects' => 'projects/index.twig'
    );
}


Target first and last items and append if greater than 2

The way I would think of it is: I print the category title, then if this is not the last category I print the separator (and or ,). I would use the loop variable revindex to distinguish the next-to-last category (which gets the and) from the others (which get the ,). loop.revindex is like loop.index except that it counts the number of iterations from the end. So your code starts to look like this:

{% for category in categories %}
  {{category.title}}
  {% if not loop.last %}
    {{ loop.revindex == 2 ? ' and' : ',' }}
  {% endif %}
{% endfor %}

That code will leave a space before the ,, which you can fix by sticking everything on one line:

{% for category in categories %}
  {{category.title}}{% if not loop.last %}{{ loop.revindex == 2 ? ' and' : ',' }}{% endif %}
{% endfor %}


Reset shipping method on cart empty and order complete

You're right, this does not seem to clear automatically when you remove all line items, but you could I think just set an extra post value in your form that calls removeAllLineItems to clear the shipping handle at the same time...because in this controller there is a call to $cart->setContentFromPost('fields'); I presume if you set the shipping handle to "", that set content will cause the shipping method to be dropped from the cart.

So basically add <input type="hidden" name="shippingMethod" value=""> to your form & it should work.


How can I build a combined search without making all fields required?

When you submit the form you have above, it's already going to have those parameters in the URL even if they have no form values selected.

http://example.com/?dateFrom=&dateUntil=&country=&priceMin=&priceMax=

But you may have the need to directly link to http://example.com/?country=France, or empty parameters may cause errors in your template. If that's the case you probably need to define default values for missing and empty parameters. The easiest way to do this is with the Twig default filter.

{% set country = craft.request.getParam('country') | default(null) %}

The null value should work as a default for some parameters. If there are other parameters you can't easily create a default for or you only want to use parameters if they're defined, you could create an array of your default options, and then use the Twig merge filter to add more options based on conditions.

{% set options = {
  section: 'events',
  order: 'score'
} %}

{% if dateFrom %}
  {% set options = options | merge({ start: '>=' ~ dateFrom }) %}
{% endif %}

{% set results = craft.entries(options) %}

Optionally, you can use the ternary operator shorthand syntax instead of {% if dateFrom %}. Whichever is easier.

`{% set options = dateFrom ? options | merge({ start: '>=' ~ dateFrom }) : options %}`


You can do

 {% image = craft.assets.id(x).first() %}

Where x is the ID of your element. You can see the ids of your elements in your cp. There is a little wheel icon below your asset sources where you can define which attributes to display. Just check the selectbox for id

You can learn more about fetching entries with ElementCriteriaModels in the docs

Your problem was: you did not fetch the element. You prepared your database query but you need to execute it with first() or find() because


OK, just did a quick look through the docs. Appears that this can be set via the config file.

Link to documentation

There's also the option to set whether the user is logged in automatically.


Customising the new CKEditor5 in Craft 3

I don't think so. You can see the entire code here

ClassicEditor
    .create(document.getElementById('{$nsId}'))
    .then(function(editor) {
        $(editor.element).closest('form').on('submit', function() {
        editor.updateEditorElement();
    });
})

This is the javascript that triggers the editor, as you can see, there are no config settings provided yet. I searched in the entire plugin but I could not find any other Javascript functions that are triggert so unless they provided a really nasty method to include them in the original editor js file you can't change them yet.

The only "configurations" are Html Purifier

Edit

However - you could create a feature request or you could implement your own code to provide settings. You only need to change a few lines - it's totally trivial


Can I set a Commerce order custom field from a plugin

You can use $order->setContent()

craft()->on('commerce_orders.onBeforeOrderComplete', function($event) {
  $order = $event->params['order'];
  $content = array('myCustomField' => 3);
  $order->setContent($content);
}


OK, my bad, this was answered here

Here is the solution :

{{ _context[ globalHandle ].aFieldHandle }}


You need to loop through the assets as follows:

{% for asset in block.memberPhoto %}
    <img src="{{ asset.url }}" alt="{{ block.memberName }}" />
{% endfor %}

See https://craftcms.com/docs/assets-fields for more info.


In my company we work with Craft and Laravel only, so this question comes up quite often and is a moving target as time passes and both platforms evolve.

Since Craft is built on Yii you can do almost everything what you can do with Laravel. You have basically 3 options here: Craft-only, Nova-only or a hybrid. I would ask myself at least the following questions to make a decision:

Do you need to write a lot of tests for the business logic? -> even though Craft caught up on testing, still +1 for Nova and Laravel
Is the editorial part of the application really trivial? Like, can you avoid having complexity in the editorial and business logic part of the application? -> +1 for the hybrid
Do both parts of the application really have to communicate with each other? Can you avoid a shared user authentication? (should generally considered as last option IMO) -> +1 for the hybrid
What about integrations, are there plugins/packages available that you can use right away? -> depends on the research
Is there any show stopper for the business logic part regarding Craft? (Arbitrary example: You need a multi-tenancy architecture, don't take Craft-only.)

So in the end the good news is, there is not necessarily a right or a wrong answer here. The bad news is, either way you go you'll always feel like: "What if I had..."

You see, personally I lean more towards Laravel for custom application development, just because I am more comfortable with it than with Yii. I would definitely consider to take the advantages of both platforms in exchange for a bigger code base and maintenance effort. But only if one application part can be dumb and the other complex.

Maybe now you are even more uncertain than before :)


We've used it successfully to generate PDF tickets for orders. It may/may not help in your case.

On our order page, we simply have:

Download PDF Tickets

Then, our order/tickets template:

{% set html %}
    {% set orderId = craft.request.param('orderId') %}

    // HTML/CSS to generate ticket

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />

        // Ticket HTML

{% endset %}

{% set settings = {
    compress: true,
    orientation: 'portrait',
    size: 'letter',
    cacheDirectory: 'cache/tickets',
    filename: 'TICKET-' ~ craft.request.param('orderId') ~ '.pdf'
} %}

{% set pdf = craft.printmaker.pdfFromHtml(html, settings) %}

{{ pdf.output }}


How to get my license.key after deleting it via Git

Right now, contacting support@buildwithcraft.com is the only way to retrieve a lost license.key file.

In the future, once we add user accounts to buildwithcraft.com, we'll also be adding order and license management, so you'll be able to retrieve it from there as well.

I've responded to your ticket with your proper license.key file.


Importing Commerce Variants from google sheet

Check the tip in this page

  TIP

  When using Google Sheet as your feed type, consult the Google Sheets API docs. Your URL should include a key value for your API key. For example:

  https://sheets.googleapis.com/v4/spreadsheets/SHEET_NUMBER/values/SheetName?key=API_KEY


Welcome to Stack Exchange! Yes, your syntax is wrong - you need to remove the curly brackets around entry.contactForm.handle, and the quotations, and actually get the handle.
{{ craft.freeform.form( entry.contactForm.handle,
    {
        instructionsBelowField: true
    }
).render() }}

Source: Freeform docs


Is it possible for an Element Type to return multiple content tables with the getContentTableForElementsQuery() method?

You can only return a single content table per element query.

If you need to join multiple content tables, you have two options:

Use multiple element queries, one for each group of elements that share a content table. Disadvantage of this approach is, you won't be able to order elements in SQL.
Just don’t join in any content tables in the initial elements query, and let your elements lazy-load their content rows if any custom fields are actually accessed on the elements. You can do this by having your element type’s getContentTableForElementsQuery() function return null. The only disadvantage here is that you won't be able to order/filter by custom field values, since those tables won’t have been joined in.

If you go this route, you will need to make sure that your model that extends BaseElementModel is overriding the getContentTable() function (which it should be anyway, if you’re using custom content tables). That way it will know which table to pull data from if any custom field values are requested from it.

In your case, if each element is going to have its own content table, then option #2 is probably going to be your best bet.


Carry address over with customer's order when creating user

It's not implemented, but possible.  I think it should be part of Commerce core really, and done when the user is created by default.

In the meantime, my Register On Checkout plugin does this - https://github.com/bossanova808/CommerceRegisterOnCheckout

You could adapt this more generally I guess to listen to all user registrations and see if there are addresses to move over.

The actual code that updates the addresses is here: https://github.com/bossanova808/CommerceRegisterOnCheckout/blob/master/commerceregisteroncheckout/CommerceRegisterOnCheckoutPlugin.php#L312 ... but most of the init method would be relevant I guess.


Eager Loading Relatedto & Target Elements

First of all just a few ideas about best practices

Don't

{{ entry.relatedBrand.one.url }}
{{ entry.relatedBrand.one.title }}
{{ entry.relatedBrand.one.size }}

Do

{% set relatedImage = entry.relatedBrand.one() %}
{{ relatedImage.url }}
{{ relatedImage.title }}
{{ relatedImage.size }}

Furthermore your code with eager loading

{% set brandIds = craft
    .entries()
    .section('brands')
    .relatedTo({ targetElement: category })
    .ids()
%}
{% set offers = craft
    .entries()
    .section('offers')
    .with(['relatedBrand.brandLogo'])
    .relatedTo(brandIds)
    .limit(6)
    .all()
%}

{% for entry in offers %}

    {% set relatedBrand = entry.relatedBrand? entry.relatedBrand[0] : null %}

          {% set logos = relatedBrand? relatedBrand.brandLogo : [] %}
          {% for asset in logos %}

          {% endfor %}

{{ entry.title }}

{{ entry.body }}

          {{ relatedBrand.title?? '' }}

{% endfor %}


Currently this isn’t configurable, but I suppose it should be. I’ll add it to the list, and update this answer when it’s possible.

Update:

As of Craft 2.3, each user can choose their own preferred week start day from their account settings.


Auto login user after password reset via a plugin in Craft3

Those docs were a bit confusing/misleading, so sorry about that. (I don’t even know what it meant by that!)

They’ve been updated for clarity:

  After the user successfully logs in, they will be redirected to the path defined by the setPasswordSuccessPath config setting.

Additionally, the next Craft release (3.1.8) will start automatically logging users in after resetting their password, if the autoLoginAfterAccountActivation config setting is enabled.

So to answer your question, there won’t be any custom plugin/module code needed for this; just update to 3.1.8 when it comes out and enable that config setting.


Best way to search users by a custom field inside a plugin?

Does something like this work? You might need to add some wildcards as documented here to run the right kind of search.

$criteria = craft()->elements->getCriteria(ElementType::User);
$users = $criteria->search('customField: *' . $someValue.'*');


Generate transforms only working on default install (multi-site)

From Brandon Kelly on Discord:

If you go to the Assets index page and change the site to your second
site. Are you able to see all the same assets there? (Specifically
whatever ones appear to be causing this error on your second site)

They weren't listed.

Had a feeling that would be the case. That's your problem. If you run
php craft resave/assets, does that fix it?

Yes it did! Thanks :-)


How to use categories with Sprig's "Load More" recipe

Try this:
{{ sprig('_layouts/_categories/_loadMore', {limit: 6, category: category}) }}
{{ sprig.script }}
After query category is not defined.


Structure Nav: Output "Section" Title on both Landing and Decedents

You can test for the entry's level property. Something like the following.

{% if entry.level == 1 %}

{{ entry.title }}

{% else %}

{{ entry.ancestors.first.title }}

{% endif %}


How do I query for entries, based on a value inside a table?

Craft saves all the table's data serialized to a single cell in the database, so there's not really a good way to set query conditions to match something in a table field.

What you could do is to use Andre Elvan's brand new plugin Preparse Field. With that you would add a new field to you entry type that does some predefined Twig logic on every entry save. So you could get that table cell's data you are interested in and write it to its own field that you could then use as a field parameter in your criteria model.

Another way, and this is the approach I would actually recommend, is to refactor the whole setup and use a separate channel to hold each table row as its own entry (without URL) and than have an Entries field to relate those to your week / event entry.

The third solution is a variant of the second one, but to use a Matrix field (or a SuperTable) instead of a separate channel. You would need to set up the query with Yi query builder from a custom little plugin. Let me know if you're interested in this solution and I can assist you in setting this up.


White space added to start of template's

As Brad kindly pointed out, I checked my files in the config directory and noticed a few spaces before I started the <?php in my /craft/config/imager.php file. I would never have thought to check this, so thanks Brad!


Use of App::env() compared to getenv() since Craft 3.4.18

Yes.
It’s not a requirement, but relying on App::env() is the current best practice and we’ve updated the Composer starter project to use it: https://github.com/craftcms/craft/blob/master/config/db.php


You can limit the prev/next links to only show entries with the same tags using the relatedTo param:

{% set params = {
    section: 'databytes',
    order: 'title',
    relatedTo: { targetElement: entry.tagsFieldHandle, field: 'tagsFieldHandle' }
} %}

That might do the trick, but it may lead to inconsistent prev/next page links, because you can have more that one tag associated with each entry.

Take this entry/tag setup, for example:

Pizza

Lunch
Dinner

Ice Cream

Desert

Crepe

Breakfast
Lunch
Desert

If you land on Pizza, its Next Page link would take you to Crepe, since they share the Lunch tag. But when you click on Crepe, its Prev Page link should take you to Ice Cream, rather than Pizza, because Crepe also shares the Desert tag with Ice Cream.

You can see why that might get a little confusing.

One way to keep the navigation more consistent would be to choose one single tag that all entries should have in common, and pass that tag in the Prev/Next URLs.

{#
  Figure out which tag ID we should use to limit the previous/next entries.
  It will either be set in the query string already,
  or we can just use the first tag that the current entry has.
#}

    {% set tagId = craft.request.getQuery('tag') %}

    {% if not tagId %}
        {% set tagId = entry.tagsFieldHandle.ids()|first %}
    {% endif %}

{# Find the previous/next entries that have that tag #}

    {% set params = {
        section: 'databytes',
        order: 'title',
        relatedTo: { targetElement: tagId, field: 'tagsFieldHandle' }
    } %}

    {% set prevDatabyte = entry.getPrev(params) %}
    {% set nextDatabyte = entry.getNext(params) %}

{# Output their links, and pass the tag ID in the query string #}

    {% if prevDatabyte %}

    {% endif %}

    {% if nextDatabyte %}

    {% endif %}


How do you insert the site name into a default asset path?

Try using {site.handle} instead of {{currentSite.handle}} and it should work ok.


Permanently connecting templates to entries

I guess I'd refactor this and introduce different entry types for your section. Besides being able to "lock" each entry type to a specific template (→ "How can I give each Entry Type its own template?"), you can also have the CP fields (slightly) different. Maybe it makes sense to have extra fields for your special entries, if it doesn't, just add the same fields to each entry type.

Another option would be to have a dropdown field to select the template, but I like that the entry type dropdown is in the right panel in the CP.


SEOmatic - Set the SEO tags based off of a category?

Absolutely. Just create those fields then assign them to your categories under field layout just like you would do for your sections.


Is it possible to compress image transforms?

All common image file formats are compressed, even lossless formats like RAW, TIFF or PNG use compression!

To reduce file size of you images you should choose a lossy format (avoid TIFF Baseline or BMP), and accept some degree of information loss to reduce the file size. You usually set this quality to file size ratio in percentages (for the web). Craft's default quality ratio applied on transforms, defaultImageQuality, is set to 75%, but you can always set it to your needs from the Control Panel or in your templates.

There's a nice chart on Wikimedia, illustrating the relative quality of quality settings for JPG formats.

Additionally I'd recommend you to have a look at this other question about transformation performance with image libraries supported by Craft.


How to Cache Globally Except for One Page

You could add a variable like globalCacheDisabled and {% cache globally using key 'entry_' ~ entry.id ~ '_elements' unless globalCacheDisabled %} and use a {% set globalCacheDisabled = entry.disableGlobalCache %} on the given page template.

On Craft's side I'd use a Lightswitch field on the entry with handle disableGlobalCache, which is disabled by default which you can then activate on the given entry/ies.

This makes you prone to changing id's and differences across environments. (While testing make sure to purge the cache)


How about stacking all the element query params into a single object?

{% set entries = craft.entries({
    section: 'news',
    order: 'sticky desc, postDate desc',
    limit: 9,
    with: [
        ['newsHighlightImage', {
            withTransforms: ['newsMedium', 'newsSmall']
        }]
    ]
}) %}

Also, I don't believe you need to use the find() function here. The examples in the documentation only use find() when eager-loading just the image transforms related to a single asset field.

{% set assets = entry.assetsField.find({
    withTransforms: [
        'heroImage',
        { width: 100, height: 100 }
    ]
}) %}


Edit - looks like it's the specific use of token as a parameter that's causing the problem.

The route doesn't need to account for the get parameters, so it only needs to be micros-test/guest-reset-password.

You then fetch the parameter using craft.request.getParam('token').


Fetch/Remove all unused assets (by plugin)

This should work

//First fetch all ids from elements table
$allIds = craft()->db->createCommand()->select('id')->from('elements')->where([
    'not like', 'type', 'Asset'
])->queryColumn();

// query for all related Assets -> assets that are used somewhere
$usedAssetCriteria = craft()->elements->getCriteria(ElementType::Asset);
$usedAssetCriteria->relatedTo = $allIds;
$usedAssetCriteria->limit = null;
$usedAssets = $usedAssetCriteria->ids();

// query for all assets not in the list of the used one
$unUsedCriteria = craft()->elements->getCriteria(ElementType::Asset);
$unUsedCriteria->id = 'and, not ' . implode(', not ', $usedAssets);
craft()->assets->deleteFiles($unUsedCriteria->ids());


Rich text editor Redactor adding additional paragraph p tags

http://imperavi.com/redactor/docs/settings/clean/#setting-replaceDivs
http://imperavi.com/redactor/docs/settings/clean/#setting-removeEmpty http://imperavi.com/redactor/docs/settings/clean/#setting-paragraphize

Standard.json

{
    buttons: ['html','formatting','bold','italic','unorderedlist','orderedlist','link','image','video', 'table'],
    plugins: ['fullscreen'],
    toolbarFixedBox: true,
    paragraphize: false,
    replaceDivs: false
}

Edit: This bug also happens in the most recent version of Redactor as seen on their example page.


You should not do that at all. The entire process to install plugins via composer instead of the old way is to avoid this conflict. Imagine two of your plugins require the same class/library so you'll end up with a class already declared exception. Instead you can insert your requirements into the composer json of your plugin, run the composer update command for your Craft composer json and you are fine.

All dependencies will be loaded into the correct vendor folder.


What's the difference between Neo and Matrix fields?

On first blush they are very similar. I think the Craft Plugin Store description of Neo sums it up nicely:

Neo is a field type that builds upon the concept of the Matrix field type with a number of very useful features.

Neo solves one of the biggest issues people have with Matrix and adds Oreo features: no blocks within blocks. Sometimes you need this feature, other times you can get away without it.
Matrix

Built-into Craft CMS / first party support
Blocks use their "own" fields
No inception (child / nested / hierarchical) support (Matrix block within another)

Neo

3rd party plugin / extra license cost / another dependency in the stack
Uses existing Craft CMS fields
Can clone/copy/paste blocks
Blocks can be nested inside each other (inception style)
Blocks can be organized in groups / tabs / drop-downs for better authoring experience

Summary
Neo is like Craft's own Matrix field but a different and arguably more flexible take on it. However, it comes with all the risk/reward of using 3rd party plugins.
As an aside, after Craft 3 shipped, it took awhile for Neo to come over to Craft 3. I think this was partly to blame because Neo was offered as a free plugin for Craft 2 and with Craft 3's extensive changes, it's not surprising that the Craft 3 version of Neo is a paid version—3rd party developers have to eat too!
Alternatives
As an alternative to Neo, there's another plugin called Spoon which supplies some of Neo's organizational features and supercharges the built-in Matrix. That's a little bit more "future-proof"—so even if you decide to remove the plugin, your content will stay in place.
Using Super Table, you can get some of the inception level magic that Neo offers.
FWIW the plugin store allows you to try all of these plugins out on a dev instance and see for yourself which methodology you prefer.


I believe you're looking for the conveniently named useEmailAsUsername config setting.

When that is set to true, any new user that is saved with a valid email address will have that copied over to the username field as well.


Using “search” vs. “relatedTo” in a template

To be honest, those two parameters may seem to be slightly similar but provide a totally different functionality.
From their documentation on search:

search
Only fetch entries that match a given search query. (See Searching for the syntax and > available search attributes.)

Which means whatever you pass in .search(query), and there is a rather complex list here, will actually 'search' Craft for the query string you specify.
On a different note,

relatedTo
Only fetch entries that are related to certain other elements. (See
Relations for the syntax options.)

This on the other hand only 'relates' to other entries, meaning its not performing a fill search on Craft, only the entries. A detailed reference on relations can be found here.
As far as performance, the two are unrelated as it really depends on what you are trying to accomplish.
Hope this clears it up for you!


Where is the documentation for creating templates/themes?

Each Craft install is typically considered a discrete site, with its own design, information architecture, assets, etc.

This is why you might not be seeing information about "theming," per se.

However! Everything you need to start will be in craft/templates and public.

craft/templates is how you generate HTML. Files in here often correspond to your sections and routes, but can also get rendered statically, just based on where you put them and what they're named. Check out the Routing documentation to decide how you want to set up your basic templates.
public is the only folder in the installation that is accessible to the web, directly. All your CSS, JS, fonts, static images (i.e. a logo, icons), etc. will go. You can reference those files the same way you would a regular HTML file. Craft has some tags to help you with generating the proper URLs.

These are two of the primary concepts that you'll need to grasp to get started displaying your content.

Be sure to check out the Templating Overview and click through the next few Docs pages. Once you understand where a template needs to be (and why), you can dig in to the expanded templating docs.

One last (rather granular) note: Each type of content you define (Sections) that has a URL will ask you for an Entry Template. That path is within your craft/templates folder, and it'll automatically load the file when you visit that Entry's URL. (i.e. my "News" section might have _news/post as its Entry Template, which corresponds to craft/templates/_news/post.twig. The underscore prevents it from being directly accessed/rendered via mydomain.com/news/post.


Plugin Error: "Unable to find component class"

So what happened was I un-gitignored my Composer files so I could deploy them to another environment. Then I switched from that branch to a different branch with different Composer files. After I switched back, I ran into a Composer bug (mentioned here in the docs) where Composer will forget about plugins loaded using the path method if the files change.

So I had to perform these steps:

navigate to my craft project folder in the terminal
execute composer remove kgrote/siteutilities
delete the kgrote directory from craft/vendor
execute composer install kgrote/siteutilities

SUUUUUPER annoying, but there you have it.


RexEg Pattern to Exclude Using the Retour Plugin

The RegEx is only the URI part; so something like (.*.png|.*.jpg) is probably what you want.


What's the best place to store and load static data for plugins?

What format is the source data in?  If it's already in a multidimensional PHP array, then it might be as simple as having a data.php file in your plugin and doing a require_once in your plugin's init() method and you're good to go.

Even if it's in a different format, loading it from init() and parsing it into the multidimensional array is a good option.


Assign a category group to a category field via migration

Figured it out, the format it expects is 'source' => 'group: <group UID>'

So...

    protected function createCategoriesField() {
        // Get the group
        $group = (new \craft\db\Query())
            ->select("id")
            ->from("fieldgroups")
            ->where(["name" => "common"])
            ->one();

        // Get the category group UID
        $catGroup = Craft::$app->categories->getGroupByHandle("categories")->uid;

        // Initialize the field
        $field = new \craft\fields\Categories([
            "groupId" => $group["id"],
            "name" => "Categories",
            "handle" => "categories",
            "selectionLabel" => "Select categories",
            "source" => "group:" . $catGroup
        ]);

        // Save the field
        return (Craft::$app->getFields()->saveField($field));
    }

This was, and is, going to be a big help with migrations -> https://github.com/markhuot/craftql/blob/master/src/Console/ToolsController.php


Can I move existing tags, which are currently in a global tag group, to new the new tag groups I've set up?

There is no way to do this natively in Craft through the control panel.

You could either write quick plugin that programmatically moved the existing tags to new tag groups or write some custom SQL that did it directly against the database.

For the latter, it should be as simple as updating the groupId column of the craft_tags table with the new groupId for the tags you want to move.


Found this that works well. Reverts to p tags or normal text:

https://bitbucket.org/kreisvierdigital/redactorremoveformat


How do I save a Plugin's date settings-field?

Yup, you need to use AttributeType::Mixed as Justin Kimbrell suggests. The date will then be escaped and stored in the database like this: *

{"newregistrationdate":{"date":"2\/1\/2015"}}

Now, the dateField in your settings template will expect a DateTime object for its value – so just passing getSettings() as is will make it choke. You can get around that by adding the following to the getSettingsHtml() method:

$settings = $this->getSettings();
if ( isset( $settings[ 'newregistrationdate' ][ 'date' ] ) ) {
    $settings[ 'newregistrationdate' ] = new DateTime( $settings[ 'newregistrationdate' ][ 'date' ] );
}
return craft()->templates->render( 'yourPluginHandle/settings', array(
    'settings' => $settings,
) );

...and then finally, make sure the dateField constructor looks in the right place for its value by removing the date key of the settings.newregistrationdate property:

{{ forms.dateField({
    label:        "New registrations after this date"|t,
    id:           'newregistrationdate',
    name:         'newregistrationdate',
    instructions: "Users registered after this date will get a welcome email"|t,
    value:        settings.newregistrationdate,
    errors:       settings.getErrors('newregistrationdate')
 }) }}

Solution is tested.

Note that the date object is actually serialized, escaped and stored properly even if you use AttributeType::DateTime, however getSettings() will always return the attribute value as false. Could be a bug?


Element Types are powerful and there are probably too many possible implementations to give a very meaningful example without additional information.

Here are a couple resources beyond the docs that could help you get started:

Master the Elements - A comparison of all native Craft CMS Element Types and what makes them unique.
Introduction to Element Types in Craft CMS - In this Hangout Brandon Kelly walks through a lot of details about Element Types. There are also a couple of other related videos you can find in the resources section here: Getting Started with Plugin Development for Craft CMS
Events Sample Plugin - Example plugin that demonstrates how Craft plugins can take advantage of Craft’s Element Type APIs.

I'd recommend taking a close look at the ElementType Class and related Element Type Model Class for each of the native Elements in Craft:

Asset
Category
Entry
Global Set
Matrix Block
Tag
User

Each Element implements the API slightly differently and understanding those differences will help you make sense of what you may need to include in your Element, or where you can piggy back on existing behavior.

There are also several plugins that use Elements. Each implementation is fairly custom, so which examples will work best for you are hard to say. Off the top of my head, there are plenty of examples:

Craft Commerce:

Commerce_Product Element
Commerce_Order Element

Sprout Plugins:

SproutForms_Form Element (Sprout Forms)
SproutForms_Entry Element (Sprout Forms)
SproutEmail_NotificationEmail Element (Sprout Email)
SproutEmail_CampaignEmail Element (Sprout Email)
SproutEmail_SentEmail Element (Sprout Email)
SproutSeo_Redirect Element (Sprout SEO)

A few others (if anybody would like to share others in the comments, happy to add them to the list)

Neo_Block Element (Neo)
SuperTable_Block Element (Super Table)


Get random entries from a section but keep the order of these when splitting the array

One way I have achieved this is like so:

{% for entry in artists %}
  {% if loop.first %}

  {% endif %}
  {% if loop.index == 5 %}

  {% endif %}

    {% include '_includes/_components/image.twig' with {
      image: entry.artistImage[0],
      alt: 'Artists',
      transform: 'square',
      classes:'w-full',
      sizes:'(min-width:576px), 100px, 25vw',
      widthEnd: 800
    } %}

  {% if loop.last %}

  {% endif %}
{% endfor %}

But I think this circumvents the issue rather than solves the question.


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

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


You can access the categories through the category field itself.

{% for category in entry.categoryFieldHandle %}
    {{ category.title }}
{% endfor %}


Templating basics: extend, include or use?

My setup regarding includes for templates is as follows:

I'll have a 'site' structure that looks at /pages/_entry.twig for it's template. But I'd have a range of entry types within this structure, for example:

Homepage
Contact
News
Standard content

Then my /pages/_entry.twig template looks like this:

{% extends "_layout/base.twig" %}

{% block content %}
    {% include 'pages/' ~ entry.type %}
{% endblock %}

So the extending of my base template is sorted for all of them in one place (less repeated code ) and it just includes a file based on the entry type like so:

/pages
  -- _entry.twig
  -- contact.twig
  -- homepage.twig
  -- news.twig
  -- standardContent.twig

And the entry type matches the file name so each entry type has it's own template automagically.


Invalid Verification Code Customization?

There's not a native way I can see to do this.

Neither of these are clean workarounds, but assuming you're referring to Craft 3, you could either write a plugin that extended Craft's ErrorHandler class and overwrote the handleException class, inspected for that particular error messae and swapped it with one of your own. You'd need to tell Craft to use your ErrorHandler in craft/config/app.php.

Alternatively, you write a plugin that mimics Craft's UsersController's setPassword method doing your own custom logic and have the user related emails point to your plugin's controller instead of the native Craft one.


Determine Entry based on URL Parameters?

This is a longer version answer (code wise) to the one Douglas already posted. He did a very nice job of explaining how to get a URL parameter and what to pay attention to handling the results.

I will try to show you how to build a query from multiple unknown params, so any of these combinations is possible and potentially return a single (and unique) Entry Model:

http://example.com/foo?sectionId=6&entryId=170&slug=somethingclever
http://example.com/foo?sectionId=6&slug=somethingclever
http://example.com/foo?entryId=170

This also tries to handle the case, the page already comes with an entry variable pre-populated or there's already a pageTitle set. So you don't do all the requests / logic on all of your pages.

{#
 # Only try parsing the params, if this page doesn't come with an `entry`
 # var pre-populated and we don't already have `pageTitle` set.
 #}
{% if not entry and pageTitle is not defined %}

    {# Get URL params #}
    {% set entryId = craft.request.getParam('entryId') %}
    {% set entrySlug = craft.request.getParam('slug') %}
    {% set sectionId = craft.request.getParam('sectionId') %}

    {# Default query #}
    {% set query = craft.entries %}

    {# Add params to the query if they are not empty #}
    {% set query = not entryId ? query : query.id(entryId) %}
    {% set query = not entrySlug ? query : query.slug(entrySlug) %}
    {% set query = not sectionId ? query : query.sectionId(sectionId) %}

    {# Now try to get that entry and set our own `entry` var #}
    {% set entry = query.first() %}

{% endif %}

{# Set the entry title. Also handle the case our query didn't find anything #}
{% set entryTitle = entry ? entry.title : 'Title for a page that doesn’t exist' %}

{# Set the page's title #}
{% set activeTitle = pageTitle is defined ? pageTitle : entryTitle %}

Useful links for this code: craft.request and Ternary operator in Twig.


Umlauts in asset file-paths - Broken filenames on server

I ran into the same problem lately, but got no clues from the accepted answer.

As of Craft 2.4 though, is a config setting that limits asset filenames to ASCII, so I'm happy with this workaround:

'convertFilenamesToAscii' => true

When storing assets in folders derived from the entry slug, you will additionally need to add the following:

'limitAutoSlugsToAscii' => true

Minor hassle: These settings naturally won't rename existing files and entries, so you need to touch each one in the control panel to take effect.

(I'm not completely convinced this filename issue is Craft's fault, since the file paths are broken/garbled in Coda, Safari and Safari for iOS – but work just fine in Firefox and Chrome by way of in-browser url-encoding.)


It appears that the correct way to do it is using the url() method. I couldn't replicate the extra queries I mentioned in the question, and can confirm with some more testing that it doesn't cause any extra queries.

{{ teaserImage.url("transform") }}

or

{{ teaserImage.getUrl("transform") }}

Source: https://straightupcraft.com/articles/examples-of-eager-loading-elements-in-twig-and-php


You probably have to loop through all the speaker (ordered by lastName) that are related to the talks (the speaker entry is the targetElement). Then use one craft.entries (ElementCriteriaModel) for each loop to get the talk entry.

See this Q/A for a comparable problem.


it was 'table already exists' and now I understand. When I first ran the installation I had guessed at the user's db priveleges (based on another CMS) as I couldnt find the Craft ones at the time. So that created the table but with the wrong privileges. Each time I subsequently ran it, it failed as the table already existed. – a1mark Oct 22 at 8:48


How can I set the postDate and expiryDate from a front-end date picker via plugin?

I believe I have figured it out, please correct me so I can update the answer if I am too far off.

TL;DR:

I am using a date picker (no time) on a front-end form. The user chooses a date and it comes across as 09/27/2015. Here is how I converted that string to a dateTime object that I could set as post & expiry date for a newly created entry.

NOTE: I have not included any validation at this point which should be carefully considered.

MyPlugin.php

// Get the current time zone from the system.
date_default_timezone_set(craft()->timezone);

// Get the current time
$time = date('H:i:s');

// Create the post dateTime
$postDate = date('Y-m-d', strtotime(craft()->request->getPost('postDate')));
$postDateTime = $postDate . ' ' . $time;

// Create the expiry dateTime.
$expireDate = date('Y-m-d', strtotime(craft()->request->getPost('expiryDate')));
$expireDateTime = $expireDate . ' ' . $time;

// Create the DateTime object to send to Craft.
$postDate = new \DateTime($postDateTime);
$expiryDate = new \DateTime($expireDateTime);

// Put it all together.
$entry = new EntryModel();

$entry->sectionId = 3;
$entry->typeId = 1;
$entry->enabled = true;
$entry->postDate = $postDate;
$entry->expiryDate = $expiryDate;

...

if(craft()->entries->saveEntry($entry)) {
    // Success
} else {
    // Fail
}


Craft 3 with Multi-Site: how to not set a primary site, or add a first segment to all primary site URLs?

It looks like you forgot to setup siteUrl in config/general.php for your sites.

'siteUrl' => [
    'landing' => 'https://www.mycompany.com/international',
    'sales-en' => 'https://www.mycompany.com/sales/en',
    'sales-fr' => 'https://www.mycompany.com/sales/fr',
    ...
],


How to add more options to the 'Restrict allowed file types' settings?

You can now set allowedFileExtensions and extraAllowedFileExtensions in your config file. The first will re-define the list of allowed files, where the latter will allow you to add additional file types.

For example, I needed to add 3 additional formats:

'extraAllowedFileExtensions' => 'bim, dwg, rvt'

See the documentation here for details.


FreeForm and Vue - Hidden Forms in Modal - Manually refresh the Craft CRSF token and Freeform JS Honeypot field

Not sure if it's a good call or not but you could have an endpoint that just has the {{ craft.app.request.csrfToken }} outputting on it. Poll(GET) that using ajax (axios or whatever you're using in your Vue app) and update your Vue model's csrf value with the response body?

Same for the honeypot value I guess although I'm not that familiar with freeform I take it there'll be a twig variable available for this.

I'm sure there's a nicer way to do this but this seems like it should work?


Craft 3 query children of sub categories

Building on Robin's comment, the ancestorOf parameter expects either an element ID or the actual element as a parameter.

For example, if you know the ID of the fruit category is 3, you'd use .anscestorOf(3), or if you already had the fruit category element, you'd do like so:

{% set fruitCategory = craft.categories.id(3).one() %}

{% set categories = craft.categories()
    .group('food')
    .ancestorOf(fruitCategory)
    .all() %}


Detect if it is a new user or not in PHP

In Craft 3 you would do:

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event) {
        if ($event->element instanceof \craft\elements\User && $event->isNew) {
            // It's a new user
        }
    }
);


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

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

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

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

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


Don't know of any comment plugins yet but the easiest thing to do is to Integrate Disqus. You just drop the embed code in and paste in your entry ID.


List both parent entry and its child entry

This is the corrected Twig code. I simply added {{ entry.title }} as an
 item. This nav appears only on the page that I needed entry.title displaying.

{% set navList = (entry.level == 2) ? entry : entry.getAncestors().level(2).first()  %}

{% if navList.hasDescendants %}

        {% set nav =  navList.getDescendants()  %}

{{ entry.title }}

        {% nav page in nav  %}
            {% if page.id != entry.id %}

{{ page.getLink() }}

            {% else %}

{{page}}

            {% endif %}
        {% ifchildren %}

                {% children %}

        {% endifchildren %}
        {% endnav %}

{% endif %}


How to reset matrix field to have NO blocks in plugin?

Ok I'm a dummy. A matrix block is an element like an Entry, Asset, etc. So I need to delete it like an element instead of treat it like an array:

$blocks = $entry->myMatrixField->all();

if (! empty($blocks)) {

    $elementsService = Craft::$app->getElements();

    foreach ($blocks as $block) {
        /* @var \craft\elements\MatrixBlock $block */

        $elementsService->deleteElement($block);
    }
}


Importing content with feedme to single entry in 3 locales

This is how I managed to do the import

Create extra field on entry to save common ID (will be used to link 3 locales together)

Set up feed for each locale with following settings:
- import strategy: create & update
- newly created field as unique identifier

Run each import separately

Feedme will than for the first locale create the entries, and for following locales, update the first one if the id field matches & add the translation to the entry.


It looks as if you've sorted thing out (dev.nec... vs nec.dev...)

In general, I find the domain name matching in the config files to be confusing and error prone. I always follow the advice in the Foolproof Multi-Environment Config recipe. Put this at the top of your index.php:

switch (strtolower($_SERVER['SERVER_NAME'])) {
  case 'nec.dev':
    define('CRAFT_ENVIRONMENT', 'DEV');
    break;
  case 'nec.dev.stagingdomain.com':
    define('CRAFT_ENVIRONMENT', 'STAGE');
    break;
  case 'nec-inc.com':
    define('CRAFT_ENVIRONMENT', 'LIVE');
    break;
  default:
    exit('No environment defined for '.$_SERVER['SERVER_NAME']);
}

Then your db.php and general.php will look like this:

return array(
  '*' => array(...),
  'DEV' => array(...),
  'STAGE' => array(...),
  'LIVE' => array(...),
);

And when you hit dev.nec.stagingdomain.com you will see that No environment defined error and fairly quickly see what is wrong.

(There is also an Enhanced Foolproof Multi-Environment Config recipe)


Additional code to run when cache is busted(entry added/updated, etc)

Sounds like a custom plugin or module would work for you here, allowing you to hook into the entry after save event.
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;

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

        if (!$entry->getIsDraft()) {
            // Make the request to clear caches on the frontend.
        }

    }
);


Populate select input via static values on plugin settings page

If your first attempt – using a variable method – failed, it was probably because you had the "path" to that variable method wrong. If your variable method is called getOptions() and resides in a variable class called MyPluginVariable, the path should be

craft.myPlugin.getOptions

not

craft.myPlugin.settings.getOptions

Anyway, your current solution is fine. The ideal, "Craft-y" way to do stuff like this would probably be to keep the input options in a plugin config file and use a service + variable method to expose the data to the template – but for such a simple case there's really no need to over-engineer things. If you have more fields/options later, or need the data to be dynamic or stored in a database, deal with it then. Don't optimize too early.

Personally, I'd consider just hard coding the options in the template:

forms.selectField({
    'label': "myLabel",
    'instructions': "My Instructions"|t,
    'required': true,
    'id': 'myInput',
    'name': 'myInput',
    'options': {
        '' : 'Select',
        1 : '1',
        2 : '2',
        ...
    }
})


Do you happen to be on Dreamhost? I had a site there recently where they changed my permissions "for my own good".


Getting checkbox options for a new entry, without having an entry

You can pull the field directly using craft.fields:

{% set myFieldOptions = craft.fields.getFieldbyHandle('myFieldOptions') %}

The options will be available under the field's settings.options property. Each option will have attributes for value and label:

{% for option in myFieldOptions.settings.options %}
    {{ option.label }} {{ option.value }}
{% endfor %}


ElementAPI endpoint routing syntax for multi-level structure

Quite a simple solution set the criteria to uri and you just pass the endpoint as is as a catch all.

$normal =  preg_replace('/.json/', '', craft()->request->path);
return [
        'endpoints' => [
            craft()->request->path => [
                'elementType' => 'Entry',
                'criteria' => ['uri' => $normal],
                'first' => true,
                'transformer' => new DetailTransformer(),
            ],
        ]
    ];


"Giving your Plugin its own CP Section" What about the CSS?

You can include CSS for your plugin one of two ways.

1) Inline CSS

You can include CSS snippets by using {% includeCss myCss %}. This is great if you are just wanting to include a few lines of CSS. Read more here: http://buildwithcraft.com/docs/templating/includecss

2) Reference a Resource CSS file

Usually contained in your /resources folder inside your plugin you can include a CSS file by using {% includeCssResource "pluginName/styles.css" %} You can read more here: http://buildwithcraft.com/docs/plugins/resources


Commerce element query on custom field in console command

Found it: the reason for the Exception is, that the dynamic method productStartDate (coming from the CustomFieldBehavior) needs an Array as parameter.
I have no clue why I get this misleading Exception though...
So finally, this works:
use craft\commerce\elements\Product;
$product = Product::find()
                ->type('ticket')
                ->productStartDate(['>="2021-01-01 00:00:00"'])
                ->all();


User defined crop / crop modal for image assets

I haven't used this myself, but the Aviary Image Editor plugin should be ideal for what you need:

https://github.com/fruitstudios/AviaryImageEditor

They also tweeted about the plugin with a short video of it doing exactly what you are looking for in Craft. Hope this helps!


The requested URL was not found on this server

Try going to yoursite.com/index.php/(pagename). If that works, check out this article on how to remove it: https://craftcms.com/support/remove-index.php


How can I have translations for my subdomain

I'd double-check your index.php files for all domains and make sure they're all using the correct handle in the define('CRAFT_SITE') code. Sometimes I copy/paste files between sites and forget to update the site-specific variables.

I'd also make sure the Base URL for each site is correct in the settings.

Also make sure the section your homepage uses isn't set to the wrong propagation method.


Sounds like you're using craft in 'headless' mode. I've heard about that for drupal, but not for craft. I don't see any reason why it wouldn't work. You get the craft UX for creating and modifying entities, but use node as a proxy and view generator.


How can I make a product field required?

I can mark the field as required in the layout builder, but that is for the CP only I think.

Nope... marking the field as required makes it required globally (regardless of if it's coming from the control panel or the front-end).


Eager Loading Users Returning "Array to String Conversion" Error

Just checked eager-loading a text field in a template and by eager-loading it you are actually converting the field to an array and therefore unable to template it as usual. Eager-loading is generally only useful on fields like categories, assets, and matrixes.


Admin - Manage entries based on a field type choice

It's not (yet) possible to have multiple websites with dedicated front-end and back-end views within one Craft installation (Multi-site feature). There's some users that mis-use Craft's localization feature for this, but I definitely wouldn't recommend this.

But it is actually not a problem at all to route all your subdomains to individual template folders of a single installation (→ Is it possible to route a subdomain to specific template group?). And for the backend, I'd simply create a user group for each of your events and configure the permissions accordingly (→ Assign permissions to users and groups). So user group "Summer Party" has only access to sections belonging to that sub-site. Individual users can be assigned to more than one group if necessary.

Instead of having lots of single sections ("Summer Party - Home", "Summer Party - Results", "Summer Party - Media Contacts") I would recommend to look into replacing this with a single structure section ("Summer Party - Pages") with multiple entry types. And for your media channels you could also consider not using entries at all and assign fields to your assets directly.


If you click link your CraftID to your install, all of your plugin licenses should be automatically configured;  more information at the following:

https://docs.craftcms.com/v3/plugins.html#managing-plugin-licenses


You probably forgot to set the CRAFT_LOCALE constant for your French site in /fr/index.php, to tell Craft which locale's content to serve.


This knowledge base article on moving Craft’s files below the webroot should help you.


Sure:

{{  forms.checkboxField({
      label: "Twitter"|t,
      name: 'createGlobals[twitter]',
      value : 'on',
      checked: settings.createGlobals.twitter
}) }}


Search for related entries via AJAX given multiple parameters

I finally figured everything out, It took a long time to figure out what I actually needed to search for to find the answers I needed.

I put a comment at the bottom of this thread that was also of tremendous help. Passing multiple arguments to find related entries via categories.


Is it possible to use the assets modal on the front end?

Craft supports all of the fields within the Control Panel, but not on the front-end – the number of scenarios they would need to support on the front-end increases the scope of supporting a field dramatically.

Craft does however support submitting Assets from the front-end (an example with Guest Entries) and restricting Assets to user specific folders using Dynamic Subfolder Paths.

So you can do what you are describing, and may even be able to reuse some of the code they use to build out the functionality, but (currently) you will have to adapt it to your scenario and maintain it yourself.


Getting entries related to all of supplied categories, if they exist

Completely untested, but try something like:

{% set ids = [] %}

{% if craft.request.getQuery('sector') %}
    {% set ids = ids|merge([craft.request.getQuery('sector')]) %}
{% endif %}

{% if craft.request.getQuery('impact') %}
    {% set ids = ids|merge([craft.request.getQuery('impact')]) %}
{% endif %}

{% if craft.request.getQuery('topic') %}
    {% set ids = ids|merge([craft.request.getQuery('topic')]) %}
{% endif %}

{% if ids|length %}

    {% for post in craft.entries.section(section).relatedTo('and', ids|join(',')) %}
        ....
    {% endfor %}

{% endif %}


How do you get ahold of a TagModel in a template?

I figured this one out right after I posted it.

{% set blogTag = craft.tags({ tag: tag, group: 'blogTags' }).first() %}

One mistake was searching for it with "name" instead of "tag".

The other mistake was that I needed to call first() to get the TagModel. Otherwise, craft.tags() just returns an ElementCriteriaModel.


Contact form submission type in Contact Form Extensions

You can override the form name by adding a hidden field to your form like this:
<input type="hidden" name="message[formName]" value="myFormName">

Set the value of the hidden field to a unique value for each different form that you have on the site. Then submissions to each form will then be indexed in the control panel by the different values used for the hidden field.
Full documentation for the Contact Form Extensions plugin can be found here: https://github.com/hybridinteractive/craft-contact-form-extensions/blob/master/README.md
There's currently no native way to export the submissions to a CSV. There is a GitHub issue open for this (https://github.com/hybridinteractive/craft-contact-form-extensions/issues/13) which includes a suggested work around using a Twig template to handle the exports: https://github.com/hybridinteractive/craft-contact-form-extensions/issues/13#issuecomment-518668747


I don't think you can order by the types order, or get the types in your template (I might be wrong there though), but maybe you don't need to let this be completely dynamic? I guess the user won't be able to add new types or change the order of them after the site is made? If so, couldn't you just make an array of the types and do somthing like this:

{% set typesInOrder = ['handle1', 'handle2', 'handle3'] %}

{% for type in typesInOrder %}
    {% for entry in craft.entries.type(type) %}
         {{ entry.title }}
    {% endfor %}
{% endfor %}

There is of course some limitations, especially if you need to paginate the results. And it's bad for performance to do the craft.entries queries several times, especially if you have many entrytypes. Just thought I'd share this in case it's helpful for your usecase.


Create a variable from content in a matrix field

This is a twig thing. Loops in twig are scoped. Variables defined in a loop cannot be used outside of that loop. To fix this, you simply have to declare the variable before the loop:

{% set backgroundUrl = "" %}
{% for item in entry.screenshot %}
    {% for asset in item.webpage %}
        {% set backgroundUrl = asset.url %}
   {% endfor %}
{% endfor %}

If you know that you only have one asset you can shorten it a bit with:

{% set backgroundUrl = "" %}
{% for item in entry.screenshot %}
    {% set backgroundUrl = item.webpage.first().url %}
{% endfor %}


Is it possible to share a field between Matrix Blocks?

Correct - currently Matrix fields are not global, so you'll need to recreate them if you want to use them in other Matrix blocks.


Using imageoptimize plugin not showing field on entries

So a per the documentation, the Optimized Images field should only be added to an Asset Volume's layout. You do not need to, and should not add that field to your Section field layouts.

Please verify for me that after doing so, when you double-click on an Asset, you see a display similar to this:

c.f.: https://github.com/nystudio107/craft-imageoptimize/issues/106

Resolution: This ended up just being some local config issues with Asset Volumes, and then getting rid of pending stuck Queue jobs. After that, away we go!


How to fire a custom event from another plugin?

myHelpers_Post.savePost was wrong. It should have been myHelpers_post.savePost. It's okay to delete this question.


Craft 3 Registration Form Success Redirect

The URL needs to be hashed. Try using {{ redirectInput('registration-successful') }}
As documented here: https://docs.craftcms.com/v3/dev/functions.html#redirectinput-url


Turns out the issue was caused by a js error being thrown by an ad blocking plugin the user had installed on his browser.


Saving Custom Field Values to User Profile

I used August's answer, but fixed it:

Put this at the top:

use craft\elements\User;

Then the updating code

$myUser = Craft::$app->getUser()->getIdentity();
$myUser->setFieldValue('fieldHand', 'value');

Craft::$app->getElements()->saveElement($myUser, false);


Looking at your screenshots, the host names are different.  The cPanel 404 shows mysphotos instead of myphotos.

Probably a typo somewhere in your templates.


Shortlist plugin error when creating a new list

I think you're using an older version of the plugin.

That bug was definitely fixed in the current version - which is actually 1.0.4 - although oddly that is not available as a 'public release' it seems.

I'd contact Joel and get him to update his version page! http://squarebit.co.uk/contact


You could try something like following reducing the tagged entries into IDs that you then filter against (see this thread):

{% set tag = craft.tags.search('All-Stars').first() %}
{% set allEntries = craft.entries.section('news') %}
{% set taggedEntries = craft.entries.section('news').relatedTo(tag).ids %}
{% set omitIds = 'and, not ' ~ taggedEntries|join(', not ') %}
{% set untaggedEntries = craft.entries.section('news').id(omitIds) %}


This my solution, although it's not perfect. I set-up an entry loop within the form and included the following for a series of checkboxes:

{% if loop.index == "2" %}

<label>
    <input type="checkbox"
        name="{{ course2.handle }}[]"
        value="{{ course2.value }}"
        {{ course2.checked ? "checked" : "" }}
    />
</label>

<input type="hidden" name="{{ courseName2.handle }}" value="{{ entry.title
}} | {{ entry.courseDate|date('j.n.y') }}"  />

{% endif %}

So in the form submission the entry title in loop 2 is attached to the Course 2 checkbox. It would have been better if {loop.index} could be used within the handle name so the 'if' conditional is not needed. As pointed out above, the value of the checkbox can be set dynamically from the entry loop, but the result is not shown in the FreeForm control panel, just the email notification. Therefore is was necessary to include the hidden field to record the entry title. Hope that all makes sense.


I suppose you could use the \craft\commerce\services\Emails::EVENT_BEFORE_SEND_MAIL event for that.

use craft\commerce\events\MailEvent;
use craft\commerce\services\Emails;
use yii\base\Event;

Event::on(
    Emails::class,
    Emails::EVENT_BEFORE_SEND_MAIL,
    function (MailEvent $e) {
        // You would be able to access the `\craft\mail\Message` like so
        // $e->craftEmail;

        // And the `\craft\commerce\elements\Order` like so
        // $e->order

        // So adding an asset could be done by accessing the `attach` method.
        // https://www.yiiframework.com/extension/yiisoft/yii2-swiftmailer/doc/api/2.1/yii-swiftmailer-message#attach()-detail
        $e->craftEmail->attach(...);
    }
);


Can I use Craft CMS for a large custom web application?

Craft isn't opinionated on how your site works; it just organizes and outputs your content however you want it to. You have 100% control over your HTML whether you want to use templates or dish out the data for some framework like React, Vue, etc (using the Element API plugin). So that should answer your question: yes it is more than just a website CMS because it simply manages your content, not the means you choose to collect and output that content like a website, app, etc.

However, Craft out of the box obviously isn't customized to all the extra functionality you described above, so you're going to need to write your own custom module in PHP to do these things. You can use Pluginfactory to start your scaffolding.

Off the top of my head, based on what you said, it sounds like you'll eventually need to buy Craft Commerce. Your users will create an account in Craft. The bloggers/influencers will need their own user group, and they will submit a form that will create an entry in a channel called "Menus". Your general users will be in their own user group and can choose among those Menus entries. You get an unlimited number of channels, categories, purchasables, etc, and they can all be related to each other within an entry, product, etc, so go nuts and keep everything modular for reuse. Your custom plugin/module will need to handle figuring out the number of ingredients and any other customization.

That's all just my interpretation of what you wrote, so obviously you'll want to look into this stuff yourself. But I don't think you have to go reading up extensively on a bunch of stuff before finally deciding to start. You can download Craft Commerce for free (you don't have to pay for a license until you push it up to your server), and you can always start exploring custom plugin/module development. Getting your hands dirty with the code is the way to answer your question, but if you're worried about investing your time in all this just to find out that Craft prohibits you from realizing your idea, I can assure you that's not the case, and you're not going to have to make it happen by having to hack around the system like some lame Wordpress site. Craft is made to be incredibly flexible for anything that needs content managed, and that includes your idea.


Showing A Flash Message On Admin Entries Listing (Craft 3)

To show a message

Craft::$app->getSession()->setNotice($message);

To show an error

Craft::$app->session->setError($message);

There is no "default" key that is always shown or something like that. You just use the function and set a message -> the next time the user visits any page the message is shown.


Craft 3: Searching within back-end & front-end isn't giving all entries/results

You can use the craft resave/entries console command and it will (among other things) update the search index table with the latest information for your entries.


Is there a way to make conditional input fields in Craft CMS?

For what it's worth, it's coming in Craft 4. The author of the Reasons plugin has specifically said he won't port it to Craft 3, as this will be part of core in the next release.


Image in entry only showing when using entry.image instead of entry.assetFieldHandle

I assume you got Entry.assetFieldHandle from the docs? That's a way of telling you that you should call the asset field you're looking for by its handle.

You'd have to use the actual asset field handle of the asset field you're addressing, because an entry could have multiple asset fields (so there is NO attribute assetFieldHandle within the entry).

Let's say that your entry has two asset fields: images (multiple images) and logo (1 image).
In this case, this would be the way to display those assets:

{# get multiple assets from field with handle 'images' #}
{% for image in entry.images %}
    {{ image.link }}
{% endfor %}

{# if you know an asset field only contains 1 asset (because its input is limited to 1)
   you can use 'first()' to get it without any for loop #}
{{ entry.logo.first().link }}


Is there a better way to make tables in Craft?

I'd use a Table or SuperTable field

But if you want to stick to a Redactor Rich Text field, put a wrapper <div> around the {{ entry.redactorField }} Twig markup, and use CSS to style the table ala .myRedactorWrapper th etc.


Can I exclude a commerce address by ID when retrieving a list of addresses?

I still haven't found a succinct way to exclude a particular address by ID within the commerce customer addresses tags, but I did come up with the following as a way to get a nice clean set of addresses I want to iterate over.

Rather than use a conditional in my loop, I decided to create the collection first, with the address I want to exclude being kept out of the collection. This gets the job done!

{% set customerAddresses = [] %}

{% for address in craft.commerce.customer.addresses %}
    {% if address.id != craft.lhngroups.orgCommerceAddressId %}
        {% set customerAddresses = customerAddresses|merge([address]) %}
    {% endif %}
{% endfor %}


Grab first  or  src from Rich Text field

I had the exact same issue with a client and their horrendous Wordpress blog posts.

In the end, after importing all the posts and copying over the related images, I wrote a simple plugin that lets you use a |firstImage filter to grab the first image from a rich text field. I've added it to GitHub: https://github.com/DigitalSquid/Craft-CMS-First-Image

A rough example of how to use it:
{% set firstImage = entry.body|firstImage %}
{% if firstImage|length %}
    <img src="{{ firstImage }}" />
{% endif %}


How do you set a flash message in the template in Craft 3?

You can set flash messages using yii\web\Session::setFlash().

The session component is available to templates via craft.app.session.

{% do craft.app.session.setFlash('error', 'You’re not allowed to go there.') %}

For convenience, Craft’s SessionBehavior class adds shortcut setError() and setNotice() methods to the session component as well.

{% do craft.app.session.setError('You’re not allowed to go there.') %}

You can place that right before your {% redirect %} tag.


Template cache table growing very big, best way to keep it in line?

In addition to what Brad suggested, I'd also do some auditing to see what kind of benefit you're getting out of your caches. You could, for instance, use the for parameter to cache only for 24 hours or such. No reason to keep a stale cache around that isn't getting hit -> https://docs.craftcms.com/v3/dev/tags/cache.html#for

e.g.:

   {% cache using key cacheKey for 1 day %}

Let unused caches naturally expire after a reasonable period of time.

If you do it this way, all caches will not expire at the same time. In an ideal world, Craft's {% cache %} tag would allow for incrementing the cache duration based on hits, so things that are getting lots of hits would say in the cache (until otherwise busted), and unused cache entries would expire.

I don't think there is any way to do that currently, tho. So at least using for, it isn't an all or nothing proposition, and caches will expire individually, 24 hours after they are created.

I will also say that you may consider using another method of caching, such as FastCGI Cache or Varnish


It might be easier for you to set up a local domain and access it via my-site.dev rather than localhost/public/admin.

Using xampp this is a bit of a manual process. You'll need to go into:
xampp/apache/conf/extra/httpd-vhosts.conf and the following

## my site name Site
<VirtualHost *:80>
    DocumentRoot "D:/xampp/htdocs/my-site"
    ServerName my-site.dev
    ServerAlias www.my-site.dev
    <Directory "d:/xampp/htdocs/my-site">
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

The open your text editor with administrator rights and go to: c:\windows\system32\drivers\etc\hosts and add the following:

127.0.0.1 my-site.dev

For an easier process to set this up use Ampps instead the gui is simpler and everything is automated. Though you may still need to open your hosts file with your text editor if you haven't set up ampps to run with administrator privileges.

I used to use xampps, but now much prefer ampps on windows.


Group entries by section, then order and combine sections

You could do this in a few steps (warning: this is untested code):

1) Define an array of the sections you cited, in the correct order:

{# Define a list of the sections you want to display in the correct order #}
{% set sections = ['news', 'products', 'reports'] %}

2) Identify the entries that do not belong in any of these sections:

{# Create an array of entries that do not belong to any of the sections above #}
{% set otherEntries = [] %}

{# We first loop on the entries by section to identify the "other" entries #}
{% for section, entries in entriesBySection %}
    {% if section in sections %}
        {% for entry in entries %}
            {% set otherEntries = otherEntries|merge([entry])}
        {% endfor %}
    {% endif %}
{% endfor %}

3) Display all the entries of each section in the correct order

{# Loop on the sections in the right order #}
{% for section in sections %}
    {# Obtain all the entries for the current section #}
    {% set entries = entriesBySection[section] %}
    {% for entry in entries %}
        ...
    {% endfor %}
{% endfor %}

4) Display the rest of the entries

{# Finally display the "other" entries #}
{% for entry in otherEntries %}
    ...
{% endfor %}


Checking if a plugin is installed or enabled are ignored by Twig Extensions

I just a test of this locally in a sample plugin and I get expected behavior.

If I install and enable the plugin in Craft and use this in a template:

{% set plugin = craft.plugins.getPlugin('myPlugin', false) %}

{{ plugin.isEnabled() ? 'plugin enabled' : 'plugin disabled'}}

{{ plugin.isInstalled() ? 'plugin installed' : 'plugin not installed'}}

{{ craft.myPlugin is defined ? 'plugin true' : 'plugin false' }}

I get this output:

plugin enabled
plugin installed
plugin true

If I add a Twig Extension class to the plugin, then register a myPluginTestFunction function that outputs "It Works"... i.e.

public function getFunctions()
{
    return array(
        'myPluginTestFunction' => new Twig_Filter_Method($this, 'myPluginTestFunction', array('is_safe' => array('html'))),
    );
}

public function myPluginTestFunction()
{
    return 'It Works';
}

Then I do this is a template:

{{ craft.myPlugin is defined ? myPluginTestFunction() }}

Then I get the expected output of:

It Works


Here are some.

Store Hours (P&T)
match input
Mandrill (P&T)
Entry Count
Minify (9/17/2016)
MN Twig Perversion (9/19/2016)
Stamp (9/21/2016)
Inlin (9/21/2016)

Mention more in the comments, and I will add to this list.


How can I get the cart total item? I tried using a “length” filter but it’s not working with that

You can use the totalQty method to fetch total items from the cart. It’s a predefined method in the commerce plugin to get total items. Also you can find other methods like this in the documentation of the craft commerce plugin.
Right now for your answer use below totalQty method to get total item count.
{{ craft.commerce.carts.cart.totalQty }}


https://sprout.barrelstrengthdesign.com/docs/multi-site.html

Looks like multisite support for Sprout Forms is a planned/under review addition


Well, many tries later, I found a way to do it.

{% for block in currentUser.certificado %}

{{ block.nomeDoCertificado }}

{{ block.curso[0] }}

    {{ block.nomeDoCertificado }}

{% endfor %}

It is as simple as that :)


Cannot install custom Twig extension plugin

My guess is it's because your NbspPlugin class has the namespace of craft, when it should be namespace Craft.

FWIW, generating Craft plugin boilerplate code through something like https://pluginfactory.io/ is a great way to save sanity and avoid things like this. :)


Looking at the code for the plugin, it doesn't look like it.

You'd either need to make a feature request or fork the plugin, add the functionality yourself and make a pull request.


It's giving you errors because you put the variable in quotes. Ditch the quotes and try it like this...

{% set form = craft.formBuilder2.getFormByHandle(entry.formName) %}


Check to make sure your Primary Element field in the initial setup is the entry element and not the top level in your xml file, for example:

<root>

</root>

article should be the Primary Element


Yes it's possible.

You may get a notice that the licence key is in use on another domain if your testing domain is publicly accessible (rather than running on your local machine). But the site will continue to work just fine.

What you can't do is run 2 "live" sites with the same key. That's a violation of the licence.

Furthermore, by going to https://id.craftcms.com/ you can manage the licences for any Craft sites you have.


Asset uploads failing on new installation of Craft CMS

You probably just need to set upload_tmp_dir in your php.ini file to be a path under your openbase_dir paths.

Or just remove the openbase_dir restrictions.


The problem is that you are setting career inside of the if statement. Defining it there won't make it available for your elseif statement.

I've trimmed down your code so you can see exactly what the problem is:

{% set entries = ... %}

{% if entries|length > 0 %}

    {% set career = ... %}

{% elseif career %}

    ...

{% endif %}

If you want career to be available to your elseif statement, you need to define it before your if statement.