Image transform not working with different locales Working on a site that has a bunch of different locales, I'm bumping into the following issue:

On an entry in locale X, I have an image that is displayed with a transform applied to it. However, getUrl()on the asset returns the following url: /benl/cpresources/404?x=6obDEISgU.

But, when I add that exact same image to an entry in the site's main locale and view it on the front-end, the transform is generated and the image is displayed correctly.

When I then go back to the other entry in locale X (that has that same image), it uses the generated transform (from the entry in the main locale) and the page works.

So it looks like the transformed images can't be generated on the entry in the none-standard locale.

Some settings/parameters:

locales live in their own subfolder as per https://craftcms.com/docs/localization-guide
basePath is set to the main site's document root, without the locale folder
baseUrl is set the main site url, without the locale segment

Any pointers as to how to troubleshoot and/or fix this would be appreciate :)

Ran into a similar problem on a past project, it could be your .htaccess acting up and redirecting the call to cpresources to /benl/cpresources as opposed to /cpresources/.

If you look at your console on the page that the image is broken - you might be getting a 404 error. If that is the case...

Adding this rewrite rule helped my project and may help yours as well.

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^cpresources/transforms/(.*)  /cpresources/transforms/$1 [L,R,NE,QSA]

Add this rule to your .htaccess in your /benl/ directory before the default index.php rewrite.


Creating a date filtered archive template I'm trying to create an archive list template that lists entries from a News or Blog Channel based on year/month/day combinations.

However, I get no entries and can't see where I'm going wrong...I'm running the latest build of Craft.

{% if year is not defined %}
    {% redirect "news/archives/"~now.year %}
{% endif %}

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

Year: {{ year }}

Month: {{ month }}

Day: {{ day }}

{% if (year | length) and (month | length) and (day | length) %}
    {% set entryDate = year ~ '-' ~ month ~ '-' ~ day %}
{% elseif (year | length) and (month | length) %}
    {% set entryDate = year ~ '-' ~ month %}
{% elseif (year | length) %}
    {% set entryDate = year %}
{% endif %}

Entry Date: {{ entryDate }}

{% set entries = craft.entries.find({section: "news", postDate: entryDate}) %}

{% if entries | length %}
    Entries found.
{% else %}
    No entries found.
{% endif %}

I've used this method for sorting by year and month (it could be expanded to support days).

On the news/index.html template:

{% if month is defined %} {# show an archive of a month #}

    {% set sortDate = year ~ '-' ~ month %}

    Entry Date: {{ sortDate }}

    {% if month != 12 %}
        {% set nextmonth = month+1 %}
        {% set nextyear = year %}
    {% else %}
        {% set nextmonth = 01 %}
        {% set nextyear = year+1 %}
    {% endif %}

    {% set entriesToShow = craft.entries.section('news').limit(null).after(year ~ '-' ~ month).before(nextyear ~ '-' ~ nextmonth) %}

{% elseif year is defined %} {# show an archive of a year #}

    Entry Date: {{ year }}

    {% set entriesToShow = craft.entries.section('news').limit(null).after(year).before(year+1) %}

{% else %} {# assume overview page #}

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

{% endif %}

Any entries can then be displayed by one loop.

{% for entry in entriesToShow %}

Since this is made to be in on the section's index template you don't need a separate archive template. Just setup a few routes in the CP to send the archive tokens back to the index template.

Set all the token combinations you need like:

news/archive/(month)/(year)

To route to:

news/index.html


Grouping entries by a custom date conditional I'm looking to group entries based on a condition between two custom date fields and the current date. I'm not even sure this is possible, but this is how it would appear visually:

Happening Now

Entry 1

Entry 2

Happening in the future

Entry 3

Entry 4

Happened in the past

Entry 5

Entry 6

These entries all have two custom date fields, biddingStartDate and biddingEndDate. If the current date is between biddingStartDate and biddingEndDate, it should go under "Happening Now"; if the current date is before biddingStartDate, it should go under "Happening in the future"; and if the current date is after biddingEndDate, it should go under "Happened in the past".

The other large question here would be: how would the headings even be created since they're dynamic and not stored in the database?

You could fetch your entries then split them in three arrays which would give you the ability to then add headings manually and display as you need to.

{# Define today and three arrays to hold your grouped entries #}
{% set today = now|atom %}
{% set futureBids = [] %}
{% set currentBids = [] %}
{% set pastBids = [] %}

{# Fetch your entries #}
{% set entries = craft.entries().section('bids').all() %}

{# Populate your groups #}
{% for entry in entries %}
    {% set starts = entry.biddingStartDate | atom %}
    {% set ends = entry.biddingEndDate | atom %}

    {# future #}
    {% if starts > today %}
        {% set futureBids = futureBids | merge([entry]) %}

    {# current #}
    {% elseif starts <= today and ends > today %}
        {% set currentBids = currentBids | merge([entry]) %}

    {# past #}
    {% elseif ends < today %}
        {% set pastBids = pastBids | merge([entry]) %}
    {% endif %}
{% endfor %}

{# Display as you need... #}

Current Bids

{% for entry in currentBids %}
    {{ entry.title }}

{% endfor %}

Future Bids

{% for entry in futureBids %}
    {{ entry.title }}

{% endfor %}

Past Bids

{% for entry in pastBids %}
    {{ entry.title }}

{% endfor %}


How can I add banner slider on my home page? I want to add slider on my home page. How can I add slider?

In Craft, you as developer are responsible for everything that is front-end output. So if you want a banner slider, you'll have to add a field on the entry where you can add images, and in your entry's template, write the needed html to display the banner.

I'd suggest going trough the documentation to learn about entries, fields,templates, ... Also you could check out the courses at for example mijngo but those aren't free.

As carlcs pointed out, here are some popular options for displaying banners:

Slick
Flickity


Ajax Submittions to Guest Entries Does anything need to be done to allow for ajax submittions using the GuestEntries plugin?
https://github.com/pixelandtonic/GuestEntries

I'm following the method used here for Contact form, it submits fine and returns success but nothing shows up in the DB?

https://github.com/pixelandtonic/ContactForm#ajax-form-submissions

in chrome the request looks right?

Request URL: http://familiar.dev/
Request Method: POST
Request Payload:
{"action":"guestEntries/saveEntry","sectionId":"5","enabled":"1","redirect":"contact/thanks","title":"asdsa"}

any ideas?

So looks like i found the answer.  My javascript was submitting the data as json instead of as regular form data.  I reformatted and it works as expected.

Whoops.


Difference between categories and structures The recent updates to categories have been great and provide a lot of flexibility.  But now I find myself struggling to decide what should be a category group and what should be a structure.

For example we are working on a site where a lot of the content will be segmented by city.  Originally I had just assumed that cities would be a entry section but now feeling like categories make more sense semantically?

So my question is what are the functional differences between categories and structures?  As far as I can tell they are:

The category fieldtype does not let you reorder the selected categories, the way you can with related entries field.  They always stay in the category groups order
Categories don't have a post date or expiration date
Categories don't have authors
Categories don't have versioning

Are there any other important differences I should consider? It seems like the only advantages are that they get their own tab, and that the ordering is consistant across all related entries

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

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

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

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


Entry Query relatedTo Two Categories This has to be something that is easy, but I've been beating my head on my desk for a a few hours with this.  Most solutions I have come across are way to complex - when all I need to do is query a section for all entries that appear in two categories.

I'm pulling in the slugs via url,

ex: domain.com/investigators?t=primary&a=pregnancy-newborn-medicine

Then querying like so:

{% set typeQuery = craft.app.request.getParam('t') %}
{% set areaQuery = craft.app.request.getParam('a') %}

{% set cat1 = craft.categories.group('investigatorTypes').slug(typeQuery).one() %}
{% set cat2 = craft.categories.group('areaOfResearch').slug(areaQuery).one() %}

{% set researchers = craft.entries()
    .section('investigatorBios')
    .relatedTo(['and',
        {element: cat1},
        {element: cat2}
    ])
    .orderBy('bioLastName asc')
    .limit(12)
%}

What am I doing wrong?
Slugs match the respective categories in the groups.  There are only two types in the investigatorTypes I can query for - one returns all of them, and the other returns none.

Am I overlooking something obvious?

Thanks in advance, friends.

First, I might over complicate things. Maybe there is a simple solution by using:
https://docs.craftcms.com/v3/relations.html#passing-multiple-relation-criteria

But my project has a complex query built in. So I did a custom db query class. And here is one of them might working for you.

If you know how to create a twig function in craft 3 in modules, the following code will make sense to you. If you don't know how to do it. Here is the link how to do it https://docs.craftcms.com/v3/extend/extending-twig.html#register-a-twig-extension.

    /**
     * This function is a twig extension

     * @param $IdArray      array           the array of element ids used for related to
     *                                      you can join as many ids you want to.
     *                                      e.g. [
     *                                              [
     *                                                "or", ["1234","23123"]
     *                                              ],
     *                                              [
     *                                                "and", ["234","1232","12332"]
     *                                              ],
     *                                              ...
     *                                            ]
     * @return object                       craft element query object
     */
    public function elementMultiRelatedTo($elementQuery, $IdArray=[]){
        if($IdArray!=[]&&isset($IdArray[0])&&is_array($IdArray[0])){
            foreach ($IdArray as $key=>$value){
                if(isset($value[0])&&is_string($value[0])&&isset($value[1])&&is_array($value[1])&&$value[1]!=[]){
                    if($value[0]=="or"){
                        $elementQuery = $elementQuery->orWhere($this->multipleRelatedToQuery($value[1]));
                    }elseif($value[0] == "and"){
                        $elementQuery = $elementQuery->andWhere($this->multipleRelatedToQuery($value[1]));
                    }
                }
            }
        }

        return $elementQuery;
    }

    /**
     *
     * @param $id
     * @return \yii\db\Expression
     */
    public function multipleRelatedToQuery($id){
        $sourceString = "";
        $targetString = "";
        if($id==[""]||$id==""||$id==[]){
            return new \yii\db\Expression("1");
        }
        if(is_array($id)){
            foreach($id as $key => $v){
                if($key == 0){
                    $sourceString = "`sources2`.`sourceId` = '$v'";
                    $targetString = "`targets2`.`targetId` = '$v'";
                }else{
                    $sourceString = $sourceString . " OR `sources2`.`sourceId` = '$v'";
                    $targetString = $targetString . " OR `targets2`.`targetId` = '$v'";
                }

            }
        }else{
            $sourceString = "`sources2`.`sourceId` = '$id'";
            $targetString = "`targets2`.`targetId` = '$id'";
        }

        return new \yii\db\Expression("
        (
            `elements`.`id` IN
            (
                SELECT
                    `sources2`.`targetId`
                FROM
                    `craft_relations` `sources2`
                WHERE
                    $sourceString
            )
            OR `elements`.`id` IN
            (
                SELECT
                    `targets2`.`sourceId`
                FROM
                    `craft_relations` `targets2`
                WHERE
                    $targetString
            )
        )");
    }

Then in twig

{% set typeQuery = craft.app.request.getParam('t') %}
{% set areaQuery = craft.app.request.getParam('a') %}

{% set cat1 = craft.categories.group('investigatorTypes').slug(typeQuery).one().id %}
{% set cat2 = craft.categories.group('areaOfResearch').slug(areaQuery).one().id %}

{% set researchers = craft.entries()
    .section('investigatorBios')
    .orderBy('bioLastName asc')
    .limit(12)
%}

{# here cat1 and cat2 is not array, make sure put them in [] #}
{# if you want more than one id, you can try ".ids()" instead of ".one().id" #}

{% set researchers = elementMultiRelatedTo(resaerchers,
[
  [
     "and",
     [cat1]
  ],
  [
     "and",
     [cat2]
  ]
]) %}
{% researchersArray = researchers.all() %}


Error when rendering a template (for HTML email) on users.saveUser I'm writing a simple project-specific plugin that sends a notification to the site admin when a new user is registered. I have an HTML template that I'd like to use for this.

In my plugin's main class, I have the following function:

public function init()
    {
        parent::init();
        // Events
        craft()->on('users.saveUser', function(Event $event) {
            $user = $event->params['user'];
            $isNewUser = $event->params['isNewUser'];

            if ($isNewUser)
            {
                // Send notification email
                craft()->aeiMember->registrationNotification($user);
            }
        });
    }

which calls a one of my plugin's services, 'registrationNotification'. Here's the code I have for that service:

public function registrationNotification(UserModel $savedUser)
    {
        $user = new \stdClass();

        $user->firstName            = $savedUser->firstName;
        $user->lastName             = $savedUser->lastName;
        $user->email                = $savedUser->email;
        $user->aeiGroups            = $savedUser->aeiGroups;
        $user->phone                = $savedUser->phone;
        $user->mailingAddress       = $savedUser->mailingAddress;
        $user->city                 = $savedUser->city;
        $user->state                = $savedUser->state;
        $user->zip                  = $savedUser->zip;
        $user->country              = $savedUser->country;
        $user->preferredDealer      = $savedUser->preferredDealer;
        $user->dealerAccountNumber  = $savedUser->dealerAccountNumber;
        $user->school               = $savedUser->school;
        $user->expectedGraduationDate = $savedUser->expectedGraduationDate;

        $email = new EmailModel();
        $email->toEmail = '...myemailaddress...';
        $email->subject = 'New User Registration: ' . $user->firstName . ' ' . $user->lastName;
        $email->htmlBody = craft()->templates->render('aeiMember/registration_notification', array(
            'user' => $user,
        ));

        // Send
        if (craft()->email->sendEmail($email))
        {
            return true;
        }
    }

When I submit the registration form, I get the following error: "CDbException: CDbTransaction is inactive and cannot perform commit or roll back operations.". I narrowed down the issue, and if I use a non-HTML email body, everything works fine, so apparently there's an issue with rendering a template at this event.

Here's a link to a Google Doc with the stack trace: https://docs.google.com/document/d/1atFNkktuZQ91hU9QipXYMhOCHNGAavO5qUI_TF5jSeE/edit?usp=sharing

Am I doing something wrong, or is there a workaround to accomplish what I'm after? It seems like it should be pretty simple.

The issue turned out to be the result of a variable name mistake on my part. I had typed in an incorrect variable name in the email template. I actually still don't really understand what that has to do with a database transaction, though.

EDIT:
If anyone else is running into a similar issue, I've found a way to get a more useful error message, as opposed to the "CDbTransaction is inactive" message, which doesn't help much. If you go to craft/app/services/UsersService.php, and comment out line 311 ("$transaction->rollback();"), then Yii won't give you the CDbTransaction error before Craft has a chance to tell you its more helpful error. This should give you a better idea of what you're doing wrong. Obviously, don't forget to un-comment that line after you've fixed your issue.


How to reduce database size? I'm getting alarmed by the size of the database backups and the database in general. The site has Craft Commerce installed, which contributes I think, but if you look at the following list of backups there seems to have been a sharp increase in database size that has nothing to do with Craft Commerce (which has been installed since July).
Does anyone have an tips or articles to share about getting control of this? I feel it's getting ridiculous but that it has probably happened since we went live on October 17.
EDIT:
Looking at the database tables, there are definitely several tables that seem to larger than they should be:

craft_searchindex 31MiB
craft_commerce_orders 30MiB
craft_elements_i18n 20MiB
craft_content 15MiB craft_elements 13MiB
craft_commerce_customers 8MiB
craft_entryversions 3MiB
craft_deprecationerrors 1.5MiB

I'm wondering if there is a spam issue here. Could that be it?

So two primary things can contribute to database bloat:

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

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

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

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

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


How to see which database Craft is currently connected to? I was able to install Craft using a Vagrant/Homestead setup, but I can't seem to connect to the database I want. I set up my hosts file to point to a '.dev' address while working locally on my machine.

My db.php file seems to be set up ok:

return [
  '*' => [
    'server' => 'localhost',
    'tablePrefix' => 'craft',
  ],
  '.dev' => [
    'database' => 'dev',
    'user' => 'homestead',
    'password' => 'secret',
  ],
  '.org' => [
    'database' => 'prod',
    'user' => 'root',
    'password' => '********',
  ],
];

When I ssh into my vagrant box and log into mysql, I can SHOW DATABASES and see:

+--------------------+
| information_schema |
| dev                |
| prod               |
| homestead          |
| mysql              |
| performance_schema |
+--------------------+

I'm overwriting the dev, prod and homestead databases with a backedup .sql file, however when I visit my local '.dev' address, my Craft site doesn't appear to carrying over any of those changes.

Is there a way to see which database Craft is actually connected to?

You could do something like this to at least see which environment from your multi-environment config that Craft is matching:

$craft = require 'path/to/craft/app/bootstrap.php';
echo $craft->config->get('server', ConfigFile::Db);


Free-form integration to the website We have always utilised modules-forms to create our forms for our website. We've just downloaded Free Form to integrate with our marketing automation tool as the simple form wouldn't work how we wanted it to.
Now I'm trying to figure out how to actually embed a form within an actual page.
Modules-forms seems to be the only way to add forms to the site.
Please help
Bree

With freeform you can install some demo templates from which you can see how it works:
https://docs.solspace.com/craft/freeform/v3/setup/demo-templates.html#installing-the-demo-templates
You can also render your form with: {{ craft.freeform.form("formHandle").render() }}
Some additional info on that and additional custom formatting can be found here: https://docs.solspace.com/craft/freeform/v3/overview/formatting-templates.html


Impossible to invoke a method on array. How to merge multiple objects and keep as objects {% set newsletterImages = newsletter.imagesCongratulations|merge(newsletter.imagesCis)|merge(newsletter.imagesSection3) %}
{% set transformedImages = newsletterImages %}

{% for image in newsletterImages %}
  {{ image.title }}<br />

{% endfor %}

newsletterImages is merging images from 3 different global fields.
I want to then randomise and only output 6 of these images.

However, when I try

{% set transformedImages = newsletterImages.orderBy('RAND()').limit(6) %}

I get the error: Impossible to invoke a method ("orderBy") on an array. and Impossible to invoke a method ("limit") on an array.

Can anyone help point me in the right direction to achieve this?

You can achieve this with Craft's shuffle() method and Twig's slice filter (like you mentioned in your answer).

{% set newsletterImages = newsletter.imagesCongratulations.all() %}
{% set newsletterImages = newsletterImages | merge(newsletter.imagesCis.all()) %}
{% set newsletterImages = newsletterImages | merge(newsletter.imagesSection3.all()) %}

{% set shuffledImages = shuffle(newsletterImages) %}  // Shuffle our "master" array

{% for image in shuffledImages[:6] %}  // Get the first 6 images
  {{ image.title }}<br>
{% endfor %}


Is using nested extends a wise idea or will it be a performance/maintenance nightmare? Here's a basic example of using nested extends in Twig. I figured this is a probably common use-case. You have a very general _layout.html that contains your common CSS, JS, meta tags, etc.

{# _layout.html #}
<!DOCTYPE html>

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

  {% block content %}{% endblock %}

Then you have a _subpage.html template that shapes the way all your subpages should look (main content area, sidebar, etc).

{# _subpage.html #}
{% extends "_layout" %}

{% block content %}

    {% block subpageContent %}{% endblock %}

    {% block subpageSidebar %}{% endblock %}

{% endblock %}

Now I extend that _subpage.html in about.html and grab the blocks that belong to the _subpage.html template.

{# about.html #}
{% extends "_subpage" %}
{% set title = "About" %}

{% block subpageContent %}

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae cupiditate suscipit, debitis accusantium tenetur impedit, veritatis id placeat, dolor hic temporibus architecto quas atque sunt officiis corrupti voluptatibus expedita. Assumenda!

{% endblock %}

{% block subpageSidebar %}

Subpage Link 1

Subpage Link 2

Subpage Link 3

{% endblock %}

Now I realize you can use nested extends in Twig, but I'm entirely sure if I should. Is this a maintenance nightmare? Does it take a performance hit to do this? What's the best practice for template relationships?

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

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


How do I access current site handle in Craft 3 controllers When my multisite is set up as @web/site, I cannot access the current site handle from my controllers.

Craft::$app->getSites()->currentSite->handle

I think this is because my form action defaults to the root site ie @web/actions/controller... rather than @web/site/actions/controller...

Is there a way to get the current site or do I need to pass it into the controller from the form?

I know this is a year and a half late, but maybe it helps someone else. I have a large multi-site project with a site for country and language. For example:

Germany (German) - default - /de-de/
Germany (English) - /en-de/
Austria (German) - /de-at/
Austria (English) - /en-at/
etc

I was having this problem when posting to one of my controller's actions and then trying to get the currentSite within my plugin via Craft::$app->getSites()->currentSite.

In my JavaScript, my action looked like:

/actions/pluginHandle/controllerClass/actionMethod

Whenever I'd fetch the current site with Craft::$app->getSites()->currentSite it would always return the default site (Germany/German), and that's because I wasn't including the first URL segment (to get Austria/English, for example):

/en-at/actions/pluginHandle/controllerClass/actionMethod

Without that, Craft was resorting to getting the default site.


How to hide {{ entry.title }} on a {structure} page but show it on a {structure}/{category-slug} page Here's the breakdown:

» structure with two categories. Each category has +10 entries.

» Template is structure / index.html and _entryview.html

I'd like to show two links and a description of both categories on the /structure/ URL.

However...

On the /structure/index/ page, I'd like to show the entries for each category — all using the same index template.

So far I can pull the {category.title}s and the {entry.title} ... but it's the same on both pages (structure/ and structure/category)

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

  {% nav category in craft.categories
    .group('fellowsCat')
    .limit(11)
    %}

      {{ category.title }}
      {% ifchildren %}

          {% children %}

      {% endifchildren %}

  {% endnav %}

{% set entries = craft.entries({
  section:  'fellows',
  relatedTo:  craft.categories('fellowsCat'),
})
%}

{# ___________________________
this is where things fall apart.
If I'm on /structure/ I don't want to see entries.
If I'm on /structure/category, I do.
_____________________________
#}

{% if craft.categories is not null %}

  {% for entry in entries %}

  {{ entry.title }}

  {% endfor %}

{% else %}
nothing to see
{% endif %}

I suspect there's something with the {% if craft.categories is not null %} line that would do the job, but I can't figure it out.

Figured it out.

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

  {% nav category in craft.categories
    .group('fellowsCat')
    %}

      {{ category.title }}
      {% ifchildren %}

          {% children %}

      {% endifchildren %}

  {% endnav %}

{# --- this is the key line here ---#}
{% if category is defined %}

{% set entries = craft.entries({
  relatedTo:  category,

})
%}

{% if craft.entries.relatedTo(category) %}

      {% for entry in entries %}

  {{ entry.title }}

      {% endfor %}

     {% else %}
    nothing to see
     {% endif %}
     {% endif %}


Store Hours: show current open/closed state I'm wanting to do two things with this great plugin, but am having a bit of a mind-melt...

1) I'd like to show the current state; e.g. Closing soon; Open now; Closed; Opening Soon

2) I'd like to show the current day highlight:

Sunday:    11:00 AM - 05:00 PM

Monday:    10:00 AM - 08:00 PM

Tuesday:   10:00 AM - 08:00 PM

Wednesday: 10:00 AM - 08:00 PM

Thursday:  10:00 AM - 08:00 PM

Friday:    10:00 AM - 08:00 PM

Saturday:  10:00 AM - 07:00 PM

Thanks!

An answer to point 1)

{{ location.hours[now|date('w')].open < now and location.hours[now|date('w')].close > now ? 'Open now' : 'Closed' }}

And that same logic can be used to resolve issue 2)


Events calendar for Craft - which one should I use? The current state of events/calendars in Craft is:

Calendars - https://topshelfcraft.com/calendars/introduction
Venti - http://tippingmedia.com/venti
Solspace Calendar - https://solspace.com/craft/calendar

Whats the benefits of each? Anything to note?

I haven't used Venti, so I can't comment on it. However, I have tried out both Calendars from Top Shelf Craft and Solspace Calendar on a recent project.

I started out using Top Shelf Craft Calendars (Solspace Calendar hadn't been released at this point). However, during the project, I switched to Solpsace Calendar which has ended up being used on the final build.

In my view, Craft Calendars and Solspace Calendar have distinctly different approaches as to how they work.

Top Shelf Craft Calendars

In Craft Calendars, any element (entries, users, assets, etc.) can be attached to a calendar event. If you want to store custom fields associated with an event, then you would store these on the element you are attaching to the calendar event, not on the event itself.

In this way, you can think of Craft Calendars as creating a specialist fieldtype which enables you to schedule events, either on a one-off basis, or using sophisticated recurring rules. So to create an event, it must be associated with another element, since the event date is set using the Event Dates Fieldtype on the host element, rather than creating an event directly on a calendar element.

Craft Calendars doesn't currently have a nice GUI for the control panel and the front end output and styling are also left to you. This means that there is no native way to see an overview of the events that have been created. This may or may not be important to you.

Solspace Calendar

On the other hand, with Solspace Calendar, events belong to a calendar first and foremost. There is an Events Fieldtype which can be used to relate another element (entries, users, assets, etc.) to a specific event using native Craft relations.

Events can also have their own custom fields. However, at the moment it is is not currently possible to search for Solspace Calendar events based on the contents of their custom fields. You can only search for events based on 'native' Solspace Calendar attributes, such as calendar name, start date, end date and author (see the docs for full details).

The control panel GUI for Solspace Calendar really shines and is very easy to use. It is based on Full Calendar, a JavaScript event calendar JQuery plugin. Solspace provide sample front end templates using Full Calendar, so it is fairly quick and easy to get a similar system up and running on your site.

The Full Calendar interface, plus the ability to have events that weren't associated with existing elements, were the main factors in my choice of Solspace Calendar for the project I used it on. Though at the time I developed it, Solspace had not yet released their Full Calendar front end templates and there was little support for calling the event creation controllers from the front end, I was able to work through their code to see how they had achieved it in the control panel and create what I needed for the front end of my site.

However, it wasn't an easy choice between the two so I completely understand the motivation behind your question.

Comment on development and coding style

I have spent a lot of time looking through the code for both plugins and Solspace Calendar in particular. From a development and coding point of view (if that matters to you), Craft Calendars seems to me to follow Craft coding conventions more closely.

Solspace seem to have introduced extra levels of complexity and abstraction into Calendar that, in my opinion, for what it's worth, make it more complicated that it perhaps needed to be and lose some of the native behaviour you would get if they had used a more 'Crafty' approach. I have noticed this before with some of their EE add-ons. That said, they were very responsive to all the bug reports and questions I raised with them during the active development of the project.


Disable modification of assets title and name I want to disable the modification of both the file name and title of a specific asset type.
How can I do that ?

I guess this feature request will solve my problem... in the future:
http://feedback.buildwithcraft.com/forums/285221-feature-requests/suggestions/7197199-ability-to-hide-or-disable-fields-based-on-a-user

But in the meantime I did it with a small css hacking (no choice):

protected function includeResources()

switch ( $segments[ 0 ] ) {
    case 'entries' : case 'categories' : case 'assets' :
        craft()->templates->includeCssResource( 'plugin/styles.css' );
        break;
}

style.css

// remove title and name fields from modal editor in CP assets page
    .hud {
        .body.elementeditor {
            .field[id$="filename-field"], .field[id$="-title-field"] {
                display: none;
            }
            .field {
                margin-top: 0px;
            }
        }
    }

Works fine :


Inline image transform using Matrix field for image quality? Hope I'm not posting incorrectly here but don't have enough reputation yet (really don't understand that system at all) to be able to comment on another post here on the exchange.

Original Post - inline image transforms

I'd like to get this to work but not having any luck at all. This is my code in my template so far.

{% for block in entry.matrixBlocks %}

    {% if block.type == "text" %}

{{ block.text }}

    {% elseif block.type == "quote" %}

{{ block.quote }}

    {% elseif block.type == "image" %}

    {% set smallImage
        = {
        mode: 'fit',
        width: 600,
        height: 200,
        quality: {{ block.quality.value }},
        position: 'top-center'
        }
    %}

    {% for asset in block.image %}

    {% endfor %}
    {% endif %}

{% endfor %}

The quality in {{ block.quality.value }} is the name (handle) of a field I have storing a number from 1-100 in my Matrix Block. I am using Max Lazars range field to store the number.

Upon trying this say by Live Preview the page never refreshes. If I change the {{ block.quality.value }} to a number then it all works again as expected.

Would love to get this working so any help would be greatly appreciated to let me know where I'm going wrong.

Thanks,

Mark

Aha!!! Got it working at last!!

As I was using Live Preview, even though I was set to Dev Mode for any errors, they weren't showing in the Live Preview pane (maybe that should be a feature request?).

As soon as I tested it out on the live page I saw an error and it told me to place parentheses around an expression so I did this instead :

quality: (block.quality.value) and all is good with the world now!! :-)


How can I loop through a Channel entries asset folder? Basically, for every entry that I add to my 'Portfolio' channel, it creates a sub-folder inside assets/portfolio.

For example I have:

assets/portfolio/entry-one
assets/portfolio/entry-two

On my portfolio page, for each entry I want to display the first image from its asset folder and also get the url of every image in the folder.

Can anyone think of a solution that would allow me to do this? Can't figure out how to target each individual folder.  I know you can target folders by ID, but unless this can be somehow done dynamically in a loop it will not suit this situation.

I'm not sure about displaying "the first image from the asset folder" but, you can display the first asset as it's situated in the entry itself. Would that work? Maybe something like this?

{% set assetFirst = entry.myAssetsField.first() %}

{% if assetFirst %}
    {# or use getImg() (or either alias img/url): https://craftcms.com/docs/templating/assetfilemodel #}

{% endif %}

{% set assets = entry.assetsFieldHandle %}

{% if assets | length %}

    {% for asset in assets %}
        {# https://craftcms.com/docs/templating/assetfilemodel#simple-output #}
        {{ file }}
    {% endfor %}

{% endif %}


can i used craft.entries.section into my Controller I am new in Craft CMS and this is my first plugin. Below is my code to get products.

{% craft.entries.section('products').limit(9) %}

This code is working fine but can I use this code in my controller for getting products?

Thanks

If you want to use ElementCriteria in your controller, this is how to go about it:

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

$products = $criteria->find();

Read this page for more info on the subject.


How do I sort a collection of entries from multiple sections by date? I want to create a featured story slider on my website and gather the latest entries from multiple channels to populate it.

Here is what is working:

# fetch the entries
{% set featuredBlog = craft.entries.section('blogs').limit(1).find() %}
{% set featuredArticle = craft.entries.section('articles').limit(1).find() %}
{% set featuredSpecialReport = craft.entries.section('specialReports').limit(1).find() %}
{% set featuredInfographic = craft.entries.section('infographics').limit(1).find() %}

# create a collection out of the above entries
{% set allEntries =
featuredBlog|merge(featuredArticle)|merge(featuredSpecialReport)|merge(featuredInfographic) %}

# loop over the collection and output them
{% for featuredEntry in allEntries %}
  {{ featuredEntry.title }}

{% endfor %}

Now I want to sort the collection of entries by postDate so that the latest entry in the collection shows up first, no matter what section it is from. How do I do this?

I tried:

{% for featuredEntry in allEntries|group('postDate.day') %}
  {{ featuredEntry.title }}

{% endfor %}

But this doesn't work and crashes the template saying Key "title" for array with keys "0, 1, 2" does not exist

So how do I sort a collection of entries from multiple sections and show them by latest date descending?

Rather than fetching the entries at first, just grab their IDs using ids() instead of find():

{% set featuredBlogId = craft.entries.section('blogs').limit(1).ids() %}
{% set featuredArticleId = craft.entries.section('articles').limit(1).ids() %}
{% set featuredSpecialReportId = craft.entries.section('specialReports').limit(1).ids() %}
{% set featuredInfographicId = craft.entries.section('infographics').limit(1).ids() %}

Then merge all of those arrays together:

{% set featuredIds = featuredBlogId
    |merge(featuredArticleId)
    |merge(featuredSpecialReportId)
    |merge(featuredInfographicId) %}

Once you’ve got that array of all the latest featured entries’ IDs, you can fetch their full entry models all at once:

{% set featuredEntries = craft.entries.id(featuredIds) %}

{% for entry in featuredEntries %}
    {{ entry.title }}<br>
{% endfor %}


How to upload assets without user interaction? Context: we sell some magazines and other newspapers on our site, and updating all the cover images manually is a hassle.

I would like the ability to write a url in a field (www.myimageprovider.com/product1) and set a cron job to fetch any new images for the day, for that specific product, and update the entry with the new image.

I'm having a hard time figuring out how to "fake" a file upload from a craft controller/service, as if it was uploaded from the CP form. I have tried something like this:

$file = array();
$url = $entry->getFieldValue('imagefetchurl'); // somegoogleimageurl.com/image.png
$tmpfname = tempnam("/tmp", "UL_IMAGE");
$img = file_get_contents($url);
file_put_contents($tmpfname, $img);
$file['size'] = filesize($tmpfname); // 245 kB
$file['name'] = basename($url); // image.png
$file['tmp_name'] = $tmpfname; // C:\\Windows\\Temp\\UL_XXXX.tmp

$_FILES['assets-upload'] = $file;
$assetOperationResponseModel = craft()->assets->uploadFile(1);

This throws an error

PHP notice

getimagesize(): Read error! - in ...craft\app\services\ImagesService.php(114)

I can see that the image get downloaded, the size and name is correct.

Any pointers and ideas are greatly appreciated

EDIT

After some digging, looks like i have to write my own upload handler for this task. http://www.1-script.com/forums/php/simulate-file-upload-so-that-move-uploaded-file-succeeds-124012-.htm

  Basically not possible unless you change the PHP source

I suppose i could override the function, but my instinct tells me that's a bad idea. I will have to go with an alternative approach

Answering my own question for reference.
I was tunneling too hard on the PHP, a simple bash script takes care of the upload.
# assuming the image is already downloaded and no CP-login required
curl -F assets-upload=@/path/to/image mycraftsite/admin/actions/assets/uploadFile

EDIT
Better answer: Thanks to this answer I discovered the insertFileByLocalPath() function in AssetsService.
  $entry = craft()->entries->getEntryById($id);
  if($entry && isset($entry["imageFetchUrl"])) {
    $url = $entry->getFieldValue("imageFetchUrl");
    $tmpfname = tempnam("/tmp", "UL_IMAGE");
    $img = file_get_contents($url);
    file_put_contents($tmpfname, $img);
    craft()->assets->insertFileByLocalPath($tmpfname, 'fetchedImg.jpg', $myFolderId);
  }


Craft CMS 3.0 - Log file? I've been playing around with Craft 3.0 and am just about to develop a site using it. First thing I see when testing my frontpage template is "Internal server error", styled as a Craft error box.

So my question is simple, where is the log file for Craft 3.0? So I can see exactly what might be causing this?

Based on the official documentation the log files are under /storage/logs and look for the web.log file especially.

If you don't find anything check your webserver logs.


How to hide createAccount select by default • Charge 2 Plugin I'm adding a basic annual subscription to a portion of a website.

I have Registration Behaviour set to
Always - creates an account for all guest payments

But on the subscription form the createAccount select still appears (Save my account, No don't create an account".

I'm including the customerDetails fields like this:

{% include 'charge/_includes/inputs/customerDetails' with { 'registerGuest' : true }%}

I see the form logic in customerDetails.html but that doesn't feel like something that should be edited.

I want to remove the select, since I should always be creating a new account by default OR I want to replace it with a hidden field.

Eventually I just edited customerDetails.html and swapped out the select with a hidden field. Done.

{{ forms.hidden({
    name: 'createAccount',
    id: 'createAccount',
    value: 'yes'
}) }}


Argument #2 is not an array Here we go:

{% set state = craft.categories.group('locations').level(1).title(entry.title).one() %}
{% set solution = craft.categories.group('institutionSolutions').title(entry.parent.title).one() %}
{% set entries = craft.entries.section('institutions').relatedTo('and', state, solution).limit(4) %}

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

The following code does work as expected in Craft 2. According to the docs in Craft 3 we have to use the array brackets. So this

{% set entries = craft.entries.section('institutions').relatedTo('and', state, solution).limit(4) %}

will become to this

{% set entries = craft.entries.section('institutions').relatedTo(['and', state, solution).limit(4) %}

as a result I see the following message:

array_merge(): Argument #2 is not an array

What am I doing wrong? :(

When you are going to apply an and in your relatedTo in Craft 3 it expects the following arguments to be arrays with the structure like here

{% set entries = craft
    .entries
    .section('institutions')
    .relatedTo(['and',
        {element: state}, // <- or targetElement / sourceElement
        {element: solution}
    ])
    .limit(4)
    .all()
%}


Get all URLs from a multisite installation I have an multisite installation like this:

www.example.com/animal
www.example.uk/animal

Each site has a configuration like so:

'example.com' => array(
        'siteUrl' => array(
            'us_en' => 'https://www.example.com/'
        )
'example.uk' => array(
        'siteUrl' => array(
            'uk_en' => 'https://www.example.uk/'
        ).

I want to print a collection of URLs from all of the locales. For example:

www.example.com/animal
www.example.uk/animal

And check their status as well.

I don't know what version of Craft you're using, but recently it became possible to request multiple site's version of the same entry/entries. For this to work, you need to provide multiple site ID's to the siteId part of the query, or multiple handles to the site part of the query:

{#
 # Provide the entry element query with the IDs for 3 sites
 # and group those by the entry's ID, so we know which entries belong together
 #}
{% set entriesById = craft.entries.siteId([1,2,3]).all() |group('id') %}

{#
 # Loop through the grouped entries and display whatever you need to display.
 # Each entry has their own `siteId` set, so you can use .getUrl() (or .url) to display the url
 #}
{% for entryId, entries in entriesById %}

Entry {{ entryId }}

    {% for entry in entries %}
        URL: {{ entry.url }} - Status: {{ entry.status }}
    {% endfor %}
{% endfor %}

If you are using Craft 2 (or a Craft 3 version before it became possible to query multiple site's entry versions at once), I think you could do it like this:

{# Craft 2 (untested, it's been a while ... #}
{% for locale in craft.i18n.getSiteLocales() %}
    {% set entry = craft.entries.id([your entry's id]).locale(locale) %}

    {% if entry %}
        URL: {{ entry.url }} - Status: {{ entry.status }}
    {% endif %}
{% endfor %}

{# Craft 3, before my original answer became possible #}
{% for site in craft.app.sites.allSites %}
    {% set entry = craft.entries.id([your entry's ID]).siteId(site.id).one() %}

    {% if entry %}
        URL: {{ entry.url }} - Status: {{ entry.status }}
    {% endif %}
{% endfor %}


How do I make the "%20" in URL's show as "-" I'm building a site where I am linking entries based on their tags. If you click on a tag you go to a dedicated page with all entries that share the same tag.

{% for tag in craft.tags.relatedTo(entry) %}

{{ tag.title }}

{% endfor %}

The problem I have is that if a tag has more than 1 word, the URL displays like this:

http:/site.com/tag/two%20words

How do I change "%20" to a dash?

Edited

I just learned this, but as of Craft 2.4, there's a kebab filter which you can use here. This would probably give you the effect you're after, where the string "two words" would become "two-words", and punctuation characters are dropped by default.

You could use this like so:

{{ tag.title }}

Original

The %20 string is being added to replace spaces because you're using the url_encode filter on tag.title. A simple (though somewhat naïve) way to to solve this would be to use the replace filter:

{{ tag.title | url_encode | replace({"%20": "-"}) }}

However, you might still see some "%XX" characters in this string if the tag.title has other characters that url_encode might want to replace. The "%" character, for example, gets turned into "%25" after being run through url_encode.

This also probably won't do what you expect, as the link you're generating for the tag won't work unless you're doing special routing. The problem stems from the fact that tags don't have clean URL slugs at this time, so what you're doing right now is probably the best course of action.

You've probably already seen this, but there's a documentation page specially about linking to tags. This is the current best practice I know of. If you're really looking for cleaner slugs in URLs, I'd recommend using categories instead of tags if possible.


Freeforms - add error I've created a plugin that will check for a unique email address in the submissions of Freeform.
Because I don't want this check to be done with Ajax, I use the Freeform hook 'onBeforeSave'.

Whenever a email is already used, I want the user to know. I'm telling Freeforms that the form is not valid:

craft()->on(
    "freeform_submissions.onBeforeSave",
    function (Event $event) {

        // Let Freeform know the form is not valid
        $event->performAction = false;
    }
);

Unfortunately I haven't found a way to communicate this to the frontend. It would be nice if I could set a Freeform error message.

Any solutions?

I've contacted Freeforms (Solspace). Unfortunately there is no solution for this problem (yet). Solspace told me:

  This functionality currently isn't possible with Freeform. It's something on our feature requests list though.


New entry showing under old one I'm working on a website that was developed by someone else before me, I added a new section and template, I uploaded all my files, created my new section and field and created my first entry everything was looking good, I decided to add a second entry to ensure that everything is working, but when I preview the entry Craft is showing both entries on one page instead of creating separate page for the entries. Please, can someone tell what is the reason for that I'm new using Craft below is the code that I wrote for the new template?

{% extends "layout/_layout" %}

{% block breadcrumbs %}
    {% include 'includes/_Breadcrumbs' with { 'currentTitle' : entry.title } %}
{% endblock %}

{% block content %}

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

        {% include 'includes/_pageTitle' %}

        {# Top Content Section 1 #}

                        {% for block in entry.Headline %}

                                {{ block.headline }}

                            {% if block.subHeadline %}

{{ block.subHeadline }}

                            {% endif %}
                        {% endfor %}
                        {% if entry.leadInText %}
                            {{ entry.leadInText }}
                        {% endif %}

                        {% include 'includes/_asideBox' %}

        {# Start Sections 2 - 5 #}
        {% for block in entry.newContentMatrix %}
            {% switch block.type %}

                {% case "twoColumnSection" %}
                    {% include 'includes/_sectionTwo' %}

                {# Section 3 #}
                {% case "paragraphSection" %}
                    {% include 'includes/_paragraphSection' %}

                {# Double list Section #}
                {% case "listSection" %}
                    {% include 'includes/_listSection' %}

                {# Section 4 #}
                {% case "miniFormSection" %}
                    {% include 'includes/_miniFormSection' %}

                {# Call to action Banner #}
                {% case "callToActionBanner" %}
                    {% include 'includes/_callToAction' %}

            {% endswitch %}
        {% endfor %}

    {% endfor %}

    {% includeJsFile "/public/ui/js/accodion-menu.js" %}
    {% includeJsFile "/public/ui/js/SideNavTrigger.Js" %}

{% endblock %}

Craft will inject the current entry by default in your template. All you have to do is to remove this loop

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

And you are fine.

Currently you are fetching all entries within your section. If you don't want to display them all but only the current you should not do that


How do I reorder Structure entries on the front-end? I've have a page that has a drag and drop ability to reorder a group of Structure entries (using jquery).

I see order inside EntryModel (https://craftcms.com/docs/templating/entrymodel) but it looks like Structure positioning is handled outside the EntryModel.

Once dropped and and the entries are reordered it submits to an action inside a plugin. If I reorder two entries (or any number) how do I set the new structure order?

The place to do that sort of thing is StructuresService.

If we’re just talking about reordering a flat list of entries (no hierarchy), the only methods you need to worry about are moveAfter() (if an entry is being dragged after another one) and prependToRoot() (if an entry is being dragged to the first position in the structure).

$entry = craft()->entries->getEntryById(1);
$prevEntry = craft()->entries->getEntryById(2);
$structureId = $entry->getSection()->structureId;

craft()->structures->moveAfter($structureId, $entry, $prevEntry);


Front End Entry Form Select Dropdown Error My front-end new entry form works, but when I add the complexity of a dropdown to the mix - it error's and doesn't save the entry. (I found this out with trial and error, removing fields until I found the culprit - the dropdowns)

I'm unsure what errors it's returning, but I'm sure something may be off with the code.

  {% macro errorList(errors) %}
            {% if errors %}

                    {% for error in errors %}

{{ error }}

                    {% endfor %}

            {% endif %}
        {% endmacro %}

        {% from _self import errorList %}

        <form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
            {{ csrfInput() }}
            <input type="hidden" name="action" value="entries/save-entry">
            {{ redirectInput('/listings/') }}
            <input type="hidden" name="sectionId" value="1">
            <input type="hidden" name="enabled" value="1">

              Demographic
              <select class="form-control" id="listingType" name="fields[demographic]">
                {% set demographicField = craft.fields.getFieldbyHandle('demographic') %}
                {% for option in demographicField.settings.options %}
                  <option>{{ option.label }}</option>
                {% endfor %}
              </select>

            <button class="btn btn-primary btn-md semi-bold" type="submit">Create Listing</button>

        </form>

On your dropdown field's name, you need a [] on the end for it to submit properly:

name="fields[demographic][]"

As mentioned in this answer, the dropdown field is basically an array of options, so you need that empty array on the end for them to be stored in.


How do I create an external transformer class when using the ElementApi plugin? I've been trying to clean up my elementapi.php file, and one very important step in making it more DRY is to have reusable transformer classes.

But I cannot seem to get it to work, the following gives me a blank page.

So far in my elementapi.php file I have the following.

'api/articles' => function() {
// I have also tried to place this line at the very top of the file.
require_once craft()->path->getConfigPath().'transformers/EntryInfoTransformer.php';

            'criteria' => [
                'section' => 'blog',
                'order' => 'postDate desc',
            ],

            'elementsPerPage' => 5,
            'elementType' => 'Entry',
            'transformer' => new EntryInfoTransformer(),
        },

and my EntryInfoTransformer.php file has

<?php

require craft()->path->getPluginsPath().'elementapi/vendor/autoload.php';

use League\Fractal\TransformerAbstract;
class EntryInfoTransformer extends TransformerAbstract{
    public function transform(EntryModel $entry) {
        return [
            'id' => $entry->id,
        ]
    },
}

I don't get any errors, nothing in either the php or craft logs, just a blank while page. This has been tested on php 5.5 & 5.6. Site runs normally otherwise.

You're getting a whitescreen because you've got some PHP syntax errors in both files. Craft isn't reporting them because those config files get loaded before Craft has had a chance to bootstrap.  The underlying errors should be recorded in your web server's error logs depending on your default server configuration.

Try these:

elementapi.php

<?php
namespace Craft;

require_once craft()->path->getConfigPath().'transformers/EntryInfoTransformer.php';

return [
    'endpoints' => [
        'api/articles' => function() {
            return [
                'criteria'        => [
                    'section' => 'blog',
                    'order'   => 'postDate desc',
                ],
                'elementsPerPage' => 5,
                'elementType'     => 'Entry',
                'transformer'     => new EntryInfoTransformer(),
            ];
        },
    ]
];

EntryInfoTransformer.php

<?php
namespace Craft;

require craft()->path->getPluginsPath().'elementapi/vendor/autoload.php';

use League\Fractal\TransformerAbstract;

class EntryInfoTransformer extends TransformerAbstract
{
    public function transform(EntryModel $entry){
        return [
            'id' => $entry->id,
        ];
    }
}


Is it worth caching product blocks for use on a category page? So we have a Commerce project that shows lots of products per page/category as per any standard store.

Each product block comprises:

Product name
Product price
Brand (via category field) [eager loaded]
Image [eager loaded]

Is it worth caching each of these blocks with a unique key?

In short, it's worth caching anything that is at all time expensive, really.

It's always going to be significantly quicker to retrieve a cached chunk from the DB by key versus parsing a template section - and especially so a complex one with many related elements being pulled in.

However, if those are live products, i.e. with add to cart forms, you'll need to make sure the forms remain valid (think about current CSRF token, etc - you can insert these with JS on page load, for example) - and that your cache breaks whenever the cached thing is updated (which should mostly be automatic).

Note that once you start caching a lot of different things, it can take several seconds for all the stale cache chunks on complex pages to be deleted after you make changes in the control panel (you can see the little queue thing executing this after you save your updates) - so it will mean that your content changes will no longer be literally instant, and this can confuse if you're not aware of it happening.  In our case it can take up to a minute before it all washes through, so your content editors need to be aware of this.


Get entries by date but ignore time I'm trying to pull entries from a database where the postDate is a specific date.

{% set today = thisyear ~ "-" ~ thismonth ~ "-" ~ day %}
{% set today = today|date('Y-m-d') %}

{% set entries = craft.entries(params).section('calendar').status('null').postDate(today|date('Y-m-d'))%}

This only gets the entry if the Time element of the Post Date is empty or 00:00
How can I correct this to pull the entries even if it has a time associated with the Post Date

This happens because you set the parameter on the ElementCriteriaModel to get entries with that specific datetime. If you omit a time when you compose a datetime with strings, you'll still get a time (00:00:00) and even a timezone set on it:

{% set myDatetime = '2014-08-12' %}

{# Print the datetime in ISO 8601 format / 2014-08-12T00:00:00+02:00 #}
{{ myDatetime|date('c') }}

This is how you set the parameter to accept datetime ranges:

{% set myDatetime = thisyear ~ '-' ~ thismonth ~ '-' ~ day %}
{% set entries = craft.entries.postDate('and', '>= ' ~ myDatetime, '< ' ~ myDatetime|date_modify('+1 day')) %}


How can I relate PDFs and Files using an Element Select field in my custom plugin? I would like to create an elementSelect form field in my plugin, and can't find an example or description. Can someone help?

I believe you're looking for something like the example posted here which goes into detail on several items necessary to create a working Asset Relations Field in a custom plugin:
https://craftcms.stackexchange.com/a/456/115


Targeting the first entry item I'm using Craft 3 and have created a section (channel type) for my project entries. At the bottom of each project page I have my Prev and Next Project buttons. How do I target the first and last project entry based upon the post date? I want to add some space between the buttons when they're together, but dispense with it on the first and last entries because.

Below is my current code from my project _entry template for the buttons:

{% set params = {section: 'projectEntries', order: 'postDate desc', limit: null} %}
{% set entry_prev = entry.getPrev(params) %}
{% set entry_next = entry.getNext(params) %}

Then on the buttons I'm using an if statement to show the next or prev URLs.

To target the first entry I've tried using :

{% if craft.entries.section('projectEntries').order('postDate desc').one() %}
    show alt button code
{% else %}
    show regular button code
{% endif %}

Which shows my alt button code, but shows it on every project page, instead of just on the first entry.

What do I need to do?

Thanks,

Richard

The conditional {% if craft.entries.section('projectEntries').order('postDate desc').one() %} basically just tests if the craft.entries.section query returns an entry or not. Obviously, that would evaluate to true on every entry template.

Instead, you probably want to test if the first entry returned by the above query is the same as the current entry. A good way to do that, is to compare the entry IDs:

{% set firstEntry = craft.entries.section('projectEntries').order('postDate desc').one() %}

{% if entry.id == firstEntry.id %}
    ...

To test for the last entry, you could do something like this (notice that the only difference from the above query is that the sort order is reversed):

{% set lastEntry = craft.entries.section('projectEntries').order('postDate asc').one() %}

{% if entry.id == lastEntry.id %}
    ...

If, however, you have access to the entry_prev and entry_next variables within the Twig block that renders the buttons, you can avoid extra database queries altogether by simply checking if those variables are null or not:

{% if not entry_prev %}
    {# No previous entry; the current entry must be the first #}
    ...
{% elseif not entry_next %}
    {# No next entry; the current entry must be the last #}
    ...
{% else %}
    {# The current entry is neither the first nor last #}
    ...
{% endif %}

If you can't use the entry_prev and entry_next variables, a more optimized way to do it than pulling the first and last entries would be to do something like the below – note the use of ids() instead of all(); this is an optimization due to it being cheaper to just pull the entry IDs instead of the full entry models:

{% set allEntryIds = craft.entries.section('projectEntries').order('postDate desc').ids() %}

{% set firstEntryId = allEntryIds|first %}
{% set lastEntryId = allEntryIds|last %}

{% if entry.id == firstEntryId %}
    {# The current entry is the first one #}
    ...
{% elseif entry.id == lastEntryId %}
    {# The current entry is the last one #}
    ...
{% else %}
    {# The current entry is neither the first nor the last #}
    ...
{% endif %}


TwigExtension added to Craft don’t work in emails I added tomodomo/twig-pluralize-extension to my project composer, loaded with a custom module like that :

if (Craft::$app->request->getIsSiteRequest()) {
    // Add in our Twig extension
    $pluralize = new \Tomodomo\Twig\Pluralize;
    Craft::$app->view->registerTwigExtension($pluralize);
}

I use this to pluralize some string in my templates and email templates. When I check the url to my email template, everything work fine but the email didn’t send out because of "unknown function pluralize".

I have another custom module (to handle something else in my emails) and this part work fine.

Do I need to register/declare TwigExtensions with another method to get them work in emails ?

Note:

The only error related to my emails in the logs is about pluralize
function missing.
Everything work fine if I don’t use |pluralize

All you should need to do is remove this condition check:

if (Craft::$app->request->getIsSiteRequest()) {

You are only registering the twig extension for front end (site) requests, but emails can be triggered both on a cart complete front end (site) requests AND a back-end (CP) order status changes.


Commerce email receipt not sent after order, but manual Send Email in Order screen works I have placed a successful order in Commerce and it's settings have an email setup to send an email to the customer and use the example special/receipt email.
But the receipt email is not sent once the order is placed.
If we login to the admin and go to the order page, selecting Send Email and choosing the customer receipt then it does send it OK.
So the receipt email is all setup OK and sends using the function in the order screen, its just not sending after the order is placed.
There is no commerce.log in storage.
web.log doesn't have any logs related to commerce or the order.
There is nothing in the Queue related to this (only loads of failed "Updating search indexes" and "Generating products sitemap" which is a whole other issue).
Does anyone know what it could be or how I could even go about debugging this when email works and I can't find any logs about its not sending?
Thanks

Simple step missing on the setup of this. I needed to actually assign this email to the status New, to send when a New order is placed, in the Order Statuses section, as per this documentation. So simply a case of RTFM:
https://craftcms.com/docs/commerce/3.x/order-status-emails.html#selecting-an-email


Template Errors with Include on Single Entry Now I've run into a really odd issue. I've got a hero include that is working elsewhere on the site, but on this one single it's not working at all. On a working "Single" the code is this

{% extends "_layout" %}

{% block content %}

{% include '_includes/hero'
  with {
    imageName : 'page-hero-about',
    className : 'about',
    imageAlt  : 'Photo of store front',
    findStore : false,
    leadCols  : 'col-md-6',
    leadClass : 'lead'
  }
%}

And on the other non-working single the code is this:

{% extends "_layout" %}

{% block content %}

    {#{% set entry = craft.entries.id(72) %} #}

    {% include '_includes/hero'
      with {
          imageName : 'page-hero-mission',
          className : 'mission',
          imageAlt  : 'Teaching people to read',
          findStore : false,
          leadCols  : 'col-md-9',
          leadClass : ''
     }
%}

On the non working page if I don't set the entry id I get a variable "entry" does not exist (though this is not needed on the working single). However once I do set that I get this error Object of class Craft\ElementCriteriaModel could not be converted to string Have googled but can't seem to find anything.  Also the code is pretty much identical so am at a loss

In your current code, the entry variable is actually an instance of ElementCriteriaModel, which is probably the reason you're getting errors.

In order to set entry to an actual EntryModel, you'll need to add a call to first():

{% set entry = craft.entries.id(72).first() %}
...


Is it possible to change the default feed widget settings? Until you can override widgets on per user group basis, does anyone know if it's possible to change the feed settings to not display the Pixel & Tonic feed in the dashboard and either set it to be blank or another feed? Maybe using a config setting?

I have just made a plugin to do a similar thing it duplicates a selected users dashboard see https://github.com/james1238/duplicateuserdashboard


What is the handle of a section’s default entry type? For a section without additional entry types, what would be the handle value of the default entry type output by {{ entry.type }}?

The default entry type created for a Section (all types) gets the same name and handle as the Section itself.

You can change the default entry type's name and/or handle by visiting Settings -> Sections, clicking on "Edit Entry Types" next to the appropriate Section, and finally by clicking the relevant entry type's name.


Video frame for video file in a Rich Text field I am adding a video in a Rich Text field through file button in toolbar. I want to play these video in iframe. How can I do this..?

Or is there anyother option or plugin by which I can upload video which and add in richtext filed anywhere I want and show this in iframe on frontend.

If you want to upload and host the video on your site's server, then I would create a field with an Asset field type and restrict the type to Video. Without further details, it's hard to understand why you'd want to handle it within a Rich Text field.

Since you're hosting the video, you don't need an iframe. Just use the HTML5 <video> tag...

{% for video in entry.FIELDNAME %}
<video width="320" height="240" controls>
<source src="{{ video.getUrl }}" type="video/mp4">
</video>

Your servers will be handling the bandwidth for video delivery though; which is why most people post to YouTube or Vimeo and use the iframe to pass it through. To do that, you'd use the include that Brad mentioned.


How can I loop through all different Product Types in Craft Commerce? I am trying to have a overview page where I want to loop through all available product categories in separate rows. Somehow I was only able to achieve it when I specify the type of the product. That isn't ideal since I want the customer to be able to add new product types which will be displayed in a new row then.

Something like this :

{% set products = craft.commerce.products.type('all').find() %}

{% for 'type #1' in products %}
    ...
{% endfor  %}

{% for 'type #2' in products %}
    ...
{% endfor  %}

etc..

thanks a lot guys

Hoping this is what you are looking to do?

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

  {{ productType.name }}

{% for product in craft.commerce.products.type(productType.handle).find() %}

  {{ product.title }}

{% endfor %}

{% endfor %}


Related Entries Relationships I am building a site where I have users, companies and content.

Currently my users are standard Craft users, and my companies and content are entries within a channel.

I have a field in my content called company name which is an asset field and lets me create a relationship between a piece of content and a company and now I want to create a comaopny page that lists all content "owned" by that company.

I have the below as a starting point which is listing all of my content but any help on what I'd need to do to tweak it so that it only displays content where company name is equal to the entry title (which is the company name)? Hopefully that makes some kind of sense!

Many thanks in advance!

{% set relatedEntries = craft.entries()
    .companyName(':notempty:')
    .all() %}

{% if relatedEntries|length %}

        {% for rel in relatedEntries %}

{{ rel.title }}

        {% endfor %}

{% endif %}

Well, you can do:

{# Get segment 2 from the URL #}
{% set company = craft.app.request.getSegment(2) %}

{# Get content where myCompanyField matches segment 2 #}
{% set entries = craft.entries.section('mySection').myCompanyField(company).all() %}

But I need to know more about the structure of your content.


Event archives with custom date field I'm trying to set up a past events archive. Followed the guide provided by PT: craft cms guide to set up an archive.

The only difference is that I use a custom date field (dateAndTime) and not postDate. The route leads to the correct template.

The issue

When it loads the archives/agenda/2018 template (f. ex.), it displays all 2018 events (grouped by month) but also all 2019 events that where entered in Craft in 2018. This under the correct month, but obviously the wrong year.
When it load the 2019 template, only the 2019 events that where entered in 2019 show up.
I can't figure out where the code is wrong.

Route

url: archives/agenda/year (token)
template: _sections/archives/agenda/index

Nav

{% set firstEntryEver = craft.entries.section('agenda').orderBy('dateAndTime asc').one() %}

    {% for year in now|date('Y') .. firstEntryEver.dateAndTime|date('Y') %}

{{ year }}

    {% endfor %}

Index

{{ year }}

    {% set entriesInYear = craft.entries.section('agenda').limit(null).after(year).before(year+1).all() %}
    {% for month, entries in entriesInYear | group("dateAndTime|date('F')") %}

{{ month }}

            {% for entry in entries %}

{{ entry.getLink() }}

            {% endfor %}

    {% endfor %}

Try this:

{% set entriesInYear = craft.entries
    .section('agenda')
    .limit(null)
    . dateAndTime([
        'and',
        '>=' ~ year,
        '<' ~ (year + 1)
    ])
    .all()
%}

The .before() and .after() methods are convenience methods that hide the complexity of the date query on Craft's postDate field. They don't affect any other custom date fields like your dateAndTime field.

The array for your dateAndTime field condition (in the above example) is more of a Yii Framework query thing where the optional 'and' operator in the first position means all of the following conditions must apply. If omitted, it's assumed to be 'or'.

If you prefer, the array can also be expressed as a string of comma-separated conditions like so:

.dateAndTime('and, >= ' ~ year ~ ', < ' ~ (year + 1))


How do I conditionally set active state in category navigation? Here is the code I am trying to use to set an active state for category navigation:

    {% for category in categories %}

{{ category.title }}

    {% endfor %}

It seems that the conditional can't check against the category.slug output. Is this the case? What would be a better approach?

Any help is appreciated.

You don't need the quotes or braces in twig tags to reference variables.

{% for category in categories %}

{{ category.title }}

{% endfor %}

You could also use ternary operators:

{% for category in categories %}

{{ category.title }}

{% endfor %}


Redactor 2 error 'accessibility-help-label' I made the update for Redactor 2 and I'm getting this error:

VM463:1 Uncaught TypeError: Cannot read property 'accessibility-help-label' of undefined

Can anyone help? I can't find the problem.

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

Take care of using the right translations


Default settings for HTML purifier and how to extend it Is there a default.json file for the html purifier settings in Craft? Now we can configure this I want to extend to include the stripping on non-breaking spaces. However, I don't want to just extend my requirements and not replace the default.

As I understand I would create a new json file in craft/config/htmlpurifier and this file would contain the following;

{
  "AutoFormat.RemoveEmpty.RemoveNbsp": true,
}

Is this all that is required?

Craft won't merge your HTML Purifier config settings with the default ones, but the default ones are pretty simple, so I'd just include them with yours.

{
    "AutoFormat.RemoveEmpty.RemoveNbsp": true,
    "Attr.AllowedFrameTargets": ["_blank"],
    "HTML.AllowedComments": ["pagebreak"]
}


Making Craft\DateTime Object from string in Twig I'm trying to use Craft's native datepicker with a plugin I've made for the admin section.

I've got some code that works;

{% from "_includes/forms" import date %}

Start Date

{{ date({
    id: 'startDate',
    name: 'startDate',
    value: now
}) }}

but I can't seem to get it to work with any other date, no matter what I do.

In my URL I have;

startDate=09/02/2017

and in my twig template I have;

{% set startDate = craft.request.getParam('startDate') %}

What do I need to do to startDate in order to get the date picker to read that date?

Unfortunately, what you're trying to do, is not possible without writing a simple plugin to return a Craft\DateTime object that the day picker can work with.

The global variable now, is a Craft\DateTime object, which the date picker is happy to work with because it can call localeDate() on it.

However, anything returned by date or date_modify twig filters, will be a \DateTime object, which lacks functionality that the date picker relies on.

Your only option would be, to create a simple plugin that can take your date parameter, and return a Craft\DateTime object, which you can pass as a value to the date picker/date macro.

This is one of those things that you think, "this should be easy or at least possible", but I haven't found a twig-only solution yet.


Matrix fields don't load! I have some matrix fields defined:

But when I use the matrix blocks inside of an entry - I don't get all blocks - just the richText ones.
I tested it out - just the richtText Matrix blocks will be loaded when I do:
  {% include "_private/partials/matrix" with {blocks: entry.bodyContent.all()} %}

Is there something I am missing, or is this a bug?
Would be great if someone could help.

Without seeing the code of your template _private/partials/matrix it's not easy to help you.
Maybe you need to check the block type first.
I usually do that with a switch and have a different partial for each block.
So your template _private/partials/matrix could look something like this:
{% for block in blocks %}
  {% switch block.type %}
    {% case "richText" %}
      {% include "_private/partials/richtext" %}
    {% case "quote" %}
      {% include "_private/partials/qoute" %}
    {% case "image" %}
      {% include "_private/partials/image" %}
    {% case "embed" %}
      {% include "_private/partials/embed" %}
    {% default %}
  {% endswitch %}
{% endfor %}

The quote partial could look something like this
{# do something with block.style #}

{{block.quote}}

{{block.attribution}}


Use value of a dropdown field for an `include` I'm trying to have this include be updated by the option I choose in my dropdown.

{% include 'subnav_programs.html' %}

My dropdown is called entry.dropSubsection

I put {% include '{{ entry.dropSubsection }}' %} in my html file but it keeps giving me errors.

I get this error:

  Unable to find the template “{{ entry.dropSubsection }}”.

You don't need to (more specifically, you can't) nest Twig tags within other Twig tags. Ditch the inner Twig tag and its respective quotes, and just pass the variable directly into the outer Twig tag...

{% include entry.dropSubsection %}

That being said, I'm not sure this will achieve exactly what you're looking for. You may need to append .value as well...

{% include entry.dropSubsection.value %}


Is there a way to set a new property on an entry In a plugin I am creating I want to add a property to some entries.

Ideally this property would be hidden from the admin user, as I don't want them to edit it.

At the moment I am trying to do something like this (simplified):

$criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'dogs';
$entries = $criteria->find();

foreach ($entries as $entry) {
    $entry->secretName = urlencode($entry->title);
    craft()->entries->saveEntry($entry);
endforeach;

But this produces the error 'Property "Craft\EntryModel.secretName" is not defined.'

Does anyone know how to do what I am trying to do? Is there a way to set a new property to just this section?

You need to create the field in the CMS, however you don't need to assign it to any section. It should still be available to your plugin and twig templates.

The other reason your code will result in an error is because $entry->secretName is in fact being processed by the BaseElementModel magic getter method, so is the same as writing $entry->getFieldValue('secretName'), which obviously cannot be set to a new value.

The proper way to do this is using the setContent method as follows:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'dogs';
$entries = $criteria->find();

foreach ($entries as $entry) {
    $entry->setContent(array(
        'secretName' => urlencode($entry->title)
    ));
    craft()->entries->saveEntry($entry);
endforeach;

See this answer for a more thorough explanation on setting entry content.


Paginate entries when I do not have a criteria model? I have to...

merge results from multiple different criteria models
use Supersort to order my entries in the desired sort order
[...]

...and need to paginate them for my index page. As the paginate tag doesn't work with arrays of element models, is there any other solution to get this working?

This is in no means an elegant solution, and can almost certainly be improved. But it did its job just fine.

{% set veterinarians = craft.entries({
    section: 'veterinarians',
    order: 'premiumVet desc, postDate desc',
}) %}

{# more filter/search params #}

{% set entriesPerPage = 20 %}
{% set page = craft.request.getParam('page') %}
{% set page = page ?: 1 %}
{% set offsetParam = (page - 1) * entriesPerPage %}

{% set veterinarians = veterinarians.offset(offsetParam).limit(entriesPerPage) %}

{% set isNextPage = veterinarians.offset(page * entriesPerPage).limit(1)|length %}
{% set queryString = craft.request.getQueryStringWithoutPath()|replace('/page=\\d+&?/') %}
{% set queryString = queryString ? '&' ~ queryString %}
{% set nextUrl = isNextPage ? craft.request.url ~ '?page=' ~ (page + 1) ~ queryString %}

{% for entry in veterinarians %}
    {# loop entries #}
{% endfor %}

{% if nextUrl %}

        Weitere anzeigen

{% endif %}


Trying to replace an asset via replaceFile action in entry form UPDATE: We've resolved this one. Here is the working code:

<form method="post" enctype="multipart/form-data" action="" accept-charset="UTF-8">
  <input type="hidden" name="entryId" value="{{ entry.id }}">
  <input type="hidden" name="action" value="entries/saveEntry">
  <input type="hidden" name="sectionId" value="2">
  <input type="hidden" name="enabled" value="1">

  <input type="file"
         name="replaceFile-{{ asset.id }}”
         class="replace-file"
         data-id="{{ asset.id }}" />

...and...

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(".replace-file").change(function() {
  var url = '/actions/assets/replaceFile',
      fileId = $(this).attr("data-id"),
      file = $("[name=replaceFile-"+fileId+"]")[0].files[0],
      formdata = new FormData();

  formdata.append("replaceFile", file);
  formdata.append("fileId", fileId);

  $("#output").html("Uploading...");

  $.ajax({
    url: url,
    type: 'POST',
    data:  formdata,
    cache: false,
    contentType: false,
    processData: false,
    success: function(data) {
      $("#output").html("Supposedly worked...");
    }
  });
});
</script>

In short, you have the right idea, but you're not uploading any files with that JavaScript. All you're doing is sending a file id to a Craft action that expects an uploaded file as well.

You can find an insight on how to change your javascript to include file data as well here


User query in PHP does not work I would like to get user query in my custom PHP plugin.

According to this document, the code would be like this.
https://docs.craftcms.com/v3/dev/element-queries/user-queries.html#example

$queryAllUsers_email = User::find()->email($new_email);
if (count($queryAllUsers_email) > 0) {
    // ...
}

User means Craft\Elements\User class.

However, the count is 0.

It would be grateful for me if you tell me what is wrong.

Try this:

$queryAllUsers_email = User::find()
    ->email($new_email)
    ->anyStatus()
    ->all();

It's likely the email address you're searching for is for a user that isn't activated yet or suspended, etc.

Using anyStatus will search for the user regardless of their status.


What's the easiest way to generate a link to edit a given entry in Craft? Assuming I am fetching an entry like so:

{% set profile = craft.entries.id(8268).one %}

What is the easiest way to generate a link that allows you to edit that entry in Craft? I know you can do the following:

{{ siteUrl ~ 'admin/entries/profiles/' ~ profile.id }}

But surely there must be a better way?

profile.cpEditUrl is what you're looking for.


How do I wire my form action to my controller action? I'm writing my first Craft CMS plugin.

I have the following tag in my form:

<input type="hidden" name="action" value="clientnameDonation/donateForm/donate">

And then I have the following controller code to handle the action:

namespace Craft;

class ClientnameDonation_DonateFormController extends BaseController
{
    protected $allowAnonymous = array('actionDonate',
        );

    public function actionDonate()
    {
        // stuff
    }
}

When I try to submit the form, I get the following error:

  Unable to resolve the request "clientnameDonation/donateForm/donate"

Is there a piece I'm missing, or is there a casing error somewhere?

I also tried just using a raw action URL like this:

  http://URL/index.php?p=actions/clientnameDonation/donateForm/donate

I get the same routing error.

I had the plugin set up correctly but I didn't go into the administration menu and install the plugin via the GUI.


What are the consequences of choosing structures over channels? I want to build an international directory of fishing port centres in Craft. Each port will have the same custom fields and be geocoded.

The documentation here just doesn't make clear the ramifications of choosing channels versus structures. I get the ordering of structures which makes me think structures is the right approach. But do we lose out in search/RSS/templating down the line or are all entries equal in terms of there later usage?

All entries are equal. The only differences between Structures and Channels are that Structures are manually sortable and can be nested under other entries. Channels sort by Post Date by default. Unless you are doing a stream of entries (like blog posts or events), structures are a good way to go.


Installation Fails on Live Website I have installed Craft 2.2.2579 on my never-before-used website live rather than on my PC in a development environment. (I am not a developer.) Instructions were followed exactly (I believe), but when I point my browser to http://{mySiteName}/admin or the other alternatives, I get:

The index page of the website itself loads just fine as http://{mySiteName}.

Any ideas?

Open up this file:

/craft/config/db.php

... and take a look at the very first line. The file should start with this:

<?php

It sounds like that may not be the case with your file. Make sure there is absolutely nothing before that < character, not even a blank line.


Twig template not extending Folks:

I am having issue getting Twig to extend the template. The details:

Craft installed fine.
This is on a live server.
The default Craft welcome page appears as normal so Twig must be
working.
When I try to pull up an entry with one of my own templates, Twig does
not pull the content from the main Twig template. You should see the
header info and have the css pulled and all the rest. If I strip
everything out the template and leave some plain text I still see
this in the browser:

{ % extends "_layouttest" % } { % block main % } This is the correct template alright! { % endblock % }

I have done the following:

Checked that I am not pulling the template directly. I am not. This
is a proper URL for an entry I created in Craft.
Dumped the cache.
Checked the template locations from within the CP. All seems to be
pointing in the correct direction. The fact that the right template
is being pulled confirms this.
Read through this thread and this one. No joy.

Any assistance would be appreciated.

You have a space between the { and % in your twig tags. That needs to be removed. :)


Trying to list entries related to users with a specific category selected This is a category page. I am trying to display all entries from users with this specific category selected in their account (user field that is a category field type.) This is the code I have so far, but it is not returning results. No errors - just not returning anything unfortunately:

{{ category.title }}

{# Grab all the users who have this category selected (which is a 'category field type' user field) #}
{% set categoryUsers = craft.users.relatedTo(category).limit(null) %}

{# Grab all of the entries by those users #}
{% set categoryUserEntries = craft.entries.section('jobs').relatedTo(categoryUsers).limit(null) %}

{% paginate categoryUserEntries.limit(8) as entries %}

     {% for entry in entries %}

{{ entry.title }}

     {% endfor %}

     {% if paginate.prevUrl %}&laquo; Previous Page{% endif %}
     {% if paginate.nextUrl %}Next Page &raquo;{% endif %}

{% endpaginate %}

Thanks in advance!

I think I worked this out. It looks like the related entries need to be contained in the user loop. This is what I used to make this work:

{% set categoryUsers = craft.users.relatedTo(category) %}
    {% paginate categoryUsers.limit(1) as entries %}

        {% for categoryUser in entries %}
            {{ categoryUser.username }}

            {% set categoryEntry = craft.entries.section('jobs').authorId(categoryUser.id).first() %}
                {% if categoryEntry %}
                    {{ categoryEntry.positionTitle }} (And other fields not added yet.)
                {% endif %}

Testing the total found: {{ categoryUsers|length }}

        {% endfor %}

    {% if paginate.prevUrl %}&laquo; Previous Page{% endif %}
    {% if paginate.nextUrl %}Next Page &raquo;{% endif %}

    {% endpaginate %}

Still testing, but I think this is the solution. (Unless someone else has a better way of doing this. :))


Delete entries from database I believe I made a mistake by creating about 15,000 entries in a Structure section. It has caused a lot of problems and so I decided to start again with a Channel section instead. I tried deleting the old section to remove the entries but it crashes mysql. Does anyone know a way to remove entries and their content in the database?

I think I did this successfully with help from another answer on here. I removed the data from the craft_elements table by using the fieldLayoutId column to identify the entry type I wanted to remove. Seems it removed the data from the other tables as well.


Comments being overwritten on save I am trying to save comments using the core method "entries/saveEntry", but every time I submit the form the last comment is overwritten, is there a simple way of submitting this information to insert instead of update all the comments?

I the form working in that it relates a comment to an entry using the following form:

<form method="post" accept-charset="UTF-8">
    <input type="hidden" name="action" value="entries/saveEntry">
    {{ getCsrfInput() }}
    <input type="hidden" name="entryId" value="{{ entry.id }}">
    <input type="hidden" name="fields[usercomments][new1][type]" value="comments">
    <input type="text" name="fields[usercomments][new1][fields][commentuser]" value="">
    <input type="text" name="fields[usercomments][new1][fields][commenttext]" value="">
    <input type="submit" value="Publish">
</form>

I just dont get why the comments are being overwritten and how to just insert a new entry.

You'll have to resubmit all the previous comments through hidden fields aswell. You can achieve this by looping through them in the form, and put their values into hidden inputs.


Error reporting Freeform submission jumps to top of page When submitting a form with required fields and getting an error, the page jumps to the top, where it should jump to the top of the form.

In the standard Craft contact form I can add

<form method="post" action="#errortag">

To define a div or name anchor where the page should go to. How can I do this in freeform (without having to go completely manual)

Right now I'm using the standard tags:

{{ craft.freeform.form("proefles", {
    instructionsBelowField: true,
}).render() }}

By setting the action: "#errortag" seems to stop the form submitting if there are no errors.

So instead I have added the following code and this seems to work;

{% if form.hasErrors %}
{% includejs %}
$(document).ready(function () {
    $('html, body').animate({
        scrollTop: $('#formErrors').offset().top-110
    }, 1000);
});
{% endincludejs %}
{% endif %}


Search by close match I'm looking for a way to get search results, even if people make typos, so apple as a result when looking for aple. Not fuzzy search, but some implementation of, for example, a Levenshtein function. I know I could go the Algolia way and that there's even a plugin for that, but before I pay Algolia for it, I would like to know:

Is there an easy/quick way to do this without using an external service?
If so, would you be willing to share your thoughts on the subject?

Is there an easy/quick way to do this without using an external service?

Nothing easy I can think of.

For Craft 2 (which only supports MySQL), Craft turns those search queries into a MySQL query that can take advantage of MySQL's Full Text Search indexes on the craft_searchindex table, using full text wildcards as necessary for fuzzy searching the beginning and ending of a string.

It looks like the closest thing that MySQL has that might do what you're looking for is SOUNDEX(), but 1) Craft doesn't use that and 2) it doesn't appear that SOUNDEX can be used against full text indexes.

Keep in mind (just like Search Plus) any solution you find is only going to affect front-end searches (not in the CP).

You should add a thumbs-up/comment to this feature request if you'd like to see that change: https://github.com/craftcms/cms/issues/833


Using Shortlist plugin to create product wishlist I'd like to use the Shortlist plugin to allow visitors to create product wishlists - using Craft Commerce.

Currently, I have setup the 'add to wishlist' function, but I am not sure how to then display the items that a user has add to their wishlist.

The code below, is the example given on the plugin docs for how to loop through the items a user has added, but this does not produce the required results for commerce products.

{% if shortlistLists is empty %}
You have no lists at the moment.
{% else %}
    {% for list in lists %}

{{ list.title }}

    {% if list.items is empty %}
    No items in this list
    {% else %}

        {% for item in list.items %}

{{ item.title }} (Remove)

        {% endfor %}

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

The docs for the plugin are available here - https://squarebit.co.uk/software/craft/shortlist/usage/quickstart

If anyone could point me in the right direction as to how to successfully use the plugin in conjunction with Craft Commerce, that would be much appreciated.

You can definitely use Shortlist for this.  Here's some code to get you started.  Note in this I allow the favouriting of both products and pages/articles.

Code to let user add the favourites -

    {% set item = craft.shortlist.item(id) %}

And to display the favourites/wishlist - first we prepare by separating products from regular elements:

        {# Prepare the output data #}
        {% set lists = craft.shortlist.lists %}
        {% set favouriteArticleIDs = [] %}
        {% set favouriteProductIDs = [] %}

        {% if lists|length %}
            {# We just store everything in one list... #}
            {% for list in lists %}
                {% for item in list.items %}
                    {% set favId = item.elementId %}
                    {% if item.element.elementType == 'Commerce_Product' %}
                        {% set favouriteProductIDs = favouriteProductIDs|merge([favId]) %}
                    {% else %}
                        {% set favouriteArticleIDs = favouriteArticleIDs|merge([favId]) %}
                    {% endif %}
                 {% endfor %}
            {% endfor %}
        {% endif %}

...then to actually fetch & display the results we do this:

            {% if not favouriteProductIDs|length %}

                No favourite products?  Why not add some?

            {% else %}

                {% set products = craft.commerce.products.id(favouriteProductIDs).order('title').with('variants') %}

                {% import "_macros/productPreviewsLib" as productPreviewsLib %}

                {{
                    productPreviewsLib.productPreviews(products,
                    {
                        'display' : 'Table',
                        'showUnavailables' : true,
                    })
                }}

            {% endif %}

(The macro just does {% for product in products %} etc)

That should get you started!


How can I concatenate 2 variables to access array values? I am using this SO post to try to concatenate two variables in twig.

I am very close, but can't seem to get over the hump of rendering the correct syntax.

This is what I am currently using:

 {% for user in plugin.data.users %}
     ...
     {{ attribute(user, 'foo' ~ loop.index0)|raw|nl2br.bar }}
     ...
 {% endfor %}

This is what I am currently getting back:

Key "foo0"... for array with keys "...does not exist."

What I am trying to create is foo[0], foo[1] etc.

Well, I couldn't figure it out so this is how I did it. If there is a better way, I'd be happy to update the post.

{% set i = 0 %}
    {{ user.foo[i].bar }}
    ...
{% set i = i + 1 %}

I think you need to try and access the array that user.foo would have.
So your code would be something like:

 {% for user in plugin.data.users %}
  ...
  {{ attribute(user.foo, loop.index0)|raw|nl2br }}
  ...
 {% endfor %}

I haven't tested this though, just going by what I'm sure I remember doing once...