Perform "inclusive" relatedTo query with multiple categories

That and argument only applies to the other top-level relatedTo arguments. If one of those arguments targets multiple elements (e.g. categories), those will still be glued together with “OR”.

You would need to set it up like this instead:

{% set resources = craft.entries.section('resources').relatedTo(
    'and',
    { targetElement: category1 },
    { targetElement: category2 }
) %}

If you don’t know all of the categories ahead of time, you can create the parameter value dynamically like this:

{# Get the category IDs #}
{% set catIds = craft.categories[...].ids() %}

{# Create the relatedTo param value #}
{% set relatedTo = ['and'] %}

{% for id in catIds %}
    {% set relatedTo = relatedTo|merge([id]) %}
{% endfor %}

{# Now find our entries #}
{% set resources = craft.entries.section('resources').relatedTo(relatedTo) %}

Update

This is significantly easier in Craft 2.5 (currently in beta), as the relatedTo param’s element, targetElement, and sourceElement sub-properties can now begin with 'and', which tells Craft to only return elements that are related to all of the following element IDs.

Here’s a quick example:

{# Start with a list of category IDs that must be included #}
{% set catIds = [1, 2] %}

{# Find the entries #}
{% set resources = craft.entries({
    section: 'resources',
    relatedTo: {
        targetElement: ['and']|merge(catIds),
    }
}) %}


Latest update to Craft 3.1.27 crashed server

Got it working by using the local database to restore to production. "Finishing up" must have failed to update the db correctly. Fortunately, the local and production databases had been synced before the install failed.


This looks to have been fixed a few hours ago:

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

You could apply the fix yourself for an immediate solution:

https://github.com/craftcms/cms/commit/30db5af5b596e267db136a218209a65cc9fde36e


How to fetch ALL users related to a field, including unverified/pending?

The correct syntax or finding all users regardless of status is status(null), which you've tried, but the issue isn't your status parameter, it's the targetElement parameter of your relatedTo query.

It only accepts the actual element you're looking to query, not its ID.

If you already have the target element object, you can just pass that in. If you don't, you can retrieve it with:

$targetElement = Craft::$app->getElements()->getElementById($organizationId);

Then use:

array(
    'targetElement' => $targetElement,
    'field'         => 'organisation'
)

Relevant docs here: https://docs.craftcms.com/v3/relations.html#the-relatedto-parameter


Is there any reason you dont use a rich text field like redactor?
You can make a custom config so that field only has h1,2,3 and no links, lists etc.

And instead of having the class "measure-wide" on the heading element you can wrap it.

Something like {{ block.heading }}
Where block.heading is a custom redactor field.


It looks like you should be able to wrap it in an if statement like this...

{% set pageCss %}
    {{ entry.inlineCss }}
{% endset %}

{% if pageCss != ''  %}
    {% includeCss pageCss %}
{% endif %}


Apparently PHP's garbage collection does not work when you've set a custom PHP session save path.

Lame.

If you set the overridePhpSessionLocation config setting to false, Craft will go with whatever path Apache/PHP is configured to save sessions to. If you're not on shared hosting, then it's a perfectly safe change, too.

Setting that to false on a site that is on shared hosting has its own security implications.

  curious if there is work being done on Craft to fix this issue by default.

We're discussing what we can do in Craft itself to help with this.


Help with admin panel errors. Fresh install. Mysql version issue?

You need to tweak your MySQL 5.7.5+ config for it to play nicely with Craft.

MySQL 5.7.5 changed the behaviour of the GROUP_BY statement, affecting some of the core Craft queries.

The preferred solution is to add the following to your /etc/mysql/conf.d/sql_mode.cnf file:

[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

This Craft Cookbook recipe provides additional information about the problem, and the possible solutions.


Okay, I think I figured it out. 1st, I added the getContent()

I changed

    $entry->showName[] = 22;

to

    $entry->getContent()->showName = 22;

I think the problem is that the category we had set up only allowed for a single value and I was responding with an array.

Someone please correct me if am wrong.


If you set the slug directly on the entry element, it should work!

public function init() {
    craft()->on('entries.saveEntry', function(Event $event) {
        $entry = $event->params['entry'];
        $entryId = $entry->id;

        $newTitle = str_replace('Name: ', $entryId . ' - ', $entry->title);

        $entry->getContent()->title = $newTitle;

        $entry->slug = $entryId;

        craft()->elements->saveElement($entry);
    });
}


How can I get the last Matrix block of a certain type?

What about comparing the currently looped block ID with the ID of the last block of type "text"?

_entry.html:

{% set lastTextBlock = entry.simpleMatrix.type('text').last() %}
{% set lastTextBlockId = lastTextBlock ? lastTextBlock.id : null %}

{% for block in entry.contentBlocks %}
    {% include '_blocks/' ~ block.type|lower %}
{% endfor %}

_blocks/text.html:

{% if block.id == lastTextBlockId %}
    ...
{% endif %}


Users allocating permissions beyond their own

You should consider voting for this feature request: https://github.com/craftcms/cms/issues/915


Craft 2 CP session expires unexpectedly, requires repeated login

Resolved.

This ended up being an issue with, so far as I can tell, my env variables--specifically a misconfiguration with the basePath.


craft.feeds does not appear to be working

FeedsService uses SimplePie for feed parsing, but it currently does expose any errors that SimplePie may be returning when connecting to a feed.

  A feed could not be found at http://test.solutions.vwdservices.com/customers/vastned.com/page-modules/widgetrss. This does not appear to be a valid RSS or Atom feed.

Here's the error it's returning when connecting to that feed.

We'll update FeedsService to return any errors that come back from SimplePie, too.


More than one field for a fieldtype plugin

Nope – a single field can only have a single column in the craft_content table.

If you need your FieldType to save complex data, you have two options:

The easiest approach – by far – is to simply have Craft serialize the data before it's saved to the craft_content table. Simply return AttributeType::Mixed from your FieldType class' defineContentAttribute() method:

public function defineContentAttribute()
{
    return AttributeType::Mixed;
}

With the above, your FieldType's value will be an array. This means that when you save the data, you'll need to use the array syntax for the input fields' name attributes; e.g. if you had two "sub fields" called foo and bar, your input fields should look like this:

<input type="text" name="myFieldHandle[foo]" />
<input type="text" name="myFieldHandle[bar]" />

To output the sub fields in a template, you'd do something like this:

{{ entry.myFieldHandle.foo }}
{{ entry.myFieldHandle.bar }}

The other approach for saving complex values is to have your FieldType use a custom database table. Explaining this in any great detail is impossible without knowing a lot more about your particular use case and a good overview is already given in Ben Parizek's great answer to a similar question – but here's the gist of it:

First, you'll need to create a Record class, containing your custom FieldType's columns (sub fields) and their attribute types. Whenever your plugin is installed, Craft will create custom database tables based on your plugin's Records (which means that if your plugin is already installed, you'll need to uninstall and install it again to actually have Craft create the tables – if this is a publicly available plugin you should probably write a Migration to ensure the table is created whereever the plugin is already installed).

Note that your custom table should probably have foreign keys for the element and field ID's, to create the necessary relations between the field data, the field and the actual element (e.g. entry).

To actually save the data to your custom table, you'll need to add a onAfterElementSave hook to your FieldType class. This hook is run whenever an element with a field using your custom FieldType is saved. The field and element ID's (and the actual data to save), is available via the FieldType's model and element properties, respectively:

public function onAfterElementSave()
{

    $element = $this->element; // The element being saved
    $elementId = $this->element->id; // The ID for the element being saved
    $fieldModel = $this->model; // The field's model
    $fieldHandle = $field->model->handle; // The field's handle
    $data = $this->element->getContent()->getAttribute($fieldHandle); // The data you want to save

    ...

    // Some custom logic to save the data

}

To save the data via the onAfterElementSave hook, you'll most likely need to use the DbCommand class to build a custom query.

In order to populuate your field (i.e. pull the data) for use in templates and the getInputHtml() method, you'll also need to write a custom query. A good place to do this is in your FieldType's prepValue() method, i.e. something like this:

public function prepValue($value) {
    $value = null;
    $fieldId = $this->model->id;
    if ($this->element->id) {
        // Then element has been saved before and there might be existing data – try to pull it
        $value = craft()->db->createCommand()
            ->select('foo, bar')
            ->from('yourcustomdatabasetable')
            ->where([
                'fieldId' => $this->model->id,
                'elementId' => $this->element->id,
            ])
            ->queryAll();
    }
    return $value;
}

Finally, to save some overhead its a good idea to return false from your FieldType class' defineContentAttribute method (this basically tells Craft to not save anything to the craft_content table):

public function defineContentAttribute()
{
    return false;
}

Note that there are other aspects to consider as well, such as offloading the business logic in saving and retrieving the data to a service layer (a good idea), and using Models to pass data between records, the service layer and your templates (a very good idea), but it's a bit out of scope for an SE answer like this. In any case, I hope the above will get you up and running. In any case, if you simply need to two text fields, I'd go with the first approach – it's way easier.


Set Recipient in Sprout Email Notification

This is possible with the Sprout Forms Invisible Field (be sure to update to the latest version). Using the Invisible Field will ensure your email address never shows up in the template. To set this up:

1) Add an Invisible Field (invisibleFieldHandle) to your form and set its value to {recipient}

2) Setup a Notification Email and set your Recipient field to the name of your Invisible Field Handle: {invisibleFieldHandle}

3) Before your Sprout Forms displayForm tag, set the value of the Email Address where you want to trigger the Notification Email:

{% do craft.sproutForms.addFieldVariables({
  recipient: 'email@website.com'
}) %}

{% craft.sproutForms.displayForm('contact') %}


I know I'm a bit late to this, but I think it's because your {{ loop.index }} is not 0-indexed, which is necessary for the array.  It should look like this:

<input type="hidden" name="fields[selections][{{ loop.index0 }}][col1]" value="{{ item.qty }} x {{ item.description }}">

You also need an extra valueless hidden field above the loop to collect all the values into one array:

<input type="hidden" name="fields[selections]" value="">

You can see a fuller example on how to format the HTML for all fields of all types on this StraightUpCraft page.  Scroll to the very bottom for tables.


Craft 3 Admin not loading cpresources files over HTTPS

The fix was to delete the content of the /cpresources folder and that did the trick.


Maybe check out the Sprout Reports plugin? I've used it to export matrix field data.


How to list the latest 3 entries per category per section?

You need to loop over the sections. In each section, you then loop over the categories, and display your entries inside them. Something like this.

{% set categories = craft.categories.group('groupHandle').find() %}
{% for section in craft.sections.getAllSections() %}
    {% if section.type == 'channel' %}

{{ section.name }}

        {% for category in categories %}

{{ category.title }}

            {% for entry in craft.entries.section(section).relatedTo(category).limit(3).find() %}
                {{ entry.title }}
            {% endfor %}
        {% endfor %}
    {% endif %}
{% endfor %}

This is a pretty quick and dirty example. I pull the categories ahead of time so I can reduce the number of database calls. I suggest using the cache to speed things up.

The template docs (especially the ElementCriteriaModel) are handy reading materials.


Getting an array of ids from an array of eager-loaded elements within Twig

You would just loop the entry models to collect the IDs (looks ugly, but it's a simple and efficient for loop). But in case you do not need anything else from the models, I'd actually expect your previous approach using the ids method to have better performance.

{% set ids = [] %}
{% for entry in entry.myEagerLoadedEntries %}
    {% set ids = ids|merge([entry.id]) %}
{% endfor %}


Reference tags in rich text fields parse and converted on save

Correct... they currently only work on plain text fields, not rich text fields.

I just updating the documentation so it's a more clear.


It turned out this was the culprit. Craft was doing a deprecationerrors query (https://github.com/craftcms/cms/issues/2539).

Turning devMode to false fixed this.

Hope this helps someone...


Force language segment in URL on multi-lingual site

Make sure to remove Craft’s default rewrite rule (“Send would-be 404 requests to Craft”) from the .htaccess in your document root, so it’s only in the .htaccess files of your locales’ subfolders. You can now remove the index.php as well and requests to your homepage domain.com/ should now respond with a 404 HTTP error.

You have now removed all (duplicate) routes starting at root level.

Last step is to redirect visits to the homepage to en/ via the .htaccess in your document root.

RewriteEngine On
RewriteRule ^$ /en [R=301,L]


With the current search implementation in Craft, if you have subLeft and subRight set to true for the defaultSearchTermOptions config setting and you search for "intaglios", what Craft does behind the scenes is search for *intaglios*, which would never match intaglio because the wildcard is after the last s.


Is it possible to exclude multiple sections from an entry search query?

The trick is to add and once before the first not

{% set entries = craft.entries.search(query).section('and, not this, not that') %}


How can I create an ElementCriteriaModel with 'and' and 'or'

It’s not currently possible to specify both of those conditions at once with the relatedTo param, so you would have to do it with two separate queries.

First, get all of the asset IDs that are related to the upload entries:

{% set uploadAssetIds = craft.assets.relatedTo(uploads).ids() %}

(Note that the relatedToUploads variable is not actually necessary here.)

Then you would get all of the assets whose ID falls within one of the uploadAssetIds, and who are related to all of the tag IDs.

{% set relatedToTags = ['and'] %}
...

{% set assets = craft.assets.id(uploadAssetIds).relatedTo(relatedToTags) %}


Localized Craft Build with Vanilla Forums?

If you install a secondary app within your Craft directory, you have to tell Craft to ignore all these requests. Just edit your .htaccess file accordingly.

See my answer here on how you can do this: "Is it possible to tell Craft to ignore requests to under a certain path?"


Template error on local development when checking entry variable

You are close, instead of checking entry|length, you can do {% if entry is defined %}

{% if entry is defined and entry.sectionId == 1 %}

So if I am understanding correctly, the full code will be:

{% if entry is defined and entry.sectionId == 1 %}

    //  Redirect to homepage

{% else %}

    // Do some checking into whether there's a corresponding entry, etc.

{% endif %}


Assuming PluginCustomClass is a class inside of a Craft plugin, then the issue is probably that you need to reference it in the Craft namespace.  Something like this should work:

->raw(') = new \Craft\PluginCustomClass(')

Depending on what type of class that is (Service, Variable, Helper, standalone, etc.), Craft might not have auto-loaded it, so you might need to manually require it as well.


Display events that appear at certain venue

When using an Entries field, you're "relating" the entry to other entries.
The ElementCriteriaModel parameter to filter by related entries is the relatedTo parameter.

Something like this should do the trick:

{% set params = {
    section: 'events',
    order: 'eventShowtime desc',
    relatedTo: venueId
} %}


Twig_Error_Runtime on Local Dev Environment

Was simply root password in DB changing since last loading up environment. Threw some more errors to finally see database connection issues and just had to update db.php to fix. Leaving this here in case anyone else has issues.


Auto enable/install plugin through config

The short answer is no. The long answer is sortof, if you’re running Craft 3.

Since plugins are technically modules in Craft 3, you should be able to bootstrap a plugin onto the application just like any other module.

To do that, update config/app.php with these modules and bootstrap sub-arrays:

return [
    'modules' => [
        'contact-form' => function() {
            $plugin = Craft::$app->plugins->createPlugin('contact-form');
            $plugin->setSettings([
                'toEmail' => 'foo@bar.baz',
            ]);
            return $plugin;
        }
    ],

    'bootstrap' => [
        'contact-form',
    ],
];

Using Contact Form as an example. For a different plugin, replace all of the 'contact-form' strings with the right plugin handle, and change the settings array to whatever the plugin is expecting. (You can find which settings keys the plugin supports by checking its Settings model – usually either src/Settings.php or src/models/Settings.php.)

Some caveats off the top of my head, though:

Craft won’t know that the plugin is installed, so it will still look like an uninstalled plugin in Settings → Plugins.
You won’t be able to edit the plugin’s settings in the Control Panel; only from config/app.php.
You won’t be able to update the plugin from the Control Panel; only via composer update.
If the plugin has an install migration, you will need to manually duplicate it as content migrations. And whenever you update the plugin, you’ll need to check if it added any new migrations, and manually duplicate those as content migrations as well. (Any migrations that were there at the time you first installed the plugin, besides the Install migration, can be ignored.)

EDIT

If you just want to be able to install a plugin programmatically, but don’t mind if the plugin ends up getting a row in the plugins DB table, that’s easy. Just create a new content migration, with the following safeUp() function:

public function safeUp()
{
    Craft::$app->plugins->installPlugin('plugin-handle');
}

Then you just need to run the migration on each of your environments. You can either do that from Utilities → Migrations in the Control Panel, or by running the following CLI command:

./craft migrate/up

Maybe worth noting that you can also install plugins directly from the terminal, using this command:

./craft install/plugin <plugin-handle>


Matrix fields can only be used as custom fields, on an element.

If you really want to use them, you would need to create a custom Element Type (see the resources at the bottom of http://buildwithcraft.com/docs/plugins/working-with-elements), and then create a Matrix field that is associated with your element type’s field layout.


Entry translation differences Craft 2 and Craft 3

It appears I have to add a site as a language before I can localise/translate any content?

Yes. If you want to add a new language, you have to add a new site in Craft 3.

  It appears changing language is done in the list view of entries.

Changing the language is a matter of changing the site, which is done via the site dropdown in your 2nd screenshot.

Relevant docs:

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

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

If you have suggestions for enhancements/improvements, feel free to share them here: https://github.com/craftcms/cms/issues


Here is what I did in my blog index:

        {% paginate craft.entries.section('blog').limit(1) as pageInfo, blogEntries %}

            {% for entry in blogEntries %}

{{ entry.title }}

Posted on {{ entry.postDate.format('F d, Y') }}

Continue reading

            {% endfor %}

        {% set numOfpages = pageInfo.totalPages %}

        <button id="more-button" data-page="{{craft.app.request.pageNum()}}" data-batch="1" data-total="{{ numOfpages}}">Load More</button>

and in my javascript:

$("#more-button").on('click', function () {
var btn = $(this),
    page = btn.data('page'),
    batch = btn.data('batch'),
    total = btn.data('total'),
    offset = page * batch,
    newPage = page + 1;

console.log(newPage);
console.log(total);

if ( newPage <= total ) {

    loadPosts(offset, batch);
    // set the buttons page attribute to the new page it is on.
    btn.data('page',newPage);
}

if ( newPage == total ) {
    $('#more-button').hide();
}

});

function loadPosts (offset, limit) {
$.get('/ajax/posts', { offset:offset, limit:limit }, function (data) {
    var postOutput = $('#post-output');
    postOutput.append(data);
});
}


Is there a way to override the formatting template used when rendering a Freeform form?

No, I don't think it's possible to pass a template file name to the render() method. The render() method is meant to use the template selected in the control panel. I don't think you can override that option.

From Freeform's documentation on the Forms Composer:

  Formatting Template
  Optional, if using the render() method, this essentially allows you to "attach" a formatting template to a form so that you don't need to include formatting inside the template(s) you place the form inside.

You can do something like pass a Freeform handle to another template via an include. If you have an entry with a Freeform field called sidebarForm it would look like this:

{% include "forms/sidebar-form" with {'formHandle': entry.sidebarForm } %}

Then the included template forms/sidebar-form could look something like this:

{% set form = formHandle is defined ? craft.freeform.form(formHandle) : null %}

{% if form %}

  {{ form.renderTag() }}

    manually iterate through fields...

  {{ form.renderClosingTag }}

{% endif %}

You can use Freeform's Formatting Template Examples as a starting place, or install their Demo Templates.


Unwanted output when using Twig conditional

I pasted your HTML into TextMate with “Show Invisible Characters” enabled, and it shows that there are two “zero width no-break space” (U+FEFF) characters in there, at the end of these lines:

{% if currentUser.isInGroup('admin') %}

-- and --

{% endif %}

Here’s a screenshot:

Those characters tend to come from code that was copied from Google+, which likes to add them at the very end of each post.

Unfortunately, Sublime Text doesn’t show these types of characters; you need to use TextMate to see them.


HTML/View Source button not working/showing in WYSIWYG Craft 2.5 / Redactor II 1.1.0

It turns out that the latest redactor seems to now have a plugin for viewing the source. You can enable this in your redactor JSON config file under plugins. Just add the "source" plugin like so:

{
    "buttons": ["format", "bold", "italic", "lists", "image"],
    "plugins":["fullscreen", "source"],
    "toolbarFixed": true
}


What is the best way to exclude an array of entries?

Craft documentation describes how to exclude entries with a given value. In this case, we want a string that looks like: 'and, not id1, not id2, not id3, not id4'

So we need a string that is all of the featured article ids separated by , not. First, get them as an array using ids():

{% set featuredArticleIds = craft.entries.section('articles').featured(1).limit(4).ids() %}

Then convert that array to a string, using twig's join filter:

{% set featuredArticleIdsString = featuredArticleIds | join(', not ') %}

Then, fetch all the articles, but not the featured ones:

{% set notFeaturedArticles = craft.entries.section('articles').id('and, not '~featuredArticleIdsString) %}

[thanks to carlcs for crucial fix]


Redactor 2 error 'accessibility-help-label'

The solution is set the right translations... the problem was using translations "pt_pt" instead of "pt_br".

Take care of using the right translations


Get all entries for a structure section including disabled

{% set events = craft.entries.section('events').first() %}
{% for event in events.children().status(null).find() %}
   {% for day in event.children().status(null).find() %}
      {% for session in day.children().status(null).find() %}
      {% endfor %}
   {% endfor %}
{% endfor %}

event.children() does not return an array of elements but an object of type ElementCriteriaModel the same as craft.entries thus you can append whatever you want until you execute it with find() or first()


If you were to do this on entry save, it'd be much easier/cleaner.

You'd write a simple plugin that listened to the onBeforeSaveEntry event.

The plugin would check the isNewEntry param to make this this is a new entry and not an existing one.

If it's new, you could generate a random numeric value with mt_rand, assign it to your custom field and left the request continue so Craft can save it to the entry.

A string field for the unique identifier would be better though, since mt_rand will not always produce unique numbers (for unique numbers you'd need to keep a separate database table and obtain id's within a transaction). If you'd use strings you could use uniqid('', true) if you deploy on a single server, or better use a uuid/guid.

If you didn't do it on save, but wanted to be auto-populated when someone clicked "New Entry", you'd have to do something much more hacky like have JS loaded load, try to target the field in the particular section with JavaScript and inject the random number into the DOM.


Can I downgrade my craft version from Client to Personal using the CP?

Yes you can. If you click the Settings icon in Craft, at the bottom of the screen you will see a box that reads:

  Upgrade Craft to take your site to the next level. Show me.

Click on that and a window will pop-up with the versions of Craft you can install. Yours will look like this:

Just click the Uninstall button and you will be downgraded to Craft Personal.


Entry slug auto appends -1 even when the original slug is unique

I don't know the specific rules Craft uses but I believe Craft auto appends the -1 when it tries to save an Element that has a matching URI in the craft_elements_i18n table.

A few scenarios that I can think of that may behave like you describe:

Somehow, there is an existing record in your database that matches the URI of your Entry using the cics-west-belden slug
You have another Section, Category Group, or other custom Element set to generate URIs in the same format as the Section you are posting the Entry to which already has an Element saved using your cics-west-belden slug.

To rule out the scenario where a matching record already exists in your database, open your database and look in the craft_elements_i18n table. Search for all records that match your slug and see if you only find the one:

SELECT *
FROM craft_elements_i18n
WHERE slug = 'cics-west-belden';

To confirm that no other URIs already match your Entry, you could do a similar search in the URI table:

SELECT *
FROM craft_elements_i18n
WHERE uri LIKE '%cics-west-belden%';


Require shipping method in Commerce order flow

Ok, so shipping is not a necessity for a Commerce site (e.g. think about  e.g. digital downloads - shipping is not relevant here) - so Commerce does not force you to set a shipping method on an order.

It's up to you to work out how and where you need to do this, if you do.

A lot (most,even) of it is often best tackled at the front end via your flow and some JS and/or general form validation stuff - you don't allow the user to proceed/submit if they have not chosen a method when you need them to.  We actually do it all, pretty much, in this end of things.

In addition, you CAN use any Commerce event you choose:
https://craftcommerce.com/docs/events-reference

...to add some extra validation (as you have with the address fields).  But it really depends on your precise checkout flow as to how you'd implement this.

For example, if your shipping page is POSTing to the Commerce controller updateCart when it submits, you could perhaps listen to:
https://craftcommerce.com/docs/events-reference#commerce_orders.onsaveorder

...and in that validate a shipping method is set (of course your order is saved many times during a commerce process so you should e.g. POST some other variable to check in there if you should actually trigger this validation).

<input type="hidden" name="validateShipping" value="true">

And then in your event handler

if(craft()->request->getPost('validateShipping')){ ... validation here }

If there is an error, then to add the error you'd add it to the model you retrieved as an event parameter:

$order->addError('shippingMethod','No shipping method supplied!');

..and to set a flash message

craft()->userSession->setFlash('error', 'No shipping selected');

....but there are MANY possible ways you can implement this (e.g. no server side validation at all, if you can handle it all at the front end) -> the key thing is to really understand your checkout flow (and all the many ways users can travel through it) - quite thoroughly BEFORE you start implement the actual validation you need.


Asset subfolder is not showing in the entry field as a folder option

Worked this out. In the entry field I was limiting uploading an image to one folder. Once this was unchecked and only images selected in the folder list the subfolder appeared.


How do I set a variable in Twig if a value exists more than once in a loop?

This can be accomplished by creating an array of the entry years. Inside the loop that's building the array, a conditional checks if the year already exists in the array... if the year exists, a variable is set to TRUE which you can use in your conditional later down on the page.

{% set files = craft.entries.section("downloads") %}
{% set dropdown = 0 %}
{% set yearArray = [] %}

{% for entry in files %}
    {% set year = entry.fileDate | date('Y') %}
    {% if year in yearArray %}
        {% set dropdown = 1 %}
    {% endif %}
    {% set yearArray = yearArray | merge([year]) %}
{% endfor %}

{% if dropdown %}
    Do this
{% else %}
    Do this
{% endif %}


After migration to staging, requesting any page other than Home results in 500 error

This is solved by this thread.

The common thread here is Rackspace Cloud Sites, which apparently needs a RewriteBase / instruction in .htaccess.

Thanks @maxx and @christopher-healey


Sure just do this

discography/{type}/{slug}


So P&T chipped in to help and of course solved my plight immediately :D

For anyone else who might encounter a similar scenario I'm posting the solution.

On the page containing the archive list:

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

    {% for year, entriesInYear in allEntries | group("postDate.year") %}

        {% set counter = ( counter | default(0) ) + 1 %}

            {{ year }}

                {% for month, entries in entriesInYear | group("postDate|date('F')") %}

{{ month }}&nbsp;({{ entries|length }})

                {% endfor %}

    {% endfor %}

Then on the actual archive page (I added this at the top of the page):

{% set month = craft.request.segment(3) %}
{% set year = craft.request.segment(4) %}

{% set firstDay = now | date_modify('first day of ' ~ month ~ ' ' ~ year ~ ' 00:00:00') %}
{% set lastDay = now | date_modify('last day of ' ~ month ~ ' ' ~ year ~ ' 23:59:59') %}

Then where you want the info to appear:

{% set archive  = craft.entries.section('sectionName').postDate('and', '>= ' ~ firstDay, '<= ' ~ lastDay) %}

    {% for entry in archive %}

{{ entry.title }}

            {{ entry.body }}

read more

{{ entry.postDate | date("d") }} {{ entry.postDate | date("M") }}

    {% endfor %}

Now here's the bit that caused the grief...  Instead of having 'month'-'year' as part of the route, P&T suggested using just '*'.

Or.. as P&T put it:

  Your dynamic route is set with the Month and Year token. If you look at the list of available tokens, you will see that Month and Year follow a specific format, which the URLs you set up in your menu do not follow. Therefore, those URLs do not follow the pattern you set in the Route and you get a 404 page.


LJ Dynamic Fields unable to output title

The values in your tagsMultiSelect are the tag ids, not the tags.
So, what you need to do in your template is convert that id to a tag:

{% for tagId in entry.tagsMultiSelect %}
  {# get the tag with that id #}
  {% set tag = craft.tags.id(tagId).first %}

  {{ tag.title ?? 'no such tag' }}
  {% if not loop.last %}, {% endif %}
{% endfor %}

If what you want is a predefined set of tags, you might also consider changing that tag group into a category - that would let you use a regular category field for your tagsMultiSelect.


What you want is craft.assets

  You can access your site’s assets from your templates via craft.assets. It returns an ElementCriteriaModel object.

Use sourceId for the parameter.

To find the sourceId, look at the craft_assetsources table in the database. There doesn't seem to be any way to query for AssetSourceModel.


It happens here (maybe intended, maybe a bug):

https://github.com/craftcms/cms/tree/master-v2/src/controllers/UsersController.php#L1757

For news users $groupIds is an empty string, which means the expression ($groupIds !== null) becomes true. At line 1780 $groupIds get passed to userGroups->assignUserToGroups() ... inside this method the $groupIds variable is casted to an array.

Eventually this overwrites the groups you've set by your onSaveUser event.

Here is a (dirty) hack that works

craft()->users->onSaveUser = function ($event) {

   craft()->userGroups->assignUserToGroups($user->id, $groupId);
   craft()->params['noGroupReset'] = true;

};

craft()->userGroups->onBeforeAssignUserToGroups = function ($event) {

   $noGroupReset = (isset(craft()->params['noGroupReset']) && craft()->params['noGroupReset'] === true);

   if (count($event->params['groupIds']) == 0 && $noGroupReset) {
      $event->performAction = false;
   }

};


You'll want to make sure you include all of the Calendar field inputs in order for this to work. If you're trying to hide them for your workflow, you can set the fields to hidden, or wrap them in a div and hide them with CSS. :)


Multiple contact forms different receiver(s)

No. It's currently not possible, but you could make this a feature request! If you don't have the time, you could fork the plugin and make the changes yourself.


How to get users with birthday today in plugin/module?

Was able to get the results I needed by using the following query:

        $users = \craft\elements\User::find()
            ->where("extract(day from content.field_birthdate) = " . date('j'))
            ->andWhere("extract(month from content.field_birthdate) = " . date('n'))
            ->group('siteUsers')
            ->status('active')
            ->all();


This may help:

Add the following to the general.php

'cacheMethod' => 'redis',
'overridePhpSessionLocation' => 'tcp://localhost:6379'

Add the following to the index.php

ini_set('session.save_handler', 'redis')


How do I sort categories by title while preserving hierarchy?

You should be able to do this with a recursive macro.
Here is a macro alphaList which is passed a list of categories (in alphabetic order). For each category, it outputs that category, and then if that category has any children, it calls itself on an alphabetic list of those children.

To get the children of a category c, you combine descendantOf with descendantDist of 1: craft.categories.descendantOf(c).descendantDist(1)

To get the initial list of top level categories, you use the level parameter: craft.categories.level(1). That will mix together categories from all your category groups, so probably you want to specify the group: craft.categories.group('myGroup').level(1).

{% import _self as self %}

{% macro alphaList(cats) %}
{% import _self as self %}
  {% for c in cats %}

      {{c.link}}
      {% set children = craft.categories.descendantOf(c).descendantDist(1) %}
      {% if children|length %}

          {{ self.alphaList(children.order('title')) }}

      {% endif %}

  {% endfor %}
{% endmacro %}

{% set topCats - craft.categories.level(1) %}

  {{ self.alphaList(topCats.order('title')) }}


Use .total() instead of .count()

.count() will query the db and fetch all fields for all items relating to your criteria and then count them.

.total() only counts the number of items your criteria returns without all of their fields.


Craft admin twig templates broken somehow

Sorted YAY!

In case this is helpful to anyone, I tried deleting and reinstalling via composer then replacing the config and .env files but no luck there so I downloaded the latest version and updated just the vendor folder. It needed to update the database which it couldn't do for me so I took a manual backup and let it do it's thing and now it's all working again!


Get entries related to selected category only and not it's ancestors

Instead of using nav, you can just use your own code for getting children. I.e. loop through level 1, then within that loop check if they have ancestors at level 2, then within that loop check if they have ancestors for level 3 etc.


I'm sure I can give you a hand (Feed Me developer here) - would you be able to submit a Help request using the instructions here - https://github.com/engram-design/FeedMe#support? Happy to post back findings here.

EDIT: Thanks for your patience - This was indeed a bug, which has been fixed in the latest master.

Let me know if you continue to have issues!


You can convert your Markdown text to HTML using yii\helpers\Markdown, which is what the |md Twig filter hooks into:

'transformer' => function(\craft\elements\Entry $entry) {
    return [
        'body' => \yii\helpers\Markdown::process((string)$entry->yourTextFieldHandle),
    ];
},

If you want the equivalent of |md('text', inlineOnly=true) (where only inline elements are parsed – no <p> tags), call processParagraph() instead of process().

If you want to parse the copy as GitHub Flavored Markdown, pass 'gfm' as a second argument to process():

'transformer' => function(\craft\elements\Entry $entry) {
    return [
        'body' => \yii\helpers\Markdown::process((string)$entry->yourTextFieldHandle, 'gfm'),
    ];
},


How do I set up Craft to send emails from my local MAMP/Virtual Host X dev environment

These days I just use Mandrill.

It's simple to set up, free unless you're sending tens of thousands of emails, and you can continue to use it on any development (or production) machine without any configuration changes.

Just set the Mandrill SMTP settings in the Craft admin area, and you're done.


Only show items related to the lowest category level

This is a truly tricky one. Let's restate the problem:

  For each category in a tree list of categories: We want to display content from an element if the element is related to the category but not related to any of the category's children.

Off the top of my head, I can't think of a really performant way to do this... So, hopefully there aren't too many categories in your setup, and caching is key.

First we need to generate a recursive structure of categories:

{% set categories = craft.categories.group(...) %}

{% nav category in categories %}

    {% include '_elementsForThisCategory' with {category: category} only %}

    {% ifchildren %}
        {% children %}
    {% endifchildren %}

{% endnav %}

(You could easily use a macro in place of that include. These days I prefer includes over macros for anything other than the very simplest use cases.)

Next (in the included template/macro), we need to create a list of elements that are related to the present category but not related to any of its children:

{# Query entries that are related to this category's children. #}

{% set relatedToChildCats = craft.entries.relatedTo({
    targetElement: category.getChildren()
    field: 'yourMatrixField.yourCategoriesField'
}) %}

{# Query entries that are related to this category,
   and exclude the entries that are related to this category's children. #}

{% set theBuckStopsHere = craft.entries.relatedTo({
    targetElement: category
    field: 'yourMatrixField.yourCategoriesField'
}).id('not', relatedToChildCats.ids) %}

{# Display the content however you want. #}

{% for entry in theBuckStopsHere %}
    ...
{% endfor %}

→ You probably noticed that my example uses Entry elements, and your stated use case deals with MatrixBlock elements. I wanted to give the example using purely out-of-the-box-friendly code, and unfortunately Craft 2 doesn't provide a template method for querying Matrix blocks... But luckily, our good friend Low wrote a nice plugin (Low Blocks), which adds a handy craft.lowBlocks template variable.


Is using nested extends a wise idea or will it be a performance/maintenance nightmare?

I like to have the document skeleton with the head, scripts etc. in a _base.html template and if there's more than one basic page layout (think sidebars etc.) I additionally extend it with _layout-a.html, _layout-b.html, templates. Everything else I use includes for.

The templates are being transpiled down to PHP and cached, so there should not be any measurable performance influence really.


find which template is used in given website?

Craft CMS does not really have ready to use templates. This is why you should not be able to find any references to that. In difference to Wordpress, etc. – usually these are hand-crafted. Is this what you were asking?


You can use the Feed Me plugin if you like! While it can save feed items as entries, you can use the template tag which allows you to simply fetch feed data without actually saving it. Then you can loop through your feed items in your templates.

Let me know if you have any issues - I created the plugin, so happy to assist :)


How to check structure type has any entries/children from anywhere on my site?

To do a check if a structure has content you could do

{% set structureNav = craft.entries({ section : 'structure_casestudies' }).first() %}

{% if structureNav != "" %}
    I exist.
{% else %}
    I don't exist.
{% endif %}


For reference to anyone else that might have this problem. Some of the tables in my database did not have foreign keys in the specific Craft format. This occurred when table changes were done manually without knowing about this extra detail.
Shout out to Brad Bell with Craft support for catching and fixing the problem.


I added a few new lines to conf:

server {
    listen      ip:80;
    server_name example.com www.example.com;
    root        /home/User/web/example.com/public_html;
    index       index.php index.html index.htm;
    access_log  /var/log/nginx/domains/example.com.log combined;
    access_log  /var/log/nginx/domains/example.com.bytes bytes;
    error_log   /var/log/nginx/domains/example.com.error.log error;

    location / {
        location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
            expires     max;
        }

        location / {
            try_files $uri/index.html $uri $uri/ /index.php?$query_string;
        }

        location ~ [^/]\.php(/|$) {
            try_files $uri $uri/ /index.php?$query_string;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            if (!-f $document_root$fastcgi_script_name) {
                return  404;
            }

            fastcgi_pass    127.0.0.1:9002;
            fastcgi_index   index.php;
            include         /etc/nginx/fastcgi_params;
       }
}

location ~* "/\.(htaccess|htpasswd)$" {
    deny    all;
    return  404;
}

location /vstats/ {
    alias   /home/User/web/example.com/stats/;
    include /home/User/conf/web/example.com.auth*;
}


From your config/app.php file you could do something like this:

return [
    'components' => [
        'otherDb' => [
            'class' => craft\db\Connection::class,
            'driverName' => 'mysql',
            'dsn' => 'mysql:host=localhost;dbname=mydb;port=3306;',
            'username' => 'myuser',
            'password' => 'mypass',
            'charset' => 'utf8',
            'tablePrefix' => '',
            'enableSchemaCache' => !YII_DEBUG,
        ],
    ],
]

You might not need all of those depending on what you're doing.

Then from PHP, could access it like:

Craft::$app->otherDb->createCommand(...);

And from a template:

{{ craft.app.otherDb... }}


So two primary things can contribute to database bloat:

If you have versioning turned on for your Sections, it will store every change in the db. The Delete Entry Versions plugin can help with this
If your backup isn't dropping temporary cache tables like templatecaches, templatecachecriteria, etc. that can contribute to the bloat as well

Given that you're seeing the backups get so much larger in a one week period makes me think it's probably the temporary cache tables causing the bloat, unless you're doing an awful lot of editing.

It's unclear how you are doing your backups, but check out the Mitigating Disaster via Website Backups; the Craft-Scripts used therein will not include the various temporary tables in the database backups.

It's also possible that too many cache tables are being created due to the way you're using the {% cache %} tags on the site; check out The Craft {% cache %} Tag In-Depth for details on what might be happening.

An easy way to check what's going on would be to connect to the database with something like Sequel Pro or what have you, and look at the number and size of the db rows in the various tables.


craftcms/vue-asset Related Error on Craft and Plugin Update

This should be fixed by P&T:

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

https://github.com/nystudio107/craft-imageoptimize/issues/171

https://github.com/nystudio107/craft-imageoptimize/issues/169


Conditionally show table column headings

This works for me:

{% set showCol1 = false %}
{% set showCol2 = false %}
{% set showCol3 = false %}
{% set showCol4 = false %}
{% set showCol5 = false %}

{% for row in entry.fieldname %}
{% if row.col1|length %}{% set showCol1 = true %}{% endif %}
{% if row.col2|length %}{% set showCol2 = true %}{% endif %}
{% if row.col3|length %}{% set showCol3 = true %}{% endif %}
{% if row.col4|length %}{% set showCol4 = true %}{% endif %}
{% if row.col5|length %}{% set showCol5 = true %}{% endif %}
{% endfor %}

        {% if showCol1 %}Col 1	{% endif %}
        {% if showCol2 %}Col 2	{% endif %}
        {% if showCol3 %}Col 3	{% endif %}
        {% if showCol4 %}Col 4	{% endif %}
        {% if showCol5 %}Col 5	{% endif %}

{% for row in entry.fieldname %}

        {% if showCol1 %}{{ row.col1 }}	{% endif %}
        {% if showCol2 %}{{ row.col2 }}	{% endif %}
        {% if showCol3 %}{{ row.col3 }}	{% endif %}
        {% if showCol4 %}{{ row.col4 }}	{% endif %}
        {% if showCol5 %}{{ row.col5 }}	{% endif %}

{% endfor %}


What is the recommended Nginx configuration for Craft?

Definitely not an nginx expert, but this has been working well for anyone that's tried it so far:

server {
  listen 8080 default;
  charset utf8;
  server_name example.com;
  root /path/to/example.com/public;
  index index.php index.html;

  # Logs
  error_log /usr/local/etc/nginx/logs/example.com.error.log debug;
  access_log /usr/local/etc/nginx/logs/example.com.access.log;

  location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }

  location ~ ^(.*)$ {
      try_files $uri $uri/ /index.php?p=$uri&$args;
  }

  location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
    expires max;
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
  }

  location = /robots.txt  { access_log off; log_not_found off; }
  location = /favicon.ico { access_log off; log_not_found off; }
  location ~ /\. { access_log off; log_not_found off; deny all; }
}

Note that it's making a few assumptions about how you've setup php-fpm and what ports things are listening on, so those may need to be adjusted.


Trouble finding the correct path to template in custom module and getting the "Unable to find the template" error

If this is a module and not a plugin, you might need to declare your base template directory in the Module's __construct using:

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;
    }
});

See Andrews's article on the subject.


Cannot delete user that was subscribed to a subscription

This is a known bug: https://github.com/craftcms/commerce/issues/1048

And some more characters for Stack Overflow's benefit.


How to populate a custom checkbox field with tag data dynamically?

I don't have enough reputation to post this as a comment, but this should help you pull the data on the front end with the LJ Dynamic Fields plugin.

Install the LJ Dynamic Fields plugin.

Create a 'Checkboxes (dynamic)' field with the following code:

{% for tag in craft.tags %}
   { "value":"{{ tag.id }}" , "label":"{{ tag }}" }
   {% if not loop.last %},{% endif %}
{% endfor %}

Front-end template code:

{% for tag in craft.tags %}
    <label>{{ tag }}</label>
    <input type="checkbox" value="{{ tag.id }}" {{ tag.id in entry.myCheckboxesDynamicField ? 'checked="checked"' }}>
{% endfor %}


Multiple Site Manager Homepages and Fields

What you're actually looking for here are the translation settings. These are stored against each field: in a multi-site installation, each field can be "translated" per site, per language or per site-group. ("Translated" is perhaps a confusing label here if your two sites are technically in the same language).

Set your Introduction field to be translatable for each site and it will be able to store unique content for each site.

This approach gives us lots of flexibility to have some fields with shared content and others with unique content, which cuts down the amount of duplicate editorial effort considerably on large multi-site installations where, for example, each site may want to use the same banner image but have different captions etc.


Yep, there's a great mystery about how the in containment operator actually works with objects. Twig Docs say it's possible:

  You can use this filter to perform a containment test on strings, arrays, or objects implementing the Traversable interface.

but I also tried this (multiple times) and did't get it working. I eventually always ended up using a workaround. In your case I'd do the following and use the entry's ID in the conditional:

{# Get arrays of entries #}
{% set entriesA = craft.entries(paramsA).find() %}
{% set entriesB = craft.entries(paramsB).find() %}

{# Prepare merge #}
{% set entriesBIds = craft.entries(paramsB).ids() %}
{% set allEntries = entriesB %}

{# Merge arrays #}
{% for entry in entriesA %}

    {# Don't merge duplicates #}
    {% if entry.id not in entriesBIds %}
        {% set allEntries = allEntries|merge([entry]) %}
    {% endif %}

{% endfor %}


Using cURL or file_get_contents is empty when calling a Craft page

Found a solution. I needed to set the requireUserAgentAndIpForSession to false,  http://buildwithcraft.com/docs/config-settings#requireUserAgentAndIpForSession

Seems like having to disable this for a particular url could open up other issues across the board.


Craft Commerce update variant field in plugin

This is the general mechanism for updating custom fields on elements - use setContentFromPost and then call the element's save function.

    $variant->setContentFromPost(array(
        'fieldHandle' => $newValue,
    ));
    craft()->commerce_variants->saveVariant($variant);

You should catch exceptions around that really, to handle any errors that may arise (as the model gets validated during save etc.)


How to check custom field not empty within params?

You’re just missing the : at the end of :notempty: in your second example. This will work:

{% set params = { section: 'sectionName', customField: ':notempty:', limit: 10} %}


Display Matrix block field base on location of query

Your code would work as-is if block.body was a Plain Text field.

But since it's a Rich Text field, it technically returns a RichTextData object and Twig's in operator doesn't know what to do with objects.

This will grab the string data from the Rich Text field so in operates as you'd expect.

{% for block in entry.supportContent.type('contentBlock') if query in block.body.getRawContent()  %}
    <h3>{{ block.heading }}</h3>
{% endfor %}


In Craft assets do not get "their own page" by default, but you can easily create them with a Dynamic Route. So go to Settings → Routes and add a new route with a number token, e.g. assets/<number> and route those URIs to a new template, e.g. assets/_entry.

With this route set up you can now link to an asset's entry page like so:

In your assets/_entry.html template you do now query for your asset via its ID, which is now available as a variable named "number". Use the exit tag to 404 the request in case no asset was found for the given ID.

{% set asset = craft.assets.id(number).first() %}

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

{{ asset.caption }}


In the upcoming Craft 2.2 release, we've added a using key parameter to the {% cache %} tag for for situations like this.

So you'd be able to do something like this for per user caching:

{% cache using key "myImportantUserCache" ~ currentUser.id %}


How can I get the correct label of a dropdown that has matching values?

Craft saves only the option value of a field, not the option description. After saving and editing again, it loops trough all the option values and compare it with the saved value. If it matchs it selects the first option.

You always need to have unique values. For example you can use 5fix and 5var as option values. If you need different outputs in your frontend template, you can use a switch case like this (code is untested, but should work):

{% switch entry.field %}
  {% case "5fix" %}
    Fixed 5%
  {% case "5var" %}
    Variable 5%
{% endswitch %}


How to update different parts of the same Entry by different Users

Definitely multiple ways to do this but I think you're close. I wouldn't want to have multiple users hitting the same entry. Use Craft's power of relations to help here.

I'm guessing you're trying to great some kind of "rotary" or networking registration system?

You need 2 more sections: Guest Names and Guest List (name these whatever you want).

Guest Names is straightforward, it basically is going to be a list of every guest name available. You just need 1 field: the name. Craft's user ownership will take care relating this back to the User who created it and the Partner it contains.
Guest List is going to hold the master list. You need a couple more relational fields, one to relate back to tell which which event it's for (in your Events section) and another to "hold" the names of the guests attending.

Now it's just a matter of wiring it all up. You're going to want users to post to the Guest List and Guest Names sections. It's up to you how you want to handle the validation on the front end as to whether a guest already exists that's "owned" by the User.

The beauty here is also if you do multiple events and the same people attend the events, when someone registers, you can simply pull up their prior Guests and offer those up as guest choices too. Again, I'm just speculating.

When it's time to pull out a guest list, just query your Guest List section based on the Event you want, loop through the event, and grab the names for each attendee.


On a Archive: how could I break cache for the current year, but not the others?

You could use the new Cold Cache pluging from P&T which:

  Adds a new {% coldcache %} tag to Craft, which works just like Craft’s
  built-in {% cache %} tag, except that this tag won’t record which
  elements and element queries are active between its tags. The only way
  caches will ever get deleted is if they expire, or an admin clears
  them using the Clear Caches tool in Settings.


Route that should be matching numbers not matching a zero?

An easy fix could be to define an additional route without the offset parameter:

return array(
    'articles/(?P<sectionId>\d+)' => 'articles/index',
    'articles/(?P<sectionId>\d+)/(?P<offset>\d+)' => 'articles/index',
);

In your template, you'd need to check if the offset parameter is defined, and if not, set it to 0:

{{ offset | default( 0 ) }}

or

{% set offset = offset is defined ? offset : 0 %}

EDIT:

Another way to solve this is by making the offset segment capturing group optional, as per @carlcs' answer to this question – in my opinion this is a bit more elegant than having two different routes:

return array(
    'articles/(?P<sectionId>\d+)(/(?P<offset>\d+))?' => 'articles/index',
);

The trick here is wrapping the last segment in parentheses, appending a question mark at the end.


A user on their local machine/intranet has a wildcard value setup to resolve to the servers IP address. Even though the DNS is configured to disregard any wildcard value, it seems as though a wildcard value is setup the point to the servers IP on a local/intranet machine.

What was happening was users mistyping the URL. With a typing of the URL "www", the page was still resolving and becoming cached in Craft.

From my local machine, I edited my host file to test this theory and it turned out to be the case.

Found that my rewrite conditions in the htaccess were messed. I've updated my htaccess rules as well (Arcustech server). Forces "WWW" over SSL.

RewriteEngine On

    # If SSL request WITHOUT WWW
    RewriteCond %{ENV:SECURE_REDIRECT} on
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # If NOT SSL request WITHOUT WWW
    RewriteCond %{ENV:SECURE_REDIRECT} !=on
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # If NOT SSL request WITH WWW
    RewriteCond %{ENV:SECURE_REDIRECT} !=on
    RewriteCond %{HTTP_HOST} ^www\..+$ [NC]
    RewriteCond %{HTTP_HOST} !^(local\..+|staging\..+|.+dev)$ [NC]
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # Send would-be 404 requests to Craft
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
    RewriteRule (.+) index.php?p=$1 [QSA,L]


Existing website written in PHP Zend Framework

We've successfully implemented a setup that will solve your issue with several sites. Unfortunately we haven't been able to open source things yet, but this is our general process:

We set up a Craft install on a separate domain (or subdomain, in our case). Then we serve the content as JSON instead of html in our layout template.

Our entry templates are totally normal, outputting html like any other template does. This layout just wraps the whole thing in a json object (and does not include the header/footer etc).

Then on the ZF side, we wrote a module to pull in the data from the separate domain and output it in our app, using the normal layouts that already existed. It is also obviously heavily caching the content it receives from Craft.

So, ZF is actually handling all of the requests by end users, and the only things going to Craft are actually curl requests from ZF.

We have ZF send along a Header telling Craft that the request is coming from ZF, and then we have Craft check for that header. If it exists, it uses layout.json, and if not, it uses layout.html.

layout.html has a dummy version of the header and footer, and is only used for Live Preview basically. The layout.json file serves our content as json to the ZF app.

Here is our layout.json:

{% header 'Content-type: application/json'
%}{% set response = {
    success:true,
    metadata: {
        {# some custom data #}
    },
    data: {
        meta: (head is defined ? head : {}),
        body: block('content')
    }
} %}{{ response|json_encode()|raw }}

So, while this doesn't mess with custom routing, it will allow you to keep your ZF app going and have Craft handle marketing/static pages.


error when trying to loop through grouped entries according to dropdown field

You have to remove the entry from your entry.resourceType

{% set allEntriesByCat = allEntries|group('resourceType') %}

will work


How to watch for changes on an Element Select Relations field?

I think there's a few ways to skin this cat, but the most robust way would probably be to listen to the the selectElements event for the BaseElementSelectInput instances bound to each field's container element (the instance will be bound to the
 node, except for Categories fields where it'll be bound to the
 node, for some reason) and can be accessed by calling $('.elementselect').data('elementSelect').

You can use the .on() method to listen to the actual events, here's one way to do it:

$('.elementselect, .categoriesfield').each(function () {
    $(this).data('elementSelect').on('selectElements', onSelectElements);
});

function onSelectElements(e) {
    var $field = $(e.target);
    var selectedElements = e.elements;
}

HUGE CAVEAT

Depending on when your plugin's JavaScript runs, the elementSelect data attribute for the element select input DOM nodes may return null.

This is because Craft actually initialises the BaseElementSelectInput instances in some inline JavaScript injected into the source, and this JavaScript is, unfortunately, written to the page after your plugin's JavaScript resources are queued up (after any inline JavaScript your plugin adds, too).

In other words, if you need to hook into the BaseElementSelctInput instances on pageload, you'll need to poll for the data('elementSelect) attribute (ew, I know):

$('.elementselect, '.categoriesfield').each(function () {
    var now = new Date().getTime();
    var getElementSelect = (function () {
        var elementSelect = $(this).data('elementSelect');
        if (elementSelect) {
            // Woo, I can haz elementSelect
            elementSelect.on('selectElements', onSelectElements);
        } else if (new Date().getTime() - now < 5000) {
            // Poll for 5 secs (then give up)
            Garnish.requestAnimationFrame(getElementSelect);
        }
    }).bind(this)
    getElementSelect();
});

Hack alert: If you don't want to poll for the elementSelect instances, there is another way. Credit due, I learnt this trick from looking at Benjamin Fleming's source code:

var elementSelectInit = Craft.BaseElementSelectInput.prototype.init;
Craft.BaseElementSelectInput.prototype.init = function () {
    elementSelectInit.apply(this, arguments);
    this.on('selectElements', onSelectElements);
    this.on('removeElements', onRemoveElements);
}

function onSelectElements (e) {
    console.log(e);
}

What the above does, is to basically hijack the BaseElementSelectInput class' init method, in order to add some custom event listeners when each BaseElementSelectInput instance is initialised. Works like a charm and – even if it's a huge hack – is quite a bit cleaner than the polling method, in my opinion.


Craft 3 Multi Site - Have a related entries field relate to another site, but respect localization

You can use a matrix field with a block and entries field for each sub-site.


Get related variants from entry and then show products for related variants and then loop only the variants that are related in commerce

After some further trial and error I have made this work like so.
However, it feels like there is or should be a simpler method....what am I missing or what is a better approach?

{% set selectedVehicle = craft.entries
  .section('vehicles')
  .id(vehicle)
  .with( [
    'vehicleBrand',
    'oemFixings',
    'afterMarketFixings'
  ])
  .one() %}

{% set variantsQuery = selectedVehicle.relatedVariants %}

{% set variantsByIDS = [] %}

{% for variant in variantsQuery %}
  {% set variantsByIDS = variantsByIDS|push(variant.id) %}
{% endfor %}

{% set wheelSpacers = craft.products
  .type('wheelSpacers')
  .hasVariant(variantsQuery)
  .orderBy('title ASC')
  .all() %}

Now Show the products and then loop only the variants that are related to the vehicle.

{% for product in wheelSpacers %}
  {% set productVars = product.variants|filter(purchasable => purchasable.id in variantsByIDS) %}

{{ product.title }}

{{ product.id }}

This product has {{ product.variants|length }} options in total

Only {{ productVars|length }} options are related

    {% for purchasable in productVars %}
      {{ purchasable.title }}
    {% endfor %}

{% endfor %}


How can I add attributes to craft field?

If you take a look at the FieldType documentation it looks as the you need to create a template for the input field in which you can specify the actual html for your field. The example in the documentation is for a textarea but in your case you can substitute this for a select.

Then once you've done that just override the getInputHtml method to render your new template.


Craft install failed with error php7 not found, but server has php 7 installed

It sounds like your server environments are different. It is possible to run different version of PHP on different parts of a server, so it really depends on your setup, but that is surely what is going on here. Without more details about your server I don't think it will be possible to give a more detailed answer. Good luck!


How do I get model/record attributes in their proper types, and not just strings?

Currently the only thing Craft does in BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() is some normalization when the attribute in either case happens to be AttributeType::DateTime or AttributeType::Mixed.

All other attribute types will be returned directly as the database returned them (as a string).

However, I agree with you that we probably should be doing more to return the exact type as the attribute specifies.  Since that's potentially a big breaking change, though, it'll have to wait until Craft 3.0.

The good news is, thanks to PHP's loose typing system, you can still workaround most cases.

For example a bool will come back as either the string '1' or '0'.

Using that in a PHP conditional if ($myModel->boolAttribute) will evaluate to true or false.

Using your float example: '1402.50' + 100.00, PHP will properly cast that to 1502.50.


Disabled product variant still shows in {% for %} loop

This should filter the variants by their enabled status:

{% set product = craft.commerce.products.id(productId).first() %}

{% for variant in product.variants if variant.enabled %}
    {{ variant.id }}
{% endfor %}


SproutForms: User permissions to edit form settings not being honored

I ran into this as well. I only wanted to client to view the submissions but not edit the actual forms. I don't believe it's a bug they just didn't give it a separate permission.

Here's my workaround:

I edited all three sproutform templates in the _layouts folder.

base.html
elementindex.html
settings.html

I moved

forms: {
  label: "Forms"|t,
  url: url('sproutforms/forms')
}

within the

if currentUser.can('editSproutFormsSettings')

Now the "Edit Form Settings" permission includes the actual forms.


How can I pre-raw a Model attribute for the Twig template? (ie. "myModel.myAttr" without requiring the raw filter)

The easiest way i've found to do that is to use TemplateHelper::getRaw()

So in your "prepValue" function inside your fieldtype class do something like this

function prepValue($value) {
    //any other data manipulation stuff
    return TemplateHelper::getRaw($value);
}

More info on prepValue in the docs.


Sprout reports timing out on thousands of records

As you suspected, Sprout Reports is not designed to handle large quantities of data if it's more than your server can handle. As for how many records you could export, it really just depends on how impressive your query is and how much your server can handle.

We could potentially consider adding support for batching large exports. I've created a ticket if you'd like to add your vote for it: Add support for batch exporting large data sets

For now, if you plan to do this on a regular basis you may want to invest in writing a script that makes this a bit easier to do or reach out and contract us to prioritize adding support for this feature.

Within the scope of optimizing the existing queries in your Twig template reports, you could potentially use techniques like:

Eager Loading.
Saving related data ahead of time using a field like the Preparse Field which could potentially reduce the need for complex joins when performing the actual query.
Advanced Twig query techniques (I don't know where these are documented but Brandon mentioned them in his slides here).
Create custom variables or twig functions in your own custom plugins to help optimize how the queries are actually being handled.

Outside of optimizing the query, you could add date range (or some other) settings that lets you give the user control over reducing the size of the full query. There is an example of creating a date range field in the example templates provided in the plugin.


Thanks for giving Placid a try, sucks you have had issues using it. I understand you're using Guzzle now, but for future reference I think I know what was going on.
Caching
In this case you would need to turn caching off for the Placid request, this is due to you needing a new request for each iteration, I will be looking to improve the caching in the near future to be more intelligent but in the meantime just setting { cache: false } should fix this:
{% for song in craft.entries.section('music') %}
  {% set params = { 'id' : song.itunesId } %}
   {% set lookup = craft.placid.get('itunesMusic', { params : params, cache: false } ) %}
   {% for track in lookup.results %}
    {{ track.trackName }}
  {% endfor %}
{% endfor %}

I've set up an example so you can see it in action here
I hope that helps if you choose to use Placid again in the future!


Probably best to just update the address business tax ID if it is in the wrong format automatically for them.
Event::on(Order::class, Order::EVENT_BEFORE_SAVE, function(\craft\events\ModelEvent $event) {
    /** @var Order $order */
    $order = $event->sender;
    if ($order->getShippingAddress() && $order->getShippingAddress()->businessTaxId) {
        $newTaxId = "AU".$order->shippingAddress->businessTaxId; // transform this into the right format based on address country (if it is not already)
        $address = $order->shippingAddress;
        $address->businessTaxId = $newTaxId;
        $order->setShippingAddress($address); //  address will save when order saves.
    }
});


Modify/add to price based on custom field?

You could simply use variants to handle this couldn't you?  A non-name and named variant, each with a different price.

There's no other built in way to do what you want without PHP, I think.  The PHP would not be too complex though, if you fancy adventuring into Craft plugins, which are super-useful with Commerce in general, opening up all sorts of extra possibilities.


Showing/Hiding children of a Structure based on categories

Something like this should do the trick! You want to get all the section parent entries, then search for child entries that are related to the category you want.

{% set parents = craft.entries.section('your_structure_handle').level(1) %}

{% for parent in parents %}
    {% set children = craft.entries.decendantOf(parent).relatedTo(category) %}
    {% if children|length %}

{{parent.title}}

        {% for child in children %}

{{child.title}}

        {% endfor %}

    {% endif %}
{% endfor %}


An error occurred when rendering a template

You can receive this error if you have uploaded a Craft website and your craft/storage/runtime/cache and craft/storage/runtime/complied_templates folders are not writable.

We made these folders writable and resolved the error.


Corruption of Link to an Entry links within Rich Text field

It's entirely possible it was the stuck tasks depending on how the task originally failed, how many (and which ones) were backed up behind it and how many (and what kind of) changes were made on the site while the tasks were stuck.

Hard to know with 100% confidence, though.


Optimize queries with list of image thumbnails

I think that's how it works and there's no way around this. That asset is related to your entry and to get the asset's URL property, Craft has to do a query to the database.

That means: each page with lots of thumbnails should be cached. :(


How to return asset from custom user field

You have to make sure you enabled the option Assets in this volume have public urls in your volume settings at /admin/settings/assets/volumes/.

This checkbox is disabled by default thus your getUrl() function will always return an empty string/null.


Delete CSRF cookie on submit form success

I guesss this could be accomplished using the cookies plugin or a simple jquery cookies library like js-cookie.

This is how you would go about it with the cookies plugin: set the cookies name without any value:

{{ setCookie( NAME ) }}


Dynamic upload location for Super Table within a Matrix field?

Have you tried using {owner.owner.slug}? If you've got Matrix > Super Table > Asset, and you're trying to get an attribute on the Entry/Element, you'll need to go two level out from the Super Table field.

Entry
  Matrix
    Super Table
      Asset Field

The owner of the Super Table field is the Matrix field. The owner of the Matrix field is the Entry.


I'd suggest giving the Matrix templating docs a once-over.
If steps is the name of your Matrix field, then {% for row in entry.steps %} is going to be looping over each of the Matrix blocks you've defined.
Then you'd want to check for the stepImage asset field in the correct block. i.e.
{% for block in entry.steps %}
    {% if block.type == 'myBlock' %}
         {% set image = block.stepImage.one() %}

         {% if image %}
             {{image.url}}
         {% endif %}
    {% endif %}
{% endfor %}


What is the most adviceable way to combine a staging and live database?

The way we do it is we take a copy of the live database when we begin development work, do the dev work on local/stage, get sign off... then manually add the new fields etc onto the live database. Otherwise, you're going to lose data.

I don't know of any way you could automagically merge two different databases.

One method to help speed up copying fields from one database to another (which is what you're doing) is to use the Field Manager plugin, which can export fields as JSON from your staging version, and you can import that JSON using Field Manager again on the live version. You'll still need to manually assign those fields to the associated sections.


Simplify templating query with Super Table

Someone else will surely better answer the larger question you're asking, but one small point: as you've written it, you're running the filter currentDay|lower many, many times.

Since that will be static for the duration of the loop, even if Craft/twig doesn't have more efficient ways to handle your query, you should do something like {% set currentDayLower = currentDay|lower %} once around line 4 and then compare {% if day == currentDayLower %} in order to avoid re-doing a filter in a loop.


Until the plugin store officially becomes a thing, Straight up Craft has got the most curated list of plugins available for Craft at the moment.

I'm not seeing anything like you're describing for users, but it is definitely something a plugin should be able to handle.


You're getting "Couldn’t save the new user: Array" because $newUser->getErrors() returns an array of validation errors (in case there are more than one).

If you want to print them all to a log file, you can do something like this:

AutoUserEntryPlugin::log('Couldn't save the new user: '.implode(', ', $newUser->getErrors()), LogLevel::Info);


How to link to previous/next entries in a section?

You are probably not using this within a craft.entries loop. Position it inside a loop or set custom parameters for your prev and next elements:

{# Set parameters for prev/next elements list #}
{% set params = craft.entries.section('blog').order('title asc') %}

{# Get the prev/next elements #}
{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}

{# And make sure to only output the links if the element exists #}
{% if prevEntry %}Previous{% endif %}
{% if nextEntry %}Next{% endif %}


Showing pagination for a date range of entries

It's difficult to give specific code help without seeing some input/output examples, but here's a go-by:

You can say that an event occurs during a date range if:

The event begins before the date range ends
and, the event ends after the date range begins

So, the pseudocode looks something like:

Prepare a DateTime representation of the range rangeStartTime (e.g. today at 00:00)
Prepare a DateTime representation of the range rangeEndTime (e.g. tomorrow at 00:00)
For each event, check if the criteria are satisfied: eventStartTime < dayEndTime and eventEndTime > dayStartTime
If the criteria is satisfied, include the event.

So, let's say each of my Event entries has eventStartDate and eventEndDate fields, and I want to list out all the events that occur today (i.e. including, for example, events that started yesterday and end tomorrow).

I could do something like...

{% set dateRangeStart = today|date('Y-m-d') %}

{% set dateRangeEnd = tomorrow|date('Y-m-d') %}

{% set eventsInRange = craft.entries
    .section('events')
    .eventStartDate('<'~dateRangeEnd)
    .eventEndDate('>'~dateRangeStart)
%}

Now eventsInRange is an ElementCriteriaModel that finds all Event entries in our date range. And since it's an ElementCriteriaModel, you can plug it into the {% paginate %} tag to get paginated results according to whatever other parameters you desire.


How to show entires from past 12 months?

I used the after parameter in my query.

{% set query = craft.entries({
    after: now|date_modify('5:00 -12 months')
}).all() %}

I'm grabbing todays date, then modifying with the date_modify filter. The 5:00 string makes sure it changes at the same time everyday.

I got the usage of date_modify from carlcs's answer here: How to only show entries older than 12 months


Bypass Varnish cache if user is logged in

So the answer is to test the cookie for a name with username in it, and pass if it exists. You could also check for an exactly 32 digit alphanumeric cookie name I guess.

if (
 req.http.Cookie ~ "username" # Craft sessions have the word username in them
)
{
    return (pass);
}`


How can I make an entries query based on currentUser is author or relatedTo currentUser

A blanket relatedTo query should do the trick.
craft.entries().section('thename').relatedTo(currentUser).all()


Using element queries in general.php config file

Add this at the top of config/general.php file:

use craft\elements\Entry;

And change your loginPath value to:

'loginPath' => function() {
   return Entry::find()->section('login')->one()->url ?? null;
},


I think there's a few ways you can do this with twig.

You should be able to check whether the category slug exists as an attribute on the entry object:

{% for category in craft.categories.group('foodMenuCategories') %}
    {% if category.slug in entry.getAttributes|keys %}
        ...

Or by using the category slug in an array accessor:

{% for category in craft.categories.group('foodMenuCategories') %}
    {% if entry[category.slug] is defined %}
       ...

Or whether the getAttribute() method on the entry model returns anything truthy for that handle:

{% for category in craft.categories.group('foodMenuCategories') %}
    {% if entry.getAttribute(category.slug) %}
        ...

It's also important, that the slug is the same in every language!


I needed to set the base-url to @web in:

Settings > Websites > "your Website" > base-url

This helps on my local docker-environment. Make sure, that your DEFAULT_SITE_URL="domain.something" is set in your .env file and that you are using the latest 3.2.x version.


Guest user registration using Commerce 3

This can definitely be done, but I don't think it's possible to do it all in the same form without using a custom module to handle either creating the user programmatically and then submitting to the Commerce controller or vice versa.
Craft has support for creating a user account via a front-end form (see the User Registration Form in the Craft docs) but you can't submit to that controller and also submit to the Commerce subscriptions controller as per the standard example template at the same time.
It might be possible to achieve something close to what you're looking for by showing a user registration form first, and then set the redirect input for that form to the payment page. However, if you want to have the user logged in directly after registration but before payment in order to save the user's payment details etc., you're going to need to do some custom development work to log the user in programmatically first since the default user registration controller just creates the account but doesn't log the user in.
I've done this sort of process where the user account is created, then logged in automatically, then they enter their billing address and payment details, but that was using Commerce Pro and a multi-step registration/payment form which is a bit more complex than your use case.


As mentioned in the comments on the Question, the solution here is to enclose your desired path with a url() function like so:

add item

The url() function will take your current SiteURL and append the provided path. You can view the offical documentation about url() here.


Updating a matrix row in an existing entry using a frontend form

You only use new1, new2 etc for creating new matrix blocks during the submission. For editing existing blocks, you need to use the block's ID in that same place. In your case that would be block.id.


Sub-Entries: Adding new Entries on Entries field

The thing you are talking about is a Craft.BaseElementEditor

You can see a working example within all ElementIndex js files

Craft.createElementEditor(this.elementType, {
    hudTrigger: this.$newCategoryBtnGroup,
    elementType: 'craft\\elements\\Category',
    siteId: this.siteId,
    attributes: {
        groupId: groupId
    },
    onBeginLoading: $.proxy(function() {
        this.$newCategoryBtn.addClass('loading');
    }, this),
    onEndLoading: $.proxy(function() {
        this.$newCategoryBtn.removeClass('loading');
    }, this),
    onHideHud: $.proxy(function() {
        this.$newCategoryBtn.removeClass('inactive').text(newCategoryBtnText);
    }, this),
    onSaveElement: $.proxy(function(response) {
        // Make sure the right group is selected
        var groupSourceKey = 'group:' + groupId;

        if (this.sourceKey !== groupSourceKey) {
            this.selectSourceByKey(groupSourceKey);
        }

        this.selectElementAfterUpdate(response.id);
        this.updateElements();
    }, this)
});

So it could look like

var button = $('#yourButton');
Craft.createElementEditor('craft\\elements\\Entry', {
    hudTrigger: button ,
    elementType: 'craft\\elements\\Entry',
    siteId: this.siteId,
    attributes: {
        sectionId: 1, // <-- insert your section id here
        typeId: 1 //<-- important, insert your valid type id otherwise it won't work
    },
    onBeginLoading: $.proxy(function() {
        button.addClass('loading');
    }, this),
    onEndLoading: $.proxy(function() {
        button.removeClass('loading');
    }, this),
    onHideHud: $.proxy(function() {
        button.removeClass('inactive').text('New Entry');
    }, this),
    onSaveElement: $.proxy(function(response) {
        // insert the id of the saved element to hidden input
    }, this)
});


Class not found error when running unit test on a plugin service

I figured out the problem, I needed to load in the service, and then my service needed to load in the model and record. So for the test code, I added the function:

protected function loadServices()
{
    require_once __DIR__ . '/../services/TournamentData_IndividualService.php';
}

Then for my setUp function, it became:

<?php
namespace Craft;

use \Mockery as m;
use PHPUnit_Framework_TestCase;
class TournamentData_IndividualServiceTest extends PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        $this->loadServices();
        $this->ingredientRecord = m::mock('Craft\TournamentData_IndividualRecord');
        $this->service = new TournamentData_IndividualService($this->ingredientRecord);
    }
}

Then in my service method, I added require statements for the model and record like so:

<?php

require_once __DIR__ . '/../models/TournamentData_IndividualModel.php';
require_once __DIR__ . '/../records/TournamentData_IndividualRecord.php';

namespace Craft;

class TournamentData_IndividualService extends BaseApplicationComponent
{
    protected $individualRecord;

    public function __construct($individualRecord = null)
    {
        $this->individualRecord = $individualRecord;
        if(is_null($this->individualRecord)) {
            $this->individualRecord = TournamentData_IndividualRecord::model();
        }
    }
}

Ironically, I managed to find the answer to my problem almost immediately after deciding to ask the community, but hopefully this helps somebody else in the future!


You're getting null back simply because the saveRelations() method doesn't actually return anything.

If you need to return true from addCategoryRelation if the relations are successfully saved, or possibly an error message (or false) if they aren't, you can consider wrapping the call to saveRelations() in a try/catch block – something like this should work:

public function addCategoryRelation(CategoryModel $category, EntryModel $entry)
{
    ...
    if (in_array($entry->id, array_values($relationsIds))) {
        return [
            'error' => 'Entry already saved.',
        ];
    }
    try {
        $relationsIds[] = $entry->id;
        return craft()->relations->saveRelations($field, $category, $relationsIds);
    } catch (\Exception $e) {
        // Something went wrong – return `false` or an error message, log the exception?
        return false;
    }
    return true;
}


Nothing clever I can think of, but it's an interesting idea.

You can either manually setup the redirects in your .htaccess file, or there are a couple of plugins that appear to let you manually manage redirects from the control panel.

A feature request to the plugin developers might be to get them to add support to listening to an (as-of-yet non-existent) "onMoveStructuredEntry" event in Craft that automatically creates the redirect for you.


View Sprout Form Entries in CP displaying error

The form handle can't contain special characters like - or *, the validation of that field is not working, but we'll fix that in the next release. In the meantime please update the form handle.


Convert a PHP image resource to a new Asset

You'll need to save the image to the filesystem and use that path as $tempPath.

https://www.php.net/manual/en/image.examples.merged-watermark.php


Calling template from controller redirects to dashboard

You will need to include your plugin handle, like:

$this->renderTemplate('myPluginHandle/index', array());


You can get the rest of the path from your asset's source and folder, I think something like this should do it:

$source = $asset->getSource();

if ($source->type != 'Local')
{
    throw new Exception(Craft::t('Paths not available for non-local asset sources'));
}

$sourcePath = $source->settings['path'];
$folderPath = $asset->getFolder()->path;

$assetFilePath = $sourcePath.$folderPath.$asset->filename;


Loading email templates in a Craft 3 plugin

I think you have to set the template mode to 'SITE', to let Craft know where to look for the template:

$view = \Craft::$app->getView();
if ($view->getTemplateMode() !== $view::TEMPLATE_MODE_SITE) {
    $view->setTemplateMode($view::TEMPLATE_MODE_SITE);
}

Craft::$app->mailer->compose('_email.html', ['body' => $emailBody])
    ->setFrom($fromMail)
    ->setTo($toMail)
    ->setSubject($subject)
    ->send();


So the problem is that you're using an example from my older article, which was written for Craft 2.x. This line:

craft()->config->set('generateTransformsBeforePageLoad', true);

...and also these lines:

if (craft()->plugins->getPlugin('Imager')) {
    $image = craft()->imager->transformImage($srcImage, [

...are specific to Craft 2.x; anything craft() is Craft 2.x; you can see some of the changes here: https://docs.craftcms.com/v3/extend/updating-plugins.html#high-level-notes


Those parameters are only meant to be used on entries within Structure sections. (Just updated the docs to make that more clear.)

If you want to get the next/previous entries within a Channel section, you can use EntryModel::getNext() and getPrev().

There’s a bit of a trick with those functions though, because “next” and “previous” are ambiguous. (Only consider the entries in a specific channel? Or just the ones with a specific custom field value? etc.) So you need to pass element criteria params into those functions to establish what the full order of entries is.

In your case, sounds like you want the next/previous entries within your news section. I’ll assume you want those entries to be listed by Post Date in descending order (so the latest stories are shown first), and the “Next” entry in this case would be whatever story came before the current one; and the “Previous” story would be whatever came later. (If my assumption is wrong, just change desc to asc in the order param.)

{% set newsCriteria = craft.entries.section('news').order('postDate desc') %}
{% set prevEntry = entry.getPrev(newsCriteria) %}
{% set nextEntry = entry.getNext(newsCriteria) %}

{% if prevEntry %}
  {{ prevEntry.title }}
{% endif %}

{% if nextEntry %}
  {{ nextEntry.title }}
{% endif %}


Add the mailing list "field" in the form you want by dragging it from the left sidebar to the form.
Click on the field when it's added.
In the right sidebar, change the dropdown field "Mailing Lists" to the list you want.


FeedMe: How to import data into the Matrix field of a section?

It seems that FeedMe cannot process such JSON objects as it needs them to be cleaner.

I ended up doing a lot of PHP processing of my exported data until it had the below format. With that FeedMe was happy.

{
  "title":"Emily Wurramara",
  "album":[
     {
        "album_release_date":"2017-02-08",
        "album_description":"",
        "album_tracks_1":"Hey Love",
        "album_tracks_2":"",
        "album_cover":"emily-wurramura_hey-love.jpg",
        "album_amazon_link_id":"",
        "album_itunes_link_album_name":"hey-love-single/1203932967",
        "album_title":"Hey Love (Single)"
     },
     {
        "album_release_date":"2017-02-22",
        "album_description":"",
        "album_tracks_1":"Hey Love Me Too",
        "album_tracks_2":"",
        "album_cover":"emily-wurramura_hey-love.jpg",
        "album_amazon_link_id":"",
        "album_itunes_link_album_name":"hey-love-single/1203932967",
        "album_title":"Hey Love (Me Too)"
     }
  ]
},


I cannot create any more admin user accounts

Could not instantiate mail function.

That error means that the PHP mail is not installed and/or configured for use on the server you're currently on.

You can either configure that to properly work, or go under Settings->Email and choose another mail delivery option that does work for you.


How would I pass an entry URL to an iframe in a template?

Load the entries into a div then create several buttons to change the width of the div, or use JS to resize the div. Thus showing your users what happens to the responsiveness of the design at different widths. It doesn't need to be a iframe. Or just send them to a template with a UI element showing them to resize the browser.


Possible to redirect elsewhere after saving an entry?

Yes!

Assuming you're using some sort of business logic plugin (if you don't have one, get one), then simply put this code in your main *Plugin.php file...

public function init()
{

    // Trigger template hook
    craft()->templates->hook('cp.entries.edit', function(&$context)
    {

        // Check to ensure that you're in the right section
        if ('mySection' == $context['sectionHandle'])
        {

            // Specify the preferred URI
            $uri = 'special-page/'.$context['entry']->uri;

            // Set the "Save" button redirect
            craft()->templates->includeJs("
                $(function () {
                    $('input[name=\"redirect\"]').val('{$uri}');
                });
            ");

            // Set the `cmd + s` shortcut redirect
            $context['saveShortcutRedirect'] = $uri;

        }

    });

}


Method (plugin free?) to combine search results across multiple searches (and element types)

To get this working I submitted a patch to 'SortByField' - https://github.com/dannynimmo/craftcms-sortbyfield - to get this plugin to work with Commerce products - and I now do this:

    {% set product_results = craft.commerce.products.search(query).order('score') %}
    {% set article_results = craft.entries.search(query).order('score') %}
    {% set all_results = [] %}

    {% if product_results|length %}
        {% set all_results = all_results|merge(product_results) %}
    {% endif %}
    {% if article_results|length %}
        {% set all_results = all_results|merge(article_results) %}
    {% endif %}

    {% if all_results|length %}
        {% set all_results = all_results|sortByField('searchScore', 'desc') %}
    etc.

Which is working well and the combined results make sense to me.

I am just wondering if their is a better/recommended and ideally plugin free way of doing this - i.e. sorting the combined result set by score?


Craft console app within windows batch script

In Windows' cmd, commands are joined by two ampersands like you specified (cd foo && dir), however in PowerShell (which Microsoft is pushing to replace cmd), commands are joined by semicolons: cd foo; dir.

Also, it looks like you have an orphan closing parentheses ) in your code. Is that supposed to be there?


Use subdomain for S3 assets in multi-site Craft installation

Your example of setting the S3 "URL Prefix" setting to something dynamic won't work because there are only a few settings in the Control Panel that Craft parses for dynamic Twig content and that isn't one of them.  i.e. in an Asset Field's Upload Location, Section Title/URL Formats, etc.

Honestly, I don't think there currently is a way to do that in Craft 2.

This should be possible in the upcoming Craft 3 by overriding the setting in config/volumes.php and doing your dynamic logic from PHP.


After transferring local to server, Twig Runtime Error: Impossible to invoke a method all() on an array

You can't call .all() twice. In myEntryQuery you have converted the result into an array, you are then trying to call .all() again, but at this point you have an array, so .all() can't be used as it's not an entry query anymore.
entries will now be an array, at this point you can loop through this array and output what you need.


I'd try and avoid the routes.php route (pun intended).  There isn't any need to get Craft involved in a redirect when your web server (Apache?) can handle it much faster.

If you're using Apache, then adding something like this to your public .htaccess file should do the trick:

RewriteRule ^fiveminutes$ /5minutes [NC,R=301,L]

Update:

Missed the part where you said this was in a plugin.  In that case you'd want to setup something like this in your main plugin's class file:

public function registerCpRoutes()
{
    return array(
        'fiveminutes' => array('action' => 'myPluginController/fiveMinuteRedirect'),
   );
}

Then from your MyPluginController.php class have an actionFiveMinuteRedirect() method that simply did a permanent redirect:

`$this->redirect('5minutes', true, 301);`


Normally you would create variations of a product that would then be purchased by a customer. An example could be a plain t-shirt (the product), which is available in small, medium & large (each of these would be a variant of the product). This way you can easily keep track of stock, set different prices (like your No. of meters) and add different field values, if needed.

I would create a variant for each "No. of meters" as this will require a different price to be charged. However, creating a variant for each and every configuration would be overkill.

As you don't need to track stock and each product will be made to order I would instead look at adding the options to the line item using name="options[optionName]".

The following is taken from the default templates that come with Craft Commerce.

<select name="options[giftWrapped]">
  <option value="no">No gift wrap.</option>
  <option value="yes">Gift wrapped.</option>
</select>

These options are then set on the line item for that order. These would be viewable on the order summary page in the control panel.