Plugin Variable.php Problem I want to get the developer name from Plugin.php using the getDeveloper() method so I created a function devName() in Variable.php

public function devName() {
    return craft()->crmPortal->getDeveloper();
}

but when i want it to print it in my template, using this {{craft.crmPortal.devName}} I'm having this Error. Property "Craft\WebApp.crmPortal" is not defined.

It sounds like you're attempting to access the getDeveloper method on your plugin's main service class, but the class doesn't exist.

You have two options:

Create the service class, and implement a getDeveloper method.
Call the getDeveloper method on your main plugin class (which I suspect is what you're really trying to do).

Option One: Service

Your minimal service class will look like this:

<?php

namespace Craft;

class CrmPortalService extends BaseApplicationComponent
{
    /**
     * Returns the developer name.
     *
     * You could either hard-code the developer name, or you could
     * retrieve it from the main plugin class, as described in
     * option two.
     *
     * @return string
     */
    public function getDeveloper()
    {
        return 'John Doe';
    }
}

Option Two: Plugin

Craft uses Services to expose functionality, in exactly the same way that plugins do. If you're trying to figure out how to do something, just look for a Craft Service with a similar name.

In this case, you want to retrieve your main plugin file, so the PluginsService is a good place to start. We're in luck, it has a getPlugin method, which accepts a plugin handle, and returns the plugin class.

Here's how you might use that, to call the getDeveloper method in your main plugin class.

craft()->plugins->getPlugin('crmPortal')->getDeveloper();


Can I call a dynamically named variable through twig? I am using Craft 3 with the Commerce 2 plugin.

I am trying to dynamically call a variable in a twig template where this variable has to be a "placeholder" for a handle of a field inside a block inside a matrix field.

Here is an example snippet which visualises my problem:

{# 'product' variable is passed to this template #}

{% set fields = product.productFields %}
{% set categoryOptions = [] %}
{% for cats in fields.type('categories') %}
    {% for category in categories.fieldLayout.fields %}
        {% set categoryOptions = categoryOptions|merge([category.name]) %}
    {% endfor %}
{% endfor%}

{% set productId = product.id %}
{% for catOption in categoryOptions %}
    {# Here is where I try to call catOption as a 'placeholder' #}
    {% set productId = productId~ '-'~ categories.(#{catOption}).label %}
{# I have also tried using:
{catOption},
catOption,
#{catOption} etc but nothing seems to work #}
{% endfor %}

Usually I could call the 'categories' one by one but I want everything to be dynamically set.

I know that in some languages you can call a function/property like that or assign a variable with such value.

Any suggestion for a solution or a workaround would be useful. Thank you in advance!

Unless I'm misunderstanding, the title of your question is a bit misleading as you're not trying to call a Craft function in Twig, you're trying to output a dynamically named variable (a variable variable).

You can generally do that using the array syntax: e.g. categories[catOption].


SVG thumbnails black on live server On my MAMP development server, SVG files display like this in the Assets section of the Control Panel:

On my live server, they get a black background:

When I use an SVG file inside an img tag with an transform like this:

<img src="{{ iconSVG.getUrl(iconSize) }}">

I got this working fine on the MAMP server, but on the live server the file gets transformed into a PNG with a black background.

I don't necessarily have to use a transform on the SVGs, so could leave that out, but the black thumbs in the Assets isn't that pretty.

I checked both servers, and a possibly relevant difference I can see is that the MAMP does not have imagick, whereas the live server does.

How can I fix the black thumbnail issue? Would I need to disable imagick on the live server somehow?

Craft requires Imagick to do any SVG transforms, so that fact that it is working on your MAMP install without it is the only weird thing I see here. :)

Craft will attempt to use Imagick if it is available on the server and fallback to GD otherwise or you can explicitly tell it which one to use via the imageDriver config setting.

As to why it's all black on production, make sure you're using a recent version of both the Imagick PHP extension as well as the underlying Imagick library.


AJAX reload include template I'm working on getting our site set up with Craft Commerce, and I am currently working on a sidebar cart for the site. I've found examples on how to add products to the cart using AJAX and jQuery and have gotten that working successfully. However, I'm struggling to understand how to update the cart listing after a successful response.

I have the sidebar cart template set up as an include. Is it possible to use AJAX and jQuery to reload just the sidebar cart include after the successful response? Or is there a better way to show the updated contents?

There are two main approaches in general to updating your page in response to changes in the cart.

The first is just an ajax load in of a partial template.

This is really just as simple as something like:

$cart.load("/_ajax-injects/cart.html").fadeIn('fast');

....which (assuming $cart points at a div holding your displayed cart) - would load in over the old cart a new cart (assuming templates/_ajax-injects/cart.html has such a partial template in it)

This is very easy to implement, but does not look wonderfully finessed as there will be a visible result of replacing a large section of the page at one go.

The second approach is using the json response.cart object to update just the appropriate fields within your already displayed cart.

This is considerably trickier.  Each of the fields, such as your item quantities, subtotals, tax, shipping etc must have an identifying class or id on them, and then you parse through the response.cart object grabbing the appropriate values from that and inserting them into those fields.  You also need to deal with e.g. removing lineItem rows if the qty is zero and so forth.

A lot more work, however once implemented this is a visually much more finessed approach as just the fields that need updating get updated.


How to parse environment variables and globals from a field I want the ability to parse environment variables such as {siteName} and globals from channel fields, for example a rich text field.

I have been using {{ include(template_from_string(entry.fieldName)|raw) }}, but this is not suitable because it gives authors the full power of twig.
Brandon Kelly pointed out that using the replace filter can work {{ entry.fieldName|replace('{siteName}', siteName)|raw }}

Using a macro I can make this manageable.

I would like the ability to use globals too, what is the best way to have all globals being options to replace or using another method?

Would having 20 possible variable options to replace cause any issues, I would be calling this 3-4 times in a template.

You could enable your client to use Reference Tags by adding the parseRefs filter.

{% set str = '
Since {globalset:42:yearEstablished}
' %}
{{ str|parseRefs|raw }}

But this would enable them to access field values of (almost) any element (entries, assets, tags, ..), not just from global sets.
And they would also have to remember the global set's ID.

So your current replace filter solution is a good approach in my opinion. You can pass multiple replacements pairs like so
(and no, you won't notice if there's 1 or 100 of them):

{% set str = '
Since {yearEstablished}
' %}
{% set replacements = {
    '{yearEstablished}': companyInfo.yearEstablished,
    '{siteName}': siteName,
} %}
{{ str|replace(replacements)|raw }}

You could also consider building that replacements array programatically.


Craft CMS on Host Inmotion Had absolutely no issue with an older version of their host on the installation and running a Craft CMS site.

This one has been a bear

Is there a step by step on best way to install

The only real difference I see is MariaDB, yet they assured me it was just a top layer of MySQL

cPanel Version  66.0 (build 23)
Apache Version  2.4.27
PHP Version 5.6.31
MySQL Version   10.2.9-MariaDB
Architecture    x86_64
Operating System    linux

Thanks

Could not find your craft/ folder. Please ensure that $craftPath is set correctly in

This is usually one of 3 things:

The path to the craft folder defined in your public index.php file in $craftPath is incorrect.
The path defined in $craftPath is correct, but PHP doesn't have permissions to go into that folder and open index.php.
Your php.ini file has open_basedir restrictions in place that prevent PHP from opening that folder.


Extending Assets with oEmbed video references Disclaimer: I'm new to Craft, making the jump from WordPress and looking for implementation advice to a specific requirement.

In addition to images, I would like to be able to manage oEmbed video references (mostly Vimeo URLs, and any associated metadata) from one central location: Assets. This way, when specifying the media assets for an entry, I can manage images and video together in one field, and can use drag & drop to order my content.

My intention is to extend the Assets UI with an additional button (after "Upload Files", called "Add oEmbed") that will generate a static file which acts as a pointer to the embed-able video.

Is this a sensible approach? If not, how would you suggest I go about it?

Craft gives you the ability to combine different type of content in one single field, the matrix field. Configure one matrix block type for your images and one for your video links.

This setup still allows you to re-order your content (the matrix blocks) using drag & drop. You can further extend your entries with other types of content (maps, quotes, etc.) and have better accessibility to any fields assigned to your images and videos (not hidden behind double click).


Accessing Global Set Variable Just starting to play with Craft going to be a learning curve coming from wp and processwire etc.

I created a custom Global Set and called it Logo which I assumed I could use in the _layout.html template to show a logo in the header and make it easy to change etc.

I called the set Logo and it has a handle of logo. This created the Globals option in the top nav. Here I was able to upload a logo from my assets etc.

Now in the _layout.html template I am trying to access this image by using the following but nothing shows up.

Based on the docs it says:
You can access your Global Sets from any template via their handles. For example, if you have a Global Set with the handle “companyInfo”, and it has a field with the handle “yearEstablished”, you can access that field anywhere using this code:

{{ companyInfo.yearEstablished }}

I also tried

What am I doing wrong am I going about this the wrong way?

Image fields are an array, because you can have multiple images within that field. Usually you would loop through the array to output your images:

{% if Logo.logo | length %}
    {% for image in Logo.logo %}
        {{ image.url }}
    {% endfor %}
{% endif %}

Or, if you only have a single image in the array, you can just do this:

{% set image = Logo.logo.first() %}

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

More info on Asset templating here


List products related to currently active category (url) My URL:
http://localhost/product-family/compressors

How can I list the related products?
I don't understand how to get access to the compressors (a category entry of the product-family category type). The product-family is a structure - so there may be many levels.

(I thought I'd have access to the currently selected category via entry but I get error when I try to access it.)

The same way as entry is available if you hit an entry, the variable category is available if you hit a category.

Thus the following code:

{% if category is defined %}
    {# Specific category selected #}
{% else %}
    {# No specific category selected #}
{% endif %}


500 error on PNG images I'm uploading a PNG image into my assets folder and linking to it from my css file - standard stuff, nothing special. However the PNG image is returning with a 500 error in the console and not displaying. When I visit the image directly in the browser I get a lot of numbers and:

Template Error

Unexpected character ""

I'm working locally with MAMP Pro and I've only recently restored my computer from scratch. I'm wondering whether this is a Craft issue or potentially a MAMP issue. It works fine if I use a Jpg instead or an externally hosted PNG.

This is also happening when I link to it with an img tag

Host your image assets outside of the templates directory. A more appropriate place for UI assets is in the /public directory.

Craft is attempting to parse the image like it is a template, which is causing the Unexpected Character error.


Commerce products in Matrix I use Matrix to select products through a "Commerce Products" field type.

In the template, the following code displays nothing (not even an error in devMode.)

{% for block in entry.MatrixHandle %}
    {% set relatedProducts = craft.commerce.products.relatedTo({
        targetElement: entry, field: 'BlockTypeHandle.FieldHandle'
    }) %}

    {% for entry in relatedProducts %}
        {{ entry.title }}
    {% endfor %}

{% endfor %}

If you actually have products selected in that entry's matrix products field, then

{% for block in entry.MatrixHandle %}
  {% if block.type.handle == "matrixProductsBlockTypeHandle"%}
    {% for product in block.productsFieldHandle %}
        {{ product.title }}
    {% endfor%}
  {% endif %}
{% endfor %}

That is the simplest approach really.  So if that doesn't work, triple confirm the entry vairable is the one you think it s and that you do indeed have chosen products in that field.  If still nothing, check the craft.log I guess!


Performance issues from matrix vs rich text? I'm finding myself using matrices a good deal on my site for a specific client. My client has little experience with any content management systems, and I liked the structure matrices could provide.

For example: Instead of having them use the rich text editor, each time of content they can use on a certain page is part of a matrix field. They can add an image, then add a paragraph below, then add a pull quote, then maybe another image or paragraph etc etc. I thought this gave me a great deal of control over the styling as well.

But I'm wondering if matrices have an effect on performance? I suppose I could use the rich text field, though I would have to hold my client's hand a bit more.

I'm noticing my initial time for anything to load onto the screen is pretty poor. I've followed some steps from Patrick Pohler on Craft performance optimization, and after the initial wait time my page loads fine, but I'm wondering if my use of matrices has something to do with my initial load time?

Matrix does have additional overhead, but it's unlikely that it is the sole reason for any slowdown.

If you enable devMode, you can see profiling information for SQL queries as well as code execution in your browser's console to try and track down where any slowness is occurring.

If it is ultimately coming from you template, you can look into the {% cache %} tag to help with initial load time.


Cannot omit index.php from URL I know this question has come up many times before, although after reading and trying dozens of answers, I am none the wiser.
I am currently rebuilding my website with Ubuntu 16.04, PHP7 and apache. And what worked flawlessly on my old site (Ubuntu 14) is now not, and I cannot hide the index.php within the URL without the site crashing. This of course breaks any links to finish the craft completion and therefore is not operational.
Here is my .htaccess file:

   <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

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

I have entered garbage within the .htaccess and am not receiving any change, therefore I presume it is an issue with this.
The .hta is within my web route of /var/www/public_html, which is indexed correctly withing the apache config.

I've edited apache config to  allow overriding:

<Directory />
  Options FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>

I've also made sure that omitting script names is enabled:

'*' => array( // production by default
    'siteName' => '*****',
    'omitScriptNameInUrls' => true,
    'siteUrl' => 'http://' . $_SERVER['SERVER_NAME'] . '/',
    'timezone' => 'Europe/London',
    'allowAutoUpdates' => true,
    'cpTrigger' => 'mgmt',
    'rememberUsernameDuration' => false,
)

Sigh If anybody could suggest anything else, it would be very much appreciated!

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

'sudo a2enmod rewrite' was needed!

Thanks all.


How to access a structure I'm trying to build a restaurant menu using a structure.
The structure looks like that:

> Menu-part 1
  > Menu-item 1
  > Menu-item 2
  > Menu-item 3

> Menu-part 2
  > Menu-item 4
  > Menu-item 5
  > Menu-item 6

How would I now make a page accessible with those entries ? Should I create a single-page and then add those categories ? Or is there a better way ?

EDIT
What I don't understand is: Do structures exist without any page behind it? Because what I want is a page that just takes every entry from my menu-structure and builds me the food-menu on mysite.dev/lunch-menu for example.

Do structures exist without any page behind it?

No, you have to design a template for it. To make that template available under mysite.dev/lunch-menu you have multiple options.

The easiest way to do it is to simply save the template as /lunch-menu/index.html.

Another pretty common option is to use a Single section for your menu's Structure section index page. This is not very complicate to set up and because your "Lunch menu" now got it's own entry type, you can add custom fields to it. That's a good thing to have if you need other content on that lunch menu's index page besides the actual lists.

You could also create another structure (e.g. named "Pages") and make you Lunch menu structure's index page an entry of that other structure. Besides index pages, like the "Lunch menu" index or a "News" index for example, you could also add entries like "About" or "Contact" to that structure. One advantage of this approach is that you have all your pages (indexes and single content) in one structure and you can create your site navigation out of it.


Freeforms Check Submission is true I'm trying to create a form that adds a cookie so that someone who has submitted the form can see content on the thank you page to protect the download.
Currently I've got this:
{{ craft.freeform.form('handle').render() }}

{% set formcook = craft.freeform.form('handle') %}

{% if formcook and formcook.submittedSuccessfully %}
   {# Cookie Will go here #}
{% endif %}

This doesn't seem to be working, although I've seen something very similar working on a different project.
Freeforms has very little in their documentation regarding this unless I'm missing something very obvious.
Anyone spot where I've gone wrong?

This was a separate issue causing this, the above works fine.


Can't seem to get variables set in controllers I think I might be confused by https://craftcms.com/docs/plugins/controllers#posting-to-controller-actions

I have a controller that I want to return a model when validation fails:

$post = craft()->request->getPost();
$requestModel = Micros_AuthModel::populateModel($post);

if ( ! $requestModel->validate())
{
    craft()->urlManager->setRouteVariables(array(
        'requestModel' => $requestModel
    ));

    $this->redirectToPostedUrl();
}

I assumed I would have access to requestModel in the template that posted:

{% if requestModel is defined %}
    {{ inspect(requestModel) }}
{% endif %}

But I that inspect() call never fires.

What am I missing?

Close!  You want to redirect on success and let the request continue as normal on validation failure.

public function actionMyPluginAction
{
    $post = craft()->request->getPost();
    $requestModel = Micros_AuthModel::populateModel($post);

    if ($requestModel->validate())
    {
        // Yay! What I did works!

        $this->redirectToPostedUrl();
    }

    craft()->urlManager->setRouteVariables(array(
        'requestModel' => $requestModel
    ));
}


How to fetch entries from multiple sections I have five separate sections with x number of entries each. I would like to render all the entries from all the sections on a single entry template page. Is there a way to do this ? I know we can set entries like this  {% set entries = craft.entries.section('sectionHandle').limit(10) %} , but I'm not sure how to get entries from all the sections.

Any help or suggestion is highly appreciated.

Thanks!

You can insert an array of different sections instead of a single one to pull entries from multiple sections

{% set entries = craft.entries.section(['sectionHandle', 'sectionHandleTwo']).limit(10) %}

You can also write that

{% set entries = craft.entries({
  section: ['sectionHandle', 'sectionHandleTwo'],
  limit: 10
}) %}

If you remove the .section() / section:..., entirely you'll fetch all entries from all sections.
Here's a link to the docs


Search Results In a Drop List/Popup on Same Page Does anyone have an example how I would implement search results that appear in a popup on the same form (without redirecting to a results page). The idea would be that as they start to type in the search bar, after a delay I'd show a popup with a few results.

I'm good on the jS, popup part. The part i don't know about is how i would call craft cms dynamically on the same page to get the results (would i do this with JS or with the form tag, can i make the request with JSON/Ajax?). All the examples show the form directing to a results page.

Anyone have any suggestions

You can request any template via ajax using jQuery. jQuery would essentially listen for onChange events from the search field and ajax load a template that looped through the search results.

The template that you request can even be the default full search results page, with a conditional that determines which part of the template gets returned if the request is ajax.

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query).order('score') %}

{% if not craft.request.isAjax %}
    {# Full page results content can go here #}

Search Results

        {% for entry in entries %}

{{ entry.title }}

        {% endfor %}

{% endif %}

{% if craft.request.isAjax %}
    {# Drop-down results can go here. And inserted into DOM via jquery. #}
    {% for entry in entries %}

{{ entry.title }}

    {% endfor %}
{% endif %}

jQuery can then insert the results of the ajax call using an html element selector. See the jquery documentation for more information on using .load or .ajax.

You will also probably want to put the {% set entries ... %} inside the if isAjax statements so that you can limit the results, or implement pagination, for the drop down vs the full page.


Table field type defaults I have built a few fields with the Table field.  I noticed an odd behavior maybe it's normal, but want to check.

I use a Table field with defaults entered, the defaults do not show up.  Now for the odd, if I put the Table field in a Matrix field, the defaults show up.  Is that normal Table field behavior?

I just did some testing of this. I thought I noticed the same thing, but then realised that I created and added the field to my section (a single) only after it already existed. In that case the defaults didn't show. But then I added the field to a channel section and created a new entry and the defaults show in that case.

So I think the reasoning is that it won't populate defaults on an already existing entry as these could easily go unnoticed by someone editing and end up being saved to the entry when unintended.


Revoke user permissions but not change the usergroup I have  a client who would like to edit a users permissions. However instead of adding permissions on a per user basis, they would like to remove permissions for that user by unchecking the item. However because it's enabled for the users usergroup it's not possible to uncheck. Am I missing something? Or should we create a new user group?

So in the above photo I'd like to uncheck, for this user only, a couple of different permissions.

A user inherits the permissions of any user groups they belong to additively.

If you want to remove specific permissions for that user, you'd need to remove them from the user group(s) they're currently in and either create a new user group for them with their specific permission or add the permissions directly to the user.


Stop specific Twig template from rendering anything If i want specific template to stop from rendering anything, I use if:
{% if something %}
HTML markup...
{% endif %}

This however requires wrapping whole Template in if which is not ideal for readbility.
Is there maybe some kind of Twig function which when used stops rendering template in which it is used? Like this:
{% if something %}
    {% do stopRendering() %}
{% endif %}

HTML markup (will show up if we didnt stopped rendering)...

Depending on what you exactly need to happen, the {% exit %} (docs) tag my be an option for you.


How to identify the recurring payments that happen after the initial subs creation payment the in Commerce Subs I've got a custom module that I have written to inject data into various places in my site when events happen with Commerce Subs.

As per the question title, I need to update an entry when a recurring payment happens (not the initial payment as I'm already doing something with that event).

I cannot see how to identify the subsequent payments from the events I have available to me in Craft Commerce

Listen to the invoice.payment_succeeded webhook and check the billing_reason for subscription_cycle. Full answer here: https://stackoverflow.com/a/54165193/1215040

use craft\commerce\stripe\base\Gateway as StripeGateway;
use craft\commerce\stripe\events\ReceiveWebhookEvent;
use yii\base\Event;

Event::on(
    StripeGateway::class,
    StripeGateway::EVENT_RECEIVE_WEBHOOK,
    function(ReceiveWebhookEvent $e) {

        if ($e->webhookData['type'] == 'invoice.payment_succeeded') {
            $invoice = $e->webhookData['data']['object'];
            if ($invoice['billing_reason'] == 'subscription_cycle') {
                // It's not the first payment!
            }
            if ($invoice['billing_reason'] == 'subscription_create') {
                // It's the first payment!
            }
        }
    }
);


How to list the latest 5 entries per entry type? Let's say I have 4 entry types (Article, Video, Photo & Quote). What's the best way to list the latest 5 entries by each entry type?

craft.entries() fetches entries.

To fetch the entries with a given entry type, you use type. So to get the Article entries, either craft.entries.type('Article') or craft.entries({type: 'Article'})

To fetch the latest 5, you want the entries sorted by postDate, descending (this is the default sort order), and then limit that to 5. Combining with the entry type, you have: craft.entries.type('Article').limit(5) or craft.entries({type: 'Article', limit: 5})

And you have four entry types, so might as well loop over those:

{% for entryType in ['Article', 'Video', 'Photo', Quote] %}
  {% set latestFive = craft.entries({
    type: entryType,
    limit: 5
  }) %}

  {% for oneEntry in latestFive %}
    {# list that entry #}
    {{ oneEntry.title}} is of type {{ entryType }}
  {% endfor %}

{% endfor %}


Issue Excluding Entries with Multiple Categories in Query I've reference this related thread but haven't found a working solution that supports pagination and will exclude entries that have multiple categories.

The code example will not include Category One, but when an entry has Category One and Category Two it will still display because Category Two is included in the cateogries array. Is there a way to still exclude the entry even if it's second category is included?

  {# Get all the categories you want to INCLUDE #}
  {% set categories = craft.categories({
      group: 'categories',
      slug: [
        'not category-one',
      ],
      limit: null,
    }).all() %}

  {# Get entries related to your desired categories #}
  {% set latestNews = craft.entries({
      section: 'news',
      relatedTo: categories,
      with: ([
        ['image', {
          withTransforms: ['medium']
        }]
      ]),
      orderBy: 'postDate desc',
      limit: 4
    }).all() %}

Start by getting the category ID(s) you want to exclude:

{% set categoryIds = craft.categories()
    .group('categories')
    .slug('category-one')
    .ids() %}

Then get all the entry IDs that are related to them, which should be excluded:

{% set excludeIds = craft.entries()
    .relatedTo({
        targetElement: categoryIds
    })
    .ids() %}

Then run your main news query, excluding those entry IDs.

{% set latestNews = craft.entries()
    .section('news')
    .id(['not']|merge(excludeIds))
    .with([
        ['image', {
            withTransforms: ['medium']
        }]
    ])
    .orderBy('postDate desc')
    .limit(4)
    .all() %}


How do I create a Human readable sitemap in Craft CMS I'm just getting started with Craft (and digging it).

I've seen lots of xml sitemap plugins available already.  How do I create a human readable sitemap that will be browsable from the front end and that I can link to in the footer.

Thanks for your help in advance!

You could do this manually within a template.

This code should get you started – it will output all of the sections and their entries:

{# Loop through all the sections #}
{% for section in craft.sections.getAllSections() %}
  {# We only care about sections that have URLs #}
  {% if section.hasUrls %}

{{ section.name }}

      {# Loop through each of its entries #}
      {% for entry in craft.entries.sectionId(section.id).limit(null) %}

{{ entry.title }}

      {% endfor %}

  {% endif %}
{% endfor %}

Note that this won’t include any links to pages that only exist as a template. For example if you have a contact.twig template, and you don’t have a Single section in the Control Panel for it, then that will need to manually be added at the beginning or end of this list.


Display all entry titles on one line during FOR loop I have a FOR loop that should be displaying all the entry titles on one line. But instead, it is outputting them on separate lines.

I want to see:

Developer: Jane Doe, Jim Doe

Instead, I am getting:

Developer: Jane Doe
Developer: Jim Doe

My code:

{% set developers = entry.GamesDeveloper %}

{% for developer in developers %}

Developer: {{ developer.title }}

{% endfor %}

This is because you're using an html list
 element, which by default puts each element on a new line.  You could style away the newline I suppose, but why use it at all...there are a bunch of ways of doing this, but this is one simple one:

{% set developers = entry.GamesDeveloper %}
{% if developers|length %}
Developer:
{% for developer in developers %}
    {{ developer.title }}{% if not loop.last %}, {% endif %}
{% endfor %}
{% endif %}


Using a variable for a hash key I am trying to use a lookup table technique I saw in a recent Craft Link List post, but getting errors.
The general objective is to auto-generate button text from an array of possibilities using a Matrix block type as a key. Here is my code:
    {% set buttonText = {
    "video" : "Watch the Video",
    "podcast" : "Listen Now",
    "externalLink" : "Visit Site",
    }
%}

{# resource is a Matrix fieldtye #}
{% set resources = entry.resource.all() %}
{% for block in resources %}
    {% set text = buttonText[(block.type)] %}

{{ block.heading }}

{{ block.description }}

        {{ text }}

{% endfor %}

The problem is trying to figure out how to use variable as a key in this statement: set text = buttonText[(block.type)], where buttonText is the array and block.type is the key. The value of block.type is correct and matches the key in the array, so I am guessing the syntax is wrong, but can't get it figured out.
Thanks for any suggestions!

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


How can I make an entry (in this case a page from structure) only visible to users with cp access? I tried 'draft page' but that only shows it in live preview. I need it accessible through the navigation as well. I was expecting a concept button in the CP that would allow this?

Do I need to make a specific light switch and create conditionals or is there some logic in the system?

Craft has a handy {% requireLogin %} tag; this seems like the quickest and easiest solution for you.

If this particular entry has its own Twig template you can just put this tag at the top of the file.

Alternatively, as you say you could create a lightswitch field, add that to your entry type and simply tick the entries you would like to be password protected.

A simple piece of Twig code that checks the lightswitch and does what you need could look like this:

{% if entry.requireLogin %}
    {% requireLogin %}
{% endif %}


How to output an Entries Field value within a Matrix Field block I'm trying to code up a Matrix field for a homepage slider, and it contains a single 'Slide' block type. It has fields for Image (Assets), Heading (Plain Text), Sub-Heading (Plain Text), and Slide Link (Entries). I've got everything working, except for the Slide Link field (where I want to output the entry URI for the entry that was selected in that field).

Whenever I add {{ block.slideLink }} to my template, I get the following error:

  Object of class Craft\ElementCriteriaModel could not be converted to string

So I'm obviously not meant to output a link to an entry (I only have one link being selected in the field) in this way, so can someone help me out with the syntax that I need please? There weren't any Entries examples in the Matrix Field docs that I could copy from, and I couldn't figure out how to adapt the Entries Field examples to fit in with a Matrix field.

Thanks in advance for any help, and here's my code. The incorrect {{ block.slideLink }} code is on line 11:

{% extends "_layout" %}

{% block content %}

      {% for block in entry.homepageSlideshow %}

            {% set largeImage = {
              mode: 'crop',
              width: 1180,
              height: 450,
              quality: 80
            } %}

            {% set image = block.image.first() %}
            {% if image %}

            {% endif %}

{{ block.heading }}

{{ block.subHeading }}

      {% endfor %}

{% endblock %}

You get this error because {{ block.slideLink }} returns an array of EntryModels (even if you set your Entries field up to only allow 1 entry). So you need to add the first() method to get the first (and only) EntryModel that you are interested in:

{% set entry = block.slideLink.first() %}

Access the url property to return the URL of that entry:

{% if entry %}
    {{ entry.url }}
{% endif %}


Transform cannot be found I've got a Matrix field with an image. If I use a pre-defined transform that's defined in Assets everything works fine. However, I need to set a transform manually in the template but it keeps returning an error "The transform “wideCrop” cannot be found!". I have used transforms in templates all over the site that work fine so I'm puzzled why this particular one isn't working.

This is from an embedded template inside the entry:

{% for block in entry.contents %}
    {% for image in block.image %}

        {% switch block.position %}
            {% case 'full' %}
                {% set wideCrop = { width: 940, height: 360, mode: 'fit' } %}
                <img class="full" src="{{ image.getUrl('wideCrop') }}">
        {% endswitch %}

    {% endfor %}
{% endfor %}

Thanks in advance!

Remove the single quotes around wideCrop.

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

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


Text Align Buttons for Rich Text Fields I'm trying to add the ability to be able to align text left, right and center to my rich text fields. I have had a look into it and can only find a version which works perfect for body fields but not rich content.

The plugin I tried to use for this is here: https://github.com/elliotlewis/Redactor-Extras

I also looked at redactorstyles which did the same thing.

Is there possibly a way to apply this to all fields or is there another way I could go about it in redactors standard.json?

Per their configuration docs, which also link to Craft's docs on the subject, it looks like you'd just need to add "alignment" to the plugins portion of one of your craft/config/redactor/ JSON config files.

i.e.

{
    "plugins": ["alignment"]
}

Then whatever config you end up modifying, you'll want to make sure that config is selected under that field's settings in Craft (Settings->Fields->Your Rich Text Field).


Product Filtering with Tags I've built a product filtering system using tags and currently have 2 available tag groups under different fields. Size and Type

Currently if I select 1 tag from both size and type, it shows all products with either selected, however I want it to only show if the product contains both tags.

{% set query = craft.request.getQuery() %}
{% set selectedTagsIds = query.tags ?? [] %}

{% for tag in craft.tags.group('size').all() %}
    {% set checkedAttr = tag.id in selectedTagsIds ? 'checked' : '' %}
    <input type="checkbox" name="tags[]" value="{{ tag.id }}" {{ checkedAttr }}>{{ tag.title }}</input>
{% endfor %}

{% for tag in craft.tags.group('type').all() %}
    {% set checkedAttr = tag.id in selectedTagsIds ? 'checked' : '' %}
    <input type="checkbox" name="tags[]" value="{{ tag.id }}" {{ checkedAttr }}>{{ tag.title }}</input>
{% endfor %}

{% set relatedToParam = ['or'] %}

{% for id in selectedTagsIds %}
    {% set relatedToParam = relatedToParam|merge([{
        targetElement: id
    }]) %}
{% endfor %}

{% set relatedToParam = relatedToParam|length > 1 ? relatedToParam : null %}

{% set entries = craft.products.type('accommodation').relatedTo(relatedToParam) %}

{% for product in entries %}
    // Product content here
{% endfor %}

Is there a way I can modify what I have above to make it so that if user selects an option from each tag group, that it only shows products with both selected tags? And if more than 1 of each group are selected to show those too?

I've based my current code based off this answer.

Not sure i understand well, but to be sure: you want to be able to filter for (let's say you sell shirts) a Red AND Large shirt, so it filters only the shirts which contain the color red and that are available in large?

On that note, have you tried setting relatedToParam to and instead of or?

The answer you linked seems to work for multiple selections that are not related. For example: i want the website to show me all the red shirts and all the large shirts, but not necessarily just the red large shirts.

Following that logic, changing relatedToParam to and should do the trick?

EDIT (2019-02-07):

So, i tried quite a few solutions and that seems to be working, please read the comments.

EDIT 2:

There was an issue!
For example, if no size was selected, the loop simply won't do nothing. You could switch the loop to start with types, but then again, if no type is selected, same problem.
Now it's working but still really NOT versatile.
Feel free to edit or comment with a better solution!

{% set sizes = craft.tags.group('size').all() %}
{% set types = craft.tags.group('type').all() %}

{# You'll need to separate tags inside the query itself #}
{# ?size=......&type=...... #}

{# The split filter doesn't work directly on getParam #}

{# Error when getParam is empty #}
{# Because it is set to [] and we can't split on an array #}
{# You will need to find a little condition to make it bulletproof #}

{% set selectedSizesIds = craft.app.request.getParam('size') ?? [] %}
{% set selectedSizesIds = selectedSizesIds|split(',') %}

{% set selectedTypesIds = craft.app.request.getParam('type') ?? [] %}
{% set selectedTypesIds = selectedTypesIds|split(',') %}

{# You can actually use a if inside a print statement #}
{# Take a look at the "checked" print condition #}

{% for size in sizes %}
    <input type="checkbox" name="tags[]" value="{{ size.id }}" {{ (size.id in selectedSizesIds) ? 'checked' : '' }}>{{ size.title }}</input>
{% endfor %}

{% for type in types %}
    <input type="checkbox" name="tags[]" value="{{ type.id }}" {{ (type.id in selectedTypesIds) ? 'checked' : '' }}>{{ type.title }}</input>
{% endfor %}

{# Where it gets tricky #}
{% set relatedToParam = ['and'] %}

{# Loop through the second set of tags while looping through the first set of tags #}
{# Still not quite sure that's the best way to go but it works well #}

{% if selectedSizesIds|length > 0 %}
    {% for size in selectedSizesIds %}
        {% if selectedTypesIds|length > 0 %}
            {% for type in selectedTypesIds %}
                {% set relatedToParam = relatedToParam|merge([
                    { targetElement : [size,type] }
                ]) %}
            {% endfor %}
        {% else %}
            {% set relatedToParam = relatedToParam|merge([
                { targetElement : size }
            ]) %}
        {% endif %}
    {% endfor %}
{% elseif selectedTypesIds|length > 0 %}
    {% for type in selectedTypesIds %}
        {% set relatedToParam = relatedToParam|merge([
            { targetElement : type }
        ]) %}
    {% endfor %}
{% endif %}

{% set relatedToParam = relatedToParam|length > 1 ? relatedToParam : null %}

{% set entries = craft.products.type('accommodation').relatedTo(
    relatedToParam
).all() %}

{% for product in entries %}
   {{ product.title }}
{% endfor %}


Passing multiple arguments to a macro? I have a link on a website that i'd like to set a class of active on, based on different segments.
{% macro is_acitve(segment) %}
    {% if craft.app.request.getSegment(2) == segment %}active{% endif %}
{% endmacro %}

Link Title

It's not working. How would I go about this ?

You might be better off sending the values as an array, then you will only need one parameter.
{# Change the macro to check for the value in an array #}
{% macro is_active(segments) %}
    {% if craft.app.request.getSegment(2) in segments %}active{% endif %}
{% endmacro %}

{# Send an array to the macro #}
Link Title


Triggering mailshot when new entry published - solutions? A client has a Campaign Monitor email list that he wants his new site to integrate with. We want to have a form that adds new subscribers to the list, and we also need to trigger a mailout to the list when a new blog post is published (not saved, but published on the site). He also wants the text of the blog post in the email that's sent out.

We are struggling to think of a solution that would work and can't find a plugin that would do the job. Sprout Email almost does it, but the Notifications part of that plugin doesn't hook into Campaign Monitor.

Anyone got any ideas for solving this?

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

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

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


getDirtyAttributes() not showing changes I've got an event listener in a custom plugin where I want to check to see if the users email updated, but it doesnt show that attribute as dirty, even though I know it should be:
Event::on(User::class, User::EVENT_BEFORE_SAVE, static function (ModelEvent $event) {
    /** @var \craft\elements\User $user */
    $user = $event->sender;

    Craft::info('USER::EVENT_BEFORE_SAVE');

    Craft::info($user->getDirtyAttributes());
});

When I update the users name or email from the admin panel, I get an empty array in my logs

2021-02-03 17:20:18 [-][25250][-][info][application] USER::EVENT_BEFORE_SAVE
2021-02-03 17:20:18 [-][25250][-][info][application] []

From the API:

Returns whether an attribute has changed since the element was first loaded.

The way I have read that is whenever something changes on the model, it will be recorded in the above method output
What am I doing wrong/missing here?

Entries are currently the only element type which support that method fully.


How can I send email notification to different addresses using Sprout Forms I know I am able to send to multiple recipients for any given form submission.
I am curious if there is a way to send to different addresses given user input.

For example, I have a drop-down on my site that chooses the department. If I choose "support", I would like to send the notification to "support@mysite.com". But, if the users chooses "other", I'd like to send the email to "other@mysite.com"

This can be done with Sprout Forms and the Sprout Fields Email Select Field.

The Email Select field allows you to create a dropdown list of email addresses, hides those email addresses on the front-end so they can't be seen or harvested for spam (the user will only see the Name of each department or discipline you wish to have associated with each email address), and makes the selected email address available after the user submits the form so that you can use that value to trigger an email address using Sprout Forms default notifications or Sprout Email Notifications.

Legacy Answer:

As of Sprout Forms v1.1.0 and the current public plugins available (none that I know of for this use case), you can do this with a Dropdown Field.

Let's say you have a dropdown field with the handle departmentEmailDropdown. In the settings, you can create a list of People/Departments and the emails you'd like them to be sent to:

Label    Value
Support  support@mysite.com
Other    other@mysite.com

When a user submits your form, all the values in the form are available for you to reference in your notification settings using shorthand syntax.

In the Email Recipients field of your Notifications tab, you can reference your dropdown field using the syntax {departmentEmailDropdown}.

The downsides to this approach are that the email addresses in your dropdown will be visible to in your page template, so robots can swoop in and gobble them up.

We've got this on our radar and in the next couple weeks should have an update for you that will allow you to handle this as well as obfuscate the email addresses on the front-end. I'll update this answer when we have that ready.


Display entries by Category (Category in Super Table) I'm been kicking myself for hours and going round in circles trying to get list of entries displayed by category when the category is selected from within a SuperTable (static table) row. I would really appreciate if someone could please help point me in the right direction.

I have a structure entries section named "services" with a number of entries created.
I have a category group named "serviceCategories"
I have a "SuperTable" static table field handle named "service"
In my SuperTable I have a row named "serviceCategory" which allows me to select a single category from the category group named "serviceCategories".

I'd like to create a standalone web page that displays all the category titles with the list of related entries.

I've tried:

{% set categories = craft.categories.group('serviceCategories') %}
{% for category in categories %}

  {{ category.title }}

  {% set services = craft.entries.section('services').relatedTo(
    { targetElement: row.serviceCategory }
  ) %}

  {% for service in services %}
    {{ service.title }}
  {% endfor %}

{% endfor %}

Not sure if you're still looking for an answer, but relation support has just been added to Super Table 0.3.7. Previously, relations wouldn't work with Super Table, as its a little bit of a special field, having sub-queries to perform for relations (each row).

You can now query fields just like Matrix:

{% set reverseRelatedElements = craft.supertable.getRelatedElements({
 relatedTo : {
   targetElement: entry,
   field: 'superTableFieldHandle.columnHandle'
 },
 elementType : 'Entry',
 criteria: {
   section: 'someSection'
 }
}) %}


Craft3 - Getting rid of /web in my URL I am very new to craft. installed craft3 very long ago, as a beginner, and trying to solve a long-lasted-issue with my url.
my goal:

Change my base url from www.mywebsite.com/web to www.mywebsite.com

At the moment www.mywebsite.com shows 403 forbidden error.

My directory structure looks as below. As you can see, I installed craft only under public_html/mywebsite.com. I cannot move the files in /mywebsite.com into /public_html folder.
I researched and tried to follow this article however quiet unsure with the different folder structure I have.
Just in case I moved index.html file to the /mywebsite.com root, and at least forbidden error was gone while only blanc page was loaded.
I had the feeling that I could do something with index.php file to redefine('CRAFT_BASE_PATH', dirname(__DIR__));. However also not sure what to write..
Thanks a lot for your help in advance!

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


Can't install Craft 3 when deploying to AWS EC2 instance - Template not found: install Template not found: install I'm deploying my Craft 3 application to an ec2 instance using elastic beanstalk. When I navigate to "/admin/install", I get the following error:

When I ssh into my ec2 instance to check the 404 logs, the stack trace I get is:

  2018-03-02 11:47:03
  [192.195.80.235][-][-][error][yii\web\HttpException:404]
  yii\web\NotFoundHttpException: Template not found: robots.txt in
  /var/app/current/vendor/craftcms/cms/src/controllers/TemplatesController.php:69
  Stack trace: 0 [internal function]:
  craft\controllers\TemplatesController->actionRender('robots.txt',
  Array)

  1 /var/app/current/vendor/yiisoft/yii2/base/InlineAction.php(57):
  call_user_func_array(Array, Array)

  2 /var/app/current/vendor/yiisoft/yii2/base/Controller.php(157):
  yii\base\InlineAction->runWithParams(Array)

  3 /var/app/current/vendor/craftcms/cms/src/web/Controller.php(74):
  yii\base\Controller->runAction('render', Array) 4
  /var/app/current/vendor/yiisoft/yii2/base/Module.php(528):
  craft\web\Controller->runAction('render', Array)

  5 /var/app/current/vendor/craftcms/cms/src/web/Application.php(237):
  yii\base\Module->runAction('templates/rende...', Array)

  6 /var/app/current/vendor/yiisoft/yii2/web/Application.php(103):
  craft\web\Application->runAction('templates/rende...', Array)

  7 /var/app/current/vendor/craftcms/cms/src/web/Application.php(226):
  yii\web\Application->handleRequest(Object(craft\web\Request))

  8 /var/app/current/vendor/yiisoft/yii2/base/Application.php(386):
  craft\web\Application->handleRequest(Object(craft\web\Request))

  9 /var/app/current/web/index.php(21): yii\base\Application->run()

  10 {main}

  2018-03-02 11:47:03 [192.195.80.235][-][-][info][application] $_GET =
  [
      'p' => 'robots.txt' ]

Why is this happening and how can I fix it?

I suggest you to read the documentation about how to install Craft there is no such install process anymore. You just need to follow these steps, install it via composer, run the setup ./craft setup and you are done. So there is no admin/install anymore like in Craft 2


Unable to set cart currency in index.php Craft: 2.6.2976
Commerce: 1.2.1341

I want to force currency depending on language (en_us and no). The user should not be allowed to choose.

I've added two currencies 1) EUR - base, 2) NOK.

Putting define('COMMERCE_PAYMENT_CURRENCY', 'EUR'); in the index.php for the english site, and define('COMMERCE_PAYMENT_CURRENCY', 'NOK');in the index.php file for the norwegian site does not work.

The currency is always EUR.

To be clear: Using {{constant('COMMERCE_PAYMENT_CURRENCY')}} does output the correct currency as set in index.php, however the cart is what always remains in EUR (base).

Is this a bug in Commerce?

How do you render the cart?

Using {{ item.price|commerceCurrency(cart.paymentCurrency,convert=true) }} instead of {{ item.price|commerceCurrency(cart.currency) }} works for me.


How do I pass a hidden input value to plugin onSaveUser event handler? I'm writing a customer portal plugin, utilizing Crafts user registration form: https://craftcms.com/docs/templating/user-registration-form

{# User registration form: #}
<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="">

    {# What do I add / change ? #}

    {# ... #}
</form>

My plugin has two different types of account profile records, .._OrganizationProfileRecord and .._UserProfileRecord. What I want to do is send a variable to the onSaveUser event handler in my plugin main class, to tell it what type of user was just saved ("org" or "user"), and then take appropriate actions, i.e. create either an organization or user profile.

class myPortalPlugin extends BasePlugin
{
    public function init()
    {
        craft()->on('users.onSaveUser', function(Event $event)
        {
            $craftUser = $event->params['user'];
            $isNewUser = $event->params['isNewUser'];

            if ($isNewUser)
            {
                // Check if user is an organization or a regular user, and
                // create the appropriate profile record.

                // How do I check?

                // ...
        }
    }

    // ...
}

Questions:

How would I go about passing data/variable from the form to the onSaveUser event handler?
Is there a better / more convenient way to do this?

Many thanks in advance for any help you can provide in this matter!  bowing

/Monkey

I found a solution. Though I am not sure if this is the best way to go about it, but here's what I did:

<input type="hidden" name="userType" value="org">

was added to the register form, and ...

$userType = craft()->request->getPost('userType');

if ($userType == 'org')
{
    // ...

was added to the onSaveUser event handler function.


Most efficient way to check if a section has any active entries Just wondering what the most efficient way to check whether a section has any entries or not. Based on this, I'm showing some content. The content doesn't take any information from the entries in the section, so it'll be a superfluous query no matter what.

For context, this is basically what it'll look like:

{% if craft.entries.section('whatever') | length > 0 %}
    Go here
{% endif %}

You can use {{ craft.entries.section('whatever').total() }} for that.


Duplicate Entry Types into a new section Is there a way to duplicate Entry Types into a new section?  I have a section with many entry types with their fields and handles all named nicely...  I need to create a Section using exactly the same Entry Type setup?

Many thanks

Martin

You need to use a plugin to do this. I've used the architect for doing exactly this in the past. Just export the section and entry types you want to duplicate, rename the section in the json file, delete everything except for the section and entry type definitions, and import.


Trouble posting to plugin controller I'm working on a plugin to do subscription billing with paypal. I have the following controller

class PaypalSubscription_SubscriptionController extends BaseController {

    public function actionSubscriptions() {
        // This renders a form that collects some info on subscription options
    }

    public function actionSubscribe() {
        $this->requirePostRequest();
        // This takes data and starts a paypal transaction
    }
}

I can get to the form by going to /actions/paypalSubscription/subscription/subscriptions

I've tried hard coding the url /actions/paypalSubscription/subscription/subscribe as well as using actionUrl('/paypalSubscription/subscription/subscribe'). The actionUrl call prepends index.php/actions to the string which is just incorrect, and either way both approaches 404. What am I missing here?

I know that i'm logged in and that works correctly since I can reach the original form and anonymous access shouldn't be turned on, so I don't believe that's the issue.

Does the request requires login?
If it doesn't, you need to add the exception on the controller
protected $allowAnonymous = array('actionSubscribe');

Also, did you try adding admin to your URL?
<input type="hidden" name="action" value="/admin/actions/paypalSubscription/subscription/subscribe">

I was trying to post to an action once through the front-end and it only worked after adding /admin


On a Archive: how could I break cache for the current year, but not the others? I have an archive of an event based site.
I know how to break cache until the next event. No Problem

{% cache until nextEvent %}

But the archive works the following way:

archive
-- 2014 (latest year)
-- 2013
-- 2012
-- 2011

The until nextEvent part makes only sense for the latest year. The other years should be cached forever.

How could I achieve such a thing?

-- edit --

Maybe I have to go a little more into the details:
I get the year in the forth segment.
Now it should cache the whole loop and never break it, unless it's the actual year, then break it each night:

{% set latestYear = now|date("Y") %}

{% if year is not defined %}
    {% redirect "club/programm/archiv/"~latestYear %}
{% endif %}

{% set year = craft.request.getSegment(4) %}

{# Set the first day of the year and the last #}
{% set lastyear = year -1 %}
{% set nextyear = year +1 %}
{% set yearbegins = '1 January ' ~ year %}
{% set yearends = '1 January ' ~ nextyear %}
{% set unixbegins = yearbegins | date('U') %}
{% set unixends = yearends | date('U') %}

{# Today at 00:00 #}
{% set today = now|date("Y-m-d") ~ ' 00:00' %}
{% set tomorrow = now|date_modify("+1 day")|date("Y-m-d") ~ ' 00:00' %}

{% set entriesByYear = craft.entries.section('programm').limit(null).cf_date('and', '>= ' ~ unixbegins, '< ' ~ unixends, '< ' ~ today| date("U")) %} {# '> just to make syntax highlighting correct #}

{% cache until tomorrow %}
    {% for month, entries in entriesByYear | group("postDate|date('F')") %}

        {# MONTHLY HEADER #}

{{ month }} {{ year }}

        {# ENTRIES PER MONTH #}
        {% for entry in entries %}

                {% include "programm/_common" %}

        {% endfor %}
    {% endfor %}
{% endcache %}

maybe that helps someone to help me ;)
cheers
stefan

--- edit 2 and solution ---

so after the comments of victor I updated the code. and it works like a charm:

{% set latestYear = now|date("Y") %}

{% if year is not defined %}
    {% redirect "club/programm/archiv/"~latestYear %}
{% endif %}

{% set year = craft.request.getSegment(4) %}

{# Set the first day of the year and the last #}
{% set lastyear = year -1 %}
{% set nextyear = year +1 %}
{% set yearbegins = '1 January ' ~ year %}
{% set yearends = '1 January ' ~ nextyear %}
{% set unixbegins = yearbegins | date('U') %}
{% set unixends = yearends | date('U') %}

{# Today at 00:00 #}
{% set today = now|date("Y-m-d") ~ ' 00:00' %}
{% set tomorrow = now|date_modify("+1 day")|date("Y-m-d") ~ ' 00:00' %}

{# Get the Date of the next Event, to allow caching until then #}
{% set nextEvent = craft.entries.section('programm').cf_date('>= ' ~ today| date("U")).order('cf_date asc').first() %}{# '> just to make syntax highlighting correct #}
{% set nextEventDate = nextEvent.cf_date|date_modify("+1 day")|date("Y-m-d") ~ ' 00:00' %}

{# Get all the events within the year concerned #}
{% set entriesByYear = craft.entries.section('programm').limit(null).cf_date('and', '>= ' ~ unixbegins, '< ' ~ unixends, '< ' ~ today| date("U")) %} {# '> just to make syntax highlighting correct #}

{# If the year is the current year, cache it until the next event. Otherwhise, cache indefinitely #}
{% if year == latestYear %}
    {% cache until nextEventDate %}
        {% include "club/programm/_archive_common" %}
    {% endcache %}
{% else %}
    {% cache %}
        {% include "club/programm/_archive_common" %}
    {% endcache %}
{% endif %}

thanks for all the fish!
stefan

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

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


Deleting one or all Assets from a fieldusing a front end form Good afternoon All,
Im trying to setup the ability for users to delete 1 or more of their own images from a multi photo asset field and have got stuck.
This is what is have so far,  I assumed adding a blank value would remove the asset in question
{% set images = myAssetQuery.all() %}

{% for image in images %}

    <input type="checkbox" name="fields[businessStandardImages][]" value="" />

{% endfor %}

Any help would be greatfully received

Assuming you are on a front end entry form editing an entry, there are a few steps to this.
First get all assets a user can choose from:
{% set allImages = myAssetQuery.all() %}

Next, get the ids of already chosen assets:
{% set alreadyChosenImages = entry.businessStandardImages.ids() %}

Loop over all images, check the ones already selected:
{% for image in allImages %}

    {{ image.title }}
        {{ input(
            'checkbox',
            'fields[businessStandardImages][]',
            image.id,
            { checked: image.id in alreadyChosenImages }
        ) }}

{% endfor %}

Altogether:
{# Get all possible assets #}
{% set allImages = myAssetQuery.all() %}

{# Get the currently related asset IDs #}
{% set alreadyChosenImages = entry is defined
    ? entry.businessStandardImages.ids()
    : [] %}

{# Loop over images and check any already selected ones #}
{% for image in allImages %}

    {{ image.title }}
        {{ input(
            'checkbox',
            'fields[businessStandardImages][]',
            image.id,
            { checked: image.id in alreadyChosenImages }
        ) }}

{% endfor %}

There is also a complete example in the documentation.


Get additional category field when outputing entries grouped by categories I followed this sample code from craft cookbook to display my entries grouped together by category within a category group.

To add some context, the site I'm working on is for a dictionary and the words in the dictionary are the main entries. There are several category groups that I use to classify the words. For example, words can belong to different themes: household items are in the household category, names of animals are in the nature category and so on. So far, here is the code I have below:

{% set entriesByCat = {} %}
{% set entries = craft.entries.section('words') %}
{% set cats = craft.categories.group(themes) %}

{% for cat in cats %}
  {% set entries = entries.relatedTo(cat) %}
  {% if entries|length %}
    {% set entriesByCat = entriesByCat|merge({ (cat.title): entries}) %}
  {% endif %}
{% endfor %}

{% if cats|length %}
    {% for catTitle, catEntries in entriesByCat %}

{{ catTitle }}

        {% for entry in catEntries %}
          {# Entry content goes here... #}
          ...
        {% endfor %}
    {% endfor %}
{% endif %}

This works fine to output one field for the category (the category title). However, some of these categories have pictures associated with them, and I would like to be able to access those as well.

After the h2 tag I would like add a conditional to check if a category has an associated image in the "categoryImage" field for the category. If it does have an image I'd like to output the image.

I've been able to do this in other situations where I have more direct access to the category but I can't figure out how to access to the category image field within the loop structure that I have setup.

Any help would be greatly appreciated. I have to admit that I'm a bit beyond my depth with the twig template code above. :-)

Just focusing on the assets part I would try to eager-load the image and insert it into your template that way.

{% set entriesByCat = {} %}
{% set entries = craft.entries.section('words').find() %}
{% set cats = craft.categories.group(themes).find({
    with: ['categoryImage']
}) %}

{% for cat in cats %}
  {% set entries = entries.relatedTo(cat) %}
  {% set catImage = cat.categoryImage[0] ?? null %}
  {% if entries|length %}
    {% set entriesByCat = entriesByCat|merge({ (cat.title): { entries: entries, image: catImage}) %}
  {% endif %}
{% endfor %}

{% if cats|length %}
    {% for catTitle, catInfo in entriesByCat %}

{{ catTitle }}

        {% for entry in catInfo.entries %}
          {# Entry content goes here... #}
          ...
        {% endfor %}
    {% endfor %}
{% endif %}

You may want to change the naming convention a little bit, but I just wanted to try and stick to yours as is.


Is it possible to localize Freeform fields and labels? Is it possible to localize labels and other params of Freeform form fields on the multilingual site? Thanks

You can render the fields by your own and use the twig translate filter and do it with translation files. But I think there is no way to do it via the CP currently.


Check if a table field’s column has a value I am using a table field to display credits on a portfolio page.
The table field has three columns: hva, hvem and url.

The url should be optional and I want to set up an if statement showing it as a link if it has a value. Is this possible using the table field?

Also, the table field can have multiple rows.

I have tried to set up an if for row.url to see if has a value. And an else for when there is no URL.

{% if entry.credits|length %}
    {% for row in entry.credits %}
        {% if row.url == 0 %}

{{ row.hva }}: {{ row.hvem }}

        {% else %}

{{ row.hva }}: {{ row.hvem }}

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

You were close...

Chaning this:

{% if row.url == 0 %}

to this:

{% if row.url|length %}

should do it for you.


Get data from another loop from outside the current loop Sorry the question title is so random - feel free to correct it to something more succinct if you can think of one.

Related question: How to query for multiple relations with SuperTable

I have a front end Entry form which I'm using to create/edit an Entry which contains one field, a table called guestNames. The number of rows allowed in that table is set in another section's Entry (event). The SuperTable field in the event that defines how many rows are allowed is called guestAllocation. There two rows in that SuperTable, partner (Entries) and places (Number).

In my front end Entry form I want to create the correct number of input fields that are allowed. I have no problem doing that with this code:

{% for row in 1..entry.guestAllocation.relatedTo(partner).first.places %}

    Name {{ loop.index }}
    <input id="fields[guestNames][{{ loop.index0 }}][col1]" type="text" name="fields[guestNames][{{ loop.index0 }}][col1]" class="form-control">
    {% if entry is defined %}{{ errorList(entry.getErrors('fields[guestNames]')) }}{% endif %}

{% endfor %}

For the purposes of this example, that could be a static number like 5. However, I also need to provide editing functionality rather than just creating a new entry each time, so with the following line:

{% if partnerGuestList|length %}<input type="hidden" name="entryId" value="{{ entry.id }}">{% endif %} {# If there's a guest list for this partner, update it #}

I can check if the entry exists already. Now I need to provide the correct number of input fields from entry.guestAllocation.relatedTo(partner).first.places, but in those input boxes, I need to provide the data from the rows in the table partnerGuestList guestNames

To get the names I need, I can query:

{% for row in partnerGuestList.guestNames %}
    {{ row.guestName }}
{% endfor %}

Please comment if I can clarify any more!

Short version: How can I show data from an entry in a loop that isn't related to that entry?

Interesting. I'm not able to test this right now, but I think this should work...

You could first loop through the results, adding them to an array as you go...

{% set guestNameValues = [] %}

{% for row in partnerGuestList.guestNames %}
    {% set guestNameValues = guestNameValues|merge([row.guestName]) %}
{% endfor %}

And then within your loop that displays the fields set the value as...

{{ guestNameValues[loop.index0] }}

That should get the corresponding name from the array you previously set.


How do I allow a user to remove an uploaded asset from a front-end entry form? I see for users, I can add a hidden field <input type="hidden" name="deleteUserPhoto" value="1" /> to remove the uploaded photo, however I need to allow this functionality for an assets field in an entry form.

I have tried submitting an empty file field, but it just retains the existing uploaded asset after submission.

Is there a trigger similar to deleteUserPhoto that I can use here?

File fields are used for uploading new images. To delete all the Assets for a field, submit a hidden field with no values.

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

If, on the other hand, you want to retain some of them, then make that hidden field an array with the values you'd like to keep. Like this

<input type="hidden" name="fields[assetsField][]" value="someAssetId" />
<input type="hidden" name="fields[assetsField][]" value="someOtherAssetId" />

someAssetId and someOtherAssetId being the Asset IDs you'd like to keep for that field.


Daily quota for post submissions How would you go about creating a daily quota for posts? I have a simple photo gallery where users can submit images, problem is some people are a bit too excited. I'd like to limit submission to let's say 10 per day per user. Any tips how to approach this welcomed.

You would have to hide the button or page where users could upload a photo.

To do this you could query for all that users entries with today's postDate. If the total is equal to or more than 10 then you'd redirect them to a different page or hide/disable the button that submits an entry.

Something along the lines of the following

add-image.twig

{% set todaysEntryCount = craft.entries.section( 'images' ) authorId( currentUser.id ).postDate( '> ' ~ now|date_modify('-1 day') ).total() %}
{% if daysEntryCount >= 10 %}
  {% redirect /your-images?message=dailylimit %}
{% endif %}

or

{% if daysEntryCount < 10 %}
   <button type="submit">Add your image</button>
{% endif %}


Want to add a custom field in craft commerce plugin Is it possible to add a custom field in craft commerce plugin and is it a good idea to add it?

Yes, you can create new field and you can add it in it.
To add it, please go to admin panel and then follow the below mentioned sections.
settings > product type > add/select product > product fields

Then you can add custom field on field layout.
I hope this will help.


Solspace FreeForm notifications I'm a bit confused by the notifications set-up in Freeform. The instructions state 'The notification template used to send an email to the email value entered into this field (optional).' I selected the template and entered an email address in the field below, but an email notification is sent to the user of the form as well as the administrator following a submission. So how do I set up a notification to send to admin only? And if I wanted to create a separate notification for the user, how do I do that?

It's not obvious, but you need to select the email field in the form settings, then select a notification from the pane on the right to send to the value in the field.


Using relatedTo with 'Users' field I have a sports site I'm building where each team is set up as a user within a 'team' member group.  I have a channel called 'Schedule' that has only 2 fields; a user field to relate the schedule to a team and then a table for the list of games.

On the front-end if I have a profile page for each team (ie: http://www.example.com/{username}).  I'm having trouble outputting the correct schedule based on the username in the URL?

Without knowing how your templates look, I can only give you a basic example:

{% set team    = craft.users.username(craft.request.lastSegment) %}
{% set entries = craft.entries.section('schedules').relatedTo(team) %}

This should give you all entries in the schedules channel which have a relation to the team username.


Manual user activation for non-admins I am using CraftCMS 2.

Beside the admins, I have 2 user groups: Employees and Editors. As admin I can activate pending Editor accounts by clicking on 'Activate account' in the corresponding user account. However, this button is not available for non-admins (Employees), even if the non-admin has all permissions of the user module. I understand that there is no way to make this button available for non-admins in control panel.

Question: Is there a way to make this action ('Activate account') available for Employees through a frontend form? Ultimately I want Employees to be able to activate pending Editors manually.

Basically I want to do the same as Jeremy A but with non-admins.

Generally best practice is to look into the source code and see what happens in the function

/**
 * Manually activates a user account.  Only admins have access.
 *
 * @return null
 */
public function actionActivateUser()
{
    $this->requireAdmin();
    $this->requirePostRequest();

    $userId = craft()->request->getRequiredPost('userId');
    $user = craft()->users->getUserById($userId);

    if (!$user)
    {
        $this->_noUserExists($userId);
    }

    if (craft()->users->activateUser($user))
    {
        craft()->userSession->setNotice(Craft::t('Successfully activated the user.'));
    }
    else
    {
        craft()->userSession->setError(Craft::t('There was a problem activating the user.'));
    }

    $this->redirectToPostedUrl();
}

The important part is $this->requireAdmin();. Copy the function into a custom controller and remove that line and you are generally done. You can even hook into the CP template and include this the button on your own.

My Solution

I wrote a plugin that uses above method. It is accessed via a controller. I just changed the line that requires the user to be an admin. Then I just put a button somewhere in the CP that uses this controller action.

- $this->requireAdmin();

+ if (!craft()->userSession->getUser()->can('accessPlugin-MyNewPlugin')) {
+    throw new HttpException(403, Craft::t("You don’t have the required permissions for this operation."));
+ }


Why does index.php persists in my URL? I've gone through all the steps here to remove index.php https://craftcms.com/support/remove-index.php
The .htacess file is the default one that came with Craft on install
<IfModule mod_rewrite.c>
    RewriteEngine On

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

In my config/general.php file I have the setting set explicity..
'omitScriptNameInUrls' => 'true',

I wrote to Arcustech for help with the httpd.conf file as the last step and they said...

Changing that setting is not something we will update on Arcustech. If you were not already aware, we are a Craft CMS Hosting Partner and removing index.php in Craft URLs works on our servers without that update.
If you tell Craft Support you are hosted with Arcustech the Craft support team will know stuff will work here, so something else is wrong in the setup or .htaccess file. The account is not set up as a Craft Optimized plan (https://www.arcustech.com/managed/craftcms-hosting/) but that does not matter for basic functionality like that in Craft.

I asked to be moved to the Craft Optimized plan, but it doesn't sound like that's an issue.
Any idea what's going on? Somedays it's fine. Today, at the moment, it's not.

It was the single quotes around 'true' in the config file :)


Imager scrset matrix field, art directed content What I'm trying to achieve: I would like the content editor to upload 2 images to use in a matrix block, one outputs at mobile and the other at desktop (they need to be different images due to art direction from landscape formate to portrait on mobile).

Here is the matrix field setup:

Current twig:

{% for block in entry.workVisuals.all() %}
    {% if block.type == "imageContent" %}

        {% set relatedAssets = block.workImageMobile.all() %}
          {% for pic in relatedAssets %}

            {% set img = craft.imager.transformImage(pic, {
              mode: 'crop',
              width: 1920,
            }) %}

            {% set imgMob = craft.imager.transformImage(entry.workImageMobile, {
                mode: 'crop',
                width: 768,
                height: 1272,
            }) %}

            <picture>
              <source media="(max-width: 767px)" srcset="{{ imgMob }}">
              <source media="(min-width: 768px)" srcset="{{ img }}">
              <img src="{{ img.url }}" alt="{{ pic.title }}">
            </picture>
          {% endfor %}

      {% endif %}

So obviously this is outputting the mobile image for both as asked:

{% set relatedAssets = block.workImageMobile.all() %}

What do i need to do to use both in the <picture> tag?

It looks like you're looping through block.workImageMobile.all(), and that's not what you want to be doing.

You're only putting in one image into each, right, and they're paired?

So, You want the main for-loop for the blocks, then render the images in each block together "work image 1, work mobile image 1" then move to the next block, and the next image pair.

{% for block in entry.workVisuals.all() %}
    {% if block.type == "imageContent" %}

        {% set picDesktop = block.workImage.one() %}
        {% set picMobile = block.workImageMobile.one() %}

        {% set imgDesk = craft.imager.transformImage(picDesktop, {
            mode: 'crop',
            width: 1920,
        }) %}

        {% set imgMob = craft.imager.transformImage(picMobile, {
            mode: 'crop',
            width: 768,
            height: 1272,
        }) %}

        <picture>
            <source media="(max-width: 767px)" srcset="{{ imgMob }}">
            <source media="(min-width: 768px)" srcset="{{ imgDesk }}">
            <img src="{{ picDesktop.url }}" alt="{{ pic.title }}">
        </picture>
    {% endif %}
{% endfor %}

Also note - on the desktop size, you've got it set to crop, but only have a width set, you might want to add a height to that too. Otherwise, it might be better with a resize function.


Create several subcategories without using the GUI in craft I have to create the following categories hierachically : One book has between 1 and 150 chapters.
I have to do this for several books.  Dealing with chapters is painful using the GUI. Is there any way to achieve this directly using json, queries ?

Category "Book 1" is consisted of 100 chapters subcategory

Book 1 -> Chap 1
Book 1 -> Chap 2
...
Book 1 -> Chap 100

Category "Book 1" is consisted of 10 chapters subcategory

Book 2 -> Chap 1
Book 2 -> Chap 2
...
Book 1 -> Chap 10

If you have the JSON of the chapters or want to create it, you could import them using FeedMe Pro (required to import the Category element type). It'll import the categories and create child categories if they're not already created.


Checking if a matrix field with entries has more than one entry In my HTML-prototype I have two ways of showing a module of employees. One version shows one employee, and the other shows two.

To build this in Craft I have setup a Matrix field (with a handle named 'contactMatrix'). It contains a headline, some text and an entry field to pick employees (with a limit of two).

To output this in my front end I need a way to check if the user has picked one or two employees. Something like:

if one employee within the matrix field is chosen
do this html
else
if two employees within the matrix field is chosen
do this slightly different html
end if

Help, anyone?

I believe the code below should work. This code assumes you are on a single entry page or within a loop and your entry is available to you with the entry variable. You may need to adjust the block.type name and block.employees entries field name to match your proper handles. I've added comments inline to clarify each step:

{# Loop through your Matrix Field #}
{% for block in entry.contactMatrix %}

    {# Check to see which type of block you have.  You only want to check for the employees entry field if you are within the contact block #}
    {% if block.type == 'contact' %}

        {# See if your employees entries field has more than 1 entry #}
        {% if block.employees|length > 1 %}

          {# Output HTML for blocks with multiple employees #}

        {% else %}

          {# Output HTML for blocks with zero or one employee #}

        {% endif %}

    {% endif %}

{% endfor %}


How to transfer Craft configuration changes separate from web conent I am busy reworking a reasonably large website that is already in Craft. The production site is updated with new content several times a day. My current work is an interface redesign. I have a local machine environment, and then a dev environment on the same server set up at the ISP alongside the live production one. The dev will function more as a test server - I can refresh from the production server a few times to test my update process.

My rework on the local dev environments starts with an exact site copy, and will involve mostly template changes. However I suspect I might need to do some database tweaks. In the meantime the live site will undergo a number of content changes.

I am wondering how best to deploy those database tweaks to the live dev and then production servers. My current strategy is to write down what changes I made in local dev and then manually make them on the main dev or live server. These seems a bit dumb unless it is just one or two. I can't copy the whole database because then I would overwrite content changes and I can't put a hold on content changes because my work is likely to take a week or three.

What you need to do is develop some kind of workflow; the workflow that I use is described in the Database & Asset Syncing Between Environments in Craft CMS

But there are other equally valid ways to do it as well. It's really a combination of some tooling, and then just a workflow methodology that you're going to use to keep things in sync.

Writing things down and trying to then re-apply the changes is problematic, because it human error often rears its ugly head when you try to do things that way.


How to skip the first few entries in a "load more" scenario with Element API? I have a website that uses a "load more" button. The process for this button can be found here:
http://craftsnippets.com/articles/infinite-scrolling-and-lazy-loading-with-craft-cms
I made it pretty much verbatim (structure-wise with Element API) to that article, but I want to skip the first 6 entries because they are featured elsewhere on the site. So I tried to add .offset('6') to the for loop, and that did skip the first 6 entries. But when the "load more" button is clicked it would display the second 6 entries again (duplicates) then when you click the button again it properly continues down the list of entries.
So, how can I skip the first 6 entries in this scenario without having duplicates?

If you always want to skip the first 6 entries, you can modify the Element API endpoint to add 6 to the offset number in the query criteria:
$criteria = [
    'section' => $settings['section'],
    'limit' =>  $settings['limit'],
    'offset' =>  ($settings['limit'] * Craft::$app->request->getParam('offset')) + 6,
    'order' => $settings['orderBy'],
];

That should mean you're always receiving results that are offset by the required amount for your request, plus the first 6 entries that you always want to skip.


Failed to load Twig template "_includes/field", index "764771142": cache is corrupted Making first steps with Craft CMS, and it's great, but there is one thing i can't figure out:
When trying to add a new entry with a rather complex set of fields (including matrix) there is an error:

Failed to load Twig template "_includes/field", index "764771142": cache is corrupted.
in E:\craft\playground\vendor\craftcms\cms\src\templates_includes\field.html
line 17:

{% if instructions or input %}
    {% embed "_includes/forms/field" with {
        label: field.name|t('site')|e,
        translatable: translatable,
        siteId: siteId,
        required: (not static ? required : false),

Editing existing entries works fine.
Running 3.0.4
Clear Cache Tool has run, and i also delete the cache files in /storage. No custom field types.
Thanks for ideas.

Additional info: This error occurs only when devMode=true

Restricting image upload to a single folder {owner.filmtitle|kebab} possibly caused the error, replacing the folder template helped:

{% if owner.filmtitle %}{owner.filmtitle|kebab}{%else%}default{%endif%}

Nevertheless i don't understand why the former version caused the error, and the error message is very misleading.


Best Practice for Templating-Workflow, coming from static HTML I hope this question does not sound to banal:
I am currently switching to Craft CMS and I am used to build my HTML/CSS/JS templates as static pages with dummy content.

This (seemingly?) has 3 advantages for me:

I have an early, clickable prototype, presentable to the client
before I have to touch any CMS
I am not forced to insert real content via the CMS yet
It gives me a very clean Git Repository for the frontend without any
CMS dependencies yet

The disadvantage is of course that I have to manually split my static pages up later to work with Craft CMS (or any other CMS) templating logic.

Thus I was wondering how you approach templating, especially with Craft: Whether you start directly building your frontend from scratch in Craft’s Templates folder or if you start independently, and do the splitting of files every time as a necessary step …

Any suggestions?

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/


conditional does not run first in a file that is included using the extends feature for twig I have this conditional included in a layout file I use within others, using the extends feature in twig.

This is at the very top of _layouts/application.twig

{% if not currentUser %}
    {% redirect "login" %}
{% endif %}

I have this at the very top of account/index.twig

{% extends "_layouts/application" %}
{% set name = currentUser.getFullName() %}

If the user is not logged in, I expect it to redirect the user to the login page, as it contains the if not currentUser conditional at the very beginning of the extends file: _layouts/application.twig

I then copied and pasted the if not currentUser code and placed it above the extends call within the account/index.twig file (like seen below):

{% if not currentUser %}
    {% redirect "login" %}
{% endif %}

{% extends "_layouts/application" %}

and it works as I expect it to.

Why does it not work with the if conditional being included in _layouts/application.twig file that I include by using {% extends "_layouts/application" %}

The issue here is that extends isn't the same thing, neither conceptually or technically, as an include. When you extend a template with a layout template, the template is "decorated" by the layout. So, what's happening is that the code in the layout is parsed after all of the code in the template.

Check out this article on straightupcraft explains the order of which things happen in Twig. In short:

1) All code in your template, except code inside blocks, gets processed.

2) All code in your layout, except code inside blocks, gets processed.

3) Code inside blocks gets processed.

So, what the solution to your problem is, depends on your setup. But, if your code that accesses currentUser is inside the block in your page template, the redirect should fire first. If you need to access currentUser outside of the blocks in your page template, you have to do the redirect there.


`saveRelations` returning `null` I'm using the saveRelations method in the RelationsService to save entry relationships in a plugin I'm working on. Everything is working as expected, however, saveRelations is returning null on success, which seems odd.

Here is a portion of the code I'm working with:

public function addCategoryRelation(CategoryModel $category, EntryModel $entry)
{
    $field        = $craft()->fields->getFieldByHandle('handle');
    $handle       = $field->handle;
    $relations    = $category->$handle;
    $relationsIds = [];

    /**
     * Get the ids for the relations.
     */
    foreach ($relations as $entry) {
        $relationsIds[] = $entry->id;
    }

    if (!in_array($entry->id, array_values($relationsIds))) {
        $relationsIds[] = $entry->id;
        return craft()->relations->saveRelations($field, $category, $relationsIds);
    } else {
        return [
            'error' => 'Entry already saved.',
        ];
    }
}

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

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

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


Structure(s) vs. Categories for product catalog So I am working on a project that includes an online product catalog. Is there a recommended way of setting up a catalog regarding the use of structure(s) vs. categories or a combination both?

I will have

brands with a couple of product families and a few products in every
family
accessories by the same brand for the whole family
accessories by the same brand for various product families
accessories by the same brand for only certain products
accessories by other brands for a whole product family
accessories by other brands for a certain product only

Wondering if one structure or two (for brands and products) and relations would work and be efficient and flexible, or if I should work with categories as well? In total, it will be about 100 to 150 items in the catalog.

Thanks for opinions!

I find it difficult sometimes to choose between a category group and a structure, so for me it mostly boils down to semantics.

A brand can be both a structure entry and a category. If you're going to have pages with information about the brand/product faily/product, and they will be available in some kind of menu to be browsed by itself, I think I'd go with a structure. If, on the other hand, they are only going to be used for filtering and organizing, a category group feels more appropriate to me.

From what you've described, I think I'd go with:

Products (structure)
Accessories (structure)
Brands (category)
Product family (category)

But as I said, it depends a lot on the specifics of your content.


Filter by slug from URL (advanced) Channel: Restaurants

Channel: Nutrition / contains entries field named restaurant.

Required URL format:
    restaurant-name-nutrition

since the URL structure is merged I can't use getSegement(x) while getting entries.

in other scenario where the URL would be

nutrition/restaurant-name

I could use something like this

{% set seg2 = craft.request.getSegment(2)
{% for entry in craft.entries.section('nutrition').slug(seg2) %}

but what is the right approach for that one?

Why don't you use your current entry as reference?

{% set nutritions = craft.entries.section('nutrition').relatedTo({
    field: 'restaurant',
    targetElement: entry
}).all() %}

Since your current entry is related to the entry you want to fetch this would be the besser solution. However that URL structure is not really optimal to beginn with. There are many cases it will break as soon as someone edits your entries, but filtering by slug alone is never a good idea in such a way.


Incorporating data from an external database into Craft pages I'm looking at how best to incorporate various sets of data from another MySQL database into a Craft site. Using the Feed Me plugin would be one way, if the data source had feeds, but I'm thinking about alternatives. Does this make sense:

There is an Entry whose page should display data from the external DB.
The admin user can, using standard Fields, select the criteria for which data it is (eg, category, number of items, timespan, etc).
In the Entry's template, a template hook calls a Craft plugin.
The plugin makes a request to the external DB, tidies the returned data, and renders it into the page with a twig template.

Does that make sense? Anything that sounds impossible or stupid? Can you think of a better solution?

It looks like I could cache that part of the template so that it didn't make requests to the external DB with every page request. Is that right?

(For context: I haven't used hooks yet, and have only written the most basic of Craft plugins. I have years of general PHP experience, but little with Craft or Yii.)

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.


Craft asset urls not working I have checked all other questions on stack exchange with similar titles and they don't seem to help my situation.
I have added assets sources to craft CMS. but when uploading I get the following error:

  The error message was: "Error uploading the file:  The file system path "{siteUrl}assets/images/hero-images/" set for this source does not exist."

I am working locally using MAMP. I do not have multiple environments. only local.

the siteUrl variable seems to work fine when used directly in templates. just doesn't work for assets.

File system path is

assets/images/hero-images/

URL is

{siteUrl}assets/images/hero-images/

General config is set to

return array(

    // Base site URL
    'siteUrl' => "//projectname:8888/html/",

    // Environment-specific variables (see https://craftcms.com/docs/multi-environment-configs#environment-specific-variables)
    'environmentVariables' => array(),

    // Default Week Start Day (0 = Sunday, 1 = Monday...)
    'defaultWeekStartDay' => 0,

    // Enable CSRF Protection (recommended, will be enabled by default in Craft 3)
    'enableCsrfProtection' => true,

    // Whether "index.php" should be visible in URLs (true, false, "auto")
    'omitScriptNameInUrls' => 'auto',

    // Control Panel trigger word
    'cpTrigger' => 'admin',

    // Dev Mode (see https://craftcms.com/support/dev-mode)
    'devMode' => false,

);

If I open the assets in chrome, this is their file path.

http://projectname:8888/html/assets/images/hero-images/be-inspired-mobile.jpg

This is driving me mad and have checked everything.

I am using exactly the same config settings as all my other sites which work absolutely fine.
Any help will be really appreciated :)

As per the Craft Docs at https://craftcms.com/docs/multi-environment-configs#environment-specific-variables, add a basePath (or other name) variable to you config. For MAMP, it should look something like:

'basePath' => '/Applications/MAMP/htdocs/example.dev/public/'

Then in your asset source settings, change File System Path to:

{basePath}assets/images/hero-images/