How would I include the first category slug in the section's entry URL format?

This got it working for me:

/section/{categoryFieldName.first.slug}/{slug}


You'll need to register your variable in your plugin's init() method, like this:

Event::on(
    CraftVariable::class,
    CraftVariable::EVENT_INIT,
    function (Event $event) {
        /** @var CraftVariable $variable */
        $variable = $event->sender;
        $variable->set('pluginname', PluginVariable::class);
    }
);

c.f.: https://docs.craftcms.com/v3/extend/extending-twig.html


Save the form if not complete and come back another time to complete the form

The FormBuilder plugin has no option to edit a submitted form. I think the best way is to use a channel in Craft CMS and write your own form. You can find the documentation on how to create/edit entries in frontend here: https://craftcms.com/docs/templating/entry-form.


Dealing with listing multiple categories

I don't think I quite follow you, so forgive me if I'm way off. I have created (what I think) is something similar to what you are looking for. This is how I did it - maybe it will help...

Let's say I have the following url:

http://www.mystore.com/toys/my-awesome-toy

twig

{% set cat = craft.categories.slug(craft.request.getSegment(2)).first() %} {# Toys #}

{% for toys in craft.categories.group('toys').descendantOf(cat).level(2) %}
    {% if toys.getDescendants().total() != 0 %}
        {% for subToys in craft.categories.group('toys').descendantOf(toys.id).level(3) %}
            ...
        {% endfor %}
    {% endif %}
{% endfor %}


Can't get correct template for ajax call

It looks like a custom route has been set up for /updates/q which points to the updates/index.html template.

There are two places this could have been configured:

Dynamic routes set up in the control panel, or
Advanced routing set up in the routes.php file.

Look in both of those places to see if a custom route has been set up for /updates/q. If so, you will need to set up a similar one for /blog/q so that Craft knows which template to render for those requests.

Craft's routing docs are a good place to start to understand how all of this works.


From looking at your plugin's composer.json file, I think you've got the package name wrong – instead of

composer require kgrote/siteutilities

you'll probably want

composer require kgrote/site-utilities

I.e. the plugin folder's name doesn't matter – it's the name entry in your plugin's composer.json file that determines the package name.


Getting Template Errors When Using Cache Tag in some environments but not in others

So you're accessing craft.config.cache but unless you've actually added your own cache config setting in craft/config/general.php that's not going to work. There's no cache setting in Craft's Config Settings

So the reason it works on live production is it's a soft error, and you have devMode off, so it continues to work. In local dev, presumably you have devMode on, so it rightly errors.

For more information on Craft cache tags, you can read the The Craft {% cache %} Tag In-Depth article.


Undefined index error in trying to duplicate file

It's because of #2 here: https://docs.craftcms.com/v3/routing.html#dynamic-routes

index.html matches a route (likely you've got a Single section defined in Settings setup to load the index.html template).  Because of that, Craft will prepopulate the entry variable for that route in the template.

There currently isn't a route that matches preview/index.html, so Craft doesn't prepopulate the entry variable and you get the error you're seeing.


$event->isNew not working as expected after Craft 3.2 update

We just released Craft 3.2.5 which should fix this for you.

For more context about why this happened in the first place, see https://github.com/craftcms/cms/issues/4589.


In yii2 every instance of a module is stored in a public static property of the main class.

If the plugin is called image you can grab it via

Imager::getInstance()

This instance contains all the required components. The imager plugin it has 3 components

$this->setComponents([
    'imager' => ImagerService::class,
    'placeholder' => PlaceholderService::class,
    'color' => ImagerColorService::class,
]);

You can access those via Imager::getInstance()->imager or placeholder or color in this case the instance of the plugin is also stored in a static $plugin variable. You can call

Imager::$plugin->imager

as well. You can see a working example here

use aelvan\imager\Imager as Plugin;
....
return Plugin::$plugin->imager->isAnimated($asset);

This is the function that is being called when you do craft.imager.transform -> the PHP equivalent what you want to do


You could use the diff method to get the number of days between two dates. So for example:

{{ date(entry.dateCreated|date('c')).diff(now).days }} days ago

In my example between today (using now) and the entry.dateCreated.

There is a explanation as to why you need to wrap the first date in the date filter here, which is where I got the answer from!


When the System Status is set to "off", Craft will return a HTTP 503 response, which will then automatically trigger the "503.html" template in craft/app/templates to load, which is what you're seeing by default.

But if you put your own "503.html" in your craft/templates folder, Craft will load that one instead.  Same goes for the other HTTP status codes (400, 403, 404, 500, etc.).


What Might Be Causing This Serialization Error?

Update the Notifications plugin.

From Craft Support:

  Ultimately Yii/Craft is using PHP's serialize() method to do the
  serialization, which has always had quirks with serializing different
  types of objects, especially the more complex those objects are.

  We try to only serialize simple objects and primitive data structures
  (arrays, strings, bools, etc.) to try and minimize those issues as
  much as possible.

From The Developer:

  Notifications are no longer queued as this causes a lot of issues with
  serialization. Will find a better solution for this in the future.

Prior to version 1.1.0, the Notifications plugin was attempted to serialize the entire entry to place it in queue.


100% untested and I haven't had coffee yet, but I think it'd be a combination of a few things.

1) Having your plugin override BaseSavableComponentType's getSettingsModel() so that it returned a MyPluginSettingsModel().

2) Have MyPluginSettingsModel override the rules method to do something like:

public function rules()
{
    $rules = parent::rules();

    $rules[] = array('myStartDate, myEndDate', 'required');

    return $rules;
}


I think you are referring to the System Email Address under "Settings" -> "E-mail" -> "System Email Address".


Assuming you're running Craft CMS 3, the Connect plugin will let you connect to MSSQL databases (local or remote)

You'll just need to do:

composer require yiisoft/yii2-mssql

...on your Craft CMS project. To be clear, this doesn't add support for MSSQL to Craft itself, it just lets you query MSSQL databases in your Twig templates.


You could add a check at the top of all of your templates that tests if the first uri segment matches one the agent names.

{% set firstSegment = craft.request.firstSegment %}
{% set agents = craft.users.group('agents') %}
{% for agent in agents %}
    {% set agentName = agent.firstName ~ "-" ~ agent.lastName %}
    {% if firstSegment == agentName %}
        {% set requestedAgent = agent %}
    {% endif %}
{% endfor %}

{% if requestedAgent is defined %}
    {% include 'users/_profile' with { user: requestedAgent } only %}
{% else %}
    {% extend 'layouts/_main' %}

    ... normal page template goes here

{% endif %}

In your profile template you should now have a variable 'user' available with the requested agent.

{% block content %}

{% user.firstName %} {% user.lastName %}

...

{% endblock %}


Using Dynamic values in the Reply To field in Sprout Forms Notifications

Ran into the same issue, asked the support team, and they confirmed it's a bug.

Workaround is to comment out this line:
https://github.com/barrelstrength/craft-sprout-base/blob/v2/src/app/email/elements/NotificationEmail.php#L481

Tried it and it works fine.

They said it would be fixed in an upcoming release.


Is there a way a plugin can watch for live preview updates?

You will probably have to use javascript. Something like this would work.

$('.lp-iframe').on('load', function(event) {
  console.log(event);
});

edit

Try this to bind the lp-iframe after it gets added to the page.

$('.livepreviewbtn').on('click', bindIframe);

function bindIframe() {
  $('.livepreviewbtn').off('click', bindIframe);
  $('.lp-iframe').on('load', function(event) {
    console.log(event);
  });
}


Parse variables into twig email template from custom module

You can define your module's template root with the following:

Event::on(View::class, View::EVENT_REGISTER_CP_TEMPLATE_ROOTS, function (craft\events\RegisterTemplateRootsEvent $e) {
    if (is_dir($baseDir = $this->getBasePath() . DIRECTORY_SEPARATOR . 'templates')) {
        $e->roots[$this->id] = $baseDir;
    }
});

You then compose emails like so:

$first = "john";
$last = "doe";
$params = ['first' => $first, 'last' => $last];
$mailTo = "john@example.co.uk";

$mailer = Craft::$app->getMailer();
$mailer->compose()
        ->setTo($mailTo)
        ->setSubject('Failed Payment')
        ->setHtmlBody(
            Craft::$app->getView()->renderTemplate('module-id/emails/failed_payment.twig',
            ['user' => $params])
        )
        ->send();

Replace module-id with your module id as defined in your config/app.php (business-module for you I guess?).

With this in place, you can access the variables in your template by doing:

<p>
    Hi, sorry it didn't work out {{ user.first }} {{ user.last }}
</p>


Triggering mailshot when new entry published - solutions?

If you can't find an existing plugin that has the functionality, you'll have the roll a custom one.

But knowing when an entry goes from pending to live is a problem in and of itself.

Assuming you got that sorted, the plugin would have to integrate with Campaign Monitor API and send your email out to your list when the event happens.


Is it possible to include category slugs in the entry URL format?

Assuming you want the first category that's selected in the field, you'd set your "Entry URL Format" setting to:

{categoryFieldHandle.first().slug}

You can access any of your custom fields by their handle in a similar way.


You can have entry type specific templates for your entry pages, see this docs article on how you can do this. And for your archive pages, just set a route for each of them and point it to the corresponding index/listings template.

So basically you end up with something like this for your entries:

media/_entry.html (example.com/2014/01/01/example-entry)
media/_types/audio.html (included in _entry.html if entry type is audio)
media/_types/video.html (included in _entry.html if entry type is video)
...

and this for your archive pages:

media/index.html (example.com/2014/01/01/ etc.)
media/audio/index.html (example.com/audio/)
media/video/index.html (example.com/video/)
...

If you don't want to set new routes for the entry type specific archive pages you can also put the templates in a folder whose index.html template file is called automatically if no route exists (eg. audio/index.html for example.com/audio/).

Additionally I'd make good use of include and extend in these templates to make this as DRY and easy to maintain as possible.


You would do that using an ElementCriteriaModel:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'mySectionHandle';
$criteria->limit = null;

$entries = $criteria->find();

You can read all about how to work with ElementCriteriaModel’s in the Working with Elements guide in the Craft docs.


PHP Error - Cannot modify header information - headers already sent

That error means that something is being output to the browser before it's supposed to be.  In this case, it's cookie information (or more specifically, the removal of a cookie by adding one with the same name, no value and an expired date).

The question is, what's calling removeCookie?  If you enable devMode, then the error should present with a stack trace where you can follow the programs execution to see what's leading up to that call.  My guess is something in the Import plugin (or maybe another plugin) is the culprit.


Every model has a validate() function

// set the scenario to live
$entry->setScenario(Element::SCENARIO_LIVE);

// validate the model
$entry->validate();

// get the errors,
$errors = $entry->getErrors();


How to get a product variant by SKU and get parent product details as well?

Untested, but something like this should work:

{% set products = craft.commerce.products({
  hasVariant: {sku: 'my-sku-number'}
}).first() %}

See: https://craftcommerce.com/docs/craft-commerce-products#hasvariant

If you only want to search the default variant of the product:

{% set products = craft.commerce.products({defaultSku : 'my-sku-number'}).first() %}

See: https://craftcommerce.com/docs/craft-commerce-products#defaultsku


Custom Field Settings: Unknown Property Error

The name of your select is regionType thus it will try to store the property regionType in your field. When you call the field value it will set the property value in you class.

You either need to include the property or change it to an existing one.


Login redirects to home page after 2.2 update

As Brad said the new default behavior is for users to be redirected wherever postLoginRedirect is set to (if a redirect param was not in the POST data).

You can get your old behavior back by adding that hidden redirect param though, set to craft.request.getPath():

<input type="hidden" name="redirect" value="{{ craft.request.path }}">


Probably too late for you, OP, but the Entries Subset plugin for Craft 3 lets you do this and more.


I have found the solution within the answered question:
omitScriptNameInUrls is not working

'sudo a2enmod rewrite' was needed!

Thanks all.


In my experience this has been problematic - instead have looped through locales to fetch entries then merged and sorted with supersort.

Eg:

{% set locales = craft.i18n.getSiteLocales %}

{% set pages = [] %}

{% for locale in locales %}
    {% set entries = craft.entries.locale(locale.id).localeEnabled(false).find() %}
    {% set pages = pages|merge(entries) %}
{% endfor %}

{% set pages = pages|supersort('rsortAs', "{ postDate|date('Ymd') }") %}

Then loop through pages as you would your entries. Am sure there is a more elegant way of doing this but this is what we had to do for our site.


The license located at config/license.key belongs to X

Go into Utilities > Caches > Clear Caches. I can't remember exactly which cache, but try all of them (maybe untick the asset transforms ones so you don't unnecessarily regenerate transformed assets).


Migration of Craft CMS from one host to another

You need a copy of the database which you can either export via Craft's Control Panel or via phpMyAdmin or a similar database management tool.
You need these folders:

craft/templates
craft/translations (if it's multi-language)
craft/plugins
craft/config
public

They might be called differently, I am writing this as if the previous developer followed the installation instructions.

Upload a fresh copy of Craft to the new server.

Import the database.

Replace the stock folders with the ones you got from the other install.

Make sure db-credentials are correct in craft/config/db.php. Make sure all paths are correct in craft/config/general.php.

Make sure the folders that need to be writeable are writeable.

Generally speaking your site should be running now.


Is there a way to calculate the dominant color from an asset available in Craft?

Apparently there's a pretty good plugin that does the trick:
"Image Color" by Keith Mancuso
https://github.com/familiar-studio/Craft-Image-Color


Can the Freeform Plugin be used with headless mode in Craft?

Broadly speaking, any Form plugin that implements Forms using Elements can probably be used headlessly using Craft's Element API plugin.

I'll give an example using the Sprout Forms plugin.

Install the Element API plugin
Add a config/element-api.php file to your project's config folder
Build your API

The following example creates two endpoints.

The first returns a Form Element that can be used by your front-end framework to output the form. You can use the Default Form Templates as an example of how the HTML needs to be built for submission and remember to submit the form using a CSRF token. This example returns the field data and the field folder name which can be used as a unique identifier when determining which field template to display on the front-end.

The second returns a list of unread Form Entry Elements. You can customize the query however you'd like, just like any Element Query.

<?php

use barrelstrength\sproutforms\elements\Form;
use barrelstrength\sproutforms\elements\Entry;

return [
    'endpoints' => [
        'api/sproutforms/<formId:\d+>.json' => function($formId) {
            return [
                'elementType' => Form::class,
                'criteria' => ['id' => $formId],
                'one' => true,
                'transformer' => function(Form $form) {
                    foreach ($form->getFieldLayout()->getTabs() as $tab) {
                        foreach ($tab->getFields() as $field) {
                            $fields[] = [
                                'field' => $field,
                                'folder' => $field->getFieldInputFolder()
                            ];
                        }

                        $tabs[] = [
                            'title' => $tab->name,
                            'fields' => $fields
                        ];
                    }

                    return [
                        'handle' => $form->handle,
                        'tabs' => $tabs
                    ];
                },
            ];
        },
        'api/sproutforms/<formId:\d+>/entries.json' => function($formId) {
            return [
                'elementType' => Entry::class,
                'criteria' => [
                    'formId' => $formId,
                    'status' => 'unread'
                ],
                'paginate' => true,
                'transformer' => function(Entry $entry) {
                    return [
                        'id' => $entry->id,
                        'dateCreated' => $entry->dateCreated,
                        'title' => $entry->title,
                        'customField' => $entry->customField,
                    ];
                },
            ];
        }
    ]
];


How to display success message using the Contact Form plugin

You can see in the code for the plugin on GitHub that it sets a 'notice':

craft()->userSession->setNotice($settings->successFlashMessage);

As the official documentation mentions, this can later be grabbed with the following code:

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

Then used as a normal message thereafter.

{{ message }}


Advanced routing descriptive URLs to certain pages/posts

So from an SEO perspective, the first URL is actually better, in that it provides even more context for the search engines to digest, index, and understand.

It's also bad from an SEO perspective to have two pages that have the same content.  As long as you include a canonical URL it won't really hurt you, but the only real benefit I see from using your second URL schema is that it's easier to type.  Which isn't really much of a concern these days imo.


Help developing point system for sports league (w/o plugins)

Without wanting to go into any PHP or plugin development, your best bet is to set a 24 hour cache on your chunk of processing code. As you suggested, it is probably smart to not have the cache clear itself when an entry is saved. To accomplish this, just set cacheElementQueries to false in your general config file.


I think you're looking for entry types - when you open a new 'services' entry you could pick from "service" or "service-information" entry types. Each entry type has it's own field layouts.

This would mean your URLs can follow the same structure without writing new routes etc.


How to debug or log some special variables in Craft CMS? (Especially in a controller)

You could use for example the dd() method with the craft3-dumper package.
You can also use the debug toolbar.
You could also use Sentry to get a nice overview about your errors with the craft sentry package.
Or you could use xdebug. Or or or ... :)

So there are severals ways to debug something.


With good help from @carlcs here and on Slack, we found a solution:

{% set allEntryIds = craft.entries.limit(null).ids() %}

{% set usedAssets = craft.assets({
    relatedTo: allEntryIds,
    limit: null,
}).ids() %}
{% set unusedAssets = craft.assets({
    id: 'and, not ' ~ usedAssets|join(', not '),
    limit: null
}) %}


How to query/filter by the value of a lightswitch

true/false are booleans, not strings, so you shouldn't surround them in quotes:

{% set pinnedNews = craft.entries().section('news').pinned(true).all() %}
{% set unpinnedNews = craft.entries().section('news').pinned(false).all() %}


Go to https://pluginfactory.io/ to generate a boilerplate Craft plugin.

API Version: Craft CMS version 2.5.x
PluginName: Twig Session
Description: Anything
Version: 1.0.0
Plugin Author: Anything
Author URL: Anything
Github Name: Blank
Uncheck: Tweet it out
Check: Variables
Click: Build Plugin

Download twigsession.zip and unzip it. Place the unzipped twigsession folder in your craft/plugins folder.  Open craft/plugins/twigsession/variables/TwigSessionVariable.php and change:

public function exampleVariable($optional = null)
{
    return "And away we go to the Twig template...";
}

To:

public function add($key, $value)
{
    craft()->httpSession->add($key, $value)
}

And add a new:

public function get($key)
{
    return craft()->httpSession->get($key)
}

Go to Settings->Plugins in the control panel. Install the "Twig Session" plugin.

From your front end templates, you can now use craft.twigSession.add('foo', 'bar') and craft.twigSession.get('foo').


How do I stop an element from populating?

I am not really clear on what you are trying to do. My guess is you are trying to add your own validation to saving an element and trying to block that with your own custom checking of content values etc?

I don't think listening to the event will help as you cannot send a message to say this element is not valid from an event listener - the event does pass you a element that is about to be saved but you cant return the modified element from the listener.

What I would suggest is building a custom fieldType that contains some validation rules that peeks in at the content of other fields.

class My_CustomFieldType extends BaseFieldType
{

/**
 All the normal filetype stuff like name etc here.
*/

public function validate($value)
{
  $errors = parent::validate($value);

  if (!is_array($errors))
  {
    $errors = array();
  }

  // DO you logic here to test then set an $variable to true or false
  // if your conditions are met then add to the $errors array below if there is a problem.
  // if you want to access other field in this element do this:
  //
  //   $owner     = $this->element;
  //   $fieldData = $owner->getContent()->getAttribute(array('sectionId'));
  //

  if ($variable){
    $errors[] = Craft::t('You are not allowed to edit this element.');
  }

  if ($errors)
  {
    return $errors;
  }
  else
  {
    return true;
  }
}

}

Im thinking that this will be able to stop the entry being saved. Hopefully thats what you were looking for.


The following code should work for you:

 {% if entry.isEditable() %}
    Edit entry
 {% endif %}


The problem was that Frankfurt and London are not currently supported S3 bucket locations in Craft CMS v2.6.2956. Switching to Ireland solved my issue.


It's probably your second-from-last line:

{% endfor % }

should be:

{% endfor %}


If you are looking for "drag and drop" I would use matrix blocks. You can define text block, image block, video block, etc that would be available in Elementor.

Maybe you don't get as much out of the box as a plugin, but you are able to define exactly what is available to the client.

Happy coding :)


Remove the single quotes around wideCrop.

<img class="full" src="{{ image.getUrl(wideCrop) }}">

Details for why the difference in "template defined" transforms here:


How do I prevent a controller from creating unwanted routes?

After too much time spent on this, I think I found a solution to both issues.

1) To prevent controller actions meant for the CP from being accessible on the front-end (via actions/<module>/<controller>/<action> URLs), simply add this line of code at the top of the action's method:

$this->requireCpRequest();

The non-CP action URLs will now return a 400 error.

2) Although it doesn't seem possible to change the private template trigger on the CP to prevent any template from being directly accessed with a URL, using an underscore at the beginning of any file or folder in the path works. But even better -- the template root itself can be private:

// Set the base CP template directory
Event::on(
    View::class,
    View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
    function(craft\events\RegisterTemplateRootsEvent $event) {
        $event->roots['_module'] = $this->getBasePath() . DIRECTORY_SEPARATOR . 'templates';
    }
);

Notice the underscore in front of _module. This ensures that the module's templates will only render programmatically.


I think you want to have the same result as with an ElementCriteriaModel, instead of getting an ElementCriteriaModel.

What you want to do is mimic craft()->elements->findElements(), and put your own $query in it. This will more or less put the results in their models. You can just copy this function and replace the second line (where $query is defined) with your logics.

You could also do something like Conference_SessionModel::populateModels($queryResult), but by the way Craft joins the content table in findElements this would be rather slow, as it would make a new query for every content field.

What would be really nice is if you could specify $query in findElements, too bad Craft doesn't support this (yet?)


Checked "Require a password reset on next login" on my account, can't log in anymore

On your local installation if your check the "Password Reset Required" button for a user and you get a 500 Internal Server Error the next time that users logs in, there is about a 99% chance that email isn't configured/installed correctly on your server.

You can verify this by checking the craft/storage/runtime/logs files for the underlying error message.

Craft's email settings are managed under Settings->Email in the control panel.

When you tested on http://demo.buildwithcraft.com and saw the same behavior, that's because we specifically disabled all email functionality on the demo sites in order to prevent them from turning into SPAM relays.


There aren't any filters built in to Craft (or Twig) that does this, but your {% if %} conditional could be trimmed down to a single-line ternary operation:

{% set episodeNumber = (entry.episodeNumber < 10 ? '0') ~ entry.episodeNumber %}

or even

<span>{{ (entry.episodeNumber < 10 ? '0') ~ entry.episodeNumber }}</span>


The reason this doesn't work is because .type('image') won't work with eager loading. Eager loading removes the ability to use ElementCriteriaModel methods.
From the docs:

When the assets aren’t eager-loaded, entry.assetsField gives you an ElementCriteriaModel that is preconfigured to return the related assets once they’re requested (e.g. when first() is called).
However when the assets are eager-loaded, entry.assetsField gets overwritten with an array of the eager-loaded assets. So first(), find(), and other ElementCriteriaModel methods are not available. Instead you must stick to the standard array syntaxes.

As a work around, you could use a for loop to match only Matrix blocks of a particular type instead:
{% for block in entry.projectMatrix if block.type == 'imageBlock' %}
  {% set matrixImage = block.imageFile[0] %}
{% endfor %}

If you only want the first image block type:
{% for block in entry.projectMatrix if block.type == 'imageBlock' %}
  {% if loop.index == 1 %}
    {% set matrixImage = block.imageFile[0] %}
  {% endif %}
{% endfor %}


How is conflicting asset filename created

This will be possible as of the next Craft release, which will be 3.4.21: https://github.com/craftcms/cms/commit/a787fe0ef37841706a5a9910fbeae0391da3be6f


Yes the same still applies. You can either delete it via DB directly in your {{%elements}} column or you can just run

PHP

Craft::$app->getElements()->deleteElementById(x)

Twig

{% do craft.app.getElements().deleteElementById(x) %}


project.yaml synchronize error (not usable anymore)

solved it with a rebuilded project file locally.


How can I display the number of related entries?

Try something like this:

<form class="event-filter">
    <label for="filter">Filter event: </label>
    <select id="filter" name="filter">
        {% for event in craft.entries.section('event') %}
            {% set numEventBookings = craft.entries.section('booking').relatedTo(event).total() %}
            <option value="i{{event.id}}">{{event.title}} ({{numEventBookings}} bookings)</option>
        {% endfor %}
    </select>
</form>

But it'll generate one database query pr event, so it might be a bit inefficient, depending on your setup.


How would you show a specific entry 'and' its children

Try merging like this

{% set parent = craft.entries.section('pages').id(8) %}

{% set entries = craft.entries.section('pages').descendantOf(8).limit(1) %}

{% set entries = parent|merge(entries) %}

{% for entry in entries.all() %}
  output your entries here
{% endfor %}


Build Query relatedTo multiple categories

Untested, but something like this should work:

{# set base criteria #}
{% set params = {
    section: 'productsServices',
    limit: null
} %}

{# set relationship criteria #}
{% set relationParam = ['and'] %}
{% for segment in craft.request.segments %}
    {% if loop.index != 1 and segment != 'all' %}
        {% set category = craft.categories.slug(segment).first() %}
        {% set relationParam = relationParam|merge([{ targetElement:category }]) %}
    {% endif %}
{% endfor %}

{# check to ensure that at least one relationship is defined and merge criteria #}
{% if relationParam|length > 1 %}
    {% set params = params|merge({relatedTo: relationParam}) %}
{% endif %}

{# retrieve entries #}
{% set entries = craft.entries(params) %}
{% for entry in entries %}
    {{ entry.title }}
    ...
{% endfor %}

Update Added a check to ensure that not all segments are set to 'all'; Fixed 'length' syntax.

Give credit to carlcs and his ElementCriteriaModel Fu in this answer.


As of Craft 2.5.2750, you can leave off the {% endpaginate %} tag, then move your {% paginate %} tag up outside of the blocks in the posts/index.twig template, and your pageInfo variable should be available to the whole template, including the parent template that you're extending.


How do I insert a special entry into a sections list?

There's a special loop variable available in for loops which provides info about the iteration.
In your case you'd just insert that list item after the 2nd iteration:

{% for entry in entriesOnPage %}

{{ entry.title }}

    {% if loop.index == 2 %}

I'm am different

    {% endif %}
{% endfor %}

If you want to do this only on select pagination pages, you'd additionally compare  against the paginate variable available in between paginate tags:

{% if loop.index == 2 and paginate.currentPage == 12 %}


Displaying notification in control panel

Craft's JS/UI framework "Garnish" is largely undocumented, but exploring the Craft object it exposes in the console, I found a few methods that might be useful:
// Good for confirmations (blue banners):
Craft.cp.displayNotice('Your changes have been saved.');

// Good for errors (red banners):
Craft.cp.displayError('Uh oh, something bad happened!');

// Custom flash names (for anything else—requires custom CSS):
Craft.cp.displayNotification('custom-flash-key', 'Something very special happened!');

The last one, displayNotification is the abstract method, called by the first two. custom-flash-key gets added to the notification as a classname.


Upon looking at the craft/runtime/logs/phperrors.log I noticed the following error being reported:

PHP Fatal error:  Maximum function nesting level of '200' reached, aborting! in /Users/username/path/to/website/craft/app/framework/base/CModule.php

To fix the issue, I updated the following line in my php.ini:

xdebug.max_nesting_level=200

To something higher:

xdebug.max_nesting_level=500

This error might be thrown in other scenarios as well as this fix seems pretty specific to having XDebug installed. In any case, these steps helped me get it resolved.


Are there any tradeoffs if you use the null-coalescing operator in place of first()?

My gut says the first option (.first()) is going to be slightly faster, but in real world performance my guess is that it's negligible.

Personally, I think I'd prefer the cleaner, more explicit, syntax of the first.


XAMPP Windows 10 - Could not find your craft/ folder error

I believe the problem is that you've got craft within htdocs, so your web server is trying to run craft from the root, instead of where it should be, /public

To illustrate, this is where htdocs should be.

-craft

--craft
---app
---config
---plugins
---storage
---templates
---.htaccess
---web.config

--public <- htdocs
---index.php

I suggest, to test, that you change the httpd.conf to make apache run from the public folder rather than the pre-made htdocs folder xampp has given you. Go into the xampp config, click on httpd.conf and change the following lines:

DocumentRoot "your\path\to\htdocs\craft\public"

and

<Directory "your\path\to\htdocs\craft\public">

Restart your server, and you should be golden. On windows, you shouldn't have any permission issues with folders.

As an example, here is what my lines look like:

DocumentRoot "D:\Documents\work\bud\public"
<Directory "D:\Documents\work\bud\public">

I'd avoid just dumping the code in the pre-made htdocs folder provided and just route your httpd.conf to wherever your codebase is.


Besides saving the variable in a field (e.g. global set) you could also add a "Environment Variable" to
your general.php file:

'myGlobalVariable' => 'I am available in all environments'

but you can only access it from Twig, it's not possible to update it:

{{ craft.config.myGlobalVariable }}

If you do need to update from  your Twig templates, you should make a custom plugin / add to your Business Logic plugin.
There's various options to make a variable available in your Twig templates:

add a "Template Variable" to the {{ craft }} global variable

or with a Twig Extention:

add a new Global Variable using getGlobals()
add a Twig function with new Twig_SimpleFunction()

With a plugin you have these options to save your value (and update with a custom Twig function):

in a Record, update with $record->save()
directly in the plugin settings, update with craft()->plugins->savePluginSettings() (→ read more on SE)
with a config.php file in the plugin folder, not possible to update with Twig (→ read more on SE)
hard code it into the plugin PHP ;)


Best way to use custom enums in my plugin templates?

Right now that's probably the best way to do it.

For Craft 2.2, I just added a static getConstants() method to BaseEnum, so you can do can do a PluginStatus::getConstants() call that will return an array with a key => value pair of the enum options and their values that should make that cleaner.


Sorry for answering my own question.

Upon a suggestion from P&T, we found that our Nginx configuration was removing the cookies when it cached the page. When we left the cookies in, we were able to log in.

We still don't know what changed to make the site suddenly not work, but at least the control panel is usable.


Not a solution, but I strip it out as part of a cleanup macro that runs on body text.

{% macro cleanup(string) -%}
    {%- if string|length -%}
        {{- string|typogrify|replace('

','')|replace('redactor-inline-converted','')|raw -}}
    {%- endif -%}
{%- endmacro %}


What is the best way to test if a file exists without knowing which file extension a Craft install is using for templates?

That's exactly how I'd do it.

It doesn't make much sense, but there's nothing stopping a user from having both extensions for a template like:

/index.html
/index.twig

And your existing code would cover both cases.


Laravel Homestead installation nightmare

If you follow the instructions here: Local Development with Vagrant / Homestead and can't get it working, let me know.

That's the exact procedure I use whenever I set it up; I just did it 3 weeks ago to set up a new machine running Homestead without incident.


alternative global variable to siteUrl or the primary website?

You can define whatever aliases/environment variables you like. In this case, I'd probably define an environment variable in my .env file like this:

BASE_WEB=http://example.com

And then in config/general.php I'd add an alias:

<?php
/**
 * General Configuration
 *
 * All of your system's general configuration settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/GeneralConfig.php.
 *
 * @see craft\config\GeneralConfig
 */

return [
    // Craft config settings from .env variables
    'aliases' => [
        '@baseWeb' => getenv('BASE_WEB'),
    ],
];

And then to use this in a template, you'd just do:

{{ alias('@baseWeb/assets/css/main.css') }}

...and away you go. To learn more, check out the Flat Multi-Environment Config for Craft CMS 3 article.


How do I display entries depending on multiple relations?

This is not a full fletched solution, but might kickstart you.
One solution would be to add a "vintage" or "brewYear" date field to your entry's section. In twig, you can then use the contents of this field to do you further selections.
Another solution would be to use a second category group containing the years you need. Then, adding another category field (for the years) to the beer section would allow you to relate the entry to this category and subsequently in Twig you are able to filter based on this relation.
If you checkout the documentation for Craft 3 relations, you might see how you can query entry records based on multiple relations.
There is also a demo website on http://barkeeper.parhelia.ch which is based on code published by Pixel & Tonic here. Its not a 100% fit for what you try to achieve, but has some nice concepts – although it also uses the SuperTable plugin for the drink incredients.


How to add tags to an entry per site basis. And then only get the tags for that site in the frontend

currently disabling multi site for tag is not supported

unless you were to fork Craft and change the isLocalized() return
value from true to false

https://github.com/craftcms/cms/issues/3483#issuecomment-440782270
so tag itself is always created for all languages but you need another thing.
you need adding tag to entry per site basis so you have to check tag field -> advanced setting -> Manage relations on a per-site basis -it seems you enabled this already-.
now if there is two site and tag1 is added or selected for site1 entry but tag1 is not selected for that entry on site2, if you change source Locale to site2 id on your code, tag1 is not showing on results. - still tag1 is available on site1 and site2 but is not showing up on result because you enabled manage tag on per site basis and tag1 is not attached to site2 entry -