Multiple conditions in an if statement? Is it not possible to define multiple conditions in an if statement?

{% if foo == 'x' || foo == 'y' %}

I tried this and got an error:

  Unexpected token "punctuation" of value "|" ("name" expected)

Twig doesn't accept || or &&... Try using or and and instead.

{% if foo == 'x' or foo == 'y' %}

Important to note, they must be lowercase.

You may also want to take a look at this question, which shows another way to write a similar condition:

{% if foo in ['x', 'y'] %}


Using auto-generated titles against entry field type values How would you setup a section's entry type to auto-generate the titles based on the title (or slug) of another entry?

For example, we have a Software section with entries. We also have a Releases section. Each release entry has a related software entry, along with a versionNumber text field.

Ideally each release's title would be of the form :

{software.title} {versionNumber}

Where {software.title} is the title from associated entry.

We've looked at all sorts of combinations to get that value out, but any usage seems to either be ignored or throw an error on publish.

You can access the Software entry’s title exactly the same way you would in your front-end templates: software.first.title. The only difference is the single-brace tags syntax, which you don’t even have to use if you don’t want to. Both of these are identical:

{software.first.title}
{{ object.software.first.title }}


Is there a way to calculate the dominant color from an asset available in Craft? Given an image uploaded to Craft, I am wondering if there is a plug-in or a native method to detect the dominant color of said image.

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


Apply shipping without the shipping screen Folks:

All the products in the store I am working have only one shipping method (ground). It seems redundant to have people go through the shipping screen since there is only one shipping option. Is there a way to just apply the default shipping for the product(s) based on the address they enter rather than going through the shipping screen?

You can automatically set the shipping method on a cart (e.g. by an ajax call) at any point by POSTing to commerce/cart/updateCart - You just use an input with name shippingMethod and and the value you supply is the handle of your shipping method, e.g. `ground'.

Where you do this is entirely up to you, but note depending how you handle/implement this, changes in the cart contents & addresses can invalidate shipping methods, so you'd typically do this at some point after your cart index page...


Start matrix loop from block ID Is it possible to start a matrix loop from a particular block ID?

I am trying to set a new block called "New Page" so that an author can split an article into multiple pages.

Currently it's able to detect a page break and exit out of the block field loop. I have also identified the next block's ID.

{% set nextBlockAfterPageBreak = contentBlock.getNext().id %}

Now what I'd like to be able to do is to get all blocks from nextBlockAfterPageBreak.

So for example,

{% for contentBlock in matrixField where firstBlock = 237 %}

Does anybody know if this is possible?

offset works for matrix blocks the same way it does for entries.

So you can do this to skip the first 12

{# skip the first 12 blocks #}
{% for contentBlock in matrixField.offset(12) %}
  ...
{% endfor %}


Why am I getting ?p=oldpage in a 301 redirect? Not sure whether this is directly related to Craft but I’ve been using this method for years and it has always worked with other sites.

I’m replacing an old site and some pages have moved. I want to redirect any old pages to the new url since there are already indexed.

I’m using a simple redirect 301
Redirect 301 /work/project-name http://www.mysite.com/case-studies

I’m getting http://www.mysite.com/case-studies/project-name?p=work/project-name and of course a page not found since this is not where I intended the page to go.

Craft works by taking requests that normally would 404—because they don't actually exist on the server but in the database. The piece that makes this happen is the rewrite rules.

It's helpful to look at Craft's .htaccess file line-by-line:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

The request must not already exist and the file is not already an existing directory on the server.

RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]

The URL must not be favicon.ico, apple-touch-icon.whatever.png. The NC at the end means no-case (meaning case-insenstive).

RewriteRule (.+) index.php?p=$1 [QSA,L]

This is the rule that actually fires. Take those would-be 404s, redirect to /index.php (the controller). $1 means the match found in (.+).

The QSA flag means query string append. This is the part that's actually causing you issues. (You could remove it but get URLs with parameters called from controllers might not work in certain situations.)

L means last; if this rule is applied, it won't process anything else. Doesn't matter here unless you have other rules.

What you need to do is tell Apache to exclude this particular request from Craft's processing (put it after the favicon rule):

RewriteCond %{REQUEST_URI} !^/(work/project-name)$ [NC]

Now what will happen is your Redirect 301 rule will fire by itself. Since /case-studies doesn't actually exist on the server,  Apache is going to send that rule back to Craft and fire like any normal "page" which is what you want.

If you have other redirected 301s from the old /work section, you might do something like:

RewriteCond %{REQUEST_URI} !^/(work/.+)$ [NC]

That will let Craft know not to touch any of your 301s in the old work section. You still need your old Redirect 301 rules.  (You could make a RewriteRule for those if you wanted to simply things but this will get you going.)

Your completed file would look like:

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

Redirect 301 /work/project-name http://www.mysite.com/case-studies
...

I find some browsers will "cache"  an old page/redirect for awhile. To confirm it's actually working you might want to use curl -I http://site/work/project-name. If you see "moved permanently" message, you're all set.


Rating like Like/Dislike Hello!
I need a rating like Like/Dislike. That it would be possible to assign likes and sort posts by them. Are there any ready-made solutions?

The Craft Plugin Store is where you'd go to look for existing plugins/solutions for this.
The two I'm aware of that are related are:
https://plugins.craftcms.com/star-ratings
https://plugins.craftcms.com/upvote
Otherwise, you'd probably be looking at some custom plugin development.


How can I use Ajax function in Craft CMS? I want to do an autocomplete search engine on my website. But I don't know how to use Ajax in Craft CMS. How can I set an Ajax function in Craft CMS templating? The search engine must have dynamic auto-complete feature according to title and content.

Since Craft makes no assumptions about the front-end content of your website, it's 100% up to you on how you want to implement AJAX functionality on your site.  So it wouldn't be any different if you were trying to use AJAX on a simple static page with no CMS managing the content.

For example, a popular method is to use jQuery's ajax method.


Plugin not fully registered/enabled I've created my first Craft3 plugin and installed it locally via a composer.json path. After doing the composer require, the plugin showed up as installed (with a green dot) under Admin->Settings->Plugin.

However, the plugin has the following code:

$plugins=Craft::$app->plugins->getAllPluginInfo();
error_log('We have version '.$this->getVersion().' and handle '.$this->getHandle());
$plugin=Craft::$app->plugins->getPlugin($this->getHandle());
if ($plugin==null) {
     error_log('Could not find self');
} else {
     error_log('Fond self with version: '.$plugin->getVersion());
}
/* @var PluginInterface $plugin */
foreach ($plugins as $plugin) {
     error_log(json_encode($plugin));
}

calling any page and then checking storage/logs/phperrors.log shows:

22-Jan-2019 13:18:52 Europe/London] We have version 1.0.0 and handle craft-project-name
[22-Jan-2019 13:18:52 Europe/London] Could not find self
...
[22-Jan-2019 13:18:52 Europe/London] {
"developer":"myname",
"developerUrl":"https:\/\/www.example.com",
"description":"Example plugin",
"documentationUrl":"https:\/\/www.example.com",
"class":"rbairwell\\craftprojectname\\Plugin",
"basePath":"\/Applications\/Dev\/craftcms\/craft-project-name\/src",
"aliases":{"@rbairwell\/craftprojectname":"\/Applications\/Dev\/craftcms\/vendor\/rbairwell\/craft-project-name\/src"},
"name":"Craft Project Name",
"version":"1.0.0",
"sourceLanguage":"en-US",
"hasCpSection":false,
"packageName":"rbairwell\/craft-project-name",
"isInstalled":true,
"isEnabled":false,
"moduleId":"craft-project-name",
"edition":"standard",
"hasMultipleEditions":false,
"hasCpSettings":false,
"licenseKey":null,
"licenseKeyStatus":"unknown",
"licensedEdition":null,
"licenseIssues":[],
"isTrial":false,
"upgradeAvailable":false}
...

Why is the plugin unable to find itself using getPlugin even though it's confirm it's handle name and why, in the list of plugins does it come up isEnabled: false even though the admin front end shows it as installed+enabled and obviously the plugin is functioning?

You seem to have discrepancies in your naming. There is craft-project-name and craftprojectname in there. Could it be that?

Fix the naming and try to delete the plugin row in the database, composer remove it then re install..?


How can I hide entries depending on which category they are associated with? Right now, I have a staff profile page. Each person on the page has a category association (professional, leadership, student). When the students graduate, I want to add an 'alumni' category to their entry, and have them stop showing up on the active page. Right now I have student and alumni associated with the particular entry, and I want to hide all entries with the alumni category. Any idea how to go about this?

{% set leaderGroup = craft.categories.group('staffHierarchy').slug('leadership') %}
{% set leader = craft.entries.section('people').relatedTo(leaderGroup) %}
{% set staffGroup = craft.categories.group('staffHierarchy').slug('student') %}
{% set staff = craft.entries.section('people').relatedTo(staffGroup) %}

The search parameter will help you do this really elegantly.

In the code below I've called the category field categoryField, but you'll have to swap that to suit your site.

{# Get current students (students who aren't also in the alumni category) #}
{% set currentStudents = craft.entries.section('people').search('categoryField:student -categoryField:alumni') %}

{% for student in currentStudents %}
    {# Output your students here #}
{% endfor %}

This is basically asking Craft to respond with the entries that have the categoryField including student but not (indicated by the - before) including alumni.

You could probably also streamline the other bits of your code using this method.

I've tested this as working on Craft 2.5.2757

Hope that helps!


How to get next entry by date in matrix block but limit to just 1 I need to display a block from a matrix for the following week.

Basically the query I need to build is

{% for block in workshop.workshopSession.where(sessionDate > now).first() %}

I just can't quite get this to work and have been searching for a while. Perhaps I am just missing something obvious. There will be more than one entry with a date greater than "now" so I need to limit it to 1.

I think this should do it.

{% for block in workshop.workshopSession.sessionDate('>=' ~ now|date('Y-m-d')).limit(1) %}

If not you always can go with a "dirty" fix by just showing the {% loop.first %}


Form Builder plugin returns 'undefined' when I submit Today I wanted to add a contact form to my webpage, and I chose the Form Builder plugin for its ease of use. So far all went well, and I managed to display the form in the page (not that difficult), but when testing the form I got an undefined error.

As of now I have no idea what is undefined. I checked the code, the fields I use (they are all Form Builder fields, the email and the plain text), and I checked the settings of Form Builder.

Can you guys help me out?

The link to my website: www.evinwijninga.com

The code in the template

{% set form = craft.formBuilder.getFormByHandle('contactForm') %}
{% set tabs = form.fieldLayout.getFieldLayout().getTabs() %}
{% set pluginScripts = craft.formBuilder.pluginScripts(form) %}

How to contact me

    <form method="post" accept-charset="utf-8" name="{{ form.handle }}" class="formbuilder-form grid-60 prefix-20 suffix-20 {{ form.handle }}" id="{{ form.handle }}" data-parsley-errors-container=".formbuilder-notification"{% if form.hasFileUploads %} enctype="multipart/form-data" {% endif %}>
        <input type="hidden" name="action" value="formBuilder/entries/saveFormEntry">
        <input type="hidden" name="formredirect" data-redirect="{{form.successPageRedirect}}" value="{{form.redirectUrl}}">
        <input type="hidden" name="formHandle" value="{{form.handle}}">

        {% for tab in tabs %}
        {% set fields = tab.getFields() %}

        <fieldset class="{{loop.index}}">
            <legend>{{ tab.name }}</legend>
            {% for field in fields %}
            {% set input = craft.formBuilder.getInputHtml(field) %}

{{ input | raw }}

            {% endfor %}
        </fieldset>
        {% endfor %}

        {# Error/Success Messages #}
        {% if craft.session.hasFlash('error') or craft.session.hasFlash('success') %}
        {% if craft.session.hasFlash('error') %}

{{ craft.session.getFlash('error') | raw }}

{% endif %}
        {% if craft.session.hasFlash('success') %}

{{ craft.session.getFlash('success') | raw }}

{% endif %}
        {% else %}

        {% endif %}

        <button type="submit" class="grid-100">Submit Message</button>

    </form>

The fields:

and the settings in Form Builder

This is the latest error entry. The timestamp however is different than the time when I tested the form (which was later):

we ran into the same problem. If you remove "admin" on line 12 of /plugins/formbuilder/resources/js/formbuilder-form.js it works.

url = '/actions/' + $(this).children('[name=action]').attr('value');

We couldn't figure out why the path leads to something which is only accessible with admin-rights.


Is there any way to change the CP navigation item for a plugin? I'm wondering if I can have another name for my Plugin CP navigation item?

Let's say my plugin is called "Company name Social Media" but I want the navigation item to just say "Social Media". Might be a bad example but I think you understand what I mean. Let's say I'll release a commercial Craft plugin w/ my company name in it, but I want the customer to be able to add the plugin for a client without my name visible (more then on the plugins page).

Also is there any way to add dropdown-like sub-navigation items to the CP navigation for a plugin?

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

main plugin file:

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

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

settings template:

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

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


Users are always logged out on front end Users are always logged out on the front end on my Craft website.  Even when logged in as admin I can access the CMS but on the front end user session always returns the following.

Craft\UserSessionService Object
(
    [_identity:Craft\UserSessionService:private] =>
    [_identityCookie:Craft\UserSessionService:private] =>
    [_userModel:Craft\UserSessionService:private] =>
    [_userRow:Craft\UserSessionService:private] =>
    [_sessionRestoredFromCookie:Craft\UserSessionService:private] =>
    [_dontExtendSession:Craft\UserSessionService:private] =>
    [allowAutoLogin] => 1
    [guestName] => Guest
    [loginUrl] => Array
        (
            [0] => /site/login
        )

    [identityCookie] =>
    [authTimeout] => 259200
    [absoluteAuthTimeout] =>
    [autoRenewCookie] => 1
    [autoUpdateFlash] => 1
    [loginRequiredAjaxResponse] =>
    [_keyPrefix:CWebUser:private] => 4e3924125ff89a395a13e8e5580209e2
    [_access:CWebUser:private] => Array
        (
        )

    [behaviors] => Array
        (
        )

    [_initialized:CApplicationComponent:private] => 1
    [_e:CComponent:private] =>
    [_m:CComponent:private] =>
)

Does anyone have any idea why this could be happening?

I tracked down a similar problem, and documented it here: The Case of the Missing PHP Session

I'm not sure if it'll address the issue you're having specifically, but it may give you some clue on where to look.


How to remove Link To Category from Redactor Is there a way to remove the 2 Craft specific menu items from Redactor's Link menu without losing access to the "Insert link" menu item?

Removing the Link button in the redactor configs is too draconian as I don't want to lose access to the basic Insert and Unlink functions previously in that menu.

I've dug into the src, and the only hook/event I can find related to the redactor settings allows addition of menu items to the Links menu, but not removal of the Craft added "Link to an Entry" and "Link to a Category".

I don't think there's an easy way to do this natively in Craft.

Maybe you could pull it off with combination of https://github.com/lindseydiloreto/craft-cpcss and/or https://github.com/lindseydiloreto/craft-cpcjs and manipulate the DOM directly.

Or maybe by going from the Redactor site and listening to their click event.


Global Image Variables? I have setup a global set for images i use across the site. I have one for seo - where I have images for a twitter card and Facebook image in my seo settings. There is only one image for each field ( so hoping to avoid using the array syntax )

Two questions:

I am not sure how to access the images uploaded into this global variable. My global set has a handle "seo" and the image's handle is "twittercard". This isn't working :

meta(name='twitter:image:', content='{{ image.getUrl('seo.twittercard') }}')
Is this the most efficient way to store images used globally across the site? ( via global image variables?)

seo.twittercard is an ElementCriteriaModel. To access the actual asset, you need to use seo.twittercard.first (or equivalently: seo.twittercard.first()).

However, you should always check that this exists before referencing it:

{% if seo.twittercard|length %}
  <meta(name='twitter:image:', content='{{ seo.twittercard.first.getUrl() }}')>
{% endif %}

And yes, this is a fine way to store images used globally across the site.


RequirePermission not working I'm using the requirePermission tag in the templates for my Craft multisite. I only want users who have access to 'edit' that site be able to view it.

My code is:

{% requirePermission('editSite: (currentSite.id)') %}

It works fine when logged in as admin, however it returns a 403 for every other user, regardless of their permissions. Please help!

I'm aware I can use requireLogin but I want users to have access to some sites and not others

You want:

{% requirePermission("editSite:#{currentSite.id}") %}

The way you have it now, the permission it's checking is the literal string editSite: (currentSite.id) which no one will have permission for.

Edit:

Craft 3.1 doesn't store IDs anymore for permissions, instead it uses always the uids because of the project config. This is a breaking change for many existing projects so keep that in mind.

{% requirePermission("editSite:#{currentSite.uid}") %}

c.f.: Twig string interpolation


Undefined property when using cacheMethod = db What can the issue be here? I have no clue.

Config settings are like this:

'cacheMethod'           => "db",
'cacheDuration'         => 'P2M', /*2 months*/

Undefined property: Craft\WebApp::$db

/var/www/www_cmgg_cmgg_be/craft/app/services/CacheService.php(46)

34         switch (craft()->config->get('cacheMethod'))
35         {
36             case CacheMethod::APC:
37             {
38                 $this->_cacheComponent = new ApcCache();
39                 break;
40             }
41
42             case CacheMethod::Db:
43             {
44                 $this->_cacheComponent = new DbCache();
45                 $this->_cacheComponent->gCProbability = craft()->config->get('gcProbability', ConfigFile::DbCache);
46                 $this->_cacheComponent->cacheTableName = craft()->db->getNormalizedTablePrefix().craft()->config->get('cacheTableName', ConfigFile::DbCache);
47                 $this->_cacheComponent->autoCreateCacheTable = true;
48                 break;
49             }
50
51             case CacheMethod::EAccelerator:
52             {
53                 $this->_cacheComponent = new EAcceleratorCache();
54                 break;
55             }
56
57             case CacheMethod::File:
58             {

Solved. The client was using something called Samba Share on their server and that didn't work well with permissions. They changed servers and it was solved.


Freeform AJAX submission not working when two forms are on same page I have two Mailchimp subscribe forms on the same page – one in the sidebar and one in the footer. They are created as separate forms in the admin, albeit one a duplicate of the other, with different IDs on the forms and different IDs on the Mailchimp field. "Enable AJAX" is selected on both forms.

When I submit the first form from the sidebar, it submits successfully but reloads the page (No AJAX). The second form works correctly, submitting via AJAX.

Is this a known limitation of Freeform Pro or simply a matter of a duplicate ID or class that I'm missing somewhere? I'd like to have AJAX work on both.

Im running into the same issue. In my case they are completely different forms but both with "Enable AJAX" set to true. Could not find anything in the docs either.

This is the error I am seeing. I think I have it narrowed down to the honey pot field not being unique per form. Removing the honey pot setting, fixes the issue.

[DOM] Found 2 elements with non-unique id #freeform_form_handle:


Upgraded to Craft 3 and lost my Commerce Gateways I upgraded to Craft 3 and I went to my payment gateways and I have the old ones in there with no details such as keys. And my only gateway options are Dummy and Manual. I know there were changes such as .commerce being deprecated in some instances, so was this another change that I missed?  Do I have to buy a plugin for Commerce or make my own now?

Commerce 2 moved all payment gateways to plugins.  You can see the relevant bit in the docs here: https://docs.craftcms.com/commerce/v2/payment-gateways.html

There are currently seven 1st party plugins that add payment gateways and the two most popular, Stripe and PayPal are free.  You can see the table for the remaining in the above link.  All of these are currently in the Plugin Store. 3rd parties can additionally write plugins that work with other payment gateways.


Install Craft 3 on Web Server I scoured the the web to the ends of earth and couldn't find any info on how to install Craft 3 on my VPS. The package I downloaded is unconventional in many ways. Any ideas how to get Craft running?

By the way, why can't Craft 3 be installed like Wordpress?

Here's a tutorial on setting up your first Craft CMS 3 project. I'm a little sad that it didn't come up in any Google searches :(

Setting up a New Craft CMS 3 Project


Get children of specific parent This one seems deceptively simple, but I am struggling.  My home page is a single, and in that template I want to retrieve the children of a specific entry in a structure, then loop through them.  Here is a code example that does not work:

{% set entries = craft.entries.id(4).children %}
{% for entry in entries %}
    do something
{% endfor %}

This returns the page with id 4 instead of its children.

I also tried something like:

{% set entries = craft.entries.section('pages').descendantsOf('targetpage') %}

Maybe I need to retrieve the entire section and do a conditional loop for entries where the parent entry ID is 4, but the proper syntax for that eludes me.

Could someone please point me in the right direction?  Thanks!

You need to get the parent entry model before requesting its children with the getChildren method. craft.entries.id(4) only creates a criteria model prepared to query for entries matching your criteria. You now have to use the first method to query for an entry model.

{% set parent = craft.entries.id(4).first() %}

{# Check if it indead returned an entry model, could also return nothing #}
{% if parent %}
    {% set children = parent.children %}
{% endif %}


Structure Nav: Output "Section" Title on both Landing and Decedents Hi all… I have a Structure organized like this:

Arts

Journals

Submissions

Books

Sciences

Journals

Submissions

Books

…etc.

In my template, I want to grab the "Section" (e.g. Arts, Sciences) that I'm in and output it at the top of the page, both on the main page and subpages.

For decedents I can do that using:

    {% set currentSubject = entry.getAncestors().level(1) %}
    {% for entry in currentSubject %}
    {{ entry.title }}
    {% endfor %}

But if I'm on the main page (e.g. Arts, Sciences) itself getAncestors won't help. Is there a smart conditional that will give me the title of the top level page regardless of if I'm on it or a descendent of it?

For some reason, I find myself hoping this can be done without looking at segments, but maybe that's the best route for this kind of thing?

You can test for the entry's level property. Something like the following.

{% if entry.level == 1 %}

{{ entry.title }}

{% else %}

{{ entry.ancestors.first.title }}

{% endif %}


Auto add Images to entry after ftp to server I have a potential client (car dealership) where in their existing 12 year old site they daily upload an Excel file to add/update/delete vehicles in stock. One file for new vehicles and one for used.

However the excel file does not have a column for images and they are unwilling/unable to add one. Instead they want images to be added in the same way they currently are.

All images are ftp'd up to the server and are named ##_stocknumber so 01_12345, 02_12345, 03_12345 would be attached to the same entry but 01_4455, 02_4455, 03_4455, 04_4455 would be attached to a different entry. After upload the go to a link that processes the images and then emails any stock numbers that are missing images.

Is there some way that this can be achieved in Craft?

Since it sounds like you are using a third-party plugin for the initial import, you'll need a new plugin to handle the ftp uploads.
This new plugin would need to perform the following:

Basic control panel page, or Controller action for firing off the processing
Get the list of new images files from the FTP directory
For each file:

Parse the file name to get the associated vehicle stocknumber
Query your vehicle entries based on the stock
Use the Assets Service  (https://craftcms.com/classreference/services/AssetsService) to
create and store the asset appropriately
Save the associated asset to the Vehicle Entry

At the end of the run, archive/remove the original uploaded files
Email the list of stocknumbers you have image files for but not existing entries (using EmailService)

To further optimize the process/queries you could query all vehicles first and pull them out of an array by the stocknumber (instead of querying the DB each file).

If you wanted to automate the process you could even build a task-listener to fire off your image-association plugin when it sees new images have been FTP'd to the vehicle image upload directory.


Building an accordion with a Matrix field I'm trying to build an accordion in my matrix field (that also holds entries for a slideshow, button, image, etc).

Im having trouble with getting each entry to go inside

 and not repeat this accordion div over and over.

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

      {% for block in entry.sectionaccordion %}

{{ block.accordionTitle }}

          {{ block.accordionText }}

      {% endfor %}

With this setup, I keep getting Craft\EntryModel and its behaviors do not have a method or closure named "sectionaccordion".

The error has to do with the line {% for block in entry.sectionaccordion %} because it's looking for a field in your entry called sectionaccordion but sectionaccordion is not a field; it's a block inside a field (your matrix field).  So the error is basically saying "there is no field called 'sectionaccordion' for this entry".

You also don't want to use a for loop here because there's nothing to loop through.  You're already looping through matrix blocks created in this matrix field, and your code is saying "if the block is of type sectionaccordion, print the contents of it."  The contents of that block won't be another loop; it'll only be 1 Accordion Title and 1 Accordion Text field.

Lastly, by saying {% elseif block.type == "sectionaccordion" %}, you are eliminating the chance to display a slideshow since that is a different block type, one not called sectionaccordion.  If you want a slideshow inside your accordion block type, then you need to create a 3rd field for it inside sectionaccordion and just recreate whatever you did in the sectionslideshow block type.


How can I have more than one product on the same page? Using Craft Commerce, I would like to offer more than one product on my _entry template.

For example, let's say I am selling a wagon. I have a drop down of variants for color:

Choose Color

<select name="purchasableId" class="form-control">
    {% for purchasable in product.variants %}
        <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %} value="{{ purchasable.purchasableId }}">
        {{ purchasable.wagon.label }} &ndash; {{ purchasable.price|currency(cart.currency) }}
        </option>
    {% endfor %}
</select>

Now I would also like to offer a warranty. There could be different prices for different plans (variants) as well:

Choose Warranty

<select name="purchasableId" class="form-control">
    {% for purchasable in product.variants %}
        <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %} value="{{ purchasable.purchasableId }}">
        {{ purchasable.warranty.label }} &ndash; {{ purchasable.price|currency(cart.currency) }}
        </option>
    {% endfor %}
</select>

EDIT

Each "Warranty" is it's own section and has it's own product type within Commerce.
You could purchase a warranty by visiting mysite.com/warranties/my-warranty or mysite.com/wagons.

An example might look like mysite.com/warranties/basic. That page would have information about the "basic" warranty along with the option to add to cart.

In theory, you could purchase a warranty without purchasing a wagon.

I also want to (somehow) allow the user to purchase a warranty when they purchase a wagon. That's not to say I must do it this way, I am open to ideas. Currently both products are available together.

EDIT 2

Here is what my current form looks like on my product page. Is there a naming convention I should follow to pass multiple  options to the updateCart method? If I make both fields have the name of purchasableId, as expected, the system just grabs the last element. In my case it's the warranty product.

Since I would like to make the warranty a required field, maybe I need to restructure how I am selling wagons? I don't want to add to the variant list of my wagon product, that would get out of hand quickly.

Or, perhaps it's just a "Related Products" title and a link to the warranties page?

<form method="post" action="" accept-charset="utf-8">
<fieldset>
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="redirect" value="commerce/cart">
    <input type="hidden" name="qty" value="1">
    {{ getCsrfInput() }}
</fieldset>

<fieldset>
    Choose Color
    <select name="purchasableId" class="form-control">
        {% for purchasable in product.variants %}
            <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %} value="{{ purchasable.purchasableId }}">
            {{ purchasable.title }} &ndash; {{ purchasable.price|currency(cart.currency) }}
        </option>
    {% endfor %}
    </select>
</fieldset>

<fieldset>
    {% set warranties = product.warrantyOptions %}  {# This is the products field #}
    Choose Warranty
    <select name="warrantyId" class="form-control">
        {% for warranty in warranties %}
            {% for purchasable in warranty.variants %}
                <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %}
                value="{{ purchasable.purchasableId }}">
               {{ purchasable.title }} &ndash; {{ purchasable.price|currency(cart.currency) }}
               </option>
           {% endfor %}
       {% endfor %}
    </select>
</fieldset>

Currently only one purchasableId can be added to the cart in a single form action. To get around this limitation you would need to use ajax to send multiple http requests (to add both items) OR use a plugin like MultiAdd: https://github.com/engram-design/MultiAdd


Pagination base URL - any way to have pagination links go to URLs other than current one? TL;DR: Looking for something like paginate_base parameter in EE, but for Craft.

My site's homepage has content in tabs for different sections (news, products, etc.) and in each tab I would like to have pagination links that would go to 2nd, 3rd, etc page in each section.

So in News tab I display news entries and would like to link to /news/p2, /news/p3 etc, on Products tab I would have links to /products/p2, /products/p3 etc. All that on same page, with URL different from /news or /products

Is there any way to achieve that in Craft?

Not tested, but I would assume that you could simply get the total entries, divide by the pagination limit and then generate your dynamic nav using a range loop.

{% set totalEntries = craft.entries.section('news').limit(null).total() %}
{% set pageLimit = 10 %}
{% set totalPages = (totalEntries / pageLimit)|round(0, 'ceil') %}

    {% for i in range(1, totalPages) %}

    {% endfor %}


How to search for a specific field using getCriteria()? I'm looking at making a plugin and need to search news entries.
I can use:

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

However, I want to add a criteria where I search a specific field, for example: fieldabc = 'zyx'

What is the correct syntax for this?

Thanks!

As per the (new) "Working with Elements" guide from the docs, it works the same as from your templates.

  The actual list of available parameters depends on the element type. They are identical to the parameters available to your templates.

So this template example:

{% craft.entries.section('news').myPlaintextField('xyz').myLightswitchField(1) %}

Works from your plugin like so:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section            = 'news';
$criteria->myPlaintextField   = 'xyz';
$criteria->myLightswitchField = 1;

Using custom field parameters is a fast and reliable solution if you are looking for EXACT matches. I would only use the search parameter if there's no other solution.


Nesting block tags doesnt work I have pagination twig component that needs to inject seo links into  of page (rel canonical).

I tried to use {% block %} twig tag for this, but problem is that pagination component is already included in another {% block %} tag containing main content of page.

In short, im trying to do this:

layout.twig:

<html>
<head>
{% block seo %}{% endblock %}
</head>
<body>
{% block main %}{% endblock %}
</body>
</html>

page.twig:

{% extends 'layout.twig' %}

{% block main %}

some content..
{% include 'pagination.twig' %}

{% endblock %}

pagination.twig:

... pagination links

{% block seo %}
<link href="url" rel="canonical">
{% endblock %}

When im using this code, block seo is empty.
Can this be achived some other way?

Unfortunately it’s not possible for an included template to override the contents of a block in the parent template, or its layout.

You’d need to just override the seo block from page.twig do whatever you need to do from there instead.

{% extends 'layout.twig' %}

{% block main %}
  some content..
  {% include 'pagination.twig' %}
{% endblock %}

{% block seo %}
  <link href="url" rel="canonical">
{% endblock %}


Plugin development : from ExpressionEngine to Craft Coming to Craft after years with EE, I feel like a newbie again.

I painfully managed to built and install a basic plugin for craft3 with composer, (with a little help from the docs and NYstudio107's tutorial).

For now, the plugin does nothing, and to keep going, I would need to understand how to translate a pattern commonly used in EE.
Get some data from a template, process it and return it.

Get tag data and parameters

$data_to_process = ee()->TMPL->tagdata;
$process_param = ee()->TMPL->fetch_param('parameter');

Output content to template

ee()->return_data = $processed_data;

Ho do you do such things in craft ?

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

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

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

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

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

 'plugin-handle/path/to/template'


Update Asset Index in Migration I'm trying to index some asset volumes that I'm creating in a migration. These are local volumes which may already contain files.

I'm hoping to avoid the step where I have to manually update the asset indices after creating volumes.

The following code does not seem to perform the index, am I missing a step? I've studied the controller used by Utilities but I can't see where I'm going wrong.

    $volumeId = Craft::$app->volumes->getVolumeByHandle('myVolume')->id;

    $indexer = Craft::$app->getAssetIndexer();

    $sessionId = $indexer->getIndexingSessionid();

    $indexer->processIndexForVolume($sessionId,$volumeId);

Any help is much appreciated

As of 3.1.2 you can now index assets via the cli tool:

./craft index-assets/all

OR

./craft index-assets/one {handle}


Use Matrix to let client add Bootstrap Accordian Items I'm creating a careers page on a site I'm working on and the design is for the jobs to go in an accordian that will slide open on click. So I'm thinking that this would need to be a matrix block as the client will need to be able to add as many jobs to the accordian as they want.

The site is built with bootstrap, so I'm using the bootstrap accordian to build it. And for it to work each accordian item needs to have a unique ID, i.e. id="collapseOne" which links to href with the same name in the button in order to get it to expand and close. Here's an example of the code for one accordian line:

          Senior Construction Planner

    ..variable content..

So I need to work out a way to get this to work as a matrix field so that the client can add as many jobs as they need in Craft, and for it to function correctly as an accordian.

Is it possible?

Yes, you can make use of the matrix loop index to create unique ID's.

          Senior Construction Planner

    ..variable content..


How to handle search results that point to a page of aggregated entries? I have a few pages in my site that aggregate information, for example, a single awards page that gets all the entries in an awards channel. Single awards entries don't have their own URLs.

How do I handle cases like this in search results?

I guess I'll answer my own question. Use a conditional in search results and overwrite the value of the entry's URL:

{% if getSection() == 'mySection' %}
  {% set entry.url = '/mySectionUrl' %}
{% endif %}


How to calculate half, third, fourth? I'm trying to calculate some image sizes for Imager.

This works:

{% set imageSizes = [{ height: imageHeight * 4}, { height: imageHeight * 3}, { height: imageHeight * 2}, { height: imageHeight}] %}

But how do i get halfs?

imageHeight * 2.5, imageHeight * 0.5 or imageHeight / 2 does not work.

Edit:
It was my own fault.
I checked the array and only saw width's. I set the images sizes in the CP and to:

{% if imageHeight is not empty %}
  {% set imageSizes = [{ height: imageHeight * 4}... %}
{% else %}
  {% set imageSizes = [{ width: imageWidth * 4}... %}
{% endif %}

I only wrote the half calculation in "if imageHeight" for testing. But the entry i use for testing has only width's...

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

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


How to set and test a variable in child template to modify a block in parent template I would like to load some javascript on specific pages only.

I'm trying to set a block in my parent template, then test a variable and include the javascript in the child template only when necessary.

I thought I could do this by declaring the variable beforehand, to make it  accessible outside it's scope, but this is not working (nothing is returned):

Parent '_layout' template:

<html>
    <head>...</head>
    <body>

        {% block content %}
        {% endblock %}

        ...

        {# site-wide script #}
        <script src="global.js"></script>

        {# page-specific script #}
        {% block script %}
        {% endblock %}

    </body>
</html>

Child template:

{% extends "_layout" %}

{% set page_assets = '' %}

{% block content %}
...
{% set page_assets = 'true' %}
...
{% endblock %}

{% block script %}
    {% if page_assets is defined and page_assets is not empty %}
      <script src="page-specific.js"></script>
    {% endif %}
{% endblock %}

Nope, that's not going to work unfortunately, due to the way scoping works in Twig. Check out the explanation in the Twig Processing Order & Scope article


Manually creating Security Key gives PHP error I'm going on 5 days of banging my head on my desk here.

I'm simply not getting how to install it on my production server. I have Craft working beautifully locally...but getting it to my server is a whole other matter.

So I have ssh'd into my VPS, then run 'wget 'https://craftcms.com/latest-v3.zip'' and unzipped it to try and get it running as just a barebones install. So now I'm going through the install instructions, and am running into an error when running the './craft setup/security-key' step:

PHP Warning:  Module 'Phar' already loaded in Unknown on line 0

Craft requires PHP 7.0 or later.

I created a phpinfo file and it's returning PHP Version 7.0.30.

Any ideas why I'm getting this error?

Thanks in advance.

Well then. Apparently my shell user was using a different version of php than my domain. I was still at 5.6 on my shell user. I was all sorts of confused because I had a phpinfo.php file setup at my domain showing PHP 7.0, and in the web hosting domain panel, I had 7.0 chosen. Finally wrote to support and they sent directions on how to change it. Once I updated that, the security key was created just fine.


How to create menu in backend using Craft 3 How to create menus from admin panel of Craft 3 so I can render into frontend header and footer?

For Craft 2, a number of plugins exist that assist with building navigational structures. None of those has been made available for Craft 3 (yet), but one plugin-less option (thanks to Ben Parizek, who let me in on this) would be, to create a 'navigation' section (structure), in which you can create navigation entries (= navigation items) that you can than drag and drop to get the right navigational structure.

Each entry in this section has, for example:

A field that connects it to another entry
A field that let's the user add a url to navigate to
Any other field that would let the user alter the navigation's behaviour (color, open in new window, etc)

After that, it would be up to you to translate this structure to a navigation in your template(s).


What is the correct way to format a module controller action URL? Consider the following Craft 3 example module structure:
modules/
    businesslogic/
        controllers/ExampleController.php
        BusinessLogic.php

...and consider the following action in ExampleController.php:
public function actionExampleRoute()
{
    die('in example-route action');
}

Assuming everything is set up and configured correctly, is this the correct URL for triggering the action in ExampleController.php?
http://my-craft-site/business-logic/example/example-route

If so, this is not working for me; it instead results in a 404/Template not found error. I'm not sure if I misunderstand how to determine the correct URL or if I set up something incorrectly.
I am working with the example provided here and I believe I have followed the instructions correctly. The instructions include a simple test of the module, and the test succeeds--I'm just not able to get the controller action to work as expected.

It depends on the module handle you chose in config/app.php (the module handle is the key affected to your module in the modules array).
If you want the URL to be /business-logic/example/example-route, the module key must be business-logic:
use modules\businesslogic\BusinessLogic;

return [
    'modules' => [
        'business-logic' => BusinessLogic::class,
    ],
    'bootstrap' => [
        'business-logic',
    ]
];


Issue with Matrix `type` property and Live Preview? I have problems getting Live Preview to work with this Twig code that gets data from a Matrix field.

{{ entry.matrixField.type('copy').nth(0).plainText }}

As soon as I remove the type property from the criteria model, it does update on entry changes again!

Live preview have gone through a major refactoring for Craft 3.2, which addresses this issue. For Craft 3.1 and below see solutions below.

This is happening because Matrix will only show the non-live blocks so long as you don’t set any Matrix parameters in your template. As soon as you tell it to only show blocks of a certain type, it no longer feels confident that the blocks it was going to output are the right ones, so it will dump them and run a new DB query.

One possible way around this would be to do this:

Craft 2:

{% if craft.request.isLivePreview %}
    {% set firstCopyBlock = null %}
    {% for block in entry.matrixField %}
        {% if firstCopyBlock == null and block.type.handle == 'copy' %}
            {% set firstCopyBlock = block %}
        {% endif %}
    {% endfor %}
{% else %}
    {% set firstCopyBlock = entry.matrixField.type('copy').first() %}
{% endif %}

{% if firstCopyBlock %}
    {{ firstCopyBlock.plainText }}
{% endif %}

Craft 3:

{% if craft.app.request.isLivePreview %}
    {% set firstCopyBlock = null %}
    {% for block in entry.matrixField.all() %}
        {% if firstCopyBlock == null and block.type.handle == 'copy' %}
            {% set firstCopyBlock = block %}
        {% endif %}
    {% endfor %}
{% else %}
    {% set firstCopyBlock = entry.matrixField.type('copy').one() %}
{% endif %}

{% if firstCopyBlock %}
    {{ firstCopyBlock.plainText }}
{% endif %}


How do I have my control panel in English but my site locale to Dutch? I prefer my cp in English but I've noticed that it also sets the locale to "en_us" for the entire site. I need that locale to be "nl" since the site is in Dutch. Any idea how to achieve this?

This solutions works for any locale, even if you don't have it installed as a front-end locale.
It also works for Personal or Client Craft installs.

Add a translations file into craft/translations/xx.php named after the currently selected user locale or system locale for
Craft Personal installs and use this code to include any locale's translations you want. You can also customize it
further by overwriting select translations:

<?php
namespace Craft;

if (craft()->request->isCpRequest())
{
    $en = (include '../craft/app/translations/en.php');
    $custom = array(
        'Globals' => 'I freak out!',
    );

    return array_merge($en, $custom);
}

return [];


Show Category Title only where an entry has been included in an Entries field I have a Category Group with an Entries field assigned so the admin can select which existing Entries should fall within a given category.  An Entry can be assigned to multiple categories.

On the Entry page I want to be able to loop through the categories and only list those where the entry has been included.

There are six categories vs 20 or 30 entries so doing it the other way (assigning a category to the entry) would be cumbersome for end user editing if a new category is added.

I hope that makes sense?

You just need to check if it's related to the current entry. entry is the entry you're displaying.

{% for category in craft.categories().group('someGroup').relatedTo(entry).all() %}
    {{ category.title }}
{% endfor %}


404 in HTTP Header on working site I have a Craft site which seems to function properly but I see a 404 in the header http status code. I’ve located the following in the error logs:

2016/07/28 15:22:30 [error] [exception.Craft\HttpException.404] exception 'Craft\HttpException' in   /var/www/touchtunesmedia.com/craft/app/controllers/Templat$
Stack trace:
#0 [internal function]: Craft\TemplatesController->actionRender('home', Array)
#1 /var/www/touchtunesmedia.com/craft/app/framework/web/actions/CAction.php(109): ReflectionMethod->invokeArgs(Object(Craft\TemplatesController), Array)
#2 /var/www/touchtunesmedia.com/craft/app/framework/web/actions/CInlineAction.php(47): CAction->runWithParamsInternal(Object(Craft\TemplatesController), Obje$
#3 /var/www/touchtunesmedia.com/craft/app/framework/web/CController.php(308): CInlineAction->runWithParams(Array)
#4 /var/www/touchtunesmedia.com/craft/app/framework/web/CController.php(286): CController->runAction(Object(CInlineAction))
#5 /var/www/touchtunesmedia.com/craft/app/framework/web/CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
#6 /var/www/touchtunesmedia.com/craft/app/framework/web/CWebApplication.php(282): CController->run('render')
#7 /var/www/touchtunesmedia.com/craft/app/framework/web/CWebApplication.php(141): CWebApplication->runController('templates/rende...')
#8 /var/www/touchtunesmedia.com/craft/app/etc/web/WebApp.php(288): CWebApplication->processRequest()
#9 /var/www/touchtunesmedia.com/craft/app/framework/base/CApplication.php(185): Craft\WebApp->processRequest()
#10 /var/www/touchtunesmedia.com/craft/app/index.php(62): CApplication->run()
#11 /var/www/touchtunesmedia.com/public/index.php(19): require_once('/var/www/toucht...')
#12 {main}
REQUEST_URI=/

I have a home partial which is rendering fine so I’m having a hard time diagnosing where the error may be stemming from. Additionally everything returns a 200 status code in my network profiler other than the request for the document.

If I change the public dir’s index.php to echo test there is no 404 in the header status code. If I change my main layout template to a basic html file with nothing in it I get a 404 in the status code.

I resolved this by adding a new 'home' template which extends my main layout. This resolved the 404 in the header status code.


How to point a static url to a file I have a field "menu card" in my globals' section "menuCard", so I could access my file in the template with menuCard.menuCard.first().url. That is fine, but when the editor changes the menu-card file and it has a different name, the url will be different:

first week:
menu-card-17-10-01.pdf

next week:
menu-card-17-10-08.pdf

As it is a menu-card for a restaurant which gets changed every week it would be awesome to always have the current menu-card pdf available through the same url/slug like myrestaurant.com/menu and also reference the menu within my templates with /menu;

Is there a way to do so in craftcms? For example an alias which points to my global field menuCard.menuCard.first() or something like that?

Thx

You could setup a template at /menu that grabs the PDF you want and redirects with a 302 (not a 301 since it isn't permanent).

The URL would change, but that might be ok if you only care about having an easy link to share.

If redirecting is a deal breaker, you could make a small plugin that returns the file with proper headings, then call that from the /menu template.


Live preview + share button missing when switching to PRO licence At first, I thought the latest update was the problem, but apparently, by buying a license and switching to PRO, the buttons disappeared. Is there a magic trick to get them running again?

I've seen something similar happen. I don't know the cause of it, but the solution in the 2 cases I know of each has the same fix. What happened was that for some reason, the "preview targets" got wiped out. In my case, this was during an update to the database. In another person's case that I know of, I think an upgrade was involved.

From within the control panel, go to "Settings -> Sections" then click the name of the section that is missing the preview buttons. Look at the bottom of the page and see what it says in the "Preview Targets" area. It should look something like this screenshot. If it doesn't add a new row and fill it in like the image shows.


Can the Lightswitch field have a default 'on' setting? I'm creating a new lightswitch field and adding it to an entry type in a section which already has dozens of entries. I want the lightswitch to be default set to 'on'.

When I save the entry type with the lightswitch field added to a tab, then inspect an entry in that section, the new lightswitch field is set to 'off'. Is this a bug?

For entries previously created, the lightswitch field will not be on even if you specified that as a field option. However, new entries should respect that field setting.

Are new entries not honoring your field settings?


Event when an entry is enabled I've been looking for an event that get triggered when an entry is moved from a disabled to enabled status.

Currently I'm trying to find it through the EVENT_AFTER_SAVE_ELEMENT event but I have no idea what the previous status of the entry was so I can't tell if it was just updated:

current

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event)
    {
        $element = $event->element;

        // Get the status, but I don't know the previous status.
        $status = $element->status;
    }
);

I also had this pointed out to me https://docs.craftcms.com/api/v3/craft-events-setstatusevent.html but I don't know what emits this event as a parameter.

Well, that's awkward.

The SetStatusEvent was removed way back in the Craft 3.0 launch, but the class itself was never removed (will fix that for the upcoming 3.4 launch).

There isn't really a clean replacement for it.

One way would be to listen to the EVENT_BEFORE_SAVE_ELEMENT event, run a separate database query to get the current status from the database and compare the status to the element that was passed in to see if it changed.

3.4 will give you another option - you could listen to EVENT_AFTER_SAVE_ELEMENT, then check the dirtyAttributes array to see if the status has changed, since elements now keep track of what attributes have changed on a given request.


Issue with storing an Entry I am trying to store an entry in a plugin. The entry has a field 'tags' that relates to another entry. I am trying to store it with the following code.

$newsItem = new EntryModel();
$newsItem->sectionId = craft()->sections->getSectionByHandle('news')->id;
$newsItem->getContent()->tags = $tag->id;
craft()->entries->saveEntry($newsItem);

When I var_dump(craft()->entries->saveEntry($newsItem)) I get a false response.

Also, in this situation we cannot use the method setContentFromPost() so we need to do it from within the plugin and not from a front-end form.

Not sure if there is more to your code or not but looks like you need to set the title as well as other required fields. In addition the entries field is expecting an array of entryIds.

Here is a link to the saveEntry method in the EntriesService, which shows the required fields:
https://craftcms.com/classreference/services/EntriesService#saveEntry-detail

This answer is somewhat similar in that they are relating an entry, but you can see that the entryField is being set with an array.

How do I relate a user to a channel entry from a form?


Slow initial response time when website has been idle? I noticed my Craft website is slower to load when it has been idle for awhile. It can take up to 3-4 seconds for the first load, and then it goes down to about 500ms (which is fine) after the first page. I'm also using cache so I could get my query count to about 20-30 per page. I have other websites (non Craft) on the server that are fast to load even when they have been idle for awhile. Any idea what's causing this?

You mention you're using cache, which could mean a whole lot of things, but the symptoms you're describing are typical of what you'd see if you're doing some heavy-handed things inside of a {% cache %}, you let that expire, then you're the first person to hit the page when the cache has to rebuild.

That {% cache %} tag, by default, will purge its cache every 24 hours unless you've specified otherwise.


Display postdate Spout Forms entries I'm trying to display the postDate of Sprout Forms entries. The docs state that you can use standard Craft CMS tags. I tried:

{% for formEntry in craft.sproutForms.entries.formHandle('contact').order(asc) %}
   {{ formEntry.postDate|date('d F Y') }}
{% endfor %}

And all kind of variations but the system states no method or closure with the name "postDate". All other fields output fine.

Found the answer in the database. Apparently Sprout Forms uses the date field named "dateCreated". Also getting it in order by date (newest first) needs 'dateCreated desc'

{% for formEntry in craft.sproutForms.entries.formHandle('contact').order('dateCreated desc') %}
   {{ formEntry.dateCreated|date('d F Y') }}
{% endfor %}


Protect a page with a single password? Is it possible to protect a page with a single password? Instead of using crafts user features, can I allow an admin to set a specific password from the edit page? When a user visits that page, they have to type in that password to view its content.

We aren't protecting anything that requires a high level of security. But we would like to prohibit access from any old visitor.

One possibility I'm considering is to have a password text field associated with that entry. Then when the user submit the login form, we can do a simple logic check to see if the password is valid. If so, we can set a “logged-in” status to either a PHP session or a cookie.

https://github.com/lewisjenkins/craft-lj-cookies

https://github.com/stuartalexwhitehead/remember

I wonder if anyone else in the Craft community has tried to implement something like this.

I've actually done this a couple of times... a very simple "password-only" page. Then there would be a large group of people who share that same password, and can gain access to that protected page.

  Disclaimer: This example was built using the Business Logic plugin template.

There are many ways to manage your password, but it sounds like you'll want something as simple as a Global field. Create a Global field for your password, and keep track of the Global Set ID and the field handle (you'll need that info in a minute).

On your secure page, you'll want something like this:

{% if craft.businessLogic.accessGranted %}

{% else %}

Enter your access code:

    {% if error is defined %}

{{ error }}

    {% endif %}
    <form method="post" action="" accept-charset="UTF-8">
        <input type="hidden" name="action" value="businessLogic/authorize">
        <input type="text" name="pw" value="">
        <input type="submit" value="Log In">
    </form>

{% endif %}

Upon submitting that form, your plugin's Controller will authenticate the user, and set a cookie to remember the user.

Something like this for your plugin's Controller:

<?php
namespace Craft;

class BusinessLogicController extends BaseController
{
    protected $allowAnonymous = true;

    // Login authorization action
    public function actionAuthorize()
    {
        // Get password
        $pwSubmitted = craft()->request->getPost('pw');

        // Check access
        if ($this->_validPassword($pwSubmitted)) {

            // Set access cookie
            $expires = time() + (60*60*24*7); // One week
            setcookie(md5('cookieNameToBeHashed'), 1, $expires, '/');

            // Redirect
            $this->redirect(craft()->request->getPath());

        } else {

            // Output error message
            craft()->urlManager->setRouteVariables(array(
                'error' => 'Invalid access code'
            ));

        }

    }

    // Check if password is valid
    private function _validPassword($pwSubmitted)
    {
        // Get global set
        $globalSet = craft()->globals->getSetById(156);

        // Get target password
        $pwTarget = $globalSet->passwordFieldhandle;

        // Return whether password matches
        return ($pwSubmitted === $pwTarget);
    }

}

Your plugin's Variable can check if the user is already authorized.

Something like this for your plugin's Variable:

<?php
namespace Craft;

class BusinessLogicVariable
{

    // Check if access cookie is set
    public function accessGranted()
    {
        $cookieName = md5('cookieNameToBeHashed');
        return array_key_exists($cookieName, $_COOKIE);
    }

}

Which of course, brings it full circle. Your secure page will check if accessGranted before showing either the secure content, or the login form.


How can I validate that I am passing an Asset into my custom twig filter? I'm creating a custom twig filter in Craft 3 and am struggling with a really simple thing.

{{ entry.backgroundImage.one() | filter }}

In my filter, I would like to validate that I am being passed an asset.

if (!$asset instanceof Asset)
{
    return false;
}

What should I be checking the object against? Asset or something different?

Actually, you had your code just right imo:

use craft\elements\Asset;

...

if (!$asset instanceof Asset) {
    return false;
}


Creating new assets subfolder throws error right click on source > add new subfolder > dialog box asks for subfolder name > submit = "There was an error while creating the folder."

Any ideas here?

Two possible suggestions:

Are you positive that the File System Path of your assets source is correct?
Does your assets source folder have the correct permissions which would allow Craft to create a new subfolder?


Reducing memory usage? I have a relatively simple task which is exposing an issue with efficiency. In that it isn't very efficient and the server cries and quits. Here's the high level overview:

There's a category called "Locations". There are 791 locations.
Users have three Category Fields; First Choice, Second Choice, Third Choice. The pick one location in each field. There are 1809 Users.

I need to generate a report that shows how popular each location is (how many Users chose [LOCATION] as their 1st, 2nd, and 3rd choice). A nice simple table that's 4 cells wide and 791 rows deep.

I keep running out of memory and execution time regardless of how high I take each limit. I've tried it in Twig and I've tried it in PHP as a plugin.

My strategy, via creating a Service and a Variable... :

{% set locations = craft.categories.group('locations').limit(null) %}
{% set users     = craft.users.group('members').limit(null) %}

{{ craft.reporting.locationPopularity(locations,users) }}

The ReportsService.php file:

public function locationPopularity($locations = null, $users = null) {
    $response = "";

    foreach($locations as $location) {
        $firstChoiceCount = 0;
        $secondChoiceCount = 0;
        $thirdChoiceCount = 0;

        foreach($users as $user) {
            if($user->firstChoiceLocation->last() == $location){ $firstChoiceCount += 1; }
            if($user->secondChoiceLocation->last() == $location){ $secondChoiceCount += 1; }
            if($user->thirdChoiceLocation->last() == $location){ $thirdChoiceCount += 1; }
        }

        $response = $response . "

$location->title

First Choice: $firstChoiceCount, Second Choice: $secondChoiceCount, Third Choice: $thirdChoiceCount.
";
    }

    return $response;
}

How do I get this to work? 1,430,919 loop iterations seems to be a no go.

The following works, but 2400+ queries...

{% for location in craft.categories.group('locations').limit(null).find() %}
    {% set firstChoiceCount = craft.users.relatedTo({
        element: location,
        field: 'firstChoiceLocation'
    }).limit(null).count() %}

    {% set secondChoiceCount = craft.users.relatedTo({
        element: location,
        field: 'secondChoiceLocation'
    }).limit(null).count() %}

    {% set thirdChoiceCount = craft.users.relatedTo({
        element: location,
        field: 'thirdChoiceLocation'
    }).limit(null).count() %}

    ... output ...
{% endfor %}

First of all ->last() will always produce 2 queries, one fetches the total amount of results, the other one fetches the result with the offset given by the first query -> you can reduce the amount of queries by using first() if there is only one choice.

Furthermore: I would make use of eager loading so you don't even fetch the fields again and again (like currently)

{% set users = craft
    .users
    .group('members')
    .limit(null)
    .with([
        'firstChoiceLocation',
        'secondChoiceLocation',
        'thirdChoiceLocation'
    ])
    .find()
%}

Besides that - if you don't execute your $users query Craft might fetch the results again and again in certain circumstances so you don't have an array of elements but a query that is fired every single time

In the end I would highly suggest to not loop each user again and again, instead fetch the number of related users for each category via custom Query.
You can just count relations.targetId from the relations table where the sourceIds are your category ids and loop the result within PHP. I could show it for Craft 3 but I didn't use Craft 2 syntax for over a year


Guest Entries plugin - set parent entry if using section As the title suggests, is it possible to pass an entry ID in order to set a parent for the submitted entry?

The Guest Entries plugin checks for a parentId value in POST and passes that on to saveElement, so that should be all you need to do: https://github.com/craftcms/guest-entries/blob/v2/src/controllers/SaveController.php#L216


Is there a way to change prices Is it possible to reduce and increase prices on all products at one time by a specified amount or percentage without having to manually do every product. That must be visible to the customer and not just run as a promotion as this doesn't appear to display the cheaper price on the product tile.

Yes simply add a sale with no product conditions which will apply to all products.


Craft Personal for portfolio site Can I use the free version of Craft for a portfolio site?  I know the free version of ee is for personal/non-profit sites only.

Thanks

As long as the features are sufficient, you can use it for whatever you want. :)


Specifying administrators for localized sites? From what I've gleaned from other q&a, it's possible to set up multiple localized sites under one installation of Craft, but can you assign separate administrators to each? I'd like to set up multiple sites under one domain for a company with several global offices, but each office needs to have control over only their site's content— and ideally some admins could have access to more than one. Possible?

Yes. you can:

Here I created a User group which has only access to the english part of the content.
As you can see these are checkboxes. So you can grant access to multiple languages at once.


Checking if related entries are live in a for loop and setting a variable based on the results So I have a section called children and these are related to various other entries include users.
I am fetching all the children for the currentUser like so and eager-loading all the other relationships.
{% set childrenQuery = craft.entries
  .section('children')
  .relatedTo({
  sourceElement: currentUser,
  field: 'relatedChildren'
})
  .with([
  'associatedTerm',
  'tuitionClass',
  'tuitionClass.location'
]) %}

{% set children = childrenQuery.all() %}

What I then want to do is split out children in to 'Active' and 'Inactive' depending on if the related field associatedTerm is live.
I can do this fine like this;
Children (active)

  {% for child in children if child.associatedTerm|length %}

{{ child.firstName }} {{ child.surname }}

{{ child.tuitionClass[0] }}

{{ child.associatedTerm[0] }}

{{ child.tuitionClass[0].location[0] }}

  {% endfor %}

Children Inactive ()

    {% for child in children if not child.associatedTerm|length %}

{{ child.firstName }} {{ child.surname }}

    {% endfor %}

However, what I want to do is actually do this logic first, so I can then wrap the active/inactive blocks into if statements, if there are in fact any active or inactive children as I have other code (headings and text) I want to show within the block and not appear at all if they are no entries.
So I am stuck on how to do this {% for child in children if not child.associatedTerm|length %} without a for loop and just check if there are any entries that exist.
I can achieve it like this; but it feels a little weird.
{% set childrenAreInactive = '' %}
{% for child in children if not child.associatedTerm|length %}
  {% set childrenAreInactive = 1 %}
{% endfor %}

Anyone have any ideas for a better method?

You're looking for the filter filter: https://docs.craftcms.com/v3/dev/filters.html#filter
Specifically something like this (untested):
{% set activeChildren = children|filter(child => child.associatedTerm|length) %}
{% set inactiveChildren = children|filter(child => child.associatedTerm|length == 0) %}

You now have two unique arrays to do with as you please:
{% if activeChildren|length %}

You have active children

{% endif %}

Hi there

Whenever you get the sneaky feeling that a loop is overkill, look to map filter and reduce: these 3 methods are all like loops in disguise, in that they iterate through arrays and return something new based on the logic you supply.


Accessing the Element API JSON I installed the Element API plugin and the elementapi.php file within the craft/config/ folder is set up just like the example on Github. I'm also trying to use this with a section called "news" like the example. However, when I try to access news.json I get a 404. Am I missing something? Do I need to call something in my templates to make that feed available?

That plugin doesnt append any file extensions to the routes. Try either changing the route in elementapi.php to news.json or try to visit http://yoursite.dev/news


Why Does Manual Cache Clear Work But CP Task Fails? I've been having a problem with my site not properly clearing out its template caches. The task list gets stuck on "Pending" when trying to execute the "Deleting stale template caches" task.

If I manually clear the caches by going to Utilities -> Clear Caches, that works fine and it unblocks the pending task list.

I thought maybe the problem was that my PHP memory_limit was too low, but if that were the case wouldn't the manual cache clear command also cause a timeout error?

My memory_limit is already pretty high at 512M so I'm hoping there's an alternative solution to this that won't require me to remove my cache tags.

It's a fairly common problem: https://craftcms.com/guides/resolving-stalled-background-tasks


Can Section access be restricted at Entry Type level? I have a structure section that is driving the majority of a site, which works great with multiple entry types letting us handle different needs across different areas of the site.

The client now wants a new user group that can only access pages in one particular area of the site. as user group access is tied to sections without granular control of entry types within each section, that means we need a wholesale refactor of the way the site is built and managed, which is going to be a real headache at this point.

Does anybody have any approaches for this?

When you mention new user group, is that a new group of admins/back end users or just people browsing on the front end?

If it's on the front end, just checking the logged in user's group in twig against a new restricted entry type could give you want you want.

{% if entry.type == "restrictedEntryType" and currentUser and currentUser.isInGroup('newUserGroup') %}

   {# let them through #}
   {% include "whatever/restricted_content.html" %}

{% else %}

Thou shall not pass! You need to log in to see this content.

{%endif%}

If it's the back end, like you said, you'd have to do a serious refactor to manage it properly. Put all the restricted content in one structure and only give access to admins/users you want to have edit the content.  You may end up doing that anyway just to keep everything sane, depending on how siphoned off your content is.

To move a structure from one section to another, check out Brandon Kelly's canonical answer.


Passing variant info We have products with multiple variants (varHeight). The variant information get passed to the cart successfully and order emails. However, they don't show up on the control panel. How can I get the variant information to show up on the order?

Product page

<select name="purchasableId">
<option value="">Select Height</option>
{% for purchasable in product.variants %}
<option {% if purchasable.stock <= 0 and purchasable.hasUnlimitedStock == false %}disabled {% endif %}
value="{{ purchasable.id }}">{{ purchasable.varHeight }} - {{ purchasable.price|commerceCurrency(cart.currency) }}</option>
  {% endfor %}
</select>

Cart page:

  {% if item.purchasable.product.type.hasVariants %}
      {% switch item.purchasable.product.type %}
        {% case "wallpaper" %}
            {{ item.description }}

            Height: {{ item.purchasable.varHeight }}
    {% endswitch %}
    {% else %}
        {#  Non variant purchasable  #}
        {{ item.description }}
    {% endif %}

So if you have a variant attribute that is really a determining part of what the SKU actually is, you should probably consider use a dynamic title to build the variant title.

You can do this in the Product Type settings for that product type.  You do this by specifying a twig mini-template - here's an example:

There is also a twig mini template option for the variant's description to be built dynamically, and this is in fact what is shown for the line item in the order details in the control panel.  Here's another example:

This surfaces the information quite nicely:

In this case - the left side of the hyphen is the product's title, and to the right is the variant's title, which has been build dynamically from the paperSize attribute of the variant.


Best practise to use translate in admin panel I am using a lot of translation with the |t / |translate filter. But the client wants to be able to edit those translations in the admin panel.

So, I thought about different ways to achieve that. Please drop your opinion.

Create a new filter, refering to a table under the globals in admin panel. Never did that, but should be possible, right?
Try to get and edit the translation arrays in the phps in the translation folder (dont know how thats possible)
Don't use the |t filter at all. Instead maybe a matrix field type with 2  fields: one not translateable with the origin language and one translatable text field that is translateable. Disadvantage: instead of the convinient |filter I have write code to get the right translation. Also: what about performance?

You could try if the Translate plugin for Craft CMS could help you out. You can use this plugin as a base for you own and save the values in a custom table and use the registerTranslateSources hook to return the values from your table

That would be some kind of mix between options 1 and option 2. Both are totally possible. I created such a plugin for my company too. Collect all uses of |t and check if there is a language fallback in the plugin translation file or if there is one in the default Craft translation file. If not you can mark the word as "untranslated" if yes save the record as translated. In your cp you'll display all your records with the hint if they are translated or not


How can I select users that are not members of any user groups? I'm struggling to find a way to use craft.users to select all users that are not members of any groups. Looking at the User Element Type both the groupId and group parameters are used to perform additional queries which will return nothing unless a valid group Id or handle is provided... I think.

Is it possible to find users not in groups or will I have to do this post retrieving all users... I need to paginate the results so this is not ideal.

You could get the IDs of all users belonging to a group, and use these IDs prefixed with not as the id parameter in a second craft.users ElementCriteriaModel:

{% set userIds = craft.users.group('group1, group2, group3').ids() %}
{% set users = craft.users.id('and, not ' ~ userIds|join(', not ')) %}


Is there a way to speed up the CMS on UNIX server? Just finished my first Craft CMS project. There have been some first hiccups but so far I've been really impressed!

There's one thing that I can't wrap my head around. It's a quite a massive website. This client wanted to be able to create different stories per project (loving the matrix here!!!) which got pretty large.

They're full of images and stuff but still the website is loading very quick. The only thing that feels slow (on and off) is the CMS itself. When looking at the different entries sometimes the system hangs and that's pure when looking at the overview of all the entries. Switching to a different entry type overview (page to structure for example) also feels sluggish.

Any tips how to speed things up? The site itself is perfect, it's just the CMS itself.

The server is running PHP 7.0 but has 128M. Not sure if upgrading it will give a performance boost to the CMS?

First of, check your web server error log wether or not php is dying because of memory exhaustion.

Second, working with many Craft objects/models tend to be slow, you can speed this up by using { cache } blocks cleverly, but be wary that using them wrong can severely impact your performance in a negative way.
Check this blog post for some insight into the topic: https://nystudio107.com/blog/the-craft-cache-tag-in-depth

Third, the biggest improvement you can implement is caching before the application server (php), some alternatives are fastcgi cache (if using nginx), varnish, saas solutions like fastly/keycdn and probably many other I don't know about.

Implementing caching can be a big job depending on the site and should be thoroughly tested.

Fourth, you can add some sort of APM or tracer to investigate what part(s) of your solution is using the most time.

You don't mention the timings of your site, could you elaborate a bit about how slow it is?

In my experience it is hard to get a craft2 site with a lot of content down under 500ms ttfb without heavy caching, but ymmw.


Using FeedMe 2.x with a custom authentication mechanism I have a Craft 2 project which is using an older version of the FeedMe plugin 1.x. In order to use a specific XML feed this site uses, a custom XML feed service was implemented with a custom feed type available to select from the feed type option in Craft FeedMe back-end, but this involved directly editing the FeedMe plugin files.

The reason for this is because a specific authentication mechanism is required before being able to interact with the feed in the form of a unique token passed by the Authorization HTTP header obtained from a separate auth endpoint first. This is then added to the feed request via curl, so its authenticated and returns data.

The current implementation added an additional service within feedme/services/ which extends FeedMe_FeedXMLService to handle the token authorisation part and added an additional enum type, record type, model type. In theory could a separate plugin be created that provides the service without having to modify the core plugin? Or could the approach be different given the changes with the 2.x version of the plugin?

It looks v2.x has changed quite a bit looking at the core plugin files with potentially more options for customisation, but I'm not sure if the implementation we have is possible to move to 2.x easily.

So, here's what I've found after after some research. It is certainly possible to create your own datatypes. Support for it, looks to have been added since around 2.0.1. Previously, the feed type field wasn't able to have custom types as it was a fixed list, but with hooks it is now possible. There is a great plugin that shows how to add custom data types here:

https://github.com/surprisehighway/craft-feedmehelper

You do need a Pro license to use custom data types however.

Unfortunately, the documentation for data types is currently TBA on Verbb's website: https://verbb.io/craft-plugins/feed-me/docs/developers/data-types, so this is going off looking through the code of both the helper plugin and FeedMe itself. Hopefully that will be added at some point.

The way to add your own data/feed type is to call the registerFeedMeDataTypes() function in a plugin, register the datatype:

public function registerFeedMeDataTypes()
{
    return array(
        new MyCustomFeedMeDataType(),
    );
}

You'd import the MyCustomFeedMeDataType class, with Craft::import in the plugin init() function

Then in your datatype class:

<?php
namespace Craft;

class MyCustomFeedMeDataType extends BaseFeedMeDataType
{
   // Custom data type stuff here
}

The datatype should then appear in the feed type dropdown within the FeedMe feeds section in Craft for selection. By default it will use part of the class name for the field label/value, you can also set a specific name, according to this pull request:

https://github.com/verbb/feed-me/pull/172

Quick and reasonably simple in the end, but certainly provides better custom integration options for my project now!

Hope this helps other Craft CMS folk!


EntryModel::populateModels throws a 500 error I am retrieving a data set with about 5000 records and I am using the EntryModel::populateModels($results) to populate the model, this is causing a 500 error. When I limit the number of records returned to 100, it is working fine but when i set the limit to null it throws the error.

There isnt any error logged in the logs, and nor can it be a timeout because it only takes about 5 secs to return the error.

There's probably an error in craft/storage/runtime/logs/phperrors.log and there's a 99% chance the problem is you're hitting your php.ini file's memory_limit setting.

Populating 5,000 models is going to take a significant amount of memory.


Call to Undefined Method ::init Error I'm getting this error when trying to call my plugin on a template:

  Fatal error: Call to undefined method Craft\SiteUtilitiesService::init() in /path/to/my/site/craft/app/framework/base/CModule.php on line 394

The template tag:

{{ craft.siteUtilities.videoEmbed( block.video, '219181' ) }}

Content of variables/SiteUtilitiesVariable.php:

class SiteUtilitiesVariable
{
    public function videoEmbed($url, $color)
    {
        return craft()->siteUtilities->videoEmbed($url, $color);
    }
}

Content of services/SiteUtilitiesService.php:

class SiteUtilitiesService
{
    public function videoEmbed($url, $color)
    {
        // some code to get the video ID from the $url variable

        return "<some html embed code with the $color variable>";
    }
}

What's the init method the error is referencing?

I needed to extend BaseApplicationComponent in my Services file:

class SiteUtilitiesService extends BaseApplicationComponent
{
    public function videoEmbed($url, $color)
    {
        // some code to get the video ID from the $url variable

        return "<some html embed code with the $color variable>";
    }
}


Upgrading from v2 to v3 results in internal server errors I'm trying to upgrade a v2 site to v3 and have done the following:

Verified that my server meets the v3 requirements using the Craft Server Check.
Followed steps 1-3 on this page.
Followed the directions on this page.

When I go to my control panel's URL, I get the following error: "An internal server error occurred." There's nothing in my server's "error.log" file.

As a test, I even created a fresh install of v2 on a new server instance, imported my site's data, and tried upgrading that, and I still get the server error.

FWIW, I'm running Apache 2.4, Ubuntu 16.04, PHP 7.0.30, and MySQL v5.7.22.

After doing some more digging in storage/logs, it turns out that the permissions were incorrect on the "cpresources" director. Once I fixed those, the upgrade progressed as normal.


Error while trying to use dynamic routing to pass variables to the template and using them So i'm trying to pass the variables from a dynamic route to a template and then to use those variables to filter trough entries.
the catch is that the same template is used to display an "organic"(by organic i mean that it is set up from the CP) category as well.

This is the routes.php

'shop/(?P<segmentCategory>(new|used))/(?P<segmentEntryType>[a-z]+)' => 'shop/category',

And this is from the template:

{% if segmentCategory is defined %}
    {% set category = craft.categories(segmentCategory) %}
    {% set games = craft.entries({
        type: segmentEntryType,
        relatedTo: ['and',
            { sourceElement: craft.entries.section(segmentEntryType).status(null) },
            { targetElement: category }
        ]
    }) %}
{% else %}
    {% set entries = craft.entries.relatedTo(category) %}
{% endif %}

The error:

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

craft/templates/shop/category.html(47)

47 {% extends "_layout" %} ||||||||||||||(Highlighted)||||||||||||||||
48 {% block content %}

Try this:

{% set category = craft.categories(segmentCategory).first %}

Without the first at the end, you're setting category to an ElementCriteriaModel. Which would be fine in many cases, but it's not an acceptable variable type for targetElement.

Ditto for the sourceElement:

craft.entries.section(segmentEntryType).status(null).first


Render styled output using Printmaker plugin I have managed to get Printmaker up & running, spitting out images, entry data, tags etc. However I cannot style the output.

I have built up a template which has a html structure and links to an internal (same domain) CSS file. However the outputted style is browser-default sans serif text and no styling whatsoever.

Here is my template code:

        <link rel="stylesheet" href="/css/templates.css">

              // Page content here...

I have tried the .pdfFromTemplate method:

{% set vars = {
    entry: entry
} %}
{% set settings = {
    orientation : 'portrait',
    filename: entry.slug,
    cacheDirectory: 'pdf/' ~ craft.request.getSegment(1) ~ '/' ~ craft.request.getSegment(2)
} %}
{% set pdfUrl = craft.printmaker.pdfFromTemplate('technical-information/_pdf', vars, settings).url %}

And also the .pdfFromHtml way, too:

{% set html %}
    {{ include('technical-information/_pdf') }}
{% endset %}
{% set settings = {
    orientation : 'portrait',
    filename: entry.slug,
    cacheDirectory: 'pdf/' ~ craft.request.getSegment(1) ~ '/' ~ craft.request.getSegment(2)
} %}
{% set pdfUrl = craft.printmaker.pdfFromHtml(html, settings).url %}

I've had this same problem getting Printmaker use an external stylesheet.

Simply putting the styles in the head of the template sorted it out.

You could also try setting the path to your css with a . like so;

<link href="./path/to/styles.css" rel="stylesheet" type="text/css">


Get repeated events with the Solspace Calendar and Element API plugins When looping through all events in Twig, repeated events will continuously come in. On a weekly event, for instance, it pulls one for this week, one for next week, etc. Lets say I have a meeting event set to repeat weekly, it would come back like this:

{% for event in craft.calendar.events %} ...

Meeting Event
Meeting Event
Meeting Event
...

I'm looking to load events asynchronously with the Element API plugin but I'm only able to get back each event once (even the repeated ones). How do I achieve the same behavior? Here is the basic setup:

<?php
namespace Craft;

return [
  'endpoints' => [
    'api/events.json' => function() {
      return [
        'elementType' => 'Calendar_Event'
      ];
    }
  ]
];

And it only returns:

Meeting Event

Unfortunately this won't be possible with Solspace Calendar since we are extending ElementCriteria with Calendar_EventCriteriaModel, which has a layer on top of it allowing us to build recurring events and return a padded list of events. We also return Event objects instead of EventModel objects, because working with Craft Dates makes it difficult/impossible for Calendar to have the dates it needs. Sorry :/


Control CP matrix layout with CSS Is it possible to control the Matrix layout with CSS within the CP?

The Rich Text fields I have are currently displaying like this:

But I'd like this specific field to look something like this:

I'd like to avoid using a plugin if possible.

Unfortunately not. To do that kind of change your best bet would be to use CPCSS. It's a plugin but really only just provides you with a way to inject custom styles or a stylesheet for use in the control panel. It's well maintained by a responsible author so I don't see any reason to worry about that one.


Redactor formattingAdd not working I've used redactor's custom formatting option before, but now I can't get anything to work. Here's what my file currently looks like:

{
    "buttons": [
        "formatting",
        "bold",
        "italic",
        "lists",
        "link"
    ],
    "formatting": ["p","blockquote"],
    "formattingAdd": {
        "h2": {
            "title": "Heading",
            "args": ["h2"]
        },
        "h4": {
            "title": "Subheading",
            "args": ["h4"]
        },
        "caption": {
            "title": "Caption",
            "args": ["p", "class", "caption"]
        }
    },
    "buttonsAdd": ["sup", "sub"],
    "linkNewTab": true
}

I have the "h2" and "h4" under "formattingAdd" because I wanted them to use custom titles.

The problem is, none of my custom formats are working. The "p" and "blockquote" from "formatting" are working properly, but the other three styles don't do anything. They appear in the list, but don't restyle the text in the editor, or create the elements in the output.

Is there something in the syntax I'm missing? I'm in Craft 3, with the redactor plugin updated to the latest version.

That syntax looks to be for Redactor 2. The latest versions of the redactor plugin (starting from 2.0) use Redactor 3. The syntax has changed slightly


Get Entries from a specific Entry Type I'm trying to get all Entries that are from a specific Entry Type.

My Section is "Site".
Which has 3 different Entry Types.

Now I want to get all Entries from the Entry Type "Program".

I'm trying to reach my goal with Craft::$app->sections-> or Craft::$app->elements->


How do I use Guzzle to send a post request from my plugin? I have a plugin that listens for new users to be created. I am then sending that user to system "B" via an API call.

All is working fine the old fashion way, I am curious how to accomplish the same using Guzzle.

$client = new \Guzzle\Http\Client('http://api.site.dev/');
$uri = 'my/endpoint/path';

$request = $client->post($uri, array(
   'headers' => array('Content-type' => 'application/x-www-form-urlencoded'),
   'body' => array(
       'craft_id' => $event->params['user']->id,
       'name' => $event->params['user']->friendlyName,
       'email' => $event->params['user']->email
    ),
    'timeout' => 10
));

$response = $request->send();

Each time I get this response/error back:

Client error response
[status code] 422
[reason phrase] Unprocessable Entity

Which tells me that system "B" isn't getting the information in the correct format. The docs aren't so great with post examples, so I'm not quite sure where I'm going down the wrong path.

Thank you for any suggestions!

It is pretty obvious now, but indeed the API is looking for json formatted values and I was in fact sending name:value pairs.

Here is what the updated logic looks like for anyone who comes across this.

MyPlugin.php

$client = new \Guzzle\Http\Client('http://api.site.dev/');
$uri = 'my/endpoint/path';
$post_data = array(
    'craft_id' => $event->params['user']->id,
    'name' => $event->params['user']->friendlyName,
    'email' => $event->params['user']->email
);

$data = json_encode($post_data);

$request = $client->post($uri, array(
    'content-type' => 'application/json'
));

$request->setBody($data);
$response = $request->send();


Two entries same category I have two different sections that share the same category group that I want to display both on browser at the same time only if the category is the same. Doing that in Craft CMS is possible?

Thank you.

Yes. It is possible, you need to specify the craft category and set the group parameter on it and fetch the categories with .all().

{% set categories = myCategoryQuery.all() %}


How to create subfolders in the Assets view? I can't find any information on this issue, but I'm not seeing any way to create subfolders in the Assets view of the control panel. I just see all of my images with no folders. Is this feature restricted to paid versions?

What you see on the left in the Asset section, are asset-sources and their subfolders. You can configure them in Settings -> Assets -> New Source.

In this example, Drinks and Cars are asset-sources:

You can add subfolders to each asset-source (and each other subfolder) with Rightclick -> New subfolder.


How do I delete or remove temporary assets? Images were uploaded to a matrix field and then the changes were not saved, but the assets still show up in the control panel as selectable.

The asset seems to be stored here:

http://example.com/admin/resources/tempassets/field_51/file_name.jpg

I'd like to delete or remove these so that we dont't have them laying around taking up the desired file name. If I upload the same image again it appends a _x to the end of the file name as the number of times it's been uploaded.

I can't find the assets anywhere in the assets page in the control panel.

From my comment above:

I was able to find the files uploaded to the root of my assets path and deleted them there.

Then on the control panel settings page:

Updated Asset Indexes and Cleared Cache and it seems to be all working.


Display sliders on homepage I am trying to figure out how to only display the slider on the homepage so that it does not show in other page.

I am getting close but not sure what code I should write. Here is what I could think of but does not work..

{% if slider in homepage %}
    slider goes here...
{% endfor %}

I appreciate any suggestion to what the correct way of displaying content in specific page/section/entry ...

Have a look at the Sections and Entries article in the official Craft documentations. It explains how to set up sections and how to configure them to load a particular template if an entry’s URL is requested. https://craftcms.com/docs/sections-and-entries

Another important topic you should get yourself familiar with is how Craft’s routing mechanism works. https://craftcms.com/docs/routing

To configure a template for your homepage you could create a template in craft/templates/index.html and Craft will use it for homepage requests (routing case 4). Or you configure a section in such a way that the homepage’s URI matches one of the section entries’ URIs (routing case 6). Note that there’s also a special checkbox “This is for the homepage” available in the settings for single sections.

With a designated template for your homepage in place, you can now add your slider code snippet to it. In the case that this template is responsible for multiple entries, e.g., entries of a structure section, you could wrap it in a conditional to check against the entry’s ID for example.

{% if entry.id == 12 %}
    <!-- Slider code -->
{% endif %}