The asset volume needs to have public urls enabled. Thanks seb.


Why isn't Craft displaying my plugin's changelog details?

It looks like you have some en dashes – instead of hyphens - in your CHANGELOG.md version headings. These are probably causing some parsing issues.

Notice how there’s also no release date shown in the update utility.


Limit amount of entries a user can create based on their user group

I think a custom plugin is going to be the way to go with this.  Your template code would look something like:

{% set entries = craft.entries.section(‘listing’).authorId(user.id) %}

{% if entries.count >= craft.myPlugin.getEntryLimitForUser(user.id) %}
    No more entries for you!
{% else %}
    More entries for you!
{% endif %}

Your plugin would also hook onto the onSaveEntry event and keep an incrementing entry save counter for each user you're tracking.


Use getCriteria with OR condition on multiple fields

sorry I didn't try to do this and after trying, couldn't get it to work myself... So...

If you have flexibility and can replace your ligthswitches with a group of checkbox, this becomes a lot easier and potentially more flexible as you could add new 'types of logo' without reviewing your plugin whereas at the moment, you would need to manually add new 'types'.

So, if you can, change your ligthswitches for a group of checkbox called 'logos' for example and add 2 checkbox 'Web' & 'Email', then:

public function modifyUserSources(&$sources, $context)
{
    if ($context == 'index')
    {
    $sources[] = array('heading' => 'Stats Users');

    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $user_criteria->group = 'editors';
    $user_criteria->logos = ':notempty:';

        $sources['users:memberBranding'] = array(
          'label'    => Craft::t('Logo'),
          'criteria' => $user_criteria,
      );
    }
}

As long as a user 'has' a logo AND is an editor, they will show in your source.

If you can't change the lightswitch setup, I'm afraid I don't know how to do it and I would love to find out if you manage to get it working!


How do you display select Fields from a Matrix Block Type when there are multiple Fields?

It might seem counter-intuitive in cases where you only have 1 block type (i.e. quote) and only a single block, but your Matrix field will always be an array, where the blocks (i.e. the "children" of the Matrix array) aren't directly accessible:

entry.quotation
    - block1 (quote)
    ...

Usually, you'll output your blocks by looping through the Matrix field, checking each block's type. I find that using a {% switch %} statement is often cleaner than an if/else:

{% for block in entry.quotation %}

    {% switch block.type %}

         {% case 'quote' %}

{{ block.quoteText }}

             {{ block.quoteBy }}
             QuoteUrl

    {% endswitch %}

{% endfor %}

You can, however, opt to only output blocks of a certain type. This is done by "filtering" the Matrix field using the type method, and removes the need for the switch or if/else statement. This is convenient in cases where you know you'll only have 1 block type:

{% for quote in entry.quotation.type( 'quote' ) %}

{{ quote.quoteText }}

         {{ quote.quoteBy }}
         QuoteUrl

{% endfor %}

If you know there's only 1 block, you can even remove the loop entirely by explicitly targeting the first block for your filtered block type. The actual amount of code will be about the same as the above example, though:

{% set quote = entry.quotation.type( 'quote' ).first %}
{% if quote %}

{{ quote.quoteText }}

        {{ quote.quoteBy }}
        QuoteUrl

{% endif %}


How to output a placeholder image if an Assets field is empty

Thanks to Brad for the answer, and the solution was to use {% if entry.mainImage|length %} instead of {% if entry.mainImage %} for the conditional. So my working code looked like this:

{% if entry.mainImage|length %}
  {% for asset in entry.mainImage %}

  {% endfor %}
{% else %}

{% endif %}


Resaving Entries hitting a mysterious memory limit

Most likely you'll need to add this line to the Craft config file (craft/config/general.php)...

'phpMaxMemoryLimit' => '512M',

Craft 2 docs
Craft 3 docs


Offline update then upload files to server

If you're not able to increase your server's memory_limit and/or max_execution_time settings, then your current process is a way to "manually" update Craft 3.

Alternatively, if your server has Composer installed from the command line and you have SSH access, you can perform the composer update locally, then upload your composer.json and composer.lock files, then execute composer install from your project's root.

That method should use less memory than updating from the Control Panel.


Impossible to access an attribute ("created_at") on a boolean variable ("1")

That error basically means that you're trying to use the variable tweet as an object/iterable, but it's actually just a boolean (true/false).

Assuming the plugin you're using (i.e. craft.twitter) is Dukt's Twitter plugin, I think this is just a matter of your syntax being a bit off. The Dukt plugin's craft.twitter.get() method actually returns a response object where the
tweet objects are nested in an array called data. In other words, you can't loop on the object returned by craft.twitter.get() directly; you'll need to use the array in that object's data property:

{% set response = craft.twitter.get('statuses/user_timeline', {count:2}) %}

{% if response.success %}
    {% set tweets = response.data %}
    {% for tweet in tweets %}
        {% set tweetDate = date(tweet.created_at).diff(now).format('%a') %}
        ...
    {% endfor %}
{% else %}

An error occured:

{{ response.data|json_encode(constant('JSON_PRETTY_PRINT')) }}

{% endif %}

The above example is lifted from the plugin's documentation (although in the actual docs there's a typo, which could well be the cause for your issue). Note that the example also accounts for Things Going Wrong (tm), which is always a good idea when you're working with a third party API.

If the plugin you're using is not Dukt's, you'll need to check your plugin's documentation, to verify you're using it correctly. As a debugging effort, you might also want to try and dump() the response object variable to verify that it contains what you think it contains:

{% set tweets = craft.twitter.get('statuses/user_timeline', {count:2}) %}
{{ dump(tweets) }}

Note that the dump() method only works when devMode is set to true, and should not be left in production code.


No Underscores Allowed in Freeform Field Handles?

Not likely to be an issue for anyone in the future but just incase someone is looking at this... Turns out Freeform should be able to handle underscores in field handles. Just an oversight on the Solspace side and they're going to be patching in support for underscores shortly.


Access data when posting to controller from front-end

Turns out the ajax library I was using was expecting the data to be passed in a serialized format:

'comment=' + comment + '&entryId=' + entryId + '&authorId=' + authorId

With that as the body of the request, the data became accessible to my controlled by using craft()->request->getPost


I'm guessing the site you're setting up on the subdomain is on a new server?

  Craft CMS requires the PHP multibyte string extension in order to run.

That error means that the PHP multibyte extension isn't installed or enabled on your server and both Craft 2 and Craft 3 require it.


Debugging a Failed Custom Task in Craft CMS

I came across this Could not find the task component type. error upon trying to add a secondary task to my plugin.

Following the naming scheme that P&T have in the PowerNap plugin, try making sure you have one task named after the plugin itself WassermanNewsTask, and then follow the subtasks, or any other additional tasks, with the underscore naming, eg. WassermanNews_TwitterTask.

There's not really any thorough documentation on Tasks, so I can't verify this is the problem, but this is what worked for me.


Selecting descendants of a category when ancestor is clicked

Okay, please don't be afraid and give it a try. I'm using the angular way, it seems a little bit difficult but it's actually really easy once you get used to it and works perfectly as soon as you understand it a little bit. If you need changes I'll provide whatever you need.
Edit: here you can see a live example for it plunker or course without css but it is your html

Let's get into it.
For testing purposes I created this category structure in my backend and called the group filter.

First you need to include this library you can of course use the {% includeJsRessource %} as well

Then you create 2 javascript arrays one for the Culture, Democracy... I call them parents and one for their children that belong to them

// get all filters of the first level
{% set filters = craft.categories.group('filter').level(1).find() %}

In the end you'll have 2 array that could look like

Now the funny part starts
include this javascript file. You can ask whatever you want I'll explain it. Even if the syntax and everything what's going on seems a little bit strange, but make sure this is loaded after the library from above

var  myApp = angular.module('myApp',[]).config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});

myApp.controller('filterController', ['$scope', function ($scope) {
    // all parents
    $scope.parents = parents;
    // all children
    $scope.children = children;

    // return if the parent is selected or not
    $scope.filterBySelectedParent = function (item) {
        return $scope.selectedParents.indexOf(item.parent) !== -1;
    };

    // an array with all selected parent ids
    $scope.selectedParents = [];

    // include an item to the array or slice it when the input it clicked
    $scope.addFilter = function(id){
        var index = $scope.selectedParents.indexOf(id);
        if(index === -1){
            $scope.selectedParents.push(id);
        }else{
            $scope.selectedParents.splice(index, 1);
        }
    }
}]);

And finally your new html

                <input type="checkbox" ng-click="addFilter(filter.id);" value="{[{filter.id}]}">{[{ filter.title }]}

                <input type="checkbox" data-name="selectItemfocusArea" value="{[{ child.id }]}">{[{ child.title }]}

Explanation: so what actually happens is the following

you create 2 arrays in javascript based on your backend inputs
angular renders your menu based on those two arrays but the second one has a filter. Only clicked items of the first array are shown
as soon as someone clicks on an filter it is included in an array $scope.selectedParents
any change in this array is recognized automatically which results, that the html renders again => your other filters are shown.

Please tell me if I missunderstood you somehow.. based on my current state I can change nearly everything really easily in just a few clicks. For example if you would like to automatically select your children you would include ng-checked="filterBySelectedParent(child)" on your input and remove the | filter: filterBySelectedParent.. that's it


How to check how many characters there are in my string?

Twig has a length filter that can help you with that:

{% set stringLength = "Simple String" | length %}

Note that this also works on arrays to give you the number of items in the array.


I'm not sure I completely understand what you're trying to achieve, but maybe the Many to Many Field Type plugin does the trick?


Writing a plugin that triggers on a Control Panel Template Hook?

Figured it out after browsing some existing plugins' source:

Craft::$app->getView()->hook('cp.entries.edit.details', function(array &$context) {
    return 'My Button!';
});


Is [updating an entry] possible with just a twig template?

No. You'll need to write a plugin.

  How can I [let users update an entry via an URL]

There's a few ways to approach this. My recommendation would be to have your plugin expose a site route pointing to a controller method. That controller method would then take care of updating the entry, and possibly redirect the user back to the entry URI.

Assuming you want to send your users links that look like http://example.com/status/1234/live, here's what the route could look like:

'status/(?P<entryId>\d+)/(?P<status>[-\w]+)' => array( 'action' => 'myPlugin/status/updateStatus' )

With the above route, all matching URLs will be pointed to a actionUpdateStatus() action method in a controller named MyPlugin_StatusController. The controller would then need to handle the following:

Update the status for the entry matching the $entryId route variable (look at Working with Elements for ways to approach this
(Presumably) redirect the request back to the entry URI

  How can I do this in a safe way?

The URLs should probably include some sort of unique key (either as another route variable, or as a query string variable) to verify the request. For example, you could opt to include a hash of the author's email address; the controller could then decrypt the hash before updating the entry, verifying that the given email address matches the one on file for the entry's author.

Additionally, you should probably verify that the status route variable matches with a set of allowed statuses, such as "live", "pending" etc.


How to display all fields for an entry within an entry field type?

It seems on your website that you get the team listed, but not the photos. I think the problem might be that you are accessing the teamMembersPhotoof the entry, not the team.

You can try changing it to
{% for asset in team.teamMembersPhoto.find() %}


How to loop through Craft CMS query in Angular

Got it working like this:

  <ng-template ngFor let-obj [ngForOf]="entry.imageHero">
    <h1>{{ obj.heroTitle }}</h1>
  </ng-template>

This also works:

{{ entry.imageHero[0].heroTitle }}


Actually, the striptags filter (which is just a wrapper for the PHP strip_tags function) removes all HTML tags except the ones you pass in.

In other words, if you want to remove
 tags, just use the striptags filter without any parameters:

{# Will remove all HTML tags #}

{{ product.intro|striptags|raw }}

If there are other tags you want to retain, you'll need to pass those in:

{# Will remove all tags except
 and  #}

{{ product.intro|striptags('
')|raw }}

For a different take on stripping tags, you can use the Retcon plugin (which I wrote). With Retcon, you can remove all
 tags (and only
 tags; retaining their contents as well as all other tags) easily by using the retconChange filter:

{{ product.intro|retconChange('
', false) }}


Exclude certain entries and its children from navigation

If it’s true that the descendantOf param doesn’t allow to pass in multiple entries, you probably need to work around that issue and grab the descendants for each parent entry individually.

{% set parentIds = [3, 4, 5] %}
{% set excludeIds = parentIds %}

{% for parentId in parentIds %}
    {% set ids = craft.entries.descendantOf(parentId).ids() %}
    {% set excludeIds = excludeIds|merge(ids) %}
{% endfor %}

{% set idParam = 'and, not ' ~ excludeIds|join(', not ') %}

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


map values from checkbox field into category field using SQL

FeedMe plugin imports categories, so you could create an xml template file that outputs your entries and their checkbox values(separated by commas), then use FeedMe to import that file back in and map those checkboxes to your categories. They just have to match spelling, otherwise FeedMe will create a new category

FeedMe

Something like:

<xml>
  <blog>
    {% for entry in entries %}
      <entry>
        <title>{{ entry.title }}</title>{# required for import #}
        <category><![CDATA[{% for option in entry.checkboxFieldHandle %}{{ option }}, {% endfor %}]]></category>
      </entry>
    {% endfor %}
  </blog>
 </xml>


You're close!

{% set numberOfPhotos = entry.photos|length %}

{% if numberOfPhotos > 1 %}
  {# more than one #}
{% elseif numberOfPhotos == 1 %}
  {# exactly one #}
{% else %}
  {# no photos (always handle this case...) #}
{% endif %}


Limit the for loop returns with an if statement

If I'm following you correct, you can use a conditional in a for loop to do what you want.

So in your case, it would be something like:

{% for entry in craft.entries.section('news').order('articleOrder desc').limit(5).find() if entry.currentYear2 == currentEdition.currentYear2 and currentEdition.currentMonth2 in entry.currentMonth2 %}
   ...
{% endfor %}


Front-end Registration Form just refreshes with no error displayed and user not created

Solved the mystery. :) The issue was that even though my user fields were not required, there was a numeric 'year' field which had min and max values set, and this was throwing it off (and I had removed that field during my last round of testing to keep things simple). Removing those required min and max values allowed the form to be submitted. Thanks for the help Brad!


Get a list of countries available for shipping with Ajax in Craft Commerce

You need to provide a CSRF token, alternatively turn it off in your config/general.php file.
Set a token in your twig template:
{% set csrfToken = {
    csrfTokenName: craft.app.config.general.csrfTokenName,
    csrfTokenValue: craft.app.request.csrfToken,
} %}

<script type="text/javascript">
    window.Craft = {{ csrfToken|json_encode|raw }};
</script>

Then include the CSRF token name and value in your post array (data):
data[window.Craft.csrfTokenName] = window.Craft.csrfTokenValue;

Alternatively you can set enableCsrfProtection to false in your general config file.


How to add target to link within field instructions?

Craft uses Github Flavored Markdown and I don't believe targets are supported in links: https://github.github.com/gfm/#links
Honestly, not sure that I've seen any Markdown flavors that actually support that.


Get the current entry element in the CP (edit entry view)?

I've been able to modify the entry editing form by creating a plugin that will include some javascript into CP layout. Then with javascript, I use some checks to make sure that I'm in the right place before doing any adjustments.

For example, in the following code, I checked if I'm editing an entry within section 32, then the label of postDate field will be changed, and also the expiryDate field will be hidden.

public function init()
{

    if (craft()->request->isCpRequest())
    {
        $postDateLabel = JsonHelper::encode(Craft::t('Issue Date'));

        $js = <<<EOT

if (document.getElementById('entry-form')) {
    \$(function() {
        if ( \$('input[name="sectionId"]').val() == 32 ) {
            \$('#postDate-field label').html($postDateLabel);
            \$('#expiryDate-field').addClass('hidden');
        }
    });
}

EOT;

        craft()->templates->includeJs($js);

    }

}

Hope that is what you're looking for.


It seems like you're not a web developer? This is a very broad question unfortunately which will make helping hard. It depends almost entirely on how the previous agency decided to build your website, as "a footer" is not built-in functionality, but instead part of the design.

Typically, a footer would be controlled from a _layout.twig file in the templates directory. The content inside it may be "hard coded" or dynamically controlled from the CMS - there's no way for me to know. You'd need to look at the content of that file and see if you can find any text matching the text you see in your footer. Be aware though, that a footer template is usually site wide and not specific to individual pages; a change in _layout.twig would most often mean a change everywhere on your website.

You may be best off getting in touch with the prior agency, or perhaps a freelancer, and asking them to take a look.


This is untested as I dont have anything set that meets these conditions to try it out in, but I think you can use something like this:

{% set targetElements = ['and'] %}
{% for category in productSpecsCategory %}
    {% set targetElements = targetElements|merge([{ targetElement: category }]) %}
{% endfor %}

{% set entries = craft.commerce.products('footwear').relatedTo(targetElements) %}

Inspired by this answer.


Successful login with 'requireLogin' redirects to 404.shtml

I checked the http headers, and apparently my server was redirecting to a 404 page because the favicon.ico was missing.

As soon as I uploaded one it all worked fine again.


Is there any way to change the CP navigation item for a plugin?

I don't know if it's possible to change the name of the CP section, but it has become a common practice to allow each user to change the plugin-name on its setting page:

main plugin file:

function getName()
{
    return $this->getSettings()->name;
}

protected function defineSettings()
{
    return array(
        'name' => array(AttributeType::String, 'default' => 'SuperPluginName')
    );
}

settings template:

{% import '_includes/forms' as forms %}

{{  forms.textField({
        first: true,
        label: "Plugin Name"|t,
        instructions: "How the plugin should be named in the CP"|t,
        id: 'name',
        name: 'name',
        value: settings.name,
        required: true
    })
}}


I'm going to guess something else is wrong in your templates, because all the examples you provided definitely work in Twig. Perhaps you have an error or typo on an earlier line that's preventing your imageHeight calculations from working. I'd also check what imageHeight is set to as that isn't apparent from the snippet you provided; you can check by dumping the value - {{ dump(imageHeight) }}.

Here's a TwigFiddle showing how the math does work: https://twigfiddle.com/522svb
Here are the docs on mathematical operators in Twig: https://twig.symfony.com/doc/2.x/templates.html#math


Plugin development : from ExpressionEngine to Craft

If you want to render a template in Craft 3 you can do

$html = Craft::$app->getView()->renderTemplate('path/to/template', $variables);

If you want to return/render a template within your Controller action you can do

return $this->renderTemplate('path/to/template', $variables);

If you want to render a plugin template you'll need to attach your plugins handle to your path

 'plugin-handle/path/to/template'


The Sprout Email Example Notification templates are designed to illustrate an example of the the Events that take place when a user is saved. They illustrate how to set custom variables for the User Events in both the Control Panel and in the template itself.  While in most cases, you won't need to customize things in both places, the example is meant to be illustrative of what is possible so you can decide what the best option is for your situation.

The issue here arises when the Notification in the Control Panel is updated to be triggered on a Entry-related event, instead of a User-related Event, and the same notification template is used.

When the Entry-related Event is fired, the User-specific template tries to access user-specific variables and a Twig processing error causes the template to err out.

The key thing to understand here is that, when Sprout Email fires an Event, it only has two types of variables available to the template you are using:

Information about the Notification Email itself, like the Subject Line. This info is available via the entry object (i.e. {{ entry.subjectLine }})
Information about the Event the trigger is associated with.  This information may change depending on the Event you are using.  This info is always available via the object variable (i.e. {{ object.value }}), but the available values will differ based on the event.

To fix this issue, you need create templates for your Notification Email that:

Are built in a generic way so that they make no assumptions about what variables will be passed to the template.  If dynamic variables are needed, they can be handled directly in the fields within the Control Panel.
Are designed to expect the right variables for the Event that they are being used for.

If you run into trouble, try simplifying the templates you're using to hard-coded text.  Confirm that the Event is working as expected and that the Notification email is being fired as expected.  Once you confirm that, then try to add in variables in one by one and testing to confirm you're adding the variables correctly.

Sprout Email creates a log file at craft/storage/runtime/logs/sproutemail.log. You should see any template errors that may be happening there to help troubleshoot and diagnose what is happening.


Not all orders will necessarily have a craft user associated with the order.

But all orders must have a billing address, so:

order.billingAddress.firstName and order.billingAddress.lastName will get you what you need.


Create nested categories with Feed Me plugin

I would approach this by splitting up the work into two tasks:

Import the categories and their parent/child relationships first
Import the entries with a flat listing of categories (just the cities is okay).

The structure of the JSON for importing the categories would be something like this:

[
  {
    "state": "Florida",
    "city": "Key West"
  },
  {
    "state": "Florida",
    "city": "Orlando"
  },
  {
    "state": "Florida",
    "city": "Jackonsville"
  },
  {
    "state": "Florida",
    "city": "Miami"
  },
  {
    "state": "Florida",
    "city": "Tampa"
  },
  {
    "state": "Texas",
    "city": "Austin"
  },
  {
    "state": "Texas",
    "city": "Dallas"
  },
  {
    "state": "Texas",
    "city": "San Antonio"
  }
]

I know this is redundant but it works better with how Feed Me loops over the category elements and creates the category if it doesn't exist and then assigns the parent if (and creates it if it doesn't exist).

You want the mapping to look something like this:

When you go to import your entries you only need to include a flat listing of the category titles (cities) and then they'll be mapped to parent state.


Got some help and finally got this working. Here's the final code for my future self and anyone else that may need this:

{% set thisService = entry.slug %}
{% set shufflePremium = shuffle(craft.users.group('premium').search('counselingServices:' ~thisService).ids()) %}
{% set shuffleBasic = shuffle(craft.users.group('listed').search('counselingServices:' ~thisService).ids()) %}
{% paginate craft.users().id(shufflePremium | merge(shuffleBasic)).limit(16).fixedOrder(true) as pageInfo, members %}

{% for user in members %}
  (...)
{% endfor %}


Best Practice for Templating-Workflow, coming from static HTML

We used to do what you are doing, for a good many years - it was especially helpful when we didn't know what CMS we were going to use yet, or when we had a front end specialist (hello) who would send the files off to the back end specialist for implementation.

However, with Craft, we've found that the front-end people can use it well enough to not need a 'back end specialist', so we find ourselves no longer doing site builds as front-end assets first. It's just faster and easier to build the HTML/CSS/JS from inside the Craft templates.

We also used to (and still do for larger projects) build a completely non-styled "blueprint" of the website. The objective was to ensure that the site structure was correct - here's an example: http://example.bp.myvcsite.com/

That was/is part of our whole approach where we split things into blueprint; visuals; static build; CMS integration: http://example.myvcsite.com/


I would say you would need to create a custom plugin and use Hubspot webhooks.

Within this plugin you would have a controller method that, when you visit the action url, will take a response and convert it to an entry.

So for example if your plugin was called hubspotentries, you could have a controller HubspotEntries_WebhookController.php

Then inside that:

<?php
namespace Craft;

class HubspotEntries_WebhookController extends BaseController {

 protected $allowAnonymous = true;

 public function actionSync()
 {

   // If the webhook POSTS to the action url, get the php input and decode it
   $webhook = json_decode(file_get_contents('php://input'), true);

   //....Go through webhook and save entries etc.

 }
}

Your action url would be something like http://domain.com/actions/hubspotEntries/webhook/sync

You can then give this url to Hubspot and set up it so when an event occurs, they will POST or GET to this url and you'll be able to create the entries. I did something similar to this before (not hubspot but another service) and it works like a charm.

Useful Craft Documentation links

Plugin development introduction
Controllers in plugins

Hubspot Help

How do I use webhooks with HubSpot Workflows

Hope that helps you get started!


You have to activate the new locale in the section's settings.


You can get it to return the url using the siteUrl function and passing it a siteId parameter. So do:

{% set sites = craft.app.sites.getAllSites() | without(currentSite) %}
{% for site in sites %}

{{ site.language }}

{% endfor %}

I don't know if it's the best way but it works :)


You are passing a string <= startDate to the field parameter, but you actually want it to be a string <= 2016-01-01, which you can get by concatenationg the <= string with the datetime variable. So change your parameters like so:

postDate('<= ' ~ startDate) instead of
postDate('<= startDate')


Currently, no.

It is on our list to open us the asset transformation pipeline so that plugins can add new transforms that go beyond what is available out of the box in Craft, though.


I got a solution.
You can't overwrite array elements at this point, but the whole array. I also found it better to use the event "commerce_cart.onBeforeAddToCart".
My working code is now:

craft()->on('commerce_cart.onBeforeAddToCart', function($event) {
    $imageId = craft()->ultraschall->uploadCustomerImage(); // add image to asset folder
    if(isset($imageId) && is_numeric($imageId)){
        $lineItem = $event->params['lineItem'];
        $options = $lineItem->options;
        $options['image'] = $imageId;
        $lineItem->options = $options;
    }
});


Deleted matrix block means deleted data?

Any content or relationships that belong to the Matrix block will also be deleted, when you save the entry. If there were any relationships, the target elements won’t be deleted, though.


Since you already have an entry in the same structure, the simplest method is probably to use the parent and descendants properties of the EntryModel.

{% set entries = entry.parent.descendants %}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

A more round about way would be to get the segment through craft.request.segment, use that to get the entry, and use descendants to get the children.

{% set segment = craft.request.segment(1) %}
{% set entries = craft.entries.section('myStructureHandle').slug(segment).first.descendants %}

    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}

Or, if you only want the siblings without the current entry, you could use:

{% set entries = entry.siblings %}


After adding the new fields to your field layout, you still need to update your template to display the new fields.  You can read the templating docs on the Craft website to see how to output the individual fields.


Have you tried looking at commerce.log in storage/logs? (With Craft 3/Commerce 2 there is no commerce.log - you'll need to comb through the general web.log)


Looks like SEOmatic is the culprit and not Blitz caching plugin as first thought.


How do I include custom fields of an entry type in the Guest Entries form?

if you're using an Entry Form - [entries/saveEntry] you'll need to pass them in as fields.

For example if you had a text field called "Links" you would need an input like this

<input type="text" name="fields[links]" value="{{ entry.links }}">

Passing in inputs with the name fields[your_field_name] allow it to be picked up and populated correctly.


Best way to define non-purchasable products?

We use either booleans (i.e. switches) or dropdowns for this.

So we have, e.g. an availableForSale boolean we check in our template logic.  We have a sort of 'main' tab for these critical product fields (and note you can also add such a field to your variants so that for variant products you can selectively enable/disable on a per variant basis).  In your case you might choose to have 3 options - Available For Sale, Enquiries Only, Not available.  Booleans make for nice simple looking template logic, but probably use values is a better way to go if you anticipate anything beyond basic available/not available complexity.

(We use a similar but more complex field for shipping, which can be set to: Free Shipping, Can't Be Shipped, Post Shipping, Courier Only Shipping etc.  Although Commerce's now has it's own shipping category system you can and probably should use for that too, depending on how you implement your shipping).


How do I write a conditional for whether a section contains entries?

Your blog variable is an ElementCriteriaModel, which can be treated like an iterable array:

{% if blog|length %}
    Content
{% endif %}


I don’t know what it is – I swear: every time – but the next thing I tried, immediately after posting the question was this:

{% set related = ['and',] %}
{% for relation in relations %}
    {% set related = related|merge([{targetElement:relation}]) %}
{% endfor %}

{% paginate craft.entries
    .section('documents')
    .relatedTo(related)
    as entries %}

That works.


I'm not in Australia, but I've seen Luke Holder (of Perth) repeatedly mention Digital Ocean. I've heard other folks describe having a good experience with Digital Ocean as well.

  Digital Ocean


The best solution is to use sections / entries for ALL of your templates. This not only allows to automatically route each local's page URL to a single template, it also makes it possible to set local specific slugs for each entry. You might not care for translated URLs, but Google does.

So what I recommend is to restructure your setup a bit, add a bunch of singles or even better, a structure named "pages", and set the path to your templates in the section settings.


Does composer update make changes to the SQL database

No, running composer update will not – by itself – result in any changes to your database.

When you run composer update, all that happens is that Composer downloads updated versions for all your installed packages (i.e. Craft, plugins and other dependencies), before writing a manifest of your currently installed packages to the composer.lock file. Full stop; Craft isn't actually involved in this process at all.

However, sometimes an updated version of Craft (or a plugin) might need to change something in the database, in order to function. This is called a "migration", and is distributed with the package in question as a "migration file", containing the database queries necessary to perform the update that the new version of the package needs. In terms of updating core code or plugins, running these migrations is the only thing that will end up actually updating your database. You do have to run them at some point, because if there are pending migrations on your site's file system (i.e. migrations that have been downloaded but not run yet) your site will be unavailable until those migrations have been run (important – note that if you're updating Craft or a plugin through the Control Panel and not using the command line/Composer directly, Craft will attempt to auto-run any migrations for you, after Composer finishes downloading the new packages).

There are two ways to run pending migrations:

Visit the control panel in a browser, and click the prompt(s)
Execute the following from your command line (this should be run from the root directory for your project, i.e. where your composer.json file resides):

./craft migrate/up

The above command is safe to run even if there aren't actually any migrations pending, so if you're writing some sort of update/sync script, it could easily be tacked on at the end to make sure that any pending migrations that might be included with the updated code, are run (if you sync up the database instead, this won't be necessary as long as you've run the migrations locally).

In addition to the above – while your strategy for keeping Composer dependencies on the live server updated certainly works, it seems a bit unnecessary and/or convoluted to have to sync the database from local to production. I'd advise to either just run the migrate command in case there are migrations, or even follow what is generally considered the best practice for dealing with Composer dependencies: don't commit the actual dependencies (i.e. your /vendor folder) to version control, only the composer.lock file, and run composer install on the server, after the latest version has been deployed. Here's how a very simple deploy script could look:

cd /path/to/host/root
git pull origin production
composer install --no-interaction --prefer-dist --optimize-autoloader
./craft migrate/up
echo "" | sudo -S service php7.0-fpm reload


Send email notification to user's email when their entry has been enabled

You could build a small plugin to hook into Craft's onBeforeSaveEntry event (docs).
Before the entry is saved (and enabled), you'd check if it was previously disabled and its new status is live, if it is, send an email.
The code below should get you going.
Save it as NotifyPlugin.php in a craft/plugins/notify folder.
<?php
namespace Craft;

class NotifyPlugin extends BasePlugin
{
    function getName()
    {
        return Craft::t('Notify');
    }

    function getVersion()
    {
        return '1.0';
    }

    function getDeveloper()
    {
        return 'You';
    }

    function getDeveloperUrl()
    {
        return 'http://example.com';
    }

    function init()
    {
        // Trigger only from the Control Panel and Admin users
        if (craft()->request->isCpRequest() && craft()->userSession->isAdmin()) {

            // Catch the onBeforeSaveEntry event
            // https://craftcms.com/docs/2.x/plugins/events-reference.html#entries-onbeforesaveentry
            craft()->on('entries.onBeforeSaveEntry', function(Event $event) {

                // Isolate the entry from the event
                $entry = $event->params['entry'];

                // The ID of the section currently being saved
                $sectionId = $entry->sectionId;

                // The ID of the section you want to watch (change that to match your section ID)
                $sectionIdToWatch = 2;

                // Is this a new entry?
                $isNewEntry = $event->params['isNewEntry'];

                // Is it an entry from the section we are watching and NOT a new entry
                if ($sectionId == $sectionIdToWatch && !$isNewEntry) {

                    // Fetch the entry before save to use its status for comparison
                    // https://craftcms.com/docs/2.x/plugins/working-with-elements.html#fetching-elements
                    $currentEntry = craft()
                        ->elements
                        ->getCriteria(ElementType::Entry)
                        ->sectionId($sectionId)
                        ->status(null)
                        ->id($entry->id)
                        ->first();

                    // Entry status before saving
                    $currentEntryStatus = $currentEntry->status;

                    // New status being saved (from the event)
                    $statusBeingSaved = $entry->status;

                    // Are we going from disabled to live?
                    if(
                        $currentEntryStatus == BaseElementModel::DISABLED &&
                        $statusBeingSaved == EntryModel::LIVE
                    ) {
                        // Sets $toEmail to the entry's author but change to suit your needs
                        $toEmail = $entry->author->email;

                        // Prepare the message
                        $message = new EmailModel();

                        $message->subject = 'Your notification';
                        $message->body = 'Email content';
                        $message->htmlBody = 'Email content';
                        $message->toEmail = $toEmail;

                        // Send the message
                        craft()->email->sendEmail($message);
                    }
                }
            });
        }
    }
}

Change $sectionIdToWatch to match your section ID and as is, this will send the email to the entry's author.
As I said, this is just a base to get you going but it should work  :)


Change posts url without losing SEO positioning

Migrating Redirects should not be thought of as a one-time event but a process that includes a step where you make sure Redirects are in place and working.

A rough redirect strategy

Take a snapshot of where your old website stands. This can be a combination of using tools like Google Analytics, Screaming Frog, moz.com, raventools.com, or one of many other services that do similar things. The main goal of this step is to understand where your current website ranks and what errors your current website has. Whatever you do in this step, you're going to do it again after you launch and by understanding your baseline before you make significant changes you'll have a better picture of what may need correcting after you launch the new site.
Identify all the URLs that are changing and decide which ones you want to redirect. Often this is all of them. Sometimes, you might choose to clean things up or just focus on key pages. Redirects can be managed in various places. The easiest place to manage them may be via a plugin like Sprout SEO or Retour however managing them via the .htaccess file or some other lower level configuration is also an option.  A good way to consider which URLs need redirected is to look at your analytics data. You can filter Google Analytics data and get a list of all pages that have been visited in the past year ordered by page views to get a fairly accurate list of what's important that you should be caring about.
Get redirects in place. If you have a few redirects, adding them manually may be fairly straightforward. If you have lots, consider using regex patterns in your redirects. If a group of pages changes their URLs in the same way, you can likely write a single rule to match all of their URL patterns and forward those old pages to the new ones. I've given a more specific example of this below.
Once you go live, be sure to test your redirects (see notes below) and take another snapshot of your site and monitor the site for unexpected behavior. Google Search Console and various tools like the ones mentioned above can help you monitor the site for errors and make sure no big issues were accidentally introduced. Sprout SEO can help you capture all 404 Redirects and an admin can convert any pages that were missed into 301 Redirects. When you do find issues, be sure to address them as quickly as you can. The longer you let them sit, the more likely search engines will think they are the norm.

A few additional notes on redirects

There are different types of redirects. If you set a redirect to be a 301 redirect, that rule will get cached in your user's browsers. If you happen to make a mistake and try to change your redirect, the only way a user that hit your last redirect will get rid of it is if they clear their browser cache. For this reason, I recommend starting out with 302 redirects and testing all redirects as 302s. If the redirects work as expected, you can then update them to 301 redirects to signal to search engines that your changes are permanent and reduce the change that you create a scenario where incorrect rules get accidentally cached in user's browsers.

If you have several redirects that follow the same pattern, you can use regexes to simplify the number of redirects you need. The following example is an .htaccess redirect that will match all incoming article/{slug} URLs and redirect them to a new blog section (the term used in regexes for matching patterns within parentheses is Capturing Groups).

RewriteRule ^/article/(.*)$ /blog/$1 [R=301,L]

In your case, since the previous URL was very broad {slug} it may be challenging to find a pattern that matches your old URLs that doesn't also match all of your new URLS or new pages on your site. In this case, you may need to be more explicit in which URLs you are redirecting

If you do need to import 500 URLs, Sprout SEO Redirects can be converted from CSV and imported via Sprout Import.


How can I follow relations in ElementCriteriaModels from plugin code?

You're very close! Try this:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'concepts';
$criteria->limit   = null;
$criteria->relatedTo = array(
    'targetElement' => $e,
    'field'         => $field
);
$elements = craft()->elements->findElements($criteria);

Keep in mind, in this instance, $field is the field object which can be retrieved with something like the following:

$singleFieldModel = craft()->fields->getFieldById($singleField);

See the documentation (https://craftcms.com/classreference/services/FieldsService) for other ways to get a field object.


How to attach an order PDF in an order confirmation email?

You can send an email via your plugin's init() function like so:

craft()->on( 'email.onBeforeSendEmail', function( Event $event ){
    $email = $event->params['emailModel'];
    $attachment = array(
        'path'     => '/var/www/public/assets/downloads/filename.pdf',
        'name'     => 'File Title',
        'encoding' => 'base64',
        'type'     => 'application/pdf'
    );
    $email->addAttachment($attachment['path'], $attachment['name'], $attachment['encoding'], $attachment['type']);
});

Obviously, you'll want to do some checks on the Event and pass that off to a service to determine the logic for what should actually be attached.


These were moved to "Utilities" so they now have their own permission and users can have access to them without needing be have admin rights.


What's the difference between a Component and a Model in Craft 3?

Models  are classes that contains abstractions of the reality, for example you could have the model car that contains the technical information about it, how many wheels it has and it's brand. Models are usually not supposed to contain any logic. So it's just a "container" with information

Components are more like services that contains business logic to work with your models, for example the service car would handle the logic to let your car model drive and move and such. Components in Yii2 are mostly (not always) treated as singletons while you want to have many different instances of your models


How do you limit the number of items that show up in a navigation?

If this is a Craft 2 project, unfortunately there's not a super clean way to do that. You'd have to get the last top-level item in the nav you want to show, and add a bunch of conditions in the code to make sure the entry you're outputting isn't after that 5th entry.

{# get the 5th top-level page #}
{% set fifthElement = craft.entries()
    .section('productPages')
    .level(1)
    .nth(4) %}

{# get all the pages #}
{% set ppages = craft.entries()
    .section('productPages')
    .level('<=2')
    .find() %}

{# now display the nav, but only output HTML for entries that are
   within the first 5 top-level entries #}

{% nav page in ppages %}
    {% if page.lft < fifthElement.rgt %}

        {{ page.getLink() }}
    {% endif %}
  {% ifchildren %}
    {% if page.lft < fifthElement.rgt %}
{% endif %}
    {% children %}
    {% if page.lft < fifthElement.rgt %}
{% endif %}
  {% endifchildren %}
    {% if page.lft < fifthElement.rgt %}

    {% endif %}
  {% endnav %}

In Craft 3 it would be quite a bit simpler, though, as you have the power to modify the element query however you want. So we can first get the 5th top-level entry’s rgt value, and then when running our main ppages query, only get the ones whose lft value is less than that 5th entry’s rgt value.

{# get the 5th top-level page #}
{% set fifthElement = craft.entries()
    .section('productPages')
    .level(1)
    .nth(4) %}

{# get all the pages that are within the first 5 top-level pages #}
{% set ppages = craft.entries()
    .section('productPages')
    .level('<=2')
    .andWhere(['<', 'lft', fifthElement.rgt])
    .all() %}

{# now output the navigation normally #}

  {% nav page in ppages %}

      {{ page.getLink() }}
  {% ifchildren %}

      {% children %}

  {% endifchildren %}

  {% endnav %}

If you’re unfamiliar with these lft and rgt values, they are attributes of structured entries, which define their position within the structure, using the “Nested Set” model. The easiest way to think of it is, your structure section is like an XML file, and each of the entries are nodes within it. Each entry has a opening tag and a closing tag on different lines, and lft and rgt are those line numbers.

1 <top_entry>
2   <nested_entry>
3   </nested_entry>
4 </top_entry>

So when we do {% if page.lft < fifthElement.rgt %}, we are saying “make sure that this node’s ‘opening tag’ comes before the fifth element’s ‘closing tag’”.


HTTP 503 – Service Unavailable – craft\web\ServiceUnavailableHttpException

This isn't a direct answer to your question, but the first place I'd look is your logs on your server. As an example, I'm running nginx on my server and the logs are located in /var/log/nginx/.


Here are the social media plugins I see on https://plugins.craftcms.com (which is the public version of the plugin store).

Sharing related:

https://github.com/boscho87/facebook-connector
https://github.com/Rias500/craft-notifications
https://github.com/Rias500/craft-telegram-notification-channel

Integrations that don't appear to deal with sharing:

https://github.com/bymayo/craft-dribbble
https://github.com/dukt/facebook
https://github.com/dukt/social
https://github.com/dukt/social-github
https://github.com/dukt/social-linkedin
https://github.com/dukt/twitter


How can I create and validate against a url token?

My first problem is, I haven't figured out how to properly escape the anchor parameter.

I'm guessing you mean the link is being escaped (since Twig will do that by default) and you don't want it to?  If so, you can use the |raw filter (http://twig.sensiolabs.org/doc/filters/raw.html).

  My second problem is how to generate a random token. I'd like to generate a random string or something.

If you don't care if it's a cryptographically secure string, you can just use StringHelper::randomString() or StringHelper::UUID().  If you want a cryptographically secure random string, then you can use craft()->security->generateRandomString().


Entry versions aren't managed by tasks.

My guess is you've got "Enable versioning for entries in this section?" unchecked for that section's settings in the control panel.


How do you create pagination links related to entries within a Matrix Field in a single entry?

In this particular case, .relatedTo(entry) is not necessary. So long the entry the following code is located within is within the entry within the source the pagination will populate. Otherwise these will remain empty.

{% set source = craft.entries.sectionId(10).first().gallery.type('gallery').first().entries %}

{% set prevEntry = entry.getPrev(source) %}
{% set nextEntry = entry.getNext(source) %}

Next: {{ nextEntry.title }}
Previous: {{ prevEntry.title }}


It looks like Media Temple Grid accounts are limited to 99MB of memory for PHP: https://mediatemple.net/community/products/grid/204643740/cgi-and-php-resource-limits
My guess is that they are ignoring whatever values are set in php.ini for memory_limit, but you can contact them to verify.


Imager will always create and store the transformed images locally in your imagerSystemPath, even if you choose to upload and serve them from an external storage. The files in that folder acts as the cache, so that Imager knows if a transform has been created or not.

Alternatively, Imager either would have to; 1) make a request for each transformed image to see if it existed in the external storage, or 2) have some other method of keeping track of what transforms has been made (DB, DB-like file, or something). Option 1) adds an insane amount of overhead, whereas 2) adds quite a bit of complexity and possibly some overhead (like Craft's built-in transforms, which requires DB queries). So I opted for speed and simplicity, and sacrificed disk space. :)


Setting the page title for a category page

We would need to know how you render your title. Otherwise it would just be

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <meta charset="utf-8" />
    <title>{% if title is defined %}{{ title }} {% endif %}{{ siteName }}</title>
</head>

and in your category template

{% set title = 'Category ' ~ category.title %}


After some research, i found a way to achieve this. Here is my full controller:

<?php
  namespace Craft;

  class Module_ControlController extends BaseController {
   protected $allowAnonymous = true;
public function actionChangeStock()
{
    $entry = $this->getElementByField("3081001100390", ElementType::Entry, null, "variantSku");
    $entry->enabled = false;
    $entry->getContent()->setAttributes(array(
        'variantSku' => "Hello my friend!",
        'variantStock'  => "3"
    ));
    $success = craft()->entries->saveEntry($entry);
    die(var_dump($success));
}

/**
 * Returns an element by any attribute.
 *
 * @param int $elementId
 * @param string|null $type
 * @param string|null $localeId
 * @return BaseElementModel|null
 */
public function getElementByField($elementId, $elementType = null, $localeId = null, $field)
{
    if (!$elementId)
    {
        return null;
    }

    if (!$elementType)
    {
        $elementType = craft()->elements->getElementTypeById($elementId);

        if (!$elementType)
        {
            return null;
        }
    }

    $criteria = craft()->elements->getCriteria($elementType);
    $criteria->$field = $elementId;
    $criteria->locale = $localeId;
    $criteria->status = null;
    $criteria->localeEnabled = null;
    return $criteria->first();
}}


Delete your craft/storage/runtime/cache and craft/storage/runtime/compiled_templates folder after doing this manual update.

Otherwise Craft still references the (now renamed) Garnish Javascript, and the UI for the AdminCP is not functional.


Modify a field value before the element is saved

It turns out that serializeValue is what I needed.

public function serializeValue($value, ElementInterface $element = null)
{
    if ($value == 'foo') {
        $value = 'bar';
    }

    return $value;
}


Solspace Freeform: loop over all form errors

There currently isn't a way to get all errors directly from the form, but you could do it this way for now:

{% for row in form %}
    {% for field in row %}
        {% for error in field.getErrors %}
            {{ error }}
        {% endfor %}
    {% endfor %}
{% endfor %}


Populate Field Group With Fields From Another Field Group

No, there's nothing built into Craft that lets you do this.

Please note though, that you can reuse fields across sections in Craft. Field groups is just an organizational layer on top of fields to make it easier to add a group of fields to a section, and to be able to find fields more easily. It doesn't give any additional meaning to the fields. So you can't have a field with the same handle in different field groups, and it doesn't make sense to duplicate a field that's actually used across sections.

If you need to duplicate fields (because they're actually suppose to be different fields), I highly recommend the Field Manager plugin by Verbb (Craft 2 and Craft 3 versions available) which makes it super easy do to this, and in general provides a much better interface to manage fields.


Changing the Settings > Assets > Sources url fixed the problem globally. Thanks for the help, aran.


Why does my entry language selection look different from examples?

The top screenshot is from Craft 2. The entry language selector (technically, the entry site selector since Craft 3) was redesigned with Craft 3.


The problem is the ... in your contactform.php file.

The docs use it because they assume you might have some other valid config settings you want to include in that config file, but it's not real code, which is why PHP is choking on it.

Remove the ... and you should be set.


This doesn’t appear to be possible without a plugin. The formattingAdd will add additional options to the Formatting menu, but will not alter the behavior of any of the other buttons, and you can only set the tag properties to p, pre, blockquote, and h[1-6].

Another option might be to use a Matrix field with two block types: Text and List. Text blocks would have a Rich Text field, and List blocks would have a Table field with one column, plus a Dropdown field that specifies what the class should be. From your templates you would do this:

{% for block in entry.myMatrixField %}
    {% if block.type == 'text' %}
        {{ block.text }}
    {% elseif block.type == 'list' %}

            {% for row in block.myTableField %}

{{ row.myColumnHandle }}

            {% endfor %}

    {% endif %}
{% endfor %}

If you really want to keep all this within Redactor and go the plugin route, you can use our Redactor Clips plugin as a starting point.


Adding entries to an array, one at a time

The merge filter only works with 2 arrays (or 2 hashes), not with an array and an object. I think that the event you are trying to add is not an array, it is a single event (Entry Model). You might try adding the event using [ event ].

{% set todaysEvents = todaysEvents|merge([event]) %}


Incorporating data from an external database into Craft pages

That solution makes sense! I have used a similar strategy. You should absolutely cache around the template hook, or cache the database calls in the plugin itself.

Take a look at the Yii Query Builder to see how Yii/Craft handles MySQL queries. You can also look at examples Craft source code.


What needs updating when moving site from subdomain to root?

Ok so on this site:

1) I forgot that I'd moved the templates folder outside the craft folder for easy access with this in the index.php

define('CRAFT_PLUGINS_PATH',realpath(dirname(__FILE__)./../plugins").'/');

2) Making sure the assets sources url are changed is essential to get the site working.


Here's how i solved it:

$criteria = craft()->elements->getCriteria(ElementType::Asset);
$criteria->id = $assetId;
$elements = $criteria->find();
$element[0]->getContent()->title = 'New Title';
craft()->elements->saveElement($element[0]);


How to display data in field type with dropdown multi select checkbox?

A checkbox field is just a checkbox, usually checkboxes don't have several values beside true/false or checked/unchecked, Are you sure you don't want to use a select or multiselect

{{ forms.selectField({
    label: "Some Label"|t,
    id: id ~ 'someField',
    name: name ~ '[someField]',
    options: options, //<-- array [label => X, value => y]
    value: values.someField // <-- not sure what this should be.. usually you want to pass an id
}) }}

However - your PHP actually doesn't make much sense. Not sure what your goal is with that code


Is there any way to group Matrix blocks in the control panel (see image)?

There is a plugin that allows you to organize matrix blocks into groups, perhaps that is worth taking a look at. pimp my matrix


From PHP:

if (craft()->request->getIpAddress() == '255.255.255.255')
{
    ...
}

Note from the docs that this is a "best guess" and can easily be spoofed, so you shouldn't use it to hide any sensitive information.

We currently don't expose that method at the template level, but we probably should. I'll add that on the Craft 2.3 branch.

If you want to hack it in before then, you can open up craft/app/variables/HttpRequestVariable.php and add:

public function getIpAddress()
{
    return craft()->request->getIpAddress();
}

Then from a template you'd use:

{% if craft.request.getIpAddress() == '255.255.255.255' %}
    ...
{% endif %}

Just note that there is a chance that a 2.2 update could overwrite that file at any time.

UPDATE: No hack is required since Craft 2.3.2615.


Why does the matrix field produce such a massive amount of duplicate information?

Per Oli, I ran ./craft gc for garbage collection. The matrix field went from 70+ (sometimes as much as 130) rows to 8. Still a terribly non-normalized database table, but much better than 70 records for one entry.
Thanks to Oli!


Getting 'signed out' after exactly 1 minute of inactivity

This was related to the place that the sessions were being stored with my hosting company (Vidahost). Using the Utils section in Craft2, we managed to track it down to being stored with memcache. This meant that true and auto wouldn't work, and we had to set the override to false. False is meant to be the default anyway, but it seems to be working now that it's hardcoded.

The key lines to look for when debugging this are:

session.save_handler    memcache
session.save_path       tcp://10.168.1.55:11211?persistent=0&amp;weight=1&amp;timeout=5&amp;retry_interval=15`


Is it possible to subscribe a user to Mailchimp during checkout in Craft Commerce?

We offer this during checkout.

We use André Elvan's: https://github.com/aelvan/mailchimp-subscribe-craft

We implement it simply as an ajax call that happens in the background as the order is submitted for payment:

    if ($('#subscribeMC').prop('checked')) {
        // Fire this off asynchronously and with any luck it just works...
        $.ajax({
            type: 'POST',
            url: '/actions/mailchimpSubscribe/list/Subscribe',
            data: {
                CRAFT_CSRF_TOKEN: window.csrfTokenValue,
                email: email,
                mcvars: {
                    FNAME: firstName,
                    LNAME: lastName,
                }
            }
        });
    }

One thing I like about our implementation is that I added a 'check if subscribed' function to the above plugin and we only show the checkbox if they're not already on the list - it's one of my pet hates when I keep seeing a newsletter box for a list I know I am already on.

$.ajax({
    type: 'POST',
    url: '/actions/mailchimpSubscribe/list/checkIfSubscribed',
    data: {
        'CRAFT_CSRF_TOKEN': window.csrfTokenValue,
        'email': email
    },
    success: function(response) {
        //They're on the newsletter - hide the subscription form
        if (response.success) {
            $container.hide();
            $heading.hide();
        }
        //They're not on the list, bait the hook
        else {
            $container.fadeIn('fast');
            $heading.fadeIn('fast');
        }
    },
    //something went wrong, might as well show the form
    error: function(response) {
        $container.fadeIn('fast');
        $heading.fadeIn('fast');
    }
});

If you wanted to avoid JS/ajax, then I guess you could implement your own controller that you submit to at any point (e.g. intercept the commerce pay controller) - that first does your Mailchimp stuff and then calls the native controller using Craft's runController.

But the above JS works well and we get a bunch of newsletter subs with it every day...during subscribe checkout is by far the most effective way of increasing your mailing list we've found.  (And, please, whatever else you may do, do not implement a page covering newsletter signup popover!!)


Get the Sub-Category Link from Category field in a Structure (output with Nav tag)

In short, don't use the {% nav %} tag as it's not flexible enough for what you need.
Assuming your fields are called entriesFieldURL and categoriesFieldURL, try something like this:
{# Fetch the current page ID to use for your active class later on. If entry exists, we are on an entry page, else, category page or NULL fallback #}
{% set currentPageId = entry.id ?? category.id ?? null %}

{# Fetch your entries and eager-load children #}
{% set menu = craft.entries()
    .section('navDropDownMenu')
    .level(1)
    .with('children')
    .all() %}

{%- for item in menu -%}

    {# Set a link object which switches based on whether you have a category or an entry #}
    {%- set link = item.entriesFieldURL|length ? item.entriesFieldURL[0] : item.categoriesFieldURL.leaves()[0] -%}

        {# Output the link and add active class base on the current page when needed #}
        {{ link.title }}

        {# Does this item have children? #}
        {%- if item.children -%}

            {%- for item in item.children -%}

            {# As above, set a link object which switches based on whether you have a category or an entry #}
            {%- set link = item.entriesFieldURL|length ? item.entriesFieldURL[0] : item.categoriesFieldURL.leaves()[0] -%}

                {# And again, output the link and add active class when needed #}
                {{ link.title }}

            {%- endfor -%}

        {%- endif -%}

{%- endfor -%}

As you can see, there's some repetition in there which you could solve by using a short macro to build the  tags making the complete thing:
{# Fetch the current page ID to use for your active class later on. If entry exists, we are on an entry page, else, category page or NULL fallback #}
{% set currentPageId = entry.id ?? category.id ?? null %}

{# Fetch your entries and eager-load children #}
{% set menu = craft.entries()
    .section('navDropDownMenu')
    .level(1)
    .with('children')
    .all() %}

{% macro linkItem(item, currentPageId) %}
    {%- set link = item.entriesFieldURL|length ? item.entriesFieldURL[0] : item.categoriesFieldURL.leaves()[0] -%}
    {{ link.title }}
{% endmacro %}

{%- for item in menu -%}

        {{ _self.linkItem(item, currentPageId) }}
        {%- if item.children -%}

            {%- for item in item.children -%}

                    {{ _self.linkItem(item, currentPageId) }}

            {%- endfor -%}

        {%- endif -%}

{%- endfor -%}

You could further refine but hopefully, this gets you started :)


If I correctly understand your question, you want to show each location with at least one vacancy, and the number of vacancies for that location? I don't really get what block.vacancySelected is?

The way I would do this:

{# get all locations #}
{% set allLocations = craft.entries.section('locations').all() %}

{% for location in location %}
    {# get a vacancy count for this location #}
    {% set vacancyCountForLocation = craft.entries.section('vacancies').relatedTo({
        field: 'locationFieldHandle',
        targetElement: location,
    }).count() %}

    {% if vacancyCountForLocation %}
        {{ location.locationName }} ({{ vacancyCountForLocation }})
    {% endfor %}
{% endfor %}

To prevent loading all locations, even if they have no vacancies, you could also try (untested):

{# get all locations, but only if they have related vacancies #}
{% set allVacancies = craft.entries.section('vacancies').ids() %}
{% set allLocations = craft.entries.section('locations').relatedTo({
    field: 'locationFieldHandle',
    sourceElement: allVacancies,
}).all() %}

{% for location in location %}
    {# get a vacancy count for this location #}
    {% set vacancyCountForLocation = craft.entries.section('vacancies').relatedTo({
        field: 'locationFieldHandle',
        targetElement: location,
    }).count() %}

    {{ location.locationName }} ({{ vacancyCountForLocation }})
{% endfor %}


Custom plugin settings add on admin nav bar

You need to use the EVENT_REGISTER_CP_NAV_ITEMS event in the main plugin class. From the docs:
use craft\events\RegisterCpNavItemsEvent;
use craft\web\twig\variables\Cp;
use yii\base\Event;

public function init()
{
    parent::init();

    Event::on(
        Cp::class,
        Cp::EVENT_REGISTER_CP_NAV_ITEMS,
        function(RegisterCpNavItemsEvent $event) {
            $event->navItems[] = [
                'url' => 'section-url',
                'label' => 'Section Label',
                'icon' => '@mynamespace/path/to/icon.svg',
            ];
        }
    );

    // ...
}


I don't know what version of RHEL they're running, but it could certainly be added.  Whether your IT department will support it or if that breaks some support contract your company has with RH is another question all-together.

FWIW, Craft 3/Yii 2 has done away with mcrypt in favor of OpenSSL, so it's not an issue there.


Craft or Twig converting html tags to alt characters

You need to make sure that you're returning the raw version of the HTML.

In Craft 2, it looks like this...

return TemplateHelper::getRaw($result);

In Craft 3, it looks like this...

return Template::raw($result);

If you're doing this in Craft 3, you need to also be sure that you are loading the Template helper class at the top:

use craft\helpers\Template;


Why when a task is marked as “Stalled” the following tasks can't automatically processed?

why when there's a task marked as “Stalled” in the Control Panel, this one is not ignored to automatically let the following tasks processing?

Because tasks behind it might rely on the data that the successful completion of the stalled task would generate.

  And is there a way to automatically ignored these tasks marked as “Stalled”?

You could probably hack it somehow, but I wouldn't recommend it.  It's best to fix the underlying reason the task stalled in the first place.


Craft 2.x ships with a subset of the Yii framework files with things like zii and Yii widgets stripped out.

If you wanted to utilize them, you'd have to create a Craft plugin and manually include the files that you're looking to use.


How can I repopulate a matrix field on a front-end form?

Using the example above, here is how you can re-populate the given matrix field(s). The below is assuming only one matrix field is visible by default [0]. Depending on your use case, you may need to dynamically generate the index number.

...
{%- if entry is defined %} value="{{ entry.myMatrixFieldHandle[0].fieldHandle }}"{% endif -%}
...


Craft CMS 3 data structure advice for vehicle make, model, trim, year tagging

Goal: Filter documents by related vehicle characteristics.

My first idea would be to create it as such:

Create an assets volume where all your documents will be uploaded to.
Create a vehicle category group for your vehicles such as you already defined (the structure you mentioned)
Add 2 fields to the assets volume:

Vehicle (category field)
Year (date field)

This will allow you to add the relevant data to each document. You can than display the documents on your frontend and search/filter them by category and/or date.
How you do that is up to you, either with Twig serverside or with VueJS for example client side.


It’s definitely possible. Here’s the gist:

Forget the whole subdomain idea, and start by getting everything working using a URI format like /client/<slug>.
Make all subdomain traffic get routed to the same server/virtual host.
Make Craft think that subdomain requests actually had a URI in the format of /client/<slug>, so it will route the request the way it did in step 1.

How you go about the second step depends on whether you’re on Nginx or Apache.

For Nginx, add default_server to the server config’s listen directive:

server {
    listen 80 default_server;
    // ...
}

For Apache, create a _default_ virtual host definition:

<VirtualHost _default_:*>
    // ...
</VirtualHost>

Exact details depend on your hosting environment so you may need to do some of your own googling here. You’ll likely need to restart the webserver before changes take effect, too.

Once you have all subdomain traffic routing to the same place, add something like this to your index.php file:

<?php

$domainParts = explode('.', $_SERVER['HTTP_HOST']);

if (count($domainParts) === 3)
{
    $slug = $domainParts[0];

    // Fake Craft into thinking the URI was actually /clients/<SLUG>/uri/...

    // Nginx:
    $_REQUEST['REQUEST_URI'] = "/clients/$slug".($_REQUEST['REQUEST_URI'] ?? '');

    // Apache:
    $_GET['p'] = "clients/$slug/".($_GET['p'] ?? '');
}

// ...

With that in place, your client.domain.tld requests should start serving those client entry pages!


The requested URL was not found on this server. Apache/2.4.18 (Ubuntu) Server at localhost Port 80

This worked just fine.
https://craftcms.stackexchange.com/a/35846/10953
I did all steps execpt steps 3. and 4.
Thanks all!


How do image focal points work in Craft 3?

While we’re piggybacking, here’s a snippet that goes one step further and generates the necessary CSS to position an untransformed image:

{% set img = entry.headingImage.one %}

{% if img %}
    {% set imgStyles = "background-image: url('" ~ img.getUrl() ~ "');"|raw %}

    {% if img.hasFocalPoint %}
        {% set x = img.focalPoint | first * 100 ~ '%' %}
        {% set y = img.focalPoint | last * 100 ~ '%' %}
        {% set imgStyles = imgStyles ~ ' background-position: ' ~ [x, y]|join(' ') %}
    {% endif %}
{% endif %}

Mmm, backgrounds


Craft 2: get default user group from user settings

You can do this via a small plugin that provides you with a template variable. I've made you a working example here with usage example.

It's a main plugin class with the basics then a variable class that fetches the group id from your settings and retrieve the handle associated to that id.

I'm sure there are other ways to do this but that's one. Download, change... Make it yours :)


Efficient way to get all related entries assigned to matrix fields across a set of entries

If you are trying to get all people entries related to the event entry itself (what you call event "e") then I would suggest going through matrix as follows.
{% set people = craft.entries.section('people').relatedTo([
    'or',
    { targetElement: event, field: 'matrixFieldHandle.relatedEvents' },
    { targetElement: event, field: 'matrixFieldHandle.relatedArticles' }
]) %}

If you need the target element to be all children of the event then this might do the trick.
{% set eventChildren = event.children %}

{% set people = craft.entries.section('people').relatedTo([
    'or',
    { targetElement: eventChildren, field: 'matrixFieldHandle.relatedEvents' },
    { targetElement: eventChildren, field: 'matrixFieldHandle.relatedArticles' }
]) %}

You can also combine the event with its children, if necessary, as follows.
{% set eventWithChildren = event.children|push(event) %}


Element API: how can I return entries via username?

Completely untested, but something like this should work:

'dealers/<username:(.*)>.json' => function($username) {
    $author = craft()->users->getUserByUsernameOrEmail($username);

    return [
        'elementType' => 'Entry',
        'criteria' => [
            'section' => 'listings',
            'authorId' => $author->id
        ],
        'paginate' => false,
        'transformer' => function(EntryModel $entry) {
            ...


How can I do more complicated queries with an ElementCriteriaModel?

Once you've got your ECM, pass it off to the buildElementsQuery method...

$query = craft()->elements->buildElementsQuery($criteria);

This will convert your ECM into a DbCommand object. From there, you can make further modifications to the query... like adding a join for your 3rd party table.

$query->join('myplugintable myplugintable', 'myplugintable.id = elements.id');
$query->order('myplugintable.mysortcolumn');

return $query->queryAll();


Architecting a Solution with many Sites within a Site (Chapters) - How many sections can Craft Handle?

As chapter numbers grow, will this be too many sections for Craft to handle?

Probably not.  I suspect as your section list grows to the multi-thousand section range (if it will ever get that large), you'll start to run into MySQL/environmental limitations rather than any Craft ones.  But if  you do run into any UI/architectural limitations, we'd love to hear about them.

In the upcoming Craft 2.3 release, we spent a great deal of time addressing UI scaling issues around Structured Sections and Categories when they start to approach the multi-thousand range, but we've seem installations with several hundred thousands of Channel entries/assets/users running just fine.


I managed to solve it finally, by starting from what was suggested in the comments. Basically to get the filter to work in Craft I've added action="{{ url('developments') }}" to the form class, which keeps the url on the same page, and then on the  tag I added a name="county1" and some javascript to get it to reload when it's selected using onchange="this.form.submit()"

Then in the results below I set a query variable using {% set query = craft.request.getParam('county1') %} and then created a second variable called queryFilter to search the correct category, based on the selected field {% set queryFilter = craft.categories.group('developments').search(query).order('title asc') %} which to print out the results is then referenced via a for loop {% for category in queryFilter %}

So there's quite a few steps to get it to work, so it's not something that's obvious from the Craft documentation, which doesn't have hardly anything on this subject that I've found.

Here's the code as whole so that it help makes sense to someone trying to do the same type of thing:

<form class="form-inline" action="{{ url('developments') }}" method="get">

    Location

      <select id="county1" class="form-control" name="county1" onchange="this.form.submit()">
        <option value="all">All</option>
        {% for category in craft.categories.group('counties').order('title asc') %}
        <option value="{{ category.slug }}">{{ category.title }}</option>
        {% endfor %}
        </select>

</form>

        {% set query = craft.request.getParam('county1') %}
        {% set queryFilter = craft.categories.group('developments').search(query).order('title asc') %}

        {% if queryFilter %}
        {% for category in queryFilter %}

        ....markup...

        {% endfor %}
        {% endif %}


Question regarding member-owned shared assets

As you've noted, this is a complex and would require a proper discovery and planning phase to sort out all the details.  Here are a few thoughts on each stage of the process that you discussed. It looks like Luke has approached the problem in a similar way in the comments above.

User1 has a login to the site, and has access to user_1_report.pdf

This could potentially be handled by a Craft Entries or Users Relations field.  You could let somebody relate a Report to the specific User who should be able to see it, or allow a User Profile to be related to several differnet Reports.  In whichever case, you could limit who has visibility to the reports in the front-end by only displaying Reports to Users who have the right relationship to them.

User2 logs in and sends a request to User1 to view user_1_report.pdf

This will need to be handled with a plugin.  I would approach the problem in two steps.  The first part of the problem is an email notification problem, and the second part is an action that will required changing the relationship or permissions of who has access to something. Depending on how secure you need things to be, there may also be a validation component to ensure that only a User that has received an invite is able to accept that invite.

There are likely some Email plugins that could help get you started with the Email notification part of this. We have built similar authentication workflows using Sprout Email. For the particular approval action that you need, it's likely you'll need to approach that as a separate custom plugin that handles the specific action you need.

User1 receives a notification in their members area and can click Approve / Deny

This is mostly addressed in my previous comment. When you trigger the notification email, you can make sure that the notification email includes a link to help the user Approve/Deny the request. In my discussion above, those Approve or Deny actions would probably be links to controller actions that handle the behavior you need, or to a page on your site that then allows the user to trigger the right action.

User2 gains access to the user_1_report.pdf as a download link in their members area.

Once the approval workflow is sorted out, this will likely just be handled in the same way as the first scenario – via a Relations field or some permission and the standard Twig code needed to output that data.  One option could be to have an "Approved Users" field on a Report Entry, and your custom action would trigger adding the invited user as a Relation to the Report that they were invited to.


Craft database and Github - using multiple computers. Issue

It's a good practice to designate one instance on one computer (or server) as the "canonical" instance. You can make all database changes there, adding fields, etc. It's easy to download that database via the Backup Database tool in the admin panel. You can then import that dump file into databases on other machines as needed with a tool like SequelPro (Mac).

Some prefer to include an updated database dump file in the git repo every time a change is made but that can get pretty tricky.


Model validation not run when using EntriesService saveEntry method

It's normal behavior... EntriesService->saveEntry() never calls validate() on the model directly, but does call validate() on the EntryRecord and if there are errors, add it back to the model and return.

So if you want to run custom validation rules before calling saveEntry you'll need to do that yourself and respond accordingly.


Use loop index number in a Twig variable

I found the answer in the Twig documentation:
http://twig.sensiolabs.org/doc/templates.html#variables

  You can use a dot (.) to access attributes of a variable (methods or properties of a PHP object, or items of a PHP array), or the so-called "subscript" syntax ([]):

{{ foo.bar }}
{{ foo['bar'] }}

When using the subscript syntax, you can concatenate the loop.index like so:

{% for i is 1..5 %}

    {{ entry['item' ~ loop.index] }}

{% endfor %}

Or even simpler, use the i variable from the for loop.

{% for i is 1..5 %}

    {{ entry['item' ~ i] }}

{% endfor %}


This:

// The name of the database to select.
'd<my acct #>_onehanders_db' => '',

Needs to be this:

// The name of the database to select.
'database' => 'd<my acct #>_onehanders_db',


Can I call a filter on all Rich Text fields?

customAsciiCharMappings won't help you here.

There is the "Find and Replace" tool available to admins (Settings->Tools) in the Control Panel, but its' a one-off thing and searches/replaces against all textual field types (Plain Text, Rich Text, etc. both inside and outside of Matrix fields).

Honestly, probably just create a small Twig macro that wraps |replace and use that wherever you're outputting Rich Text fields on the site.


Supertable or Neo for nested Matrices and compatibility with Craft 4

In reply. In a tweet from Brandon... Neo will get a direct upgrade path to matrix.
https://twitter.com/brandonkelly/status/1114144432243265536?s=19

That being said. I used supertable more recently.


Is there a way of displaying an entry twice depending on postDate and a custom field date in one loop?

You could probably do this purely from Twig / a template, but I think it's going to end up being much easier from a plugin / PHP.

The general gist of it would be:

Grab all entries from section 1 ordered by postDate.
Grab all entries from section 2 ordered by releaseDate.
Create a new array and loop through 1 and 2 inserting via your custom sorting logic.
Return that new sorted array back to the template.


Impossible to access an attribute (title) on a string variable

entryCategory is already a single category because of "first()". So no need for the for loop. Just {{ entryCategory.title }} should do the trick here.

{% set entryCategory = entry.videoCategory.first() %}
{% if entryCategory %}

{{ entryCategory.title }}

{% endif %}


Template loads via jQuery .load(), but no {% js %} tags are included

In Craft 3, the {% js %} tag places the javascript code just before the closing </body> tag in the rendered HTML document by default.

This means that the rendered <script> tag will not be in the #newAddressForm element, but will be rendered just before the closing </body> tag.

So if you are loading the rendered template using jQuery's .load() function and specifying the #newAddressForm element, the <script> tag will be excluded from the injected code as it isn’t within the #newAddressForm element.

Your best bet is to inline the <script> tag within the Twig template rather than using the {% js %} tag to include it. That way you can ensure that the code will be included in the #newAddressForm element as you need it.

More details of the {% js %} tag can be found in the Craft 3 docs: https://docs.craftcms.com/v3/dev/tags/js.html


How to output taxCategory in Craft Commerce

You can simplify your first bit of code by using:

{{ product.taxCategory.name == 'withVat' ? '+VAT' }}

The reason you get the error with your second bit of code is because craft.commerce.taxCategories is only an array of Tax Category names. Only the models of each Tax Category would have properties such as .id and .name


How do I get the column headers of a table in a matrix?

Updated code to output the entire table (headers and data).

Try this:

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

{% for block in entry.matrixFieldHandle %}

    {% for field in block.getFieldLayout().getFields() %}

        {% set type = field.getField().type %}

        {% switch type %}
            {% case 'Table' %}

{{ field.getField().name }}

                            {% set columns = field.getField().settings.columns %}
                            {% for col in columns %}
                                {{ col.heading }}
                            {% endfor %}

                            {% set handle = field.getField().handle %}
                            {% set tableData = block[handle] %}
                            {% for row in tableData %}

                                    {% for key, col in row if key|slice(0,3) == 'col' %}
                                        {{ col }}
                                    {% endfor %}

                            {% endfor %}

        {% endswitch %}

    {% endfor %}

{% endfor %}


500 Internal Server Error after moving index.php

You have to change your Craft path accordingly. When you move your web folder, you have to edit your index.php obviously.

Your php file does not magically know where your vendor folder is


Craft 3 wont update in Laravel Valet development enviornment

I believe we were conversing via Medium yesterday on this issue.

Regarding your question, I know for a fact your PATH reference is incorrect. The path to mysqldump is never ~/.local/bin/mysqldump; mine is located at /usr/local/bin/mysqldump (I'm using MariaDB).

BUT since you said on Medium that you're using MySQL (instead of MariaDB or another database option), you should use this instead: export PATH="/usr/local/mysql/bin:$PATH".

After you add that to your .bash_profile and either source the file or quit and relaunch terminal, mysqldump should be working.


How do I use Plain Text Field in URL Format?

The Slugify plugin has a Twig filter that should do what you're looking for.


You could build a plugin that listens to https://craftcommerce.com/docs/events-reference#commerce_cart.onbeforeaddtocart and translates the front end values of 10.5 or 10'6" or whatever into the number of inches (or, if you're working in a sane part of the world, even cm!).

Then on display of the cart or updates etc, you'll want to use some JS and/or twig maths to translate that back into those crazy feet/inch units you need there.

I honestly think trying to retro-fit in partial unit sales into Commerce as a whole would be quite a considerable challenge, so I think the best way to solve this is to use your smallest unit as the back end unit of quantity for the product, and do the magic in your plugin/and display.


How pass an ElementModel to a Macro in Twig

I see a few problems. The first is that {{ grid.item(entry.image) }} is actually an ElementCriteriaModel (i.e. which behaves like an array of images) and not an ElementModel (i.e. a single image), even if only one image is defined. To get the first image you can use entry.image.first or entry.image[0].

The second problem is that in your macro,  is trying to set the url string using the whole ElementModel (or in your case the ElementCriteriaModel). Instead use: {{ thumbnail.url }}

{% macro item(thumbnail) %}
    {% if thumbnail %}

    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image.first) }}
{% endfor %}

Update: If on the other hand, for some reason you want to pass the ElementCriteriaModel then you just need to handle it appropriately in the macro:

{% macro item(thumbnail) %}
    {% if thumbnail.first %}

    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image) }}
{% endfor %}

As a side note — keep in mind that the macro can also exist in the same template and imported using _self.


500 Error with no details on site migration

It turns out my MySQL wasn't installed correctly.
I'm using RDS but my setup didn't meet the basic requirements to connect to it from PHP.


Using a Matrix field to create a homepage that shows entries from sections and categories

I figured it out.
I changed
{% set category = entry.slug %}
{% set entries = craft.entries.section(section).limit(4).orderby('postDate desc').all() %}

to
{% set category = craft.categories.slug(entry.slug) %}
{% set entries = craft.entries.section(section).relatedTo(category).limit(4).orderby('postDate desc').all() %}

and it shows up as expected.


How to create manually an Entry from command line

This is the best answer so far. Basically the easiest way is to use array, and map everything there. The saveElement function will the the rest. You can update fields, tags, categories, matrixTables etc. The given example is matrix-data only, but again the same logic could be used everywhere.

How to save Matrix data programmatically in Craft 3

The only missing point is the "merge" functionality but I guess it has to be done manually after using the toArray() function first


Steps for integrating an HTML design to a website page and managing its content from backend

I would first suggest getting your static HTML site up and running with twig, then slowly adding dynamic elements as you learn more about Craft.

Start with two template files _layout.twig and index.twig. _layout.twig is the file that all pages will extend, so it will contain all your html meta, css, js, etc. Within the _layout.twig you can define areas that can have content injected into, so in the example below I have the 'content' block.

_layout.twig:

<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>title</title>

      {% block content %}
         Content will go here, if no content found this message will display.
      {% endblock %}

We can then extend the layout from the index.twig page by defining the content area.

index.twig, accessible from yourdomain.com/index (or yourdomain.com)

{% extends '_layout' %}

{% block content %}

I love puppy dogs

Puppy dogs love me

{% endblock %}

After that, once you have created your first section you will be able to make your pages dynamic.

index.twig

{% extends '_layout' %}

{% block content %}

{{ entry.title }}

        {{ entry.body }}

{% endblock %}

In terms of creating sections and entries you will need to invest some time looking at the available resources then post here or jump on the discord server if you need help with specific things.


Using Aliases inside Admin Panel for fields

A good approach would be to use the UrlHelper class it has a function UrlHelper::url() that is available in Twig and will return the correct URL for a certain path. So you could ask your client to not insert the entire URL, only the path -> instead of example.com/entries -> entries or you can include a custom Twig function/behavior that strips the domain before you use the {{ url('entries') }} function.
Anyway: to be honest I would create a different approach in the first place. Creating static URLs in a text field is usually not a good thing. I'm always a fan of the

protect clients against themselves

philosophy so you may want to consider to create a custom field type with autosuggestion or something. SEO wise it could be a bad idea if you clients are able to insert whatever they want and you output too many dead links. Maybe a Relation field could be something for you?


Sounds like a server (DNS) configuration issue. PHP can't open the URL because it can't resolve the domain.


To debug where the delay is, you can enable devMode, which will write out a bunch of code and database profiling information to your log files in craft/storage/runtime/logs.

After you do that, save an entry then find that request in the log files.  You can look at the timestamps on that request to see what part of the code the 30 second delay is occurring on, which will point you in the direction of the underlying problem.


Smart Map - Sorting for closest location in PHP

You're very close!
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->myFieldHandle = array(
    'target' => 90210,
    'range' => 100
);
$criteria->order = 'distance';

$results = $criteria->find();

I've never actually tested it with the Element API plugin, but in theory it should work just fine.
In response to this question, I've added instructions for PHP to the docs.


Ahh this is a bit misleading because the docs don't really spell it out. "formHandle" according to the docs really feels like it might be the variable you set your form to, but it's literally the form handle you got when you titled your form in the CMS.

So if your form starts with:

{% set apple = craft.amForms.getForm('fireTruck') %}

your error code needs to be this:

{% if fireTruck is defined %}
    {{ errorList(fireTruck.getErrors('someField')) }}
{% endif %}

and not this:

{% if apple is defined %}
    {{ errorList(apple.getErrors('someField')) }}
{% endif %}


Specifics on ImageMagick and animated GIFs

For Craft to use it, yes the ImageMagick PHP extension is required because Craft uses PHP's bindings in the library they're using.

Depending on the host's OS, it should be a package manager update away. Any decent host should be able get it working incident free.


Hide or obfuscate Digital Product file path?

Well, I figured out a way to do this. This works.

{% set file = variant.songFile.one() %}
{% if file %}
  <form method="post" target="_blank">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="assets/download-asset" />
    <input type="hidden" name="assetId" value="{{ file.id }}" />
    <input type="submit" value="Download" />
  </form>
{% endif %}

Courtesy of this old answer: https://craftcms.stackexchange.com/a/22850


Delete all old versions from the database

I just wrote a plugin that deletes all versions (truncates the craft_entryversions table) and then saves a new version for each of your entries, so you can later revert back to it:

Delete All Entry Versions


How do you tell Craft to change post directions from row-to-row?

You could do multiple "for" loops on the first craft.entries request using limits and offsets:

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

{# ROW ONE #}
{% for post in posts.limit(1) %}
   html stuff for first post
{% endfor %}

{% for post in posts.limit(2).offset(1) %}
   html stuff for 2nd and 3rd posts skipping 1
{% endfor %}

{# ROW TWO #}
{% for post in posts.limit(2).offset(3) %}
   html stuff for 4th and 5th posts skipping 3
{% endfor %}

etc.

For the switching back and forth between horizontal and vertical, you can set up a couple of macros and call them where needed(or includes for that matter, lots of ways to skin this cat).

{% macro vertical(url, title) %}

    {{ title }}

{% endmacro %}

{% macro horizontal(url, title) %}{# different html #}

{{ title }}

    Learn More

{% endmacro %}

and then where you need them in the first part of your question above:

{% for post in posts.limit(2).offset(3) %}
   {{ _self.vertical(post.url, post.title) }}
{% endfor %}

and

{% for post in posts.limit(2).offset(3) %}
   {{ _self.horizontal(post.url, post.title) }}
{% endfor %}

Twig Macros

Using Macros by Mijingo

alternatively with includes

{% for post in posts.limit(2).offset(1) %}
  {% include "_includes/vertical_layout" %}
{% endfor %}


This should work (set the limit to whatever you want/need):

{% set tag = craft.tags.title(tagTitle).first() %}

{% paginate craft.commerce.products.relatedTo(tag).limit(10) as pageInfo, products %}

    {% for product in products %}

        {{ product.title }} etc

    {% endfor %}

    {% if pageInfo.prevUrl %}Previous Page{% endif %}
    {% if pageInfo.nextUrl %}Next Page{% endif %}

For more on the pagination side of things, see: https://craftcms.com/docs/templating/paginate


Saving an entry with multiple parentheses throw a 403

If you check the ModSecurity logs, you can find exactly which of its rules Redactor/that POST request is tripping.

You can either modify that rule to allow it to pass or just disabled that specific rule.


How to query with relatedTo of a Relationship Field in a Matrix Field block

You were right about the issue being that the relationship is made within a Matrix field. Because of this, you have to explicitly pass the Matrix field's handle to the relatedTo parameter.

{% for instrument in craft.entries.section('instrument') %}

{{ instrument.instrumentName }}

      {% set people = craft.entries.section('person').relatedTo({
         targetElement: instrument,
         field: 'roles.instrument'
      }) %}
      {% if people|length %}
         {% for person in people %}

{{ person.personName }}

         {% endfor %}
      {% else %}

Nobody plays {{ instrument.instrumentName }} :(

      {% endif %}
{% endfor %}

Note: Using a dot notation to specify the sub-field is only necessary if you have multiple relational fields within a Matrix, but it can't hurt.


You could set a variable to access the products model like so:

{% set product = item.purchasable.product %}

and then access the fields like normal {{ product.myCustomField }}

The snapshot holds the products fields as they were at the time the line item was added to the cart. So depending on how you're using the fields would dictate the method used.

You could also access the snapshot slightly cleaner using
{{ item.snapshot.product.myCustomField }}