In addition to How to save Matrix data programmatically in Craft 3

You'll fetch your data loop each row and fetch the element / create a new element if none exists

$section = Craft::$app->sections->getSectionByHandle('news');
$entryTypes = $section->getEntryTypes();
$entryType = reset($entryTypes);
foreach ($jsonData as $row) {
    // try to fetch an element
    $element = Craft::$app->getElements()->getElementById($row['id']);
    // no element exists, create a new one
    if ($element === null) {
        $element = new Entry(
            [
                'sectionId'     => $section->id,
                'typeId'        => $entryType->id,
                'fieldLayoutId' => $entryType->fieldLayoutId,
                'authorId'      => 1,
                'title'         => 'My Entry',
                'slug'          => 'my-entry',
                'postDate'      => new DateTime(),
            ]
        );
    }
    // get the field by handle
    /** @var \craft\fields\Matrix $field */
    $field = Craft::$app->getFields()->getFieldByHandle('matrix');

    // get the existing matrix blocks
    $existingMatrix = $element->getFieldValue('matrix');

    // serialize the data
    $serializedMatrix = $field->serializeValue($existingMatrix, $element);

   // loop your json matrix blocks
    foreach ($row['yourMatrixBlocks'] as $key => $block) {
        // append your new Matrix fields
        $serializedMatrix['new' . $key] = [
            'type'   => 'block',
            'fields' => [
                'field' => $block['field']
            ],
        ];
    }

    // set the new field value
    $element->setFieldValue('matrix', $serializedMatrix);
    $success = Craft::$app->getElements()->saveElement($element);

    // display errors - just in Case
    if($success === false){
        Craft::dd($element->getErrors());
    }
}


Empty cart should remove coupon discounts in commerce

I think this one is debatable from a functional perspective.
On first glance, it feels like if a cart is emptied then the coupon should be removed, but on the flip side, if they are simply changing their order and the cart is emptied along the way during that process, why should they have to re-enter the coupon?  The coupon itself is still valid, so if they have entered it, and then the cart later becomes valid for that coupon, why should it not then automatically re-apply?
I believe the only way to clear the coupon code as you wish would be to detect if the cart is empty (i.e. has no lineitems) and then post (e.g. by ajax) to update-cart an empty coupon code...something like:
<form method="POST" id="remove-coupon">
    {{ csrfInput() }}
    {{ redirectInput('/cart') }}
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    <input type="hidden" name="couponCode" value="">
    ...etc


Error updating programmatically a plugin's setting

I made a simple mistake by defining the array with the setting value.
I wrote array('currentInvoiceNumber', $newInvoiceNumber) instead of array('currentInvoiceNumber' => $newInvoiceNumber).


Can a non-admin add Entry types into a section?

You would have to write a custom plugin that provided its own UI (outside of the Settings portion of the control panel) and that plugin's controller could mimic Craft's SectionsController (with the exception of not requiring an admin) while calling SectionsService's saveEntryType.

For security your plugin should also register a custom "canSaveEntryType" permission so you can have fine-grained control over who can call that method.


Using $model->validate() with AttributeType::Url

Craft extends Yii's CUrlValidator to add support for protocol-less URLs as well as URLs without a TLD (such as your example of http://sdfsdfsfsdfsdf).

If you need other behaviors for your URL validation, you can always write a custom URL validator.


Is it possible to create a cleaner replace?

I'm just gonna post my comment as an answer, because I think it's the way to go.

I'd use the kebab filter instead of url_encode, like this: {jobTitle|kebab}


Tasks runs only after admin is logged in

Got it. Added the following code.

if (!craft()->tasks->isTaskRunning()){
    $task = craft()->tasks->getNextPendingTask();

    if ($task){
        craft()->tasks->runPendingTasks();
    }
}


Use a custom field type in Matrix Blocks - Craft 3

I'm not sure what it has to do with a matrix - you can use every field normally and inside a matrix, there is no restriction - but I usually create a custom field type.

You can see how to create Plugins in the documentation all available fields in Craft extends the base Field class

There are function like getInputHtml where you define the html that should be displayed while you create your entry/category and the function serializeValue that defines which value should be saved into the db.

You should take a look at the default Craft fields to get used to it. Change the values you need and create your own field.

However: I think the most common approach is to look what Pixel and Tonic does and understand how it works. Then you can create custom fields via Plugin or Module

Edit
You can see how to register custom fields here. As you can see they say the same

  You can refer to Craft’s own field classes for examples


Stop currency translation in Craft Commerce

I don’t think it is possible to stop the filter to translate the $ symbol. I don’t know Arabic, but it seems weird to me that the filter does that. If you agree you could consider sending a feature request to Pixel and Tonic.

To work around the issue now you could set the format option to false and only use the commerceCurrency filter to convert the value. Then format it for the output manually with help of the number_format filter.

{% set total = item.total|commerceCurrency(cart.paymentCurrency, convert=true, format=false) %}

{% if cart.paymentCurrency.iso == 'usd' %}
    ${{ total|number_format(2, '.', ',') }}
{% elseif cart.paymentCurrency.iso == 'eur' %}
    {{ total|number_format(2, '.', ',') }} EUR
{% endif %}

Here is how you can apply the manual formatting to select currencies only.

{% if cart.paymentCurrency.iso == 'usd' %}
    {% set total = item.total|commerceCurrency(cart.paymentCurrency, convert=true, format=false) %}
    ${{ total|number_format(2, '.', ',') }}
{% elseif cart.paymentCurrency.iso == 'eur' %}
    {% set total = item.total|commerceCurrency(cart.paymentCurrency, convert=true, format=false) %}
    {{ total|number_format(2, '.', ',') }} EUR
{% else %}
    {{ item.total|commerceCurrency(cart.paymentCurrency, convert=true, format=true) }}
{% endif %}

It’s probably a good idea to use a Twig macro for this snippet.


It sounds to me like you're running into a collision with Vue's template delimiters vs Twig's, which by default are the same as each other ({{ ... }}). The solution is to change Vue's delimiters to something else when you initialise, like this:
const vm = new Vue({
    el: '#app',
    delimiters: ['${', '}'],
    ...
    ...
});

You'd then need to use ${ ... } as your Vue delimiters.


Return JSON array without extra square brackets

change $products[] = to $products = in your for each loop, that should fix the extra square brackets. And if you want to get all entries and their titleVariation fields you should use 'elementType' => Entry::Class

'pricelist/<entryId:\d+>.json' => function($entryId) {
    return [
        'elementType' => Entry::Class,
        'criteria' => [
            'section' => 'products',
            'descendantOf' => $entryId,
        ],
        'transformer' => function(Entry $entry) {

            $products = [];
            // "orderItem" is entry field
            foreach ( $entry->orderItem as $product ) {
                $products = [
                    'title' => $product->titleVariation,
                ];
            }
            return $products;
        },
    ];
},


Lightspeed retail POS integration with Craft Commerce

I'm not aware of a plugin that does this integration and a quick Google and Plugin Store search isn't coming up with anything, so it looks like it would need to be custom developed.


Fields Missing. Gone from Database as Well as Control Panel

It sounds like something/someone is updating which could be causing the migrations to run and then subsequently fail... that could cause data loss but that's hard to say or know exactly.

When this sort of thing happens, you should be reverting to a last known good backup and then figuring out what went wrong.

That's going to be the only sane way to debug this. I wouldn't try to push something locally onto a bad state on production unless you overwrite everything (which is a hail mary move to restore to a good state).

Are you using Craft 3? The Migration Manager plugin is now called Migration Assistant. Make sure you're using updated versions of the software, as old versions can cause weird issues.


How can I handle the identical SEOmatic config for multi-sites?

So check out this issue for ways I'm thinking about tackling this problem; any input from you would be welcome: https://github.com/nystudio107/craft-seomatic/issues/227


You should be able to use something similar to the following:

use Craft;
use verbb\feedme\FeedMe;
use verbb\feedme\queue\jobs\FeedImport;

$feeds = FeedMe::$plugin->feeds->getFeeds();

foreach ($feeds as $feed) {
    $limit = null;
    $offset = null;
    $processedElementIds = [];

    Craft::$app->getQueue()->delay(0)->push(new FeedImport([
        'feed' => $feed,
        'limit' => $limit,
        'offset' => $offset,
        'processedElementIds' => $processedElementIds,
    ]));
}

The above will add all your feeds to Craft's queue system and start them.


Missing field validation on user account edit

Errors for the users/save-user action are recorded against the user object, not the session object. If the user is logged-out, the object is named user but if they are logged-in you must use currentUser.
Generally speaking you can retrieve errors from Yii objects in several ways, but for field-by-field errors, I prefer the simplicity of getFirstError() (You might also want to use getErrors() or getErrorSummary()). Here's what I'm using for each question:
{% set user = currentUser ?? user ?? null %}
...

    Email &bull;
    <input required id="email" type="email" name="email" value="{{ user is defined ? user.email }}">
    {% if user is defined and user.getFirstError('email') %}
        {% include '_partials/fieldErrors.twig' with { errors: user.getErrors('email') } %}
    {% endif %}

(You could of course use a macro instead of an include as many examples demonstrate).
fieldErrors.twig:

{% if errors %}

        {% for error in errors %}

{{ error }}

        {% endfor %}

{% endif %}


Get all elements (entries) where a field exists

Fields are related to entry types via their field layout.

You need to find all field layouts your field is attached to then find entry types using these field layouts. Once you have that, fetch all your entries by types.

If you already know your field's id, you don't need this but to find the id of your field by its handle:

$fieldId = Craft::$app->getFields()->getFieldByHandle('yourfieldHandle')->id;

Get all field layouts using that field:

$fieldLayouts = (new Query())
    ->select(['layoutId'])
    ->from(['{{%fieldlayoutfields}}'])
    ->where(Db::parseParam('fieldId', $fieldId))
    ->column();

Get all entry types using the field layouts you've just fetched:

$entryTypes = (new Query())
    ->select(['handle'])
    ->from([Table::ENTRYTYPES])
    ->where(Db::parseParam('fieldLayoutId', $fieldLayouts))
    ->column();

Or you can do both the above at once (get entry types by field id):

$entryTypes = (new Query())
    ->select(['entrytypes.handle'])
    ->from(['{{%entrytypes}} entrytypes'])
    ->innerJoin('{{%fieldlayoutfields}} fieldlayoutfields', '[[entrytypes.fieldLayoutId]] = [[fieldlayoutfields.layoutId]]')
    ->where(Db::parseParam('fieldlayoutfields.fieldId', $fieldId))
    ->column();

Once you have your entry types, get all entries matching:

$entries = Entry::find()->type($entryTypes)->all();

Altogether:

use Craft;
use craft\db\Query;
use craft\elements\Entry;

...

// Fetch your field by its handle, if you know the id, just manually set it here
$fieldId = Craft::$app->getFields()->getFieldByHandle('yourFieldHandle')->id;

// Find all entryTypes using the fieldLayouts your field is attached to
$entryTypes = (new Query())
    ->select(['entrytypes.handle'])
    ->from(['{{%entrytypes}} entrytypes'])
    ->innerJoin('{{%fieldlayoutfields}} fieldlayoutfields', '[[entrytypes.fieldLayoutId]] = [[fieldlayoutfields.layoutId]]')
    ->where(Db::parseParam('fieldlayoutfields.fieldId', $fieldId))
    ->column();

// Find all entries by entryType
$entries = Entry::find()->type($entryTypes)->all();


Stuck when grouping entries to get any other parameters like url, id etc

The group filter creates an associative array so the location Twig var in your loops is the array item key, which is a string.

I think you'll have to get the location object that's related to the entry you're currently working with in the loop in order to access its URL. Maybe try setting the location object to a variable by adding something like {% set locationObj = entriesInLocation[0].location.one() %} right after {% for location, entriesInLocation in allEntriesByLocation %}. Then, you should be able to access the location URL using {{ locationObj.url }}.


Check for logged in user with the Element API plugin

Assuming you want to do this from your transformer, then something like this should work:

'transformer' => function($entry) {

    $isLoggedIn = craft()->userSession->isLoggedIn();

    if ($isLoggedIn) {
        // Do your custom logic.
    }

    return array(
        'title' => $entry->title,
        'url' => $entry->url,
        'description' => (string) $entry->description,
        'photos' => $photos
    );
},


Element API - Entries Related to a Category

The slower but easier approach is to fetch all of them and search for related entries

'elementType' => Category::class,
'criteria'    => [
    'group'   => 'yourGroup',
],
'paginate'    => false,
'transformer' => function(Category $category) {
     $entries = Entry::find()
        ->relatedTo($category)
        ->select(['title'])
        ->asArray()
        ->column();

    return [
        'title'   => $category->title,
        'entries' => $entries
    ];
}

Learn more about Element Queries especially the different ways to fetch entries via one(), all(), column()


If you've setup a channel, it does not include a "blog index" by default, for this you need to make it yourself by placing an index.twig file within the blog folder (If that is a directory in your templates folder).

Check the answer in this question for an example on how to do the twig code.
What's the right way to create a simple blog in Craft?


How can I use aliases in a module / plugin?

Would it be an option for you to use

Craft::getAlias('@webroot');

Yii2 Aliases


Freeform: Remove default styling injection

This is probably injected as part of the form template that's used to render the form. In the Freeform section of the CP, if you edit a form and choose the 'cog' icon in the right-hand pane to access the form settings, you'll see a dropdown labelled 'Formatting Template', which lets you choose a template to render out the form markup, with a number of popular frameworks listed (Bootstrap, Foundation etc.).

In order to override this markup (and remove the CSS include), you can create your own custom templates using one of these templates as a guide. The Freeform docs cover how to do this here.

The default templates are located here:

vendor/solspace/craft3-freeform/src/templates/_defaultFormTemplates.

Make a copy of the file you want to use as a base, and place it in your own templates directory; I tend to use templates/_forms for form templates. Give your new form template a meaningful name - Freeform does some nice parsing of custom template names to display them in the Formatting Template dropdown, so it's worth naming it well.

Open your new custom template and look for a line right at the top that looks like this:

{% css formCss %}

Remove that line from your template and save it. Finally, make sure in the Admin CP > Freeform Lite/Pro > Settings > Formatting Templates, you've included the path to your custom forms template directory relative to your main templates directory. For my example directory above, I'd enter _forms as the directory path.

Now, edit your form and when you open the Formatting Template dropdown in the form settings, you should see your new custom form template. Select it, save your form and refresh the front-end form page. Hopefully, the Freeform CSS that was being injected is now removed from the markup.

Hope that helps!


Issue with uploading files from frontend

Have you tried enabling devMode in the craft/config/general.php file? You can do this by adding 'devMode' => true to the array. You should then be able to see an error on submission.

If this fails to output anything then it could be that your input requires square brackets adding to the name, e.g. name="useruploads[]"

Even though you have limited the field to 1 upload, it may still be expecting an array to be posted to it.


This is indeed possible.  You'll want to update your route to point to an array with and identify your controller path with the key action:

public function registerCpRoutes()
{
  return array(
    'pluginname/edit' => array('action' => 'pluginName/editItem'),
  );
}

In your plugin controller, you can create any number of variables you need and hand them off to your template as the second argument in the renderTemplate() method:

// PluginNameController.php
public function actionEditItem()
{
    // Create any variables you want available in your template
    $variables['variable'] = craft()->request->getSegment(3);

    $variables['items'] = craft()->pluginName->getAllItems();

    // Load a particular template and with all of the variables you've created
    $this->renderTemplate('pluginname/_edit', $variables);
}

Check out the article How do I setup a route to point to a controller action instead of a template? on Straight Up Craft for a more in depth discussion that also goes into how to render the template from your control, hand off variables to your template, and reference multiple controllers.


Try using accessSiteWhenSystemIsOff.  If you're on a case-sensitive file system, that will matter.

  does anyone know if it's possible to set a group permission that gives access to a plugin

You'll want a plugin for that. You can use the registerUserPermissions hook to register a custom permission.


How to output entries related to a locale, IF a section is targeted to all locales?

Craft always outputs entries in one locale only. If you really want to list all entries in all of their enabled locales you would need to explicitly query for them using the locale parameter and then merge the results.

What probably confuses you is that Craft automatically clones an entry on the first save to all other locales. Try to edit an entry / disable it for one locale only and see the differences on you index pages!

If you really don't get the locale specific content for your different URL formats

example.com
example.com/locale1

there probably goes something wrong with your setup. The first thing I would check is the index.php files (→ Localization guide – Step 5: Set up the files)!


Uploading local asset hangs and produces jQuery console error

You can use this support article to help debug failed uploads: https://craftcms.com/support/upload-troubleshooting


Is it possible to populate a user field in the CP using custom logic upon registration?

The Preparse plugin may help you accomplish what you want. https://github.com/aelvan/Preparse-Field-Craft


Multiple Sections Within a Structure Group?

First, try to separate the concepts of content modeling (how things are set up in the CP) and information architecture (how things are going to be presented to the user on the front-end site) in your mind. Are these “Employees” and “History” pages inherently sub-content of “About”, or is that just how you’re choosing to display it on the front-end? My hunch is it’s the latter, in which case a Structure section is not the right choice to begin with - and perhaps 3 separate Single sections makes more sense.

  I don't want to use Entry Types, because I need to use the layouts in multiple places on the site. For example there's a Brochure-type page in the site's 'Careers' area. If something about the layout changes I don't want to have to go through multiple Entry Types to make the changes over and over.

I feel you on the annoyance for having to maintain multiple (near-)identical field layouts, and this is something we hope to make better someday, but I would argue that it’s not going to be as bad in practice to keep these field groups in sync as you’re fearing – or at least not bad enough that the currently-possible workarounds will be worth the effort.


Adding more data to the "commerce/cart/update-cart" action

You could either extend the craft commerce update-cart controller
or get the specific fields via element-api what will unfortunately result in an extra api call.


Is it possible to add a custom error message when a migration is aborted?

Currently not, but as Lindsey points out, that's not a bad idea for a feature request.


Conditional check if Matrix block field is empty (no content)

I'm assuming your matrix field is not called hours? Because in your current code you are handeling it like it is.

I think this should work

   {% for block in entry.matrixfieldHandle %}
       {% if block|length %}
           {{block.days}} - {{block.time}}
       {% else %}

Do something else

       {% endif% }
    {% endfor %}

In your code you want to loop over all the different entries (blocks) within the matrix. If you want to add other types you can easely check for hours like so:

{% if block.type == "hours" %}
   do stuff
{% elseif block.type == "anotherblocktype" %}
   ...

However. Since you only use one type of content I'm not sure if a matrix is the best solution. You could easely put this in a table or supertable .

Then you could just do

{% for row in entry.tableHandle %}
   {% if row|length %}
       {{row.text}}
   {% else % }

Fallback

{% endif %}

Another option is to check this little plugin: Store hours


Use same handle for different fields on different entry types

You need two different fields since you can only select one category group per category field. As you said, having two fields with the same name isn't possible. One way to work around this would be to add a behaviour that checks the entry type and returns the categories from the corresponding field (i.e. jobCategories for job entries and blogCategories for blog entries).
However, this is more complicated than it needs to be. You can just define a macro and pass it the appropriate field depending on the template:
{# macros/macros.twig #}
{% macro category_list(categoryQuery) %}

{{ categoryQuery.all()|column('title')|join(', ') }}

{% endmacro %}

{# blog/_entry.twig #}
{% from "macros/macros.twig" import category_list %}

{{ entry.title }}

{{ category_list(entry.blogCategories) }}

{# job/_entry.twig #}
{% from "macros/macros.twig" import category_list %}

{{ entry.title }}

{{ category_list(entry.jobCategories) }}

If you have a single entry template for both entry types, you can also check the different fields inside the macro:
{# macros/macros.twig #}
{% macro category_list(entry) %}
    {% switch entry.type.handle %}
        {% case "job" %}
            {% set categories = entry.jobCategories.all() %}
        {% case "blog" %}
            {% set categories = entry.blogCategories.all() %}
        {% default %}
            {% set categories = [] %}
    {% endswitch %}

{{ categories|column('title')|join(', ') }}

{% endmacro %}

{# entry/_entry.twig #}
{% from "macros/macros.twig" import category_list %}

{{ entry.title }}

{{ category_list(entry) }}


Where do I run validation before database insert?

Records and models are similar in that they are both containers for data, but records have the additional functionality/overhead of being able to write and read from the database via the Active Record pattern.  There is also not a 1:1 relationship between records and models.  A model can define attributes from multiple records.

In practice, records should never leave your service layer, because you don't want them floating up to the controller or template level, for example.  If that happened, then people could inadvertently insert/update/overwrite data directly from a template.

From your service, you do all of your Active Record / database related logic, and call populateModel(s) with the resulting data and return the models from your service and let those safely transport your data throughout your layers.

The general pattern for all of this, including validation, looks like this:

class SomeController extends BaseController
{
    public function actionDoSomething()
    {
        $myModel = new MyModel();
        $myModel->myProperty = 1;

        // Validate the model
        if ($myModel->validate())
        {
            // Pass it to the service.
            if (craft()->myService->doSomething($myModel))
            {
                // Success!
                $this->redirectToPostedUrl();
            }
        }

        // Return the model back to the template so the errors can be displayed.
        craft()->urlManager->setRouteVariables(array(
            'model' => $myModel
        ));
    }
}

Your service can grab the info it needs from the model and create or grab any necessary records.  It can then, if it needs to, call $record->validate() on any of the records.  If a record fails validation in the service, it can add those errors to the original model and return false like:

$myModel->addErrors($record->getErrors);

And those errors will bubble up to the template to be displayed.


Usually when you see this, PHP is running out of memory trying to load the page.  Bump your php.ini file's memory_limit setting to something higher and that should fix it.

Update:

Actually, this is in your phperrors.log file:

[23-Sep-2014 15:11:20 UTC] PHP Fatal error:  Maximum function nesting level of '100' reached, aborting!

See here for the fix.


How do I get the right entry data based on locale and slug?

Probably the CRAFT_LOCALE isn't set correctly. There is an in-depth knowledge article here.

To solve this, you could add a conditional to the /public/index.php:

// Path to your craft/ folder
$craftPath = '../craft';

//Locale
if ( preg_match("/\/nl\//i", $_SERVER['REQUEST_URI']) ) { //Check if /nl/ is in the uri
    define('CRAFT_LOCALE', 'nl_nl');
}
else {
    define('CRAFT_LOCALE', 'en_us');
}


Front end form with Matrix won't add more than one row

According to the craft cms docs

  To show a “New Block” form, first come up with a temporary ID for the
  block, prefixed with new:. For example, new:1, new:2, etc.

so, you need to you use prefix new: with the colon is a must.


Maybe use a smarter slider? I frequently use Slick, which will only initialise when the number of items is > 1.

In addition, within my template code I would only include the markup required only for the slider if the number of slides is > 1, as I like to keep my markup clean. Something like:

  {% if entry.hero|length > 1 %}
{% endif %}
    // Hero / Slider markup goes here…
  {% if entry.hero|length > 1 %}
{% endif %}


My SuperSort plugin is built for use cases exactly such as this. It allows you to render each object in your array using a Twig object template and sort the array based on the rendered value.


How do I get entries of a child category, related to a parent category, defined in a URL segment?

I don't think that there's a "relation" between categories and their sub-categories.
But that's what you currently have as a parameter on craft.categories.
Use the ancestorOf() parameter instead to filter your subcategories:

{% set mainCategory = craft.categories.group('section').level(1).slug(secondSeg).first() %}
{% set secondLevelCategories = craft.categories.ancestorOf(mainCategory).slug(lastSeg) %}


Is it possible to have one Craft install running

Sure it can. Craft 3 has multi-site support.
And for using a subdomain, you don't even need that, just point that subdomain at the correct template URL (eg. forward blog.example.com to example.com/blog).
The about single at example.com would just be your homepage.


Well as always with Craft there are many ways to skin this particular cat.

A simple approach would be to have a catalogue template (either just one for all product types or separate ones for each product type if you want to vary the format significantly).

Assuming just one template for your various catalogues, this could live in your  templates folder at e.g. _site/product-catalogue.html

You could set up a route in Settings->Routes, such that

*/catalogue pointed to  /_site/product-catalogue

this template would then load whenever someone went to e.g.

yoursite.com/monitors/catalogue

In there you could query for all products of that type and display them:

{% set segment_1 = craft.request.getSegment(1) %}
{% set products = craft.commerce.products.type(segment_1).find() %}

...and proceed from there any way you like, really, in terms of display.

In terms of building you nav:

{% for productType in craft.commerce.productTypes %}

{{ productType.name }}

{% endfor %}

(Another approach would be to add all the products to a category, and then use category fields and a category template to display your product list).

I haven't used tags much, and I am not sure I'm 100% on what you're asking (do you want to highlight sections with new products, or create an extra element in your nav for these?)....but in essense you'd probably have to search for products in that category and look for a tag of New.  Here's some sketch code:

{% for productType in craft.commerce.productTypes %}
   results = search for entries with this type that have the tag New
   if the length of results > 0

*** NEW *** {{ productType.name }}

   else

{{ productType.name }}

   endif
{% endfor %}

Craft docs on doing the search are here: https://craftcms.com/docs/searching


API endpoint to show/add/modify/delete content

I've got 0 experience with React, but you can write a Craft plugin (generate boilerplate code at https://pluginfactory.io), that has a controller action(s) your webapp can post to.

From there you can use EntriesService->saveEntry (craft()->entries->saveEntry()) to update/create entries just like Craft/any other plugin does.


From the Freeform docs:

  The Freeform Form (or Submissions) fieldtype lets the user assign any
  Freeform form (or form submissions) to any element: a section entry,
  categories, assets, etc.

In a nutshell, this means you can embed forms to any entries you have, like so:

This section within the docs shows you how to correctly code your templates.


How can I debug `craft\web\User::_validateUserAgentAndIp()` warnings

Most likely since it's a production site, it's from bots/scripts hitting the site's login page probing for vulnerabilities.

I'd suggest changing the cpTrigger config setting and see if the occurrences go down.


Save same Entry more than once with help of custom relations field

No, but you could use a Matrix field containing a Entries field.


Change custom element Index title via getTableAttributeHtml?

I finally found the answer to this question.

From BaseElementType defineAvailableTableAttributes() docs,

  The first item that this array returns will just identify the database
  column name, and the table column’s header, but will not have any
  effect on what shows up in the table’s body. That’s because the first
  column is reserved for displaying whatever your element model’s
  __toString() method returns (the string representation of the element).

So all you need to do is add a __toString() method in your model and return the string representation of your element:

For example:

public function __toString()
{
   return $this->id;
}

Result:


You might find the Hacksaw plugin useful for this https://github.com/ehousestudio/craft_hacksaw/ this will truncate text for you and has a wealth of options available for doing so, specifically the append parameter, which will do exactly what you want :)


Customize the field.html file for Sprout Forms

To override field.html you will also have to provide an override for tab.html and errors.html.

The field.html template is a bit more complex and the Twig code to get it to work depends on a few other files to work properly.

I've updated the documentation to better reflect this requirement: Template Overrides

If you only need to update the classes, you may also want to consider Rendering Options.

Rendering options would let you dynamically pass the class names to the underlying form code. Depending on how predictable your field names are, it could work like this:

{% set options = {
    "class": "form-class form-class-customized",
    "errorClass": "form-has-error",
    "fields": {
        "fieldHandle": {
            "class": "my-fancy-class",
            "errorClass": "field-has-error",            }
    }
} %}

{{ craft.sproutForms.displayForm("formHandle", options) }}


I'm not sure about best practice, but we always use our clients details. They normally own the site, so they should also own the social login flow.

We normally ask them to let us set it up, then they can change the password with the provider (if they want to) once it is working.


I got it! The Sprout Notes Field plugin was what I needed. It allows HTML input with various formatting options.


Use REQUEST variable as dynamic upload location

That field accepts any valid Twig code, so something like this should work:

challenges/{{ craft.request.getPost('challenge_id') }}/

Fair warning, though... I'd also be wary of accepting untrusted front-end input like this that ends up on the file system.


Import / Aggregation DB - with 50 Million Records - Best Practice?

I'm not sure why you would do two different servers.

Your front end can be cached with Blitz / NGINX which will take a load off the server and admin.

How often are you aggregating the data?

I've just imported 10k records from a source and I would recommend writing your own module to handle the imports as commands. From there you could set up a cron which would run at a scheduled interval. These commands wouldn't run via the web server so you wouldn't be restricted to memory / timeout limits.


Using Asset folder variables with Sprout Forms

I have created a form with a hidden field and asset field. The hidden field appears before the asset field:

We'll want to make the email field required because we are using that field in the auto-generated subfolders. (if it is empty it will generate an error)

Place a forward slash in before the folder location of the asset field: /{jobid}/{email}

The object variable will not work in the Sprout Forms context. We can use the field handle ({id}, {name}...) or the form object ({form.id}, {form.name}...) if you want to be more specific.

Regards.


Using a plugin, how can I manipulate entry data?

You are correct in stating that Records typically define a new custom table for your plugin. However, don't forget that Craft already comes with many pre-existing Records.

Take a look inside this folder:

/craft/app/records

Although based on your question (and the ensuing comments thread), it looks like you may not need to tap directly into any Records at all. I'd recommend you peruse the built-in API to see what may help you get the job done.

Specifically, take a look at the EntriesService API...

  http://buildwithcraft.com/docs/apis/entriesservice

I suspect that everything you need to do can be done using those methods. After all, they already allow you to get, modify, and delete entry data.

An important thing to note when dealing with the EntriesService API... You're not directly accessing Entry Records. Instead, you'll be dealing with Entry Models. This is greatly preferred, and you'll find that it's much easier to do what you want with a Model. (Behind the scenes, your model will tie into an Entry Record as needed.)

On a separate note, it looks like you'll need to take advantage of Events. You mentioned in a comment that you'd like an action to take place "when an entry is saved". To do that, you'll definitely want to take advantage of the entries.onSaveEntry event.

In summary, I don't think that you will need to create a custom Record, nor build your own custom Yii query.


is it possible to edit an entry from the front-end when you're not logged in?

You should be able to edit that entry using craft()->entries->saveEntry($entry) with $entry->authorId set to a registered user with the necessary permissions. To get the ID of the user that created the entry, access the Guest Entries plugin settings in your plugin:

$settings = craft()->plugins->getPlugin('guestentries')->getSettings();
$authorId = $settings->defaultAuthors[$entry->section->handle];


As Ryan has said in the comments, there currently isn't a native cookie consent feature within Craft CMS.

You'll need to either install a plugin (Cookie Consent plugin for Craft CMS is good) or use a service like Silk Tide Cookie Consent.

Both options require you to have access to your website via FTP.

For the plugin, you'll upload it to the /craft/plugins/ directory and activate it via the Craft CMS control panel.

The Silk Tide method requires you to add some code between the <head></head> tags.

If you need help with this, there are lots of developers on here (including myself) that can help.


How do I pull the last level of a category?

.last is the opposite of .first, meaning that you can only apply it at the end of your query.

{% set markets = craft.categories.group('markets').relatedTo(entries).last() %}

And similar to .first, the .last method will only return a single Entry.


You can not run Commerce 1 on Craft 3.

Commerce was completely re-written for Craft 3 compatibility.  Indeed the final release of Commerce 2 actually requires Craft 3.1.

That said, your license for Commerce 1 should work for Commerce 2 once you have that installed but note there is a lot more to upgrading sites to Craft 3/Commerce 2 than just installing the new versions - there are extensive changes needed to both - including template and fundamental changes to custom plugins if you have written any of those.

See:

https://docs.craftcms.com/v3/upgrade.html
https://docs.craftcms.com/commerce/v2/changes-in-commerce-2.html


When you include templates and pass multiple different variables to them with different types that may have a different field layout it is required to code defensively and check for variable types. Actually you should never print something without further checking. Anything bad that could happen will happen. Especially in such a case

{% if country[fieldhandle] is defined and country[fieldhandle] is not empty and  %}
    {% for element in country.getFieldValue(fieldhandle).all() %}
        {{ element.title }}
    {% endfor %}
{% endif %}

You may as well include a instance of check

{% if element.getFieldValue(fieldHandle) is instance of('craft\\elements\\db\\ElementQuery') %}
    {% set relatedElements = element.getFieldValue(fieldHandle).all() %}
{% else %}
    // eager loading, the result is an array, no need to fetch it
    {% set relatedElements = element.getFieldValue(fieldHandle) %}
{% endif %}


Min/Max numeric search returning odd results

Aha! Another lightbulb moment.

The wage field was set to be plain text. I changed it to number and things work as expected.


Whoops! Sorry. As I went to check the code I realised, I was using {{ category.uri }} instead of {{ category.url }}.


Problem was being caused because I was trying to access the server through 'localhost' instead of '127.0.0.1'.


So... just to be clear. This /style.css is a static asset, it's not sitting in the craft/templates folder, right?

Assuming that's the case, something is definitely wrong if https is taking 2 seconds to load it. Sounds like something with your server is misconfigured.

How are you measuring this, exactly?


I forgot we added a tool for this, too, under Settings->Tools->Clear Caches Tool->Asset Transform Index.


Image Optimize Field - adding ImOp field to a volume causes images in that volume to not be found

Worked with @andrew.welch and found that, although our site is using /html for the webroot, there also existed a /web folder.  For a reason not yet identified, the plugin brought the /web folder to the surface as it was attempting to look in that folder.  I simply deleted the /web folder, and everything works.

The file craftcms/cms/src/console/Request.php sets the path based on what folders it finds on the filesystem, and "web" is before "html" in the array that it checks

    foreach (['web', 'public', 'public_html', 'html'] as $folder) {
        if (is_dir($dir . DIRECTORY_SEPARATOR . $folder)) {
            $dir .= DIRECTORY_SEPARATOR . $folder;
            break;
        }
    }

Thank you Andrew!


In Craft 3, how to clear stuck "Deleting Stale Template Caches"

The answer was, to delete the first row of the queue table in the correct database.
Also, it helped to increase max_execution_time in /etc/php/7.1/apache2/php.ini


You don't have to fill in the quote's or the curly brackets.

You could just put it down like this:

{% set title = category.title %}

You already "called" twig so you dont need to do that again.


Sprout Import: Place entries under a parent in structure section?

Turns out you can set the "parentId" field under the "attributes" list in the import JSON data to set a structure parent (to the entry id of the parent entry). This probably means you need to chunk your import into separate steps, for example:

Import only the top-level entries.
Run a query on the CMS to retrieve entry id's for those just-imported top-level entries.
Using the list from step 2, assign the proper entry id to the 2nd-level children and import those.
Run a query to get the 2nd-level entries you just imported.
etc. etc. for each level of your hierarchy

Would be awesome if you could just nest the JSON structures and the import plugin magically figured out how to set parent ids, but that sounds like a lot of work to implement for a free plugin :)


Upload user profile image from custom plugin controller

The image data is not going to be in POST variable. You should be using

$userPhoto = UploadedFile::getInstanceByName('userPhoto');


The request for the craft font needs to be rewritten, since the actual file is (usually) outside of the public web root. Usually, this will be handled by the location block in your nginx configuration that rewrites requests to index.php. After you added the location block that adds the CORS header, though, all requests for font files are processed by this block only (see this thread for more on location priority). nginx only processes one location block pr request, it doesn't "add them up". The best solution would probably be to make the location block for adding the CORS headers more specific, so that the regexp doesn't match the Craft fonts.

Here's an example on what I did on a previous project where the fonts were inside my /assets folder:

location ~* ^/assets/.*\.(?:eot|ttf|woff)$ {
   add_header Access-Control-Allow-Origin *;
}


Your example isn't working because block.type is actually a shorthand for block.type.handle. Use the latter instead and it should work. You can tell this is the case by dumping out block.type - it's not a simple string, it's a great big object.
buttonText[block.type.handle]


As long as the features are sufficient, you can use it for whatever you want. :)


Multiple Photos/Assets in one upload entry

Forget about the front-end for a moment... That would be a separate, unrelated issue.

When you mass-upload, do all files appear on the back-end (screenshot #2)? And then when you hit "Save", are all of those assets saved?

If the answer to either of those questions is no, then you should file a bug report. Use the "Get Help" widget on your Dashboard, and be sure to include your logs, database export, and files.

If the answer to both of those questions is yes, then the problem is not with your file upload. The problem is somewhere in your template. In that case, please post a new question to ask why your template isn't showing all of your uploaded images.


Where to put where() for a query looking for a lightswitch field

You can just query for the field value directly How to use Element Queries

{% set featuredEntry = craft.entries({
    section:  ['resources'],
    orderBy:  {postDate: SORT_DESC},
    limit:    1,
    featured: 1,
}).all() %}


This might not be the answer you were looking for, but I don't think you need to go to great lengths trying to achieve something that in my opinion is not necessary. While it might seem to be not "clean" to have database table columns that are not required by your application/plugin, consider that todays ICT infrastructure is powerful enough to not slow down due to a few additional columns in a database and its tables.
I would even consider it more risky trying to alter the "base" of Craft or the Yii framework than to live with a few autogenerated columns.
If you are very sensitive to performance and have many database requests, you might not want to use active record since its higher level of abstraction can come with a performance penalty in certain situations.


How can I dynamically set checkboxes to be named variables?

So I had missed the entry.checkboxFieldHandle.contains('tequila') line in the docs, which allows me to access the checkbox values outside the for loop.


Control panel field name & instructions translations

If your main language site is dutch for example, you can do that using your own php files locale and naming them according the other locales languages, en.php, fr.php and put those files in craft/translations/ (a folder you must create yourself). Then you can translate in the array all your string (field name and instructions).

Have a check at the documentation:

Translating Static Text


Is it possible to create event with multiple date/time (out of box)

I know this is a while ago, however you could do something like:

Default Times: 09:00-18:00
Monday Time:
Tuesday Time:
Wedneday Time:
Thursday Time: 09:00-20:00
Friday Time:
Saturday Time:
Sunday Time:

When listing times check if that day has a specific time, otherwise use the default time. Will save you changing 6 times anytime there is a change in opening times.

Not a complex solution but one that can be easily understood by a content manager.


It’s not currently possible to upload assets via URL, but if we’re only talking about images that are already uploaded into Craft, you could have them selected by their existing asset IDs, rather than URLs, and it would work.

First, go into your Assets field settings and check the “Restrict uploads to a single folder” checkbox.

Then in your entry form, write a UI for selecting an existing asset. Something like this:

    {% for image in craft.assets.source('images') %}

                <input type="radio" name="fields[myAssetsField][]" value="{{ image.id }}">
                {% do image.setTransform({ width: 100, height: 100 }) -%}

    {% endfor %}


Where can I download previous versions of Craft?

In Craft 2:

You can download previous versions of Craft from https://download.craftcms.com.

Previous versions and builds of Craft are available with the following URL format in both zip and tar.gz versions:

http://download.craftcms.com/craft/{version}/{version}.{build}/Craft-{version}.{build}.zip (or .tar.gz)

For example, if you wanted Craft 2.1 build 2557 in tar.gz format, it would be

http://download.craftcms.com/craft/2.1/2.1.2557/Craft-2.1.2557.tar.gz

Note that downloading Craft releases directly still binds you to Craft’s license agreement, and keep in mind that Craft does not support rolling back to previous versions automatically.

If you’ve already updated your site past a certain release and want to go back to it, you’ll need to find and restore a database backup that was created with the version you’re going back to.

In Craft 3:

You can download previous Craft 3 versions in several ways:

From pre-built packages in this format:

http://download.craftcms.com/craft/{majorVersion}/Craft-{majorVersion}.{minorVersion}.zip (or .tar.gz)

For example:

http://download.craftcms.com/craft/3.0/Craft-3.0.26.1.zip (or .tar.gz)

Directly from the Craft Github repo release page
Since Craft 3 is Composer based, you can modify your composer.json's craftcms/cms line to install the previous version you're looking for.


Get a twig | replace to output html rather than the text

Try using twig's raw filter.

{{ jobs.jobStatement|replace({'%Job Title%': "" ~ jobs.jobTitle ~ "" })|raw }}


You are returning an elementCriteriaModel (which always returns an array-like object regardless if there is one or more than one result), which you either need to loop over or just grab the first entry (because in this case there can only be one).

{% set gameEntries = craft.entries.section('games').relatedTo(entry) %}

Info:

{% for gameEntry in gameEntries %}

{{ gameEntry.title }}

{% endfor %}

or

{% set gameEntry = craft.entries.section('games').relatedTo(entry).first %}

{{ gameEntry.title }}


Error: Craft\EntryModel and its behaviors do not have a method or closure named "Case Studies"

Welcome Ross! If you have 'Case Studies' as a Section and not a field, try changing your syntax to:

{% for entry in craft.entries.section('caseStudies').find() %}

    {{ entry.title }}
    ...

{% endfor %}

Here's an updated example, showing an additional custom field...

{# Find all Entries in the Case Study section #}
{% for entry in craft.entries.section('caseStudies').find() %}

    {# Display the entry's Title #}

{{ entry.title }}

    {# Display the contents of the Intro Summary (plain text field) #}

{{ entry.introSummary }}

{% endfor %}


503 Response on fresh install, FastCGI possible culprit

Okay, my next stackexchange question will be "Where is the dunce cap?" because I could use one. My problem was not actually a problem, and Lindsey D was exactly right: I was just going to mysite.com, not to mysite.com/admin.

And I see now that that was clearly stated in the install instructions, a tab that I was referring to over the course of the whole afternoon!

Thanks, Lindsey, my morning just opened up. And to the dev of posterity who finds his way to this question and answer: I know it hurts.


Click read more on a single and it takes you to items in a structure

You can access any information from just about anywhere in craft. In fact, the only thing that distinguishes one 'page' from another is that craft conveniently populates a predefined 'entry' variable populated with the 'current' entry (EntryModel) using the template that you defined in your section settings. But you can choose to use that 'entry', ignore it, redefine it, or grab entirely different content altogether.

If I understand your requirements, it sounds like you are trying to create an 'index' page of sorts in your single, which links to entries in your structure.

{{ entry.title}}

{% set entries = craft.entries.sections('myStructureHandle').limit(null) %}

    {% for entry in entries %}

{{ entry.title }}

{{ entry.description }}

            Read more

    {% endfor %}


Craft Commerce - Bad Request The CSRF token could not be verified

My bad - sorted it out by adding {{ getCsrfInput() }} - as per https://craftcms.com/support/csrf-protection


There is not really a very simple way to do this. One thing to keep in mind is that channels and structures do not have an 'index' page defined by default. Essentially there are no uri's for channels and structures as a whole, only for the entries within them. You need to create index pages yourself, using:

Singles (one for each of your index pages), or
a Structure (using different EntryTypes for the different levels and/or page types), or
Template files (placed directly in your templates folder)

The other problem is that you may have channels that do not represent pages at all, but are just collections of data to be used elsewhere; likewise, sections do not really have a way to define order. Overall not really a good mechanism to generate nav.

There are, however, other ways to do this.

One solution is to use a dedicated Structure specifically for navigation (called 'primaryNav' for example) with a related entries field that links to other entries and a custom url field to link to other pages as needed. You can then loop through that structure to generate your nav.

Another option is to define all of your top level pages (what might normally be considered singles) within a structure using EntryTypes to differentiate the various page types and define the field requirements (i.e. a structure called 'pages' for example). You can then loop through this structure to generate your nav, using the EntryType to determine which template code to display.

Either of these techniques can be used with other channels and or structures as needed to generate lower level pages where there are many of the same type (i.e. news, blog, articles, projects, etc.).

There are a lot of good examples of this on the exchange site. Also have a look at craft's nav tag in the documentation.


It sounds like you have access to the CP, but not the server.
In order to modify the template files (usually stored in the templates directory, next to the public web folder), you'll need SSH or FTP access to the server itself.
For example, if your site's web root was here:
/home/username/website.com/web

…your templates folder is probably here, out of public view, but still accessible to Craft:
/home/username/website.com/templates

To find the template you need to edit, look in Settings → Sections -> Section Name, under the "Site Settings" heading. This table will show you what template is rendered (relative to the templates directory, above) for each type of content defined in the CP.
Depending on how the site is structured, each page may be assembled from many Twig "includes," so not all the HTML for a page will be present in the primary template!
Craft doesn't provide a template editor as part of the CP, so your only option is to edit or replace the Twig templates that live on-disk.

I strongly recommend heeding the advice you've seen, vis-a-vis working locally. Whenever possible, it's a good idea to keep a local copy of the site's files (checked in to Git or other source control)—that way, if you edit a template on the server and break something, it's easy to undo and copy an old version back.


How can I prevent my client from auto-updating Craft in production?

You can use the config/general.php file to specify whether auto-updating is allowed:

Craft 2

'allowAutoUpdates' => false

  https://docs.craftcms.com/v2/config-settings.html#allowAutoUpdates

Craft 3

'allowUpdates' => false

  https://docs.craftcms.com/api/v3/craft-config-generalconfig.html#property-allowupdates

Combined with a multi-environment configuration, this can be very helpful.

Admittedly, this doesn't prevent the "Updates are available" notification from appearing... There have been some discussions about future versions of Craft possibly adding a separate config setting which will allow you to disable that notification as well.


Figured it out:

use craft\commerce\Plugin as Commerce;

$gatewayService = Commerce::getInstance()->getGateways();
$variables = [
    'gateways' => $gatewayService->getAllGateways(),
];


In Twig, you'll never need to double up on your curly brackets.  I.E.

{{ {{ }} }}

or

{% {{ }} %}

Change this (which is already inside of {% %}:

event_startDateTime: '<= {{ now }}',

To use string concatenation like this:

event_startDateTime: '<= ' ~ now,

And you should be set.


This setup works fine with Craft 3:

Nginx-Craft


Update Craft CMS, now I get HTTP ERROR 500

If the error 500 is displayed by craft, look in craft/storage/logs (i.e. phperrors.log)

Otherwise have a look at the server logfiles, if you have access to them. The Apache (or whatever http server you use) error log might be useful.


That's the beauty of Globals... they can be used anywhere!

Common usage examples include (but not limited to):

Content in your header
Content in your footer
Content in your sidebar
Anything else that appears frequently in your website

It's not a strict rule, but Globals tend to work great in situations where you only need a small amount of content to be commonly repeated throughout your site.


How to change the display order of columns in Entry List view?

You need to reorder the $attributes array to do this. You can do this in various ways, here is how I would do it depending on the position you wanted for the new column:

public function modifyEntryTableAttributes(&$attributes, $source)
{
    if ($source == 'section:3')
    {
        // insert column in first position (using array_merge)
        $attributes = array_merge(array(['id'] => Craft::t('ID'), $attributes);

        // insert column in fourth position (using array_splice)
        array_splice($attributes, 3, 0, array('id' => Craft::t('ID')));
    }
}


Add a button to the entry edit screen via plugin

Not sure if you can put it next to the Share button, but check out the Triggers feature of Button Box...

  https://github.com/supercool/buttonbox

You can create a "Triggers" field, which is just a button that hooks up to JS. Then use the JS to ping your Controller via AJAX.

The button exists as a field, so you could just put that field at the top of your field layout. It's not well documented, but it's really easy to do.


How can I display a message after login?

You can achieve this using a plugin and the UserSessionService.

craft()->on( 'userSession.onLogin', function( Event $event ){
  // Sets the flash message on log in
  craft()->userSession->setFlash( 'message', "You've been logged in" );
});

craft()->on( 'userSession.onLogout', function( Event $event ){
  // Sets the flash message on log out
  craft()->userSession->setFlash( 'message', "You've been logged out" );
});

And then in your template you can see of a flash message exists and print it out.

{% set message = craft.session.getFlash( 'message' ) %}

{% if message %}
  {{ message }}
{% endif %}

The message for the incorrect login details will be handled by Crafts login controller. Take a look at the example front end log in page in the docs to see how this is handled.


What is the best to find a developer to create a Craft plugin?

There are a couple of options, as far as I know:

Straight Up Craft community site
Craft Slack has a jobs channel
Work With Craft


Can you run two different Stripe accounts as two different gateways in Craft Commerce?

Yes you can, and yes it will work.

This text here is to meet the minimum answer length.


Making changes to existing page - how do I make a draft page first?

After Step 3, you can hit Ctrl+S (windows) or Cmd+S (macOS). That will just save that update to the entry as a new draft.

Though Craft 3 brings autosaving, I'd still recommend you to use these shortcuts to save the draft.

When that particular draft gets approved, go back to that draft and hit on the big red Save button at the top-right corner. You should see another Save as a Draft grey button before that bit save button.

Current button drop-down shows the document's version history - as in who worked on that particular entry along with the timestamp.


Display news (from a channel) on the Homepage

Hi Magnus and welcome to Craft.

Your homepage should ideally be a Single. As the Craft site says these are one-off pages that have no special requirements or hierarchy.

You would then create a Channel called News (or Blog, whatever you require) and here you would have entries for each news article on your site.

Once you have everything set up, outputting the latest news article on your homepage is a very simple process:

{% set latestNews = craft.entries.section('news').limit(1) %}

{% if latestNews|length %}

    {% for article in latestNews %}
        <p>{{ article.title }}</p>
    {% endfor %}

{% endif %}

This code would sit in your index.twig template and grabs the 1st entry in the News section. Simple!


Detecting if page is a 'category' or 'entry'

It'd be nice to see an example of your HTML block. From your comments it sounds like you may be using the same HTML block for Entry and Category pages but need to know which variable to use in the code.

Assuming you know that your code is running on the Entry or Category pages, and that the fields across both your Entries and Categories for this part of the page are the same, you can place your common HTML in an include and pass both the entry and category variable to that include with the same variable name.  In the example below, we're handing off the entry and category variables and using the variable name object in the include template:

_entry.html

{% include '_partials/shared-template' with { object : entry } %}

_category.html

{% include '_partials/shared-template' with { object : category } %}

_partials/shared-template

    {{ object.fieldName }}

    {% for item in object.someOtherFieldName %}
      {{ item }}
    {% endfor %}

If some of the field names are different, you may need to use some conditional logic or reconsider what variables are being passed to the included template.  You could pass dissimilar variables under the same variable names to a common template in the following way:

index.html

{% if entry is defined %}
    {% include '_partials/shared-template' with {
        title : entry.title,
        someOtherVariable: entry.fancyFieldOne
    } %}
{% endif %}

{% if category is defined %}
    {% include '_partials/shared-template' with {
        title : category.title,
        someOtherVariable: category.fancyFieldTwo
    } %}
{% endif %}

_partials/shared-template

    {{ title }}

    {% for item in someOtherVariable %}
      {{ item }}
    {% endfor %}


Expire an entry according to a date field

You can set the Expiration Date in the control panel. It is at the bottom of the column on the right (on wide screens), or at the bottom of the page (on narrow screens). I don't think there is any way to set the Expiration Date from the konzertdatum, so you would have to either use the Expiration Date as the concert date, or maintain both of them.


Using a virtual host result in internal error

Looks like the .htaccess file included with Craft is not being read or you didn't rename it (should be .htaccess with the period at the beginning).

That's why /index.php/admin is working but /admin/ is not.

One other possibility is Apache is setup to ignore .htaccess files. If that's the case, add this to your httpd-vhosts.conf file.

<Directory "C:\wamp\www\y-lynx">
    AllowOverride All
</Directory>

(If you already have a <Directory "C:\wamp\www\y-lynx"> block, just add in AllowOverride All somewhere inside.)


So, it looks as though I was overcomplicating things! All it needs to be is this:

{% set exhibitors = craft.entries.section('exhibitors').order('title') %}

{% for exhibitor in exhibitors %}
    {% set room = entry.rooms.relatedTo(exhibitor).first() %}

    {{ room }} <-- No longer a null entry

{% endfor %}


Instead of grabbing all entries in the eventsEntry section, then filtering by the current date/time, you could do the filtering on the database side first, so you're returning only the entries you're interested in.

Something like this:

{% set pastEvents = craft.entries.section('eventsEntry').eventdate('<= ' ~ now|atom) %}

{% for date, entries in pastEvents | group("pastEvents.eventdate|date('Y')") %}

{{ date }}

        {% for event in pastEvents.all() %}

                {{ event.eventdate|date('d/m/y') }}
                {{ event.title }}

        {% endfor %}

{% endfor %}


I'm a little unclear but I think you're looking for:

{% set products = craft.commerce.products.type('productTypeHandle').order('postDate desc') %}


Try rewriting your element query like so...

craft.entries
.section(['etiquette','style','culture'])
.requiredReading(true)
.orderBy('id desc')
.limit(12)
.all()

In Craft you can do queries against fields in this way. The where() isn't necessary for what you're trying to achieve.


How to loop through entries by importance?

Yes, you can use .order with any custom field, an example is below.

craft.entries.section( 'sectionHandle' ).order( 'customFieldHandle' )

For more info see the docs
https://craftcms.com/docs/templating/craft.entries#order


Display related entries across different entry types using tags in different tag groups?

Ok, I believe this does what you want:

{% if entry.tags1 | length %}

    {# get tag names from our current entry #}
    {% set entryTagNames = [] %}
    {% for tag in entry.tags1 %}
        {% set entryTagNames = entryTagNames | merge([tag.name]) %}
    {% endfor %}

    {% if entryTagNames | length %}

        {# get tags from the other tag group with the same names #}
        {% set otherTags = craft.tags({ group: 'group2', name: entryTagNames }) %}

        {# get entries related to these tags #}
        {% set retaledEntries = craft.entries({ section: 'news', relatedTo: otherTags }) %}

        {# output related entries. just debugging that this actually works #}
        {% for relatedEntry in retaledEntries %}
            {{ relatedEntry }}

            {% for relatedEntryTag in relatedEntry.tags2 %}
                - {{ relatedEntryTag.name }}

            {% endfor %}

        {% endfor %}

    {% endif %}

{% endif %}

My first section, which the current entry is in, has a field named tags1, connected to the tag group group1. My second section is named news, has a field named tags2, connected to the tag group group2.

It seems a bit sketchy to rely on tag names, but.


You would need to create a custom route in the Control Panel that matches the same basic routing as your entries. Then in the entry template, you need to add some extra code that pulls disabled entries. Something like below.

{% if entry is not defined %}
    {% set entry = craft.entries.section('whatevs').uri(craft.request.url).status(null).first() %}
    {% if entry is null %}{% redirect '404' %}{% endif %}
{% endif %}


Receiving 'template loader exception' when trying to view asset (image) after upload

I assume this is all in context of the control panel and not the front-end, correct?

If so and I had to guess, it looks like you're missing some Craft files on your box.  Try downloading a fresh copy of Craft from http://buildwithcraft.com and replace your existing craft/app folder with the freshly downloaded one.


Give this a shot...

{% set transform = (asset.thumbnailCrop.value ?: "portrait") ~ "ThumbSmall" %}
{{ asset.url(transform) }}

If asset.thumbnailCrop is a dropdown field (or similar), you'll need to specifically extract the value from it. If no value is found, it'll fall back to using the "portrait" string.


Craft 3 version - How to get entries related to current category only (not children)

These two pages should help you from the Craft 3 docs

https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#relatedto

https://docs.craftcms.com/v3/relations.html


Trimming lastSegment from a URI trims that PLUS the last number of the previous segment

Twig's |trim filter is just a wrapper for PHP's trim() method, which says:

  Strip whitespace (or other characters) from the beginning and end of a string

So in your example, you're telling it to strip all / and 2 from the beginning and end of the given string, which explains the output you're seeing.

I think you'll be better off by installing something like the Twig PCRE plugin, which gives Twig full access to the PHP preg_ regex methods.

Then you'd just do a preg_match to target exactly what you're looking for and replacing it with new values as necessary.


Is there a way to programmatically clean/Redactorize HTML?

The Purify setting for the Rich Text field will run the data through HTMLPurifier, which will do its best to try and remove any malicious code from the data.

I think what you're seeing is Redactor itself cleaning the rogue HTML elements before submitting to POST/Craft.

I think it's probably going to be easier trying to clean your HTML with some custom logic/regex before saving rather than trying to figure out how to spin up Redactor to do the cleaning.


Plugin Development - Template Resources?

No such reference currently exists. Your best bet is to backwards-engineer what you see in the control panel.

Since the makers of Craft do such a great job of "eating their own dog food", they've made sure that most of their CSS classes are fairly generic and reusable. So if you see an element that you want to imitate (ie: a button), just inspect the element, and copy its classes.


I've managed to achieve something which works in the least technical way I can think of. Other solutions might involve migrating data directly within the database, but I figure this is a good starting point.

Let me know how you get on.

Create an RSS feed, ensuring that the data you want to move is populating the feed.

Here's a RSS template from the CraftCMS documentation...

Grab the FeedMe plugin...

Within FeedMe, the Entry Title is required for it to work, so, if the Entry Title is what you need to move to another field, you will need to make sure  it appears more than once within a RSS-item e.g.

        {% for entry in craft.entries.section('location').find() %}
        <item>
            <title>{{ entry.title }}</title>
            <link>{{ entry.title }}</link>
            ...
        </item>
        {% endfor %}

In my test example, I have a Channel called 'Locations' - the Title field contains names of Cities.

I want to migrate these Titles, to a new custom field called 'City name'.

Within FeedMe, create a new Feed, choosing the destination Section and Content Type. Hit the 'Save & Continue' button.
The last screen of FeedMe allows you to 'field match' (assign) the different RSS tag content, to a specific field e.g. 'Link' -> 'City name'. See image below...

In my test, I migrated field contents between two fields within the SAME Section and Content-Type.

Thoughts welcome.


multi environment nginx, how to check $_SERVER['SERVER_NAME']

$_SERVER['SERVER_NAME'] is a global server variable (not a craft variable) and should be available. I don't use nginx, so I can't comment on where the $_SERVER['SERVER_NAME'] comes from exactly — but a quick google search seems to explain things:

  Blockquote
  nginx – $_SERVER['SERVER_NAME'] is the first entry in the server_name directive.

As far as multi-environment config — this is the method which I have adopted, which has proven to be reliable and flexible. (*The only issue that I've encountered is that it doesn't seem to like non-standard ports — if your using port :8888 in a virtual dev environment for example. Perhaps there is a way to add support for non-standard ports as well).

In your main index.php page (adapted from this craft cookbook recipe).

<?php

// Path to your craft/ folder
$craftPath = '../craft';

// Multi-environment Configuration
define('CRAFT_ENVIRONMENT', call_user_func_array(function($a,$b){if(array_key_exists('APP_ENV',$_SERVER)&&in_array($c=$_SERVER['APP_ENV'],array_keys($a))){return $c;}foreach($a as $c=>$d){$e=$_SERVER['SERVER_NAME'];if((is_array($d)&&in_array($e,$d))||$e==$d){return $c;}}return $b;}, array(

    // Environment Definitions
    array(
        'local' => array('myproject.craft.dev'),
        'dev' => array('myproject.mydevsite.com'),
        'stage' => array('stage.myproject.com'),
        'production' => array('myproject.com'),
    ),

    // Default Environment
    'production',

)));

// Do not edit below this line
$path = rtrim($craftPath, '/').'/app/index.php';

if (!is_file($path))
{
    exit('Could not find your craft/ folder. Please ensure that $craftPath is set correctly in '.__FILE__);
}

require_once $path;

And then in your config.php file (adapted from this stack exchange answer by Ben Parizek):

<?php

/**
 * General Configuration
 */

// Ensure our urls have the right scheme
define('URI_SCHEME', ( isset($_SERVER['HTTPS'] ) ) ? "https://" : "http://" );

// The site url (doesn't work well when port numbers are required, i.e. http://site.com:8888)
define('SITE_URL', URI_SCHEME . $_SERVER['SERVER_NAME'] . '/');

// The site basepath
define('BASE_PATH', realpath(CRAFT_BASE_PATH . '/../') . '/');

return array(

    // default config for all environments
    '*' => array(

        // environment variables
        'environmentVariables' => array(
            'baseUrl'  => SITE_URL,
            'basePath' => BASE_PATH . 'html/'
        ),

        // localization settings
        'siteUrl' => array(
            'en-us' => SITE_URL,
        ),

    ),

    // specific environment config

    'local' => array(

        'devMode'    => true,

    ),

    'dev' => array(

        'devMode'    => true,

    ),

    'stage' => array(

        // environment variables
        'environmentVariables' => array(
            'baseUrl'  => SITE_URL,
            'basePath' => BASE_PATH . 'public/'
        ),

    ),

    'production' => array(

        // environment variables
        'environmentVariables' => array(
            'baseUrl'  => SITE_URL,
            'basePath' => BASE_PATH . 'public/'
        ),

    ),

);


Checking if related entries are live in a for loop and setting a variable based on the results

You're looking for the filter filter: https://docs.craftcms.com/v3/dev/filters.html#filter
Specifically something like this (untested):
{% set activeChildren = children|filter(child => child.associatedTerm|length) %}
{% set inactiveChildren = children|filter(child => child.associatedTerm|length == 0) %}

You now have two unique arrays to do with as you please:
{% if activeChildren|length %}

You have active children

{% endif %}

Hi there

Whenever you get the sneaky feeling that a loop is overkill, look to map filter and reduce: these 3 methods are all like loops in disguise, in that they iterate through arrays and return something new based on the logic you supply.


Sprout email notifications - setting the recipient?

Sprout Email allows Craft Object Syntax for the object that is available when an event is triggered, in the same way you would use the Sections Title Format field.

If your form is submitting an Entry the dynamic object being submitted is an EntryModel and all values from that EntryModel will be available to several of your fields in Sprout Email. To access those values you can use one of two syntaxes:

Shorthand Object Syntax

{title} or {customFieldHandle}

Object Syntax

{{ object.title }} or {{ object.customFieldHandle }} - this longer form can also be used in more advanced twig constructs like {% if object.title %}

Both of these syntaxes are comparable to how you would use {{ entry.title }} or {{ entry.customFieldHandle }} in your templates.

This is described with a few more examples on the Dynamic Values page of the docs


Is there any way which does not remove Specific Html tags from the redactor editor using striptags only?

You can simply use striptags filter which removes all HTML tags. But if you want an html tag to be not removed by striptags so you can pass it as argument, then It removes other tags except the ones you pass in.
In other words, if you don’t  want to remove  tag, just use it in this way:
{{entry.content|striptags('<strong>') | raw }}


How do I make use of the order fields In Commerce?

The text that is submitted using your <input> field will display as expected with Your Reference: {{ cart.customerReference }}.

However, I have a feeling that because the page is re-rendered with the inputs value as empty, when the /updateCart action is submitted again the blank value will override and erase the old value.

To solve this use the customerReference stored on the cart in the value attribute of your text <input>.

<input ... value="{{ cart.customerReference|length ?? cart.customerReference }}">


How to create a new Entry model in Craft 3?

Just so there's an answer here. OP was using Craft 2 code in a Craft 3 environment.

The code should be something like this in Craft 3:

$entry = new Entry();
$entry->sectionId = $yourSectionId;
$entry->typeId = $yourEntryTypeId;
$entry->authorId = $yourAuthorId;
$entry->enabled = true;
$entry->title = "Foo";
$entry->setFieldValues([
    'field1' => "Foo",
    'field2' => "Bar",
]);
$success = Craft::$app->elements->saveElement($entry);
if (!$success) {
    Craft::error('Couldn’t save the entry "'.$entry->title.'"', __METHOD__);
}


This solves my problem:

{% for block in entry.transformerProductNavigation %}
{% set chosenCategory = block.transformer.last() %}

      {# set a variable – chosenCategory to the 'last' category ensuring any nested categories are accessible   #}
      {{ chosenCategory.title }}

{% endfor %}

Thanks to this answer: How to fetch only selected child category?.


Can't Backup Database - "Failed with exit code 1" (WAMP Server)

Following up on your last comment:

  So I guess my final question is: how can I either manually create the required file (which is missing) or amend the query?

You can completely override Craft's default backup command by specifying it in the backupCommand config setting.

Craft will attempt to execute whatever is in there when it goes to perform a backup.


Multiple Craft install configuration in subdomains

I also use MAMP. Here's my general process (I've used generic names in this example; but feel free to rename folders, hosts, as needed):

create the folders for your two sites:

/Applications/MAMP/htdocs/domain.craft.dev
 /Applications/MAMP/htdocs/subdomain.domain.craft.dev
Download craft, unzip and copy the public and craft folders to your new folders:

/Applications/MAMP/htdocs/domain.craft.dev/craft
 /Applications/MAMP/htdocs/domain.craft.dev/public
 /Applications/MAMP/htdocs/subdomain.domain.craft.dev/craft
 /Applications/MAMP/htdocs/subdomain.domain.craft.dev/public
Create two new hosts in MAMP, 'domain.craft.dev' and 'subdomain.domain.craft.dev'; set the 'document root' to the respective '/public' folders; start server. (I also have the server set to serve on port 80 instead of the default 8080; which avoids problems with your craft configuration).
Using Sequel Pro (phpMyAdmin), create two new databases. 'craft_domain' and 'craft_domain_subdomain'.
In each of the sites.

Rename 'public/htaccess' to 'public/.htaccess'
Set permissions on the following folders and all contents to 777 (for now; will want this more restrictive on public servers)

craft/app
craft/storage
craft/config (technically only need it on the license.key file)

(optional) delete 'web.config' from 'public' and 'craft' folders (assuming you don't need them)

Open 'craft/config/db.php' and set the database connection details (server, port, user, password, database).
Open 'craft/config/general.php' and set your config settings, if any.
Open 'public/index.php' and confirm that $craftPath = '../craft'
Navigate to your site in the browser (domain.craft.dev) and (subdomain.domain.craft.dev) and follow on screen instructions to continue install.
Have a beer and celebrate. (maybe 2... one for each site?)

(Did I miss anything?)

Advanced. For steps 6, 7 and 8 above, I actually use a slightly different setup. Instead I use this multi-environment configuration method from the craft cookbook site which allows you to define your environments from within your 'index.php' file; combined with Ben Parizek's technique as described in this answer for automatically configuring 'siteUrl' and 'basePath' environment variables. Note: doesn't work well if MAMP is set to serve on port 8080.


How can I add and replace classes in the markdown field?

I would rather recommend to stick to semantic HTML and <ol> elements for your ordered lists. This not only makes showing the numbers easier, it really should be done out of accessibility reasons and it’s good practice in general.

There are a couple of good solutions to modify the way numbers are displayed in ordered lists using CSS, if you are not happy with the way they are shown by default.

I can recommend using display: table-row; for it. Example code: https://stackoverflow.com/a/23947414

And here’s some example code for formatting content: counter(); in pseudo elements: https://craftcms.stackexchange.com/a/1781/125


Is it possible to hide a custom field type plugin from the popup tab when double clicking an entry?

If you're looking for a setting you can apply to the plugin that corresponds to your custom field, it doesn't look like such a setting exists.

Update: I was just made aware of this Craft CP JS plugin in another question. It looks like you could potentially hide your plugin from displaying. It's not as elegant as a first-party solution but it may be worth a shot


How can I break up a product into two page templates?

I think you just need to create a dynamic route to either ignore customise/ in the url or serve up a different template altogether.

See my answer on this ticket for more information. Secondary Template for Structure


I found a solution. In my control panel module javascript, I can do

Craft.cp.on('setJobInfo', function(e){
  console.log(e);
});


Craft sometimes takes several minutes to respond to a request

I have had this same experience many times, but only with certain hosting providers, so I suspect it has something to do with server configuration.  One thing that I noticed was that saving an entry, for example, would hang, but the entry had indeed been saved pretty much immediately.

I know it is not my local setup, because my co worked, who works from a different location, had the same issues at the same time.  Next time it happens I will try accessing via IP.


Missing 'Plugin Store' tab in admin panel

The Plugin Store is a feature introduced in Craft 3, so isn't available in previous versions.

See: Missing Plugin Store Navigation on Craft 3 Admin Section
And: Announcing Craft 3 Blog


How to get an element query into json (for vue) without extra data?

You can use the asArray function to return arrays instead of elements

{% set sections = craft
    .categories
    .group('teamCategory')
    .select(['title','elements.id','groupId'])
    .asArray()
    .all()
%}


What's the difference between CraftSessionId and a normal PHP session?

They are one in the same.

Craft simply renames it to "CraftSessionId" rather than the default "PHPSESSIONID".

The only additional things we do to it is set the "httpOnly" flag so that JavaScript can't read it and change the place it is saved to by default (varies per server) to craft/storage/runtime/sessions.

You can see that in action in HttpSessionService, which extends Yii's CHttpSession, which is a convenient wrapper for PHP's session functionality.


How to list an entries selected nested categories?

The final solution I got to work:

{% set cats = entry.categories %}
{% for cat in cats %}
    {% if cat.slug == 'secondlevel1' or cat.slug == 'secondlevel2' %}
        {% set catChildren = cats.descendantOf(cat.id).descendantDist('1') %}
        {% if catChildren | length %}
            {% for childCat in catChildren %}
                {% set image = childCat.buildingBlockIcon.first() %}
                    {% if image %}
                        <img alt="{{ childCat.title }}" src="{{ image.url }}" />
                    {% endif %}
            {% endfor %}
        {% endif %}
    {% endif %}
{% endfor %}


How to add a conditional elements into the title of a page?

I suggested an edit to Jamies suggestion (hope that's okay - don't know all the rules yet).
Here's the suggestion

{% set title = (entry.artistFirstName) ? [entry.artistFirstName, ' ', entry.title]|join : entry.title %}
{{ title | capitalize }}

Here i'm joining the two variables if entry.artistFirstName exists, by first putting all the parts into an array, and then using the join filter to glue them together. I like this approach, because it's easy to add many parts without having to put ~ ' ' ~ for every space you need.

In general, if you want to glue strings like this together, you use the ~ operator, like this:

{{ 'string1' ~ 'string2' ~ 'string3' }} -> {{ string1string2string3 }}

An alternative approach to the one I suggest above is therefore like so:

{% set title = (entry.artistFirstName) ? entry.artistFirstName ~ ' ' ~ entry.title : entry.title %}

This is just as fine, but the first approach might be nicer if you have more parts.

A third way is this, which might be just as nice/clean, but maybe slightly less readable?

{% set title = (entry.artistFirstName) ? '%s - %s'|format(entry.artistFirstName, entry.title) : entry.title %}


Trying to style Printmaker Plugin PDF by linking css in head of PDF template

You can link to the CSS in this way, but if it's not working for you then try changing the path to

<link href="./pdf.css" rel="stylesheet" type="text/css">

assuming that your CSS is in the site root.


Sprout Forms - Notification Based on Checkbox Value

You're on the right track.

The first thing to note is that the Send Rule field does support shorthand syntax like in your question, however, if you are using compound logic, you will want to use the full object syntax for that logic.

So, instead of (with no reference to object. and single curly braces):

{ checkBoxFieldHandle == 'value' }

You'll want to use the full object syntax to get the expression to evaluate:

{{ object.checkBoxFieldHandle == 'value' }}

The next thing to note is that the checkbox field is a multi-select input, meaning more than one value can be selected. This could be present additional logic challenges for what you are trying to do but assuming you have a checkboxes field with a single checkbox or an opt-in field the logic is more predictable.

Checkboxes are submitted as arrays, so you'll need to make sure you are targeting the correct node in the array. In the case of a single checkbox, we know the first checkbox will be index 0 in the array. Once we have the target checkbox, we can see if it's selected by checking the selected attribute:

{{ object.checkboxFieldHandle.getOptions()[0].selected == true }}

And we can update the same statement to check for false if we want to only send if the checkbox is unchecked:

{{ object.checkboxFieldHandle.getOptions()[0].selected == false }}


Stripe checkout, card declined but no frontend error

As usual it is just me being stupid.
The error is accessible with:

{% set error = craft.session.getFlash('error') %}
{{ error }}

Maybe it will help some other people.


Sorting entries A-Z, ignoring 'The' and grouping by first letter

That SQL code snippet Brad posted only works with the order parameter.
The group filter doesn't allow SQL, but you could try to replicate the logic using Twig's ternary operator.

{% set artists = craft.entries.section('lineup').order('(CASE WHEN field_sortTitle IS NULL OR field_sortTitle = "" THEN title ELSE field_sortTitle END)') %}
{% set artistsGrouped = artists|group('{ object.sortTitle ? object.sortTitle[:1]|upper : object.title[:1]|upper }') %}

{% for letter, artistsInGroup in artistsGrouped %}
    {{ letter }}
    {% for artist in artistsInGroup %}
        {{ artist.title }}
    {% endfor %}
{% endfor %}

To shorten the expression a bit I used the slice filter's short syntax [:1] instead of |slice(0, 1).


You have to insert your matrix field into the rated to param like here

{% set entries = craft.entries.section('subShops').relatedTo({
    targetElement: sandwich,
    field: 'sandwichBuilder.breads'
}) %}


Solspace Freeform - Change "submit" button to "next"

If you click on the button that you are adding while making the form, it allows you to change the text to whatever you want it to say. Is that not what you are wanting to do?


Turn devMode on https://craftcms.com/support/dev-mode

If you want the errors to log regardless of devMode or not, pass in true as the third parameter, e.g.:

Craft::log("There was an error", LogLevel::Info, true);

https://straightupcraft.com/articles/how-do-i-log-errors-warnings-and-info-in-my-plugins-to-a-craft-log-file


Is it possible to always show Assets folders as opened?

From what I know this isn't possible in Craft2 (it's a known issue). P&T has probably addressed this in Craft3 with the many updates to Assets in that release.


Do you have multiple language set? If yes, check that you're selecting the right language on the entries drop-down.


Multi Country website - Using locales is the best approach?

Yes you can do this by going to the craft/app/framework/i18n/data folder and copying the language file for each occurrence.  You must give each a unique name es_pn, es_co, es_nc.  Inside each of those files you must add each of those names along with the long form name.

languages => array(
'es_pn' => 'Panama',
'es_co' => 'Costarica',
'en_nc' => 'Nicaragua',

From here you would select each of those locales from the CP and setup the rest of your site as you would for multiple locales, using your custom ones. Updates have currently never broken this.  We have been using this method for several clients, it works well.


Try using ElementsService:

$entry = craft()->elements->getElementByUri( 'blog/article1' );


Displaying images from a matrix field from a related field

Relationship field is defined like:

{% for relatedItem in entry.relatedItemField %}
  {{ relatedItem.someField }} {{ relatedItem.someOtherField }}
{% endfor %}

So maybe:

{% if entry.associatedGallery | length %}
    {% for theGallery in entry.associatedGallery %}
        {% for matrixBlock in theGallery.albumImages %}
            {% if matrixBlock.imageFile | length %}
                {% for asset in matrixBlock.imageFile.first() %}

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


In Craft 3 you can use getRawSql() at the end of the element query.

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

{{ entries }}


Difference between categories and structures

Great question. Categories are used to organize a variety of content including entries, assets, even other categories. Categories themselves do not have content (besides maybe a description and key image), but can be related to content. They are a great way to group related entries together and provide a semantic structure (little s) to your content.

Structures (big S) are entries. They are content. The biggest difference between Structure entries and Channel entries is that Structure entries can have children, parent, and sibling entries. Additionally, Structure entries should not be "date driven" like Channel entries would be (blogs, for example, are date driven).

If your content needs to be segmented by cities, and is in some way date sensitive, I would recommend setting up city Categories and have a Channel for your entries. Fortunately, Categories can also have parent, children, and siblings, so if you needed to organize your cities by state, you could accomplish that easily with Categories. This is why the category fieldtype does not let you reorder them.

For quick reference, check out the documentation on section types and categories.


I'm by no means a Varnish pro, but I'm currently working on a project where we're running Varnish 4.0 in front of our nginx servers. I've uploaded an example of our VCL 4.0 file in this gist. It is based on the Varnish 4.0 template made by Mattias Geniar with some adjustments for Craft.

It is NOT an exact port of the 3.x file you're referencing, so it's important to understand what it does.

First of all, the 3.x file sets the ttl of cacheable requests in the VCL. Not sure if this is because it's harder to set the correct headers in ExpressionEngine, but I prefer to leave this to the backend server. If you don't set expire headers in your templates your pages won't be cached. To set a page to expire in 7 days you add this to your template:

{% set expiry = now|date_modify('+7 days') %}
{% header "Cache-Control: max-age=" ~ (expiry.timestamp - now.timestamp) %}
{% header "Pragma: cache" %}
{% header "Expires: " ~ expiry.rfc1123() %}

You can add all kinds of logic to this, setting different cache duration based on entry section, entry age, custom fields, or whatever.

In the 3.0 example file, all asset folders (like /scripts, /assets/, /files, etc) are excluded from caching. This is probably a good idea in most cases, see the comments from the original 4.0 template regarding this. But, in my project all content files are uploaded to Amazon S3, so the only assets served by nginx is css, js, font files, and some small assets. I've opted to just let Varnish handle everything for now.

I'm taking a heavy handed approach to cookies, because I don't need them, and I had some problems removing the Craft ones. I've left in some of the original stuff from the template, mostly for reference.

All requests to the Craft admin is passed on to the backend server. I had some issues with just excluding /admin, because the control panel sometimes add index.php to the url, so I'm excluding everything that contains /admin or p=admin.

All in all, this might not be a perfect VCL file, but it seems to work fine. Running Varnish on a DigitalOcean 1GB/1CPU droplet, I've cut the response time on my test page from ~1.5s (unoptimized/uncached template with a lot of matrix going on) to 40ms. Static tests with ApacheBench within the local network shows Varnish delivering ~900 requests/sec. Pretty awesome, me thinks.

But comments and fixes are greatly appreciated. :)

I'm also working on a Craft plugin for purging URLs when entries are changed, but it's not working very well at the moment.

UPDATE:
My Varnish Purge plugin is now available here. Also, check out Josh Angell's CacheMonster plugin here for a different take on the same problem.


To get the pagination to work as expected, you need to incorporate the if into your craft.entries query. There may be a more elegant solution to do this, but looking at the database, the selected choices is saved as an array-like string:

["blue","red"]

This means that you can search for the value in the field like this:

craft.entries.section('eventRentals').rentalColor('*"red"*').relatedTo(category).limit(12).order('title')


Installing Craft without installer screens

Would this be something? Craft CLI Installer


Yes, the example templates are designed to be used inside a subdirectory like /shop. This does not stop you from putting the example templates anywhere else (like the root template directory), but links inside the example template referencing /shop would need to be updated.


How to override UserController.actionLogin or the login form template in Craft 3?

Alright so I was actually misunderstanding how modules work with craft and yii. The init function in your module actually fires before crafts core controllers do, so you could use that to do whatever you need to do before the request continues on. I'm coming from WordPress so I thought I had to 'hook' into something. Here's an example of how you would override the login action on a post request. In the real world you would probably want to extract this logic to a Service but for the sake of clarity I'm just putting it in the init function here.

So, I guess the way to override any core controller is to look for that url or action in your modules init function and do whatever you need to do to override it.

namespace ldap;

use Craft;
use craft\elements\User;

class LdapModule extends \yii\base\Module
{
    public function init()
    {
        Craft::setAlias('@ldap', __DIR__);

        if (Craft::$app->getRequest()->getIsConsoleRequest()) {
            $this->controllerNamespace = 'ldap\\console\\controllers';
        } else {
            $this->controllerNamespace = 'ldap\\controllers';
        }

        parent::init();

        $isActionRequest = Craft::$app->getRequest()->getIsActionRequest();
        $isLoginAttempt = Craft::$app->getRequest()->getFullPath() === 'admin/actions/users/login';
        $isPostRequest = Craft::$app->getRequest()->getIsPost();

        if ($isLoginAttempt && $isPostRequest && $isActionRequest) {
            //...Ldap functionality and creating/activating new user if need be goes here. The request
            // will then continue on to crafts core UserController to log them in.

            // As an aside, if you want to create a user programmatically to login
            // here's more or less how to do it.
            // @reference craft\controllers\UsersController.actionSaveUser
            $user = new User();
            $user->email = 'wolf@inyourface.com';
            $user->username = 'wolf';
            $user->firstName = 'Wolf';
            $user->lastName = 'Face';
            $user->pending = true;
            $user->newPassword = 'secret';
            if ($user->validate(null, false)) {
                Craft::$app->getElements()->saveElement($user, false);
                Craft::$app->getUsers()->activateUser($user);
                Craft::$app->getUserPermissions()->saveUserPermissions($user->id, ['accessCp']);
            }
        }
    }
}


This was an error in a module I have built for this site. Going through the docs and some tutorials again fixed it.


Get entry by slug with EntriesService in ElementAPI

Don't know if this is the most efficient way, but you can always get the category using the ElementsService.

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->group = 'categoryGroup';
$criteria->slug = 'categorySlug';
$categories = $criteria->find();

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'section';
$criteria->relatedTo = array(
    'targetElement' => $categories,
    'field'         => 'relationField'
);
$entries = $criteria->find();


Freeform - using multiple fields on the same form

No there isn't. In the same way as Craft, each field has a unique handle which is used both for templating and for email notifications.

Solspace support might have some other ideas, but I think this is just the way Freeform is built.


How do I output the value of a field from a Category selected from a Matrix?

Without knowing what your field handles are, this is the gist of how you’d do it:

{#
   Loop through each block within your Matrix field,
   assigning them to a `block` variable:
#}

{% for block in entry.myMatrixField %}

    {#
       Loop through each category within this Matrix block,
       assigning them to a `category` variable:
    #}

    {% for category in block.myCategoriesField %}

        {#
           Output the plain text field value:
        #}

        <p>{{ category.myPlainTextField }}</p>

    {% endfor %}

{% endfor %}