SuperTable and related entries I'm trying to pull through content based on items within a SuperTable entries field.

After searching around I currently have this:

{% set individuals = craft.entries({section: 'barristers', relatedTo: { targetElement: entry, field: 'specialisms.linkToPage'}}) %}
{% for entry in individuals %}
  {{ entry.title }}

But it's not pulling anything through?

Any help appreciated

Thanks

Unfortunately, you can't use Craft's built in relations service for reverse relations lookup with Super Table. This is because there's actually a special case for nested relations, such as a Matrix field. Craft's own relations service has special handling for Matrix fields, which we also need to make use of.

Fortunately, Josh Angell (the star that he is) has submitted a fix for this, without having to hack the core. You'll just need to alter your code to use the following:

{% set reverseRelatedElements = craft.supertable.getRelatedElements({
  relatedTo: {
    targetElement: entry,
    field: 'specialisms.linkToPage'
  },
  section: 'barristers'
}) %}

{% for relatedEntry in reverseRelatedElements %}
  {{ relatedEntry.title }}
{% endfor %}


Using the Matrix field to output content in a slideshow I want to use two block types in one Matrix field. These blocks will be output in a div. At the moment my code adds a new
 for each block type. How can I output two block types in the same
?

  {% for block in entry.homepageSlider %}

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

{{ block.sliderHead }}

{{ block.sliderText }}

        {{ block.sliderButton }}
      {% endif %}

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

        {% endif %}
      {% endif %}

  {% endfor %}

I reduced your code a little: You can use elseif to cycle trough each block so you don't have to write each if statement. Now where do you want your div?

If you want each block with one separate div you write them inside the if statement (As I did in this example).

 {% for block in entry.homepageSlider %}

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

{# content of first block #}

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

{# content of second block #}

        {% endif %}

 {% endfor %}

If you want to add the content of both blocks into one single div it would look like this:

 {% for block in entry.homepageSlider %}

       {% if block.type == "sliderText" %}
         {# content of first block #}
       {% elseif block.type == "sliderImage" %}
         {# content of second block #}
        {% endif %}

 {% endfor %}

But this is basically what you already did. So I'm not sure If I understand what you are trying to accomplish.


Outputting Assets Instead of Entries Apologies if I am dense, it won't be the first time.

I have thousands of product images that I will output on more than one page, under varying conditions.  Rather than having to do an entry for each product in these circumstances, can I just:

attach product  description fields to the asset field
upload the assets
use Bob Olde Hampsink's import plug-in to populate all the product info to assets fields
fetch the asset and the associated fields in a template
skip the entry part altogether?

This way I could use the same asset in multiple instances without having to reinvent the wheel.

  A. Is this possible?
  B. Is this wise?
  C. If A and B =='yes' what is the most direct way to go about this?

Since there is several moving parts here, i'll make a few assumptions.

You got a list of some kind with the product images and their containing metadata.
Your product image filenames have a consistent naming scheme. Something like product-condition1-01,product-condition2-01, product-condition2-02
You are able to write a couple PHP scripts and/or some frontend code that uploads your images, and then creates an list with the returned fileIds and the matching image filename. Take a look at AssetsService and the uploadFile action in AssetsController. For the uploading part, you can probably make a simple JS snippet that loops through the file list and uploads them.
After you got that list, write a script that runs through the product list (an CSV or something), and replace the placeholders matching your image filenames (product-condition-xx etc.) with the previous fetched fileId(s).
You will then end up with a comma-separated list of fileIds in your CSV fields, which Craft expects to able to relate the Assets to the imported Entries.
Import the entries with Import.
List the connected assets in your entries template the normal way.

I have not looked into how to save field info for Assets, but you can for sure make fields and then add them to the field layout for your Assets Sources.

(Not sure I understand all the conditions, but I think my outline should work pretty well for your case. Not able to comment yet, so I could not ask any questions beforehand. I'll update my answer if you add some follow-up information).


Retrieve section slug by handle I want to be able to get the slug of my news section dynamically by searching for its handle.
Slugs tend to change during the development phase, but the handle doesn't. That's why I want to hard code the news handle in my template to refer to the news section from any other page.
How to do such a query?

{% set newsSlug = craft.entries().section('news').select('elements_sites.slug').one().slug ?? null %}

news - handle your section news;
select('elements_sites.slug') - for get only slug your section;
?? null - in case if there is no such section;


How can I check from a plugin config file if devMode is enabled? Using the Pixel & Tonic Contact Form plugin, I added a config file (config/contactform.php) to override plugin settings from the CP.

I would like to change some settings if devMode is enabled : recipients from the contact form plugin, to separate my tests addresses from my client addresses.

<?php

$recipients = array(
    'devMode' => 'example@domain.com,example@domain.com',
    'prodMode' => 'john@doe.com,jean@dupont.com'
);

if (devMode == true) {
    $recipients = $recipients['devMode'];
} else {
    $recipients = $recipients['prodMode'];
}

return array(
    'toEmail' => ($recipients ?: null),

How can I check if devMode == true? Can I access to this value using craft()->config or something else that?

For those coming here using Craft 3, it's now Craft::$app->getConfig()->general->devMode.


What happens when extending an extended template? If template2.html contains {% extends 'template1.html' %}
and template3.html contains {% extends 'template2.html' %}, what happens to things like {% block %}{% endblock %} and variables?

So I tried it, made three files, one extending the first, and another extending the second, and it all worked more or less as one would expect.

bozo.html

<!DOCTYPE HTML>
<html>
  <head>
    {% set title = title ~ 'Main' %}
    <title>{{ title }}</title>
  </head>
  <body>
    Where was {% block whereWasBozo %}Bozo?{% endblock whereWasBozo %}<br>
    Variable A is {{ a }}
  </body>
</html>

ex1_bozo.html

{% extends 'bozo.html' %}
{% set title = title ~ 'Bozo 1 = ' %}
{% set a = 'ex1' %}
{% block whereWasBozo %}
  Bozo wasn't here.
{% endblock whereWasBozo %}

ex2_bozo.html

{% extends 'ex1_bozo.html' %}
{% set title = 'Bozo 2 + ' %}
{% set a = 'ex2' %}
{% block whereWasBozo %}
Bozo was in Bozoland.
{% endblock %}

When I pulled up page ex2_bozo.html, the end result was the page title said:

Bozo 2 + Bozo 1 = Main

and the web page said:

Where was Bozo was in Bozoland.
Variable A is ex1

So the blocks extend all the way through. The variables are first set in the file you initially call. They are modified in the middle 'extension' and modified again in the final extension.


Sprout Forms - Use Case - Retrieve/Store form data into a custom db table We have a placement tool that is currently based on a proprietary PHP MVC framework.  We have a need to quickly build custom forms that contain various checkbox, radio and text fields.

We want to store/retrieve the entire form data in our database, outside of Craft, into a custom jsonb column, along with special key fields, etc.  We currently call our custom Craft plugins from our legacy framework via specified url/action and parameters (which displays the content in an iFrame).  We'd probably use the same method for forms as well, until we can migrate or go to a Vue.js/Headless Craft setup.

Other forms tools, I have reviewed, store the forms within Craft as 'submitted' forms.  We need to keep them in our own database.

Thanks!

Generally speaking, as I may not understand everything you are trying to do, it may be easiest to just have a custom module watch the \barrelstrength\sproutforms\elements\Entry::EVENT_BEFORE_SAVE Event and store the data as a JSON blob wherever you'd like.

If you don't wish to store the data in the normal way Sprout Forms lets you disable saving data to the database, or enable it and set the default to off so you only need to turn it on for use cases where you may want it to store the data in the plugin itself.

As far as retrieving that data, that would be up to you as you're storing it in a way that Sprout Forms wouldn't understand unless you retrieve and re-populate a Form Entry Model at some point in your workflow.

For a more integrated solution, you may want to explore Sprout Forms Custom Integrations API.

Integrations will run after a Form Entry is submitted and validated so you can use the Sprout Forms form builder to build and validate forms (and use features like conditional fields) and then, once the form is submitted you can hand things off to your Custom Integration and send the data wherever you'd like (to a third-party API or just somewhere else in the same database as you describe).

Some of the default integrations give examples on how you can build an Integration to handle custom mappings where you give the admin user an option to map the form fields they create to wherever you want to send the data to, however, Integrations don't require a mapping. If you just want to send the whole payload to a custom endpoint, you can do so and configure the endpoint of your other application to know what to expect.


Cannot change cart email within Craft Commerce while logged-in The provided addresses template for the Craft Commerce checkout only shows the email to logged-out users. We need logged-in admin staff to be able to put orders through on behalf of a customer, over the phone. So, I'm showing the email input to logged-in users as well.

When the admin person arrives at the addresses template, the email field is pre-populated with the admin person's address. They replace their email with the customer's email. They submit.

The cart email remains the admin person's email address.

Can anyone think of a workaround for this?

I don't think there is an easy workaround here as you're dealing with logged in user functionality, and by definition that's not really designed to be easy to workaround.

Probably the easiest thing is for the admin to use the 'log in as XXX' functionality, and then complete the order for the customer (assuming the customer had a Craft account which is not, per se, a given with Commerce).  If they're guest customers, the admin should probably jsut log out, complete the order as a guest, and then log back in, basically.

Order entry for admins (via the backend) is on the Commerce plans, though, so a better solution may well appear.


Default values when using 2 locales I have a field in a site I'm creating which is weather and uses a TABLE field in order to enter the MONTH, TEMP, RAIN etc etc. Im using 2 locales within the site, EN and FR...

Initially I've setup the default values for the MONTH to include JANUARY > DECEMBER which is great, i don't really want the client to have to re-enter this information each time. But is it then possible to set the DEFAULT french values for this field too?

Cant see to find a way around this...

B.

It's not possible to have different defaults per locale with the Table field type. Also keep in mind that the content from the first locale you edit is copied over to all other locales on the first save.

But how about using numbers for the months in the table and to show the full month names in your templates get them from craft.i18n.getLocaleData:

{% for row in myTableField %}
    <li>
        {{ craft.i18n.getLocaleData().getMonthName(row.col1) }}:
        {{ row.col2 }}
    </li>
{% endfor %}

Another way would be to use the date filter:

{{ ('2015-' ~ row.col1 ~ '-1')|date('F') }}


load include not until its needed I have created an infinite loop by crossreferencing two includes to each other. On one page. My aim is to load pop up layers on a page (teachers and instruments) and have links to each other.

{#      include: _layer_instrument      #}

                        {{ teacher.title }}
{% include "includes/_layer_teacher" %}

{#     include: _layer_teacher         #}

                        {{ instrument.title }}
{% include "includes/_layer_instrument" %}

Is it possible to use ajax to not load the includes until they are needed?

You can create a custom plugin with Pluginfactory.io and check the box for Controllers but leave the name blank. Copy the downloaded files into your path/to/craft/craft/plugins/>>nameofyourplugin<</ directory and install it in your cp.

Then you'll insert a function like this in your controller

public function actionRenderTemplate(){
    $id = craft()->request->getParam('id');
    // do some checks if the id is valid or not here...

    $html = '';
    $success = false;
    $message = '';

    if($entry = craft()->entries->getEntryById($id)){
        // as example to render different templates based on entry type
        $entryType = $entry->getType()->handle;
        $html = craft()->templates->render('path/to/your/template/' . $entryType, array(
            'entry' => $entry
        ));
        if($html){
            $success = true;
        }
    }else{
        $message = Craft::t('could not find entry with id ' . $id);
    }

    $this->returnJson([
        'message'   => $message,
        'success'   => $success,
        'html'      => $html
    ]);
}

And your Javascript could be this

$('.load-instrument').click(function(){
    var data = {
        action: "pluginname/actionRenderTemplate",
        id: $(this).data('id')
    };
    $.ajax({
        type: "post",
        url: '',
        data: data,
        success: function(data){
            if(data.success === true){
                $("#idOfYourDiv").html(data.html);
            }else{
                // display error messages here
            }
        },
        error: function (XMLHttpRequest, textStatus) {
            console.log("Status: " + textStatus);
        }
    });
});

However I would recommend you to read the docs about Controllers and about templates to fully understand what you have to do here

edit: your html could be

<button data-id="{{instrument.id}}" class="load-instrument" value="click me">Click me</button>


Freeform conditionals This code works as expected...

{% if submission.symptomCheckerSymptoms == "Itching" %}
    it works
{% endif %}

... but when when multiple options are selected, it doesn't.

The field is a checkbox group. What am I doing wrong?

The solution is:

{% if "itching" in submission.symptomCheckerSymptoms.value %}
{% endif %}


Best way to define non-purchasable products? Not every item in my store is available to buy online.

What would be the best way to classify these items in Craft Commerce?
(So that the 'Buy' button can be swapped for 'Enquire')

There are multiple product categories this applies to.

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

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

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


Where did the @property delcarations for the inbuilt services go? I've noticed in a recent (not sure which exactly) version of Craft that the @property-read declarations for each of the inbuilt services have been dropped from /craft/app/Craft.php.

This means in PHP Storm, I no longer receive valuable code hints following a craft()-> statement:

Is there a new way to access these hints in the recent version? Maybe I've missed something and accessing services via craft() is no longer the preferred method?

The bad news is it's been a bug in PHPStorm since 9.0.1.

The good news is it's been fixed in the PHPStorm 11 EAP and will be in the 11 final release.

https://youtrack.jetbrains.com/issue/WI-28394


AJAX Update Entry (500 Internal Server Error) I'm trying to update an entry on the front end with a click and without a form. I'm a bit new with AJAX but would love to simply put a new title for the entry that the button relates to. I'm currently getting 500 Internal Server Errors when trying.

{% for entry in currentUserSubmissions %}
  {{ entry.title }}
  {{ entry.submissionUrl }}
  Approve
{% endfor %}

This is my AJAX

{% js at endBody %}

  $('.btn-approve').on('click', function() {

    var entryId = $(this).data('id');
    var data = {
        value: entryId,
        name: 'entryId',
        title: 'hello test'
    };
    var tokenName = '{{ craft.app.config.general.csrfTokenName }}';
    data[tokenName] = '{{ craft.app.request.csrfToken }}';

    // send ajax request
    $.ajax({
      method: "POST",
      dataType: "json",
      url: "/actions/entries/saveEntry",
      data: data,
      headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      success: function (data) {
        console.log('success', data);
      },
      error: function (error) {
        console.log('error', data);
      }
    });
  });
{% endjs %}

  /actions/entries/saveEntry 500 (Internal Server Error)

Try changing the url from "/actions/entries/saveEntry" to "/actions/entries/save-entry"


In a plugin, how do I save an entry with a related entry In my plugin, how do I save a relationship when creating a new entry? The example below works for all but the "quiz" relationship.

$triviaSet = craft()->entries->getEntryById($data['itemId']);
$entry = new EntryModel();
$entry->sectionId   = 3
$entry->typeId     = 2
$entry->authorId   = 1;
$entry->enabled    = true;
$entry->getContent()->setAttributes(array(
    'title' => 'My New Entry',
    'score' => $data['score'],
    'quiz' => $triviaSet
));
$success = craft()->entries->saveEntry($entry);

Relations fields can store multiple related values (even if you only have one item).  Perhaps try to pass an array to the 'quiz' value:

'quiz' => array($data['itemId'])

Alternatively, if you are submitting all of your content, in the correct format, you can get rid of your $entry->getContent()->setAttributes line and use the setContentFromPost method.

All you need to pass to the setContentFromPost method is the name of the custom content fields array you are submitting to the content table.  For example, if your fields above were structured as follows in your front-end form template (this is a bit simplified for your complex field types like relations, but as long as your submitting the right values this should work):

<input type="text" name="title" value="My New Entry">
<input type="text" name="fields[score]" value="101">
<input type="text" name="fields[quiz][]" value="101">

Note that in the input field name of quiz relations field we are passing an array: fields[quiz][].

You can then receive your submitted data and hand it off to the ContentModel tied to your EntryModel. Your title is handled slightly differently than your custom content as the title field is a default attribute of the ContentModel:

$entry->getContent()->title = craft()->request->getPost('title');

And your array of submitted custom content can be handed off silently to the setContentFromPost field by just passing it the name of all of the fields.

$entry->setContentFromPost('fields');

You don't even need to capture your post data using something like craft()->request->getPost('fields'), just passing the 'fields' value to the function does all the heavy lifting for you.


Display entries by current entry author? I have a blog section on my site and would like a "More posts by this author" list. How would I go about this, the logic is clear but the syntax to write for it is not forthcoming.

In order to display all other entries by an author except the current one, you will need to perform another step — either by filtering out the current entry from the query or adding a conditional.

{% set authorId = entry.author.id %}
{% set allEntryIds = craft.entries.section('blog').authorId(authorId).limit(null).ids() %}
{% set otherEntryIds = allEntryIds|without(entry.id) %}
{% set otherEntries = craft.entries.section('blog').id(otherEntryIds) %}

    {% for entry in otherEntries %}

{{ entry.title }}

    {% endfor %}

or

{% set authorId = entry.author.id %}
{% set authorEntries = craft.entries.section('blog').authorId(authorId).limit(null) %}

    {% for authorEntry in authorEntries %}
        {% if not authorEntry.id == entry.id %}

{{ entry.title }}

        {% endif %}
    {% endfor %}


New user validates without confirming email I've built a plugin that does some work before saving the user from the standard Registration Form. My only issue is it does not fire the activation email which I added in. But it lets the user login without verification, so I'd like to know what I'm missing as I thought if I use craft()->users->saveUser() it automatically deals with this for new users. My code is as follows I think I may be missing something from the model?

$newUser = new UserModel();
$newUser->username = $username;
$newUser->email = $email;
$newUser->newPassword = $password;

$success = craft()->users->saveUser($newUser);

if ($success)
    {
        // Code added to send email
        craft()->users->sendActivationEmail($newUser);

        $this->redirectToPostedUrl($newUser);
    }

Since you're bypassing Craft's own UsersController->actionSaveUser(), you'll need to replicate a bit more of its functionality in order for it to work like you're wanting.

First you'll want to make sure that "Require Email Verification" is checked under Settings->Users->Settings in the control panel.

Then your UserModel will also need to set a few more things:

$user->unverifiedEmail = $email;
$user->pending = true;

Completely untested, but that should do it.

I highly recommend looking over Craft's default actionSaveUser implementation as there are many permissions/security guards in place for public registration that you should probably consider as well.


Getting a entry link created by current User I am trying to create a link that would allow a logged in user to access their profile from the front end. Basically, the user has one page they can edit from the front end when logged in, and I'd like to link to that page in the navigation. I've seen similar things done in Craft 2 but not in Craft 3. So far I tried this: but it didn't work.

{% set myEntry = craft.entries.section('userProfiles').authorId(currentUser.id).limit(1) %}
My Profile

as well as..

{{ myEntry.limit(1).url() }}

Thank you!

You need to fetch the entry with one() keep in mind in order to be able to be an author the user needs the permission to create entries in that section

{% set myEntry = craft.entries.section('userProfiles').authorId(currentUser.id).one() %}
My Profile

You should also consider to code defensively and check if there is a current user and if myEntry is not null


How do I set a class if entry is a child of a particular parent? I have a structure section which is three levels deep and I want to add a class when the entry has a parent id of X. I am trying something like:

{% for entry in craft.entries.section('brand').descendantOf(entry.id).level(3) %}

  ...

{% endfor %}

This gives me a "Recoverable error":

  Argument 1 passed to Craft\BaseElementModel::isAncestorOf() must be an
  instance of Craft\BaseElementModel, string given

What am I doing wrong?

Updated code:

{% for entry in craft.entries.section('brand').descendantOf(entry.id).level(3) %}
{% set entryWithId13 = craft.entries.id(13).first() %}
{% set entryWithId23 = craft.entries.id(23).first() %}
{% set entryWithId23 = craft.entries.id(29).first() %}

...

{% endfor %}

If you want to test whether entry-with-id-X is an ancestor of entry, do this (assuming x = 13):

{% set entryWithIdX = craft.entries.id(13).first() %}
...
{% if entryWithIdX.isAncestorOf(entry) %} ... {% endif %}
{# or #}
{% if entry.isDescendantOf(entryWithIdX) %} ... {% endif %}

isAncestorOf and isDescendantOf take an entry as parameter, not an entryId.

It would be a good idea to test to see whether craft.entries.id(13) returns anything before calling first() on it, but that's a separate issue.


Is it possible to update a Twig variable based on user interaction without page refresh? I'm currently trying to use the excellent "Charge" plugin to set up a simple Stripe checkout form for charity donations. The basic example provided in the docs works nicely.

<form method="post">
  <input type="hidden" name="action" value="charge/charge"/>
  {% set options = {
    planAmount : 99.99,
    description : 'This is an extra description',
   checkout : {
     name: 'Acme Corp',
   }} %}
  {{ craft.charge.setCheckoutOptions(options) }}
</form>

However I'm trying to update the 99.99 to use an amount that can be chosen by the client. My attempt at doing this involved having a separate form with a select box which when updated needs to update the planAmount.

I tried to do this using craft.request.getPost('name') tying up to a jQuery post submit but I'm not sure if I'm even going about this the right way?

Is there any other way to update a variable in Craft/Twig through JS (or other user interaction)?

I'm the developer of Charge.

You need to go about the form setup a slightly different way.

By design there are 2 ways to define the value for a Charge, either

Setting the planAmount variable in your twig template, and passing it to the setCheckoutOptions/setPaymentOptions method.
Passing the allowDynamic : true setting to the setCheckoutOptions/setPaymentOptions method. With the allowDynamic option passed, you can then pass the planAmount as a hidden or visible input in your payment form, named planAmount. This can be directly updated by your users, and is explicitly designed for variable amount and charity donation form setups.

An example of this behaviour is included in the demo templates in template/charge/donation.html and is also visible here : http://demos.squarebit.co.uk/charge/donation


Multi-environment config issue I'm trying to set up Craft and on deployment to a staging server am getting the following error message:

  An exception has been thrown during the rendering of a template
  ("Craft can't connect to the database with the credentials in
  craft/config/db.php.") in "_layout" at line 39.

The config file in question is posted up at https://gist.github.com/cole007/f32c7ba984a3d35b1d24

Any thoughts?

Cheers in advance,

Cole

Sorted, thanks. The keen-eyed of you will notice that there was a space character in the server connection details. Idiot


Multi-lingual site with a splash (language select screen) at the root I'm trying to get something working and I keep breaking my internal links doing it.

Here's what I'd like:

public/index.html (this page would be the language select screen and can be dealt with outside the cms)

public/fr/index.php (craft loader for french)
public/en/index.php (craft loader for english)

I would also like the CP to load from the root.  I thought of having it redirect to a "craft.php" page that would be the loader if the requested file doesn't exist, and it worked for the CP.  But of course, it grabs any of the calls to the site that is not fr/ or en/ only.  As soon as there's something else in the uri, it goes to 404.

Any idea for this one?

Well that was easy enough.  I had forgotten about the .htaccess in the subfolders.  Everything works like planned now.

public/.htaccess (redirects to craft.php if file doesn't exist)
public/index.html (splash page)
public/craft.php (craft loader)

public/fr/.htaccess (redirects to index.php if file doesn't exist)
public/fr/index.php (craft loader for french)

public/en/.htaccess (redirects to index.php if file doesn't exist)
public/en/index.php (craft loader for english)


From a template, how can you order entries by one field, and if that field is empty a different field? Is it possible to put conditions on the ordering of a loop of entries?

I have two fields: title and alphaTitle. I want to order alphabetically, by alphaTitle if it has a value, otherwise by title. Title will always have a value but I only want to order by title if there is no alphaTitle. I've been having some trouble figuring out if this is possible or how to do it - any chance someone can point me in the right direction?

There are several ways you could attack this, but probably the easiest is directly from the SQL side with something like this using a SQL CASE statement:

{% set entries = craft.entries.section('news').order('(CASE WHEN field_alphaTitle IS NULL OR field_alphaTitle = "" THEN title ELSE field_AlphaTitle END)').find() %}

    {% for entry in entries %}

TITLE = {{ entry.title }} / ALPHA TITLE = {{ entry.alphaTitle }}

    {% endfor %}

Note that is assuming that alphaTitle is a custom field and title is the standard one available to all entries.


Advice on entry form file uploads and S3 Just planning out an entry form that includes a file upload field – an assets field hooked up to an S3 bucket. I see some documentation on entry form assets here, but need some advice on getting this working with S3 if anyone's done this before? Any help very much appreciated.

This is a great learning resource. Worth the investment, IMO, if you're building a lot of sites with Craft CMS.
https://craftquest.io/lessons/switching-from-craft-local-assets-volume-to-s3


How to include twig in the editor? e.g. Shortcodes for dynamic content I would like to display dynamic content in the middle of a text block. For example, a list of entries pulled in from the backend, in the middle of content.

In Wordpress we can use Shortcodes. Does Craft have something similar?

Can I just add an include statement to include a template? (I cant get this working using normal twig include code).

I could create a new field for someone to add in in between two other text block fields, but its quote over the top for what should be a simple include statement to include a template.

Thanks!

The typical 'Craft' way of doing this would be via a Matrix field instead of a single text block field, so that editors can sandwich the dynamic content (which would be its own block type) in between whatever other block types they select. That way is very powerful, flexible, extensible, and clean...

However, assuming migrating your content to a Matrix setup would be too onerous or undesirable for other reasons, there's nothing to stop you creating your own basic shortcode replacement functionality via Twig's replace filter. For example, in your body field you might insert arbitrary markers like [list-of-entries]... then in the template that outputs the field, you can go to town with defining what each shortcode represents and then replace them like this:

{% set listOfEntries %}

        {% for item in craft.entries.section('something').all %}

{{ item.title }}

        {% endfor %}

{% endset %}

{% set parsedBody = entry.body|replace({
    "[dynamic-address-injection]" : craft.entries.section('something').one().addressField,
    "[video]" : entry.videos.one().embedCode,
    "[list-of-entries]" : listOfEntries
}) %}

{{ parsedBody }}


Console command runing from Cron job failing after Craft update I have had a custom console command running fine for several months now which sent out reminder emails to users when there accounts are about to expire.

After the latest Craft update (I believe) it stopped working. Here is the error:

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054
Unknown column 'users.locked' in 'field list'
exception 'CDbException' with message 'CDbCommand failed to execute the SQL statement:SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.locked' in 'field list'' in CDbCommand.php:543

The lines of code from the plugin service which cause the error are:

$user_criteria = craft()->elements->getCriteria(ElementType::User);

$user_criteria->userExpiryDate = date('Y-m-d',strtotime("+7 days"));

$users = $user_criteria->find();

Basically it fails when running the find() method.

Strangely I haven't managed to replicate the error on my local machine.

Does anyone have any idea what might be causing this?

This ended up being a case of looking at the wrong database.  The version/build/schema numbers for the correct database were all in sync.


layout file changes get deleted overnight I've had a problem for a few weeks whereby any changes to a layout.html file get deleted overnight on a server. As a sanity check I just want to make sure there isn't anyway this can be done by Craft? (The updates have expired on the install, but surely this can't be the problem?)

Craft isn't doing that automatically.

Guessing you've got some automated deploy that happens at midnight or some such and it's overwriting manual changes?


ajax call breaking onBeforeSaveUser I have a plugin that has an onBeforeSaveUser event. This fires the mailchimpsubscribe plugin to subscribe users to selected newsletters.

Everything works correctly the user is subscribed and then the saveUser function saves the users newsletter preferences to the database.

I am now trying to get it to work with an ajax call, which again works correctly and subscribes the user to mailchimp. However after sending the json response it does not appear that the saveUser function is being fired as nothing is updated in the database for the selections made.

Could the ajax be stopping the saveUser from being fired?

Ajax:

// Get the post data
var data = $(this).serialize();

// Send it to the server
$.post('/', data, function (response) {

    if (response.success) {
      $form.parents('.question-box').fadeOut(function () {
        $(this).remove();
        $('.question-box').first().fadeIn();
      });
    } else {
        var message = response.message;
      alert('Unfortunately, we were unable to save your data at this point. Please try again later.'+message);
    }
});

Mailchimp Plugin:

if ($api->errorCode) { // an api error occured

      // Respond appropriately to Ajax Requests.....

} else { // list subscribe was successful

      // Respond appropriately to Ajax Requests
      if (craft()->request->isAjaxRequest())
      {
        return $this->returnJson(array(
          'success' => true,
          'errorCode' => 1,
          'values' => array(
            'email' => $email,
            'vars' => $vars
          )
        ));
      }

      //.....
}

Cheers

Had a response from Pixel & Tonic on this. Which explains the process.

The problem you're seeing is caused by returnJson() as that also ends the process after outputting the JSON data. Most likely onSaveUser (without Before) is a better place for this code; that ensures the user has been saved to the database before running the event code.


Can I output the Placeholder Text of a plain text matrix block? Is there a way to output the Placeholder Text of a plaintext field if there's no specific value entered to the Entry?

(Am I missing something — should it happen automatically if there's no specific value entered?)

The docs say: "The text that will be shown if the field does't have a value" — does shown just mean in the form on the Entry form in the admin, or also on the front-end as a value of block.FIELDNAME ?

The "docs" means only on the admin form. For outputing a default text on empty fields in frontend you can use the following code in you template:

{{block.FIELDNAME | default("Placeholdertext") }}


Dukt Analytics Plugin - Web Profile not showing up I'm trying to configure the Dukt Analytics Plugin to a site for my first time. I was able to successfully configure oAuth on my Google account, and get the account connected via the Analytics Plugin panel in Craft.

However, I'm having some issues getting the web profile dropdown list to populate. While connecting to Google Analytics, the only permissions it asked for was "have offline access" which may be part of the issue.

Is there any sort of troubleshooting methods that can be done to figure out why no web profiles are showing up?

After doing the latest Craft Update, the plugin seems to be working fine now. It was either a bug in Craft that has been fixed, or you just have to give Google a few days before it's able to fetch the list of hosted analytics accounts.


Changing the default admin path I am trying to reset the default path to the dashboard from admin to something else. I have this in config/general.php:

return array(
    'cpTrigger' => 'new-url',
    'omitScriptNameInUrls' => true,
    'devMode' => true,
);

But when I go to devsite.myurl.co.uk/new-url, I get a 404 error. I got this working locally but not since I installed the site on a staging server, and imported the database and changed the general and db files. Any ideas?

If I take out the cpTrigger line, and just use devsite.myurl.co.uk/admin, everything is fine.

Have you got your htaccess file working ok? By default the htaccess file is named incorrectly, it should be .htaccess nothtaccess`. You can read about renaming that file in the installation docs.

As a quick test you could try:
"/index.php/new-url"

If that works it's your htaccess file.


Is there a way to manually trigger an asset transform before calling getUrl()? I have a site where I serve quite the amount of images which are saved on Google Cloud Storage. I have set generateTransformsBeforePageLoad to true in my general config because I'm caching the output for Fastly (based on Varnish). The downside is that on first request it's awfully slow and at one point even returns a 503 error.

Is there a way that assets can be transformed before getUrl() is being called? Other solutions are more than welcome.

You could use my Preparse Field plugin to generate transforms when an entry (or any other element) is saved.

Create a preparse field and create some twig that makes the same transforms that you do in your template. Don't care about the output, the only thing you want it to do is generate the images on save. Assuming you attach the field to an entry, and you have a field named myImageField, the code could look something like this:

{% if entry.myImageField | length %}
  {% for image in entry.myImageField %}
    {{ image.getUrl({ width: 1600 })
    {{ image.getUrl({ width: 1200 })
    {{ image.getUrl({ width: 800 })
    {{ image.getUrl({ width: 400 })
  {% endfor %}
{% endif %}

When you save the entry, this code will run, and create any new image transforms. When the entry is displayed in the front-end, the image transforms will already have been created.

Beware that this will not actually increase the speed of the transforms, only shift the time it takes from the front-end user over to the admin. But I find that this is more acceptable in most of my use-cases.


I ended up doing it this way:

$records = Plugin_CollectionSectionRecord::model()
        ->findAllByAttributes(['collectionId' => $collectionId]);
}

$ids = [];
foreach($records as $value) {
    $ids[] = $value->sectionId;
}

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->elementType = 'Entry';
$criteria->sectionId = $ids;
$result = $criteria->all();
return $result;


How do you correctly handle errors using PT Contact Form when submitting via AJAX? I'm trying out AJAX submission for the PT Contact Form for the first time. I've managed to get errors appearing on the frontend, but I don't feel like I'm doing it the right way. It also doens't integrated at all with the {% macro errorList(errors) %} code that comes with the form. This is my form JS:

$(function(){
    $('#ajax-form').submit(function(ev) {
        // Prevent the form from actually submitting
        ev.preventDefault();

        // Get the post data
        var data = $(this).serialize();

        // Send it to the server
        $.post('/', data, function(response) {
            if (response.success) {
                $('#thanks').fadeIn();
            } else {
                // response.error will be an object containing any validation errors that occurred, indexed by field name
                // e.g. response.error.fromName => ['From Name is required']
                if (response.error.fromName) {$('ul.errors').append('
'+response.error.fromName+'
');}
                if (response.error.fromEmail) {$('ul.errors').append('
'+response.error.fromEmail+'
');}
                if (response.error.subject) {$('ul.errors').append('
'+response.error.subject+'
');}
                if (response.error.message) {$('ul.errors').append('
'+response.error.message+'
');}
            }
        });
    });
});

Form code:

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

    {% for error in errors %}

{{ error }}

    {% endfor %}

{% endif %}
{% endmacro %}

{% from _self import errorList %}

<form method="post" action="" accept-charset="UTF-8" id="ajax-form">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="contactForm/sendMessage">
    <input type="hidden" name="redirect" value="/contact">

    Name *
    <input class="form-control" id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

    Email *
    <input class="form-control" id="fromEmail" type="text" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

    Subject
    <input class="form-control" id="subject" type="text" name="subject" value="{% if message is defined %}{{ message.subject }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('subject')) }}

    Message *
    <textarea class="form-control" rows="10" cols="40" id="message" name="message">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
    {{ message is defined and message ? errorList(message.getErrors('message')) }}

    <button type="submit" class="btn btn-primary">Submit</button>
</form>

I've had to put a blank

 under my form, as the .error ul that comes with the contact form doesn't appear. Where am I going wrong?

Desired result: I get exactly the same error handling as I would if I wasn't submitting via AJAX - i.e., the error messages relating to specific fields appear under those fields in the form.

If you want the error messages to be displayed identical to P&T's template/macro default, this should do the trick:

$(function(){
    $('#ajax-form').submit( function(ev) {

        // Prevent the form from actually submitting
        ev.preventDefault();

        // Remove any existing error messages from previous attempts
        $(this).find( '.errors' ).remove();

        // Get the post data
        var data = $(this).serialize();

        // Send it to the server
        $.post('/', data, function(response) {

            if (response.success) {

                // All good!
                $('#thanks').fadeIn();

            } else {

                // Loop through the errors and append to relevant fields
                for ( var fieldId in response.error ) {

                    // Create the

                    var $errors = $( '
' );

                    // Wrap the error messages in
 tags
                    var messages = $.map(response.error[fieldId], function(message){
                        return '
' + message + '
';
                    });

                    // Append the error messages to the ul
                    $errors.append( messages.join( '' ) );

                    // Select the input element and append the .errors
 after it.
                    $('#'+fieldId).after($errors);

                }

            }
        });
    });
});

Just to be clear though, the PT Contact Form template doesn't force you to display your error messages in any given way; both the contact form template as a whole, and specifically how error messages are displayed (both the template macro for non-Ajax requests and the stuff in the response.error object) is obviously totally up to you.


Craft search only shows results matching 'title' of entries I´m doing a search on Blog entries, i want to get all relevant entries searching on several fields, and seems that only matches the title. I try already using search(query), now i added the fields, same result. Maybe the search item should be re-generated? i don´t know how to do it in console, but i have only 4 blog entries at the time, i already change and saved all of them, same result...
Any help is welcome. Thanks.
{% paginate craft.entries({
             search: 'title:' ~ query ~ ' OR categoriaBlog:' ~ query ~ ' OR etiquetasBlog:' ~ query ~ ' OR resumenBlog:' ~ query ~ ' OR subtituloBlog:' ~ query ~ ' OR contenidoBlog:' ~ query,
             orderBy: 'score',
             section: 'blogSec'
        })
        .limit(6) as pageInfo, blogs %}

Search via search() can be used only for text fields, if you want to search by categories or records you need to use the relatedTo() method, also do not forget to specify search keywords when creating the field.

Links: https://craftcms.com/docs/3.x/relations.html#terminology, https://craftcms.com/docs/3.x/searching.html#supported-syntaxes.
Practical example:
{% set searchResults = [] %}

{% set queryParamsText = queryParamsText|merge({
        search: {
            query: 'title:' ~ searchWord
        }
     })
%}

    {% set category = craft.categories.group('category').search(searchWord).one() %}

    {% set relatedParams = relatedParams|merge([{ targetElement:category }]) %}

    {% if relatedParams|length > 1 %}
        {% set queryParamsRelated = queryParamsRelated|merge({'relatedTo':relatedParams}) %}
    {% endif %}

{% set searchResultsText = craft.entries(queryParamsText).section('canAddSectionHandleOrId') %}

{% set searchResultsRelated = craft.entries(queryParamsRelated
).section('canAddSectionHandleOrId') %}

{% set searchResults = searchResultsText|merge(searchResultsRelated)|unique %}


How do I do routing for something like {city}/pricing, {city}/how-it-works, etc. while loading the same template and dataset? I'm trying to set up a site for clients that have locations in multiple cities and who want to be able to display something specific to that location on certain pages. I would like to set up routes using the city name as a variable, followed by the page (i.e. mysite.com/chicago/pricing, mysite.com/boston/pricing, etc.), and have it route to the same section and template with all of that section's corresponding entry fields.

I was planning to grab the URL parameter as a variable that enables me to dynamically load content based on a simple string match for that variable. I want to do something like this

{% set location = matches[1] %}

{% if not location %}
  {% set selectedLocation = locations.defaultLocation %}
{% else %}
  {% set selectedLocation = location %}
{% endif %}

....

{% for plan in entry.pricingPlans %}
    {% if plan.location == selectedLocation %}
      ...
    {% endif %}
{% endfor %}

I can route to the template itself just fine, but I don't get the data. Any suggestions on how best to achieve this? I'm not very PHP savvy and have only recently started getting to more advanced tasks in Craft.

Is the problem you're not getting the segment from the URL?

{% set locationSlugInUrl = craft.request.getSegment(1) %} or {% set locationSlugInUrl = craft.request.firstSegment %} should do that for you.

Or you're not getting the entry? In which case you need to either specify the template in that section's settings or do something like {% set entry = craft.entries.section('pricing').first %} or whatever the section slug is (assuming it's a single).

And what kind of field is entry.pricingPlans? If it is a matrix field, what type of field is plan.location?


What is the difference between elements.enabled and elements_i18n.enabled? It appears, toggling the status button on an entry affects only the elements.enabled value.  What affects the elements_i18n.enabled value?  When and how would we choose to update the enabled column in the elements_i18n table?

If your section is enabled in multiple locales, each locale will get its own status lightswitch setting, which maps back to elements_i18n.enabled. It’s how you can have individual entries enabled/disabled on a per-locale basis.


Custom element index page (cp) sortable on dateCreated? I have a plugin with custom elements that can be sorted on a handful of fields in my CP element index page. I can get the DATECREATED displaying correctly that Craft generates automatically but I cannot sort by it. I am getting an ambiguous column error in SQL and not sure how I am supposed to include these native columns so they can be sorted like in the CP entries section. The other field, SCORE, is an example of one of my fields that I adjust the html display a bit (add a '%' sign) when it's rendered and sorting doesn't seem to work. Anybody with some tips? I tried referencing the craft app EntryElementType file but still could not quite figure it out. Thanks

public function defineSortableAttributes()
{
    $attributes = array(
        'id'            => Craft::t('ID'),
        'userId'        => Craft::t('User'),
        'testId'        => Craft::t('Test ID'),
        'score'         => Craft::t('Score'), // no errors but not sorting properly
        'dateCreated'   => Craft::t('Date Created'),
    );

    return $attributes;
}

/**
 * Returns the attributes that can be shown/sorted by in table views.
 *
 * @param string|null $source
 * @return array
 */
public function defineAvailableTableAttributes()
{
    $attributes = array(
        'id'                => Craft::t('ID'),
        'userId'            => Craft::t('User'),
        'testId'            => Craft::t('Test'),
        'results'           => Craft::t('Results'),
        'score'             => Craft::t('Score'),
        'ipAddress'         => Craft::t('IP Address'),
        'dateCreated'       => Craft::t('Date Created'),
    );

    return $attributes;
}

The error for dateCreated (when trying to sort by the field) is below. When trying to sort by SCORE I don't notice an error but the order doesn't seem to change, so I'm not terribly sure what's not quite right there. Maybe something to do with sorting on fields where I customize the html output?

CDbException
CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'dateCreated' in order clause is ambiguous. The SQL statement executed was: SELECT `elements`.`id`, `elements`.`type`, `elements`.`enabled`, `elements`.`archived`, `elements`.`dateCreated`, `elements`.`dateUpdated`, `elements_i18n`.`slug`, `elements_i18n`.`uri`, `elements_i18n`.`enabled` AS `localeEnabled`, `ts`.* FROM `craft_elements` `elements` JOIN `craft_elements_i18n` `elements_i18n` ON elements_i18n.elementId = elements.id JOIN `craft_testcenter_submissions` `ts` ON ts.id = elements.id WHERE (elements_i18n.locale = :locale) AND (elements.archived = 0) GROUP BY `elements`.`id` ORDER BY `dateCreated` ASC LIMIT 50. Bound with :locale='en_us' (/volume1/storage/___/HTML/01/craft/app/framework/db/CDbCommand.php:543)

Here is my modifyElementsQuery

public function modifyElementsQuery(DbCommand $query, ElementCriteriaModel $criteria)
{
    $query
        ->addSelect('ts.*')
        ->join('testcenter_submissions ts', 'ts.id = elements.id');

    if ($criteria->userId)
    {
        $query->andWhere(DbHelper::parseParam('ts.userId', $criteria->userId, $query->params));
    }

    if ($criteria->testId)
    {
        $query->andWhere(DbHelper::parseParam('ts.testId', $criteria->testId, $query->params));
    }
}

The issue was in the modifyElementsQuery function. When you select all columns addSelect('*') to the query your SQL will select the dateCreated and dateUpdated columns of your custom table as well.
As soon as you want to order by one of those columns the database does not know which dateCreated should be sorted.

You need to select only the unique attribute columns in your custom element table.

To debug your score sorting issue the best thing is to go into craft/app/elementtypes/BaseElementType.php and check the function getIndexHtml. You can var_dump the results of the following variables

// Combine them, accounting for the possibility that $order could contain multiple values,
// and be defensive about the possibility that the first value actually has "asc" or "desc"

// typeId             => typeId [sort]
// typeId, title      => typeId [sort], title
// typeId, title desc => typeId [sort], title desc
// typeId desc        => typeId [sort]

$criteria->order = preg_replace('/^(.*?)(?:\s+(?:asc|desc))?(,.*)?$/i', "$1 {$sort}$2", $order);

and compare the output with default Entry fields.


Redirect 'expired' or deleted entries I have a job board running on Craft. We're "auto expiring" the posts from listing pages based on the post date.

However, I want to redirect the actual entry page to either a 'this job has expired' page in cases where some one is linking from an external site.

Is that possible?

Hadn't thought about using simple if logic here in the template

{% if entry.postDate <= now|date_modify('-90 days') %}
    {% redirect 'jobs/expired' %}
{% endif %}


Craft files and DB out of sync A client's site is currently showing this message:

  Craft does not support backtracking to this version. Please upload
  Craft 2773 or later.

I understand how to fix it, but I don't understand how it's happened.

In Craft’s request log I can only see one update:

2016/02/22 15:37:15 [info] [application] [Forced] Updating from 2.5.2761 to 2.5.2763.

But in the craft_info table the version and build are 2.6 and 2773, updated_at 2016-03-09 22:07:49.

Also in the log are several requests hitting 404s - /wordpress/, /administrator/index.php, /wp/, etc.

Then at 2016/03/10 04:07:42 (6 hours after craft_info was updated) in the log I'm seeing a load of these errors:

******************************************************************************************************
2016/03/16 09:11:25 [error] [exception.Craft\HttpException.503] exception 'Craft\HttpException' in /chroot/home/lincshub/lincshub.com/craft/app/etc/web/WebApp.php:229
Stack trace:
#0 /chroot/home/domain/domain.com/craft/app/framework/base/CApplication.php(184): Craft\WebApp->processRequest()
#1 /chroot/home/domain/domain.com/craft/app/index.php(62): CApplication->run()
#2 /chroot/home/domain/domain.com/html/index.php(19): require_once('/chroot/home/li...')
#3 {main}
REQUEST_URI=/
---

The last deployment (local to production) was made on 5 Feb 2016 12:44.

Could anyone shed some light on what's going on here please?

It looks like the database schema (at Craft version 2.6.2773) is ahead of the craft/app files on your file system (at Craft version 2.5.2763).

Since (I assume) you're not seeing any update info being logged in production around 2016-03-09 22:07:49 (from the dateUpdated column in the craft_info table), my guess is that someone updated the site/database locally, then restored the updated database to production with the older files still in place.


Is there a way to convert a Craft MySQL database to PostgreSQL? I have an existing Craft installation using MySQL and I've only recently realized the error of my ways and would like to convert the database to PostgreSQL.
Is this possible?

First, I'm glad you've realized what a mistake you made.
There's not a fool-proof way to do this, other than to do a fresh installation of Craft using PostgreSQL and migrate the content over.
There is a tool called pgloader that purports to be able to convert a MySQL/MariaDB database into PostgreSQL and it gives it the old college try.
My experience is that it works a good 70% of the time depending on things like environmental configurations and the size/complexity of the original database, so here's hoping luck is on your side.
Be sure and check their issues if you run into any errors.
Make backups. YMMV. UAYOR. Test the #@*! out of the resulting database.

What You’ll Need

An existing Craft CMS install that uses MySQL or MariaDB
Running MySQL and PostgreSQL servers, and the DSN for each
pgloader

Steps

Download and install pgloader. If you’re on a Mac, you can use brew install pgloader.

Save and customize a local command file* for pgloader:
LOAD DATABASE
    FROM mysql://root:root@mariadb/craft3
    INTO pgsql://craft3:secret@postgres/craft3
    WITH quote identifiers
CAST type datetime to timestamp
ALTER SCHEMA 'craft3' RENAME TO 'public'

AFTER LOAD DO
    $$ ALTER TABLE craft_searchindex ADD COLUMN keywords_vector tsvector; $$,
    $$ UPDATE craft_searchindex SET keywords_vector = CAST (keywords as tsvector); $$,
    $$ ALTER TABLE craft_searchindex ALTER COLUMN keywords_vector SET NOT NULL; $$
;

This one assumes your MySQL username and password are root, the host is mariadb, and the source database is craft3. The PostgreSQL username and password are craft3 and secret, the host is postgres, and the target PGSQL database is craft3.
Be sure to adjust the  craft_ table prefix to match whatever you’re using on your MySQL database.
If you need to specify a port for either DSN, append a colon and that number to the hostname. (For example, specifying port 3306 for mysql would become mysql://root:root@mariadb:3306/craft3).

Tell pgloader to read the MySQL database into PostgreSQL:
pgloader /path/to/command-file

Example conversion output, which includes useful stats and warnings.

*Why use a command file?
You could run pgloader mysql://root:root@mariadb/craft3 postgresql://craft3:secret@postgres/postgres/craft3, but column names would all be lowercased, some critical type conversions and search index updates would be missing, and using a password in any terminal command is usually a bad idea since it will be visible in that shell’s command history.


How to disable plugin Disable and Uninstall? I am developing a site with a customer logged in area. I don't want anyone to access the section if they are logged out and instead redirect them to the login form.

I could just add {% requireLogin %} to the top of all the member templates, but its open to error, especially if we have loads. I am concerned we may forget to add it, accidentally delete the line one day. Then private pages are public, not good.

So I thought I would add the function to a plugin I have created for this site, to remove it from the template, and I can also target the whole /account/ segment where member templates are located.

BUT, the plugin can be uninstalled or disabled. Various people will be Admins, and there is always the possibility someone could disable this for some reason, and then all private pages become public!

So can we disable the ability to disable and uninstall plugins in the CP? The plugin will contain this and other site essential functions that we cant just have someone delete. They need to be fixed into the system to prevent accidental disabling.

If not, is there an alternative way to add functions without using a plugin or controller, so we can override core actions like this without any CP control.

Thanks!

This can be easy, write a module which can't be disabled or uninstall. See what's difference between module and plugin https://docs.craftcms.com/v3/extend/#modules-vs-plugins or https://nystudio107.com/blog/enhancing-a-craft-cms-3-website-with-a-custom-module


Temporary Uploads - disable? When browsing the assets, there is a "Temporary Uploads" folder. What is it for? Can I disable/hide it?

Each user account gets their own "temporary uploads" folder that by default will be a subfolder under storage/runtime/assets/tempuploads.

There are several places there this is used in Craft... one example is if an Asset field has its "Upload Location" set to something dynamic based on the value of another field.  When saving a new element, Craft won't know the value of that upload location until after the element is actually saved, so it keeps the uploaded file for the Asset field in the "temporary uploads" folder, then moves it out of there after the element has been successfully saved.

  Can I disable/hide it?

You can't disable it natively, but you'd probably be able to use some CSS to hide it if you really wanted: https://github.com/doublesecretagency/craft-cpcss


Can guests upload files to assets in an entry form? I'm using Craft Guest Entries plugin and the Entry Form technique elsewhere on my site. I'm currently trying to add a file upload to it. The entry is publishing but nothing is making it to assets.

Here's the code:

<form class="ajax-form" method="post" action="" enctype="multipart/form-data" accept-charset="UTF-8">
    <input type="hidden" name="action" value="guestEntries/saveEntry">
    <input type="hidden" name="sectionId" value="17">
    <input type="hidden" name="enabled" value="1">
    <input type="hidden" name="fields[whitepaperCategory]" value="{{entry.title}}">

    Name
    <input type="text" id="name" name="title" required>

    Email Address
    <input type="email" id="email" name="fields[email]" required>

    Resume and Cover Letter (.pdf)

        Upload Resume and Cover Letter
        <input type="file" id="resume" name="fields[resumes][]" class="upload" multiple>

    <button type="submit" class="btn btn-submit">Submit</button>
</form>

Is there anything obvious I'm missing?

I just tested this locally and it's working fine (with the caveat that the latest build 2.1.2568 introduced a separate, unrelated bug that broke front-end asset uploading that's been fixed in build 2.1.2569).

Most likely something is failing validation when the entry is saving.

Try using this to see if there are any errors:

<form class="ajax-form" method="post" action="" enctype="multipart/form-data" accept-charset="UTF-8">

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

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

    <input type="hidden" name="action" value="guestEntries/saveEntry">
    <input type="hidden" name="sectionId" value="17">
    <input type="hidden" name="enabled" value="1">
    <input type="hidden" name="fields[whitepaperCategory]" value="{{entry.title}}">

    Name
    <input type="text" id="name" name="title" required>

    {% if entry is defined %}
        {{ errorList(entry.getErrors('title')) }}
    {% endif %}

    Email Address
    <input type="email" id="email" name="fields[email]" required>

    {% if entry is defined %}
        {{ errorList(entry.getErrors('email')) }}
    {% endif %}

    Resume and Cover Letter (.pdf)

        Upload Resume and Cover Letter
        <input type="file" id="resume" name="fields[resumes][]" class="upload" multiple>

    {% if entry is defined %}
        {{ errorList(entry.getErrors('resumes')) }}
    {% endif %}

    <button type="submit" class="btn btn-submit">Submit</button>
</form>


'Unknown error' caused by redirect in htaccess I was getting an 'unknown error' when trying to access the admin. I couldn't see anything in the Craft logs apart from 404 related errors.
I replaced the app folder but still no luck, eventually I discovered it was a rewrite rule in my .htaccess causing the problem.

# redirect PHP or HTM to no extension
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.(php|htm?)
RewriteRule ^ /%1 [L,R=301]

I'd love to understand why, and how I can get around this in the future?

It might be down to the order you have the code in your htaccess file? Did you try putting your code above the Craft rewrite code?

# redirect PHP or HTM to no extension
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.(php|htm?)
RewriteRule ^ /%1 [L,R=301]

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

Also I tend to exclude certain directories when I don't want rewrites to apply. One way to do this would be;

# ------------------------------------------------------------------------------
# | Exclude directories from the rewrite rules                                 |
# ------------------------------------------------------------------------------
RewriteRule ^craft - [L]


Get entries which have a certain category assigned to them So, i have a channel called images and a couple of category groups one of which is called "images" which has categories called family, animals, individuals in it.

So, i just want to grab the entries that have one of those categories assigned / related to them.

Figured something like this would do it

    {% for entry in craft.entries.section('images').relatedTo('photography').find('family') %}
        <h3>{{ entry.title }}</h3>
    {% endfor %}

But i figured wrong! Any ideas would be gratefully received!

This should do what you are looking for:

{% set category = craft.categories.slug('family') %}
{% set entries = craft.entries.section('images').relatedTo(category).find() %}

{# If there are any entries, loop through them #}
{% if entries | length %}

    {# For each entry we find, do this #}
    {% for entry in entries %}
        <p>{{ entry.title }}</p>
    {% endfor %}

{% endif %}

So we are creating a variable called category, in which you set the category you want to get the list of related entries from.

Next we set a variable called entries, which checks to see if there are any entries in the Image section that relate to the category we set.

It then loops through the entries that we find (if there are any).

EDIT

More than one category group might have the Family category. To get round this you can target a specific category group when we set the category variable:

{% set category = craft.categories.group('categoryGroup').slug('family') %}


craft.entries and lightswitch This is super simple, and I don't get why it's not working.

{% set results = craft.entries.section('events').lightSwitchField('1') %}

Returns all entries in Events where the light switch field is green.

{% set results = craft.entries.section('events').lightSwitchField('0') %}

Returns all entries in Events. Period. Not all entries that the lightswitch is set to off.

I want to get all entries where the lightswitch field is off. Later I'm going to chain some other fields to the query too.

What have I not understood about how this works?

This is a known behavioral issue. PHP considers 0, "0", false, and similar values to be “empty”, and Craft only factors most criteria param values into the query if they are not empty. So setting a Lightswitch field’s criteria param to '0' is the same as not setting it at all.

The workaround is to use not 1:

{% set results = craft.entries.section('events').lightSwitchField('not 1') %}


Entries related to an entry in a list of entries I try go get entries (of channel B) related to an entry (of channel A) within a list of entries (of channel A). All entries of channel B have a relationship field and at least one relation to an entry in channel A. But I get no results from channel B.

{% set entries = craft.entries.section('candidates').order('postDate asc') %}
{% for entry in entries %}
    {% set feedbacks = craft.entries.section('candidates_feedbacks').relatedTo(entry.id) %}
    {{ entry.title }}
    {% for feedback in feedbacks %}
        {{ feedback.title }}
    {% endfor %}
{% endfor %}

What am I doing wrong?

Thank you very much for your feedback.

Thank you very much for your support. The code shown in the question is correct.

I have replaced the relationship field - and now it works perfect. The problem could have been that I defined the field first as a number field an then changed to a relationship field - but this is just speculation.


How can I filter Craft Commerce products by price I'm trying to use price as a parameter for filtering my Craft Commerce products, but I cannot get it to work. I think the problem is with the way that I'm referring to the product price, but at the same time I'm not sure how to change it so that it will work.

Is it possible to filter by product price as I'm trying to do here ?
Does anyone know what exactly I need to change to get my query to work ?

Any pointers in the right direction would be most appreciated.

{% set queryParams = {
    relatedTo: category,
      price: [
       'and',
       '>= ' ~ 200,
       '<= ' ~ 500,
      ]
 } %}

{% set products = craft.commerce.products(queryParams) %}

{% for product in products %}
    ....output product data
{% endfor %}

Looks like defaultPrice is the property on the Commerce_ProductElementType class you can use for this:

i.e.

{% set queryParams = {
    relatedTo: category,
        defaultPrice: [
            'and',
            '>= ' ~ 200,
            '<= ' ~ 500,
        ]
    }
%}


Accessing and Manipulating a Variable Hopefully simple variable / concatenation question: What is the best way to retrieve the url of a specific asset the name of which should be concatenated from an asset field variable and a text string?

I need to end accessing the url of an asset like so – {{asset.portraitThumbSmall.url}}, but I am in a loop where “portrait” could also be “landscape” ...or “square”, and is derived from an asset field variable on an asset called “thumbnailCrop”. With me so far?

So something like...

    {{asset.thumbnailCrop ~ "ThumbSmall" ~ .url}}

…only, unlike this, it should actually work.

I did read this -> How can I incorporate a variable into a string? …but I’m trying to incorporate a string into a variable. Not sure it applies.

Someone in the Slack channel suggested...

    {% set thumbnail = attribute(asset, thumbnailCrop ~ "ThumbSmall") %}
    {{ thumbnail.url }}

But it doesn't work, and I was also wondering if it wasn't possible to make something more compact.

Any help would be appreciated!

Give this a shot...

{% set transform = (asset.thumbnailCrop.value ?: "portrait") ~ "ThumbSmall" %}
{{ asset.url(transform) }}

If asset.thumbnailCrop is a dropdown field (or similar), you'll need to specifically extract the value from it. If no value is found, it'll fall back to using the "portrait" string.


Entry URI format with postDate not working I have a News channel that's looped on an 'News Index' template. Each news entry is linked to its respective link via {{ entry.url }}. In my News channel settings, I have the entry URI format to be news/{postDate.year}/{slug}. However, the {{ entry.url }} link goes to news/{slug}. I assumed that if you set the URI format in the channel settings, it would create entry URLs based on the specified URI format. But that doesn't seem to be working. Can someone let me know where I'm going awry?

Craft 3 removed the extended DateTime class, so {postDate.year} doesn't work with Craft 3. It must be formatted as {postDate|date('Y')} in the Entry URI format field.


Overriding isSystemOn setting for a single page I have a staging site that has the isSystemOn set to false since I don't want people to stumble upon the site and be able to view content. I would like to have 1 page still "visible" though. This URL would a simple health check page, that I direct a monitoring service to check on. I'm stumped at overriding a system level isSystemOn config setting.

Can I have staging.example.com/my-secret-health-check-url return a valid code of 200 so my monitoring service can correctly see that my staging site is working?

I realized there is a simpler solution after stepping away from this issue for a bit. There is one page that still returns a 200 code on a Craft site even when the isSystemOn (or isSystemLive as of Craft 3.1) is false. Using the control panel login page as a health check url is the solution.


How can I skip a required field if is not in the form? The problem is that I have a register page where I have 3 fields, Username, Email, Password. There is another page with some more fields which are required. So when I try to register a user form my register page I get errors about my required fields which I don't have in the register page. How can I skip them form cheking on my register page, but still have them as required on my profile page? Thank you in advance!

If they're required, then they're required... it doesn't matter if the form is being submitted on the front-end or back-end.

The easiest solution to this would be to simply provide that data as hidden inputs...

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


User activation via email does not work when system status is "off" System Status is set to off
Create a new user, with permissions to Access the site when the system is off and Access the CP

As long as the system is off, the activation email sent to the user is broken, and instead goes to the "Service Unavailable" page.

Is this by design? It seems like if those specific permissions are granted when creating the user, they should still be able to activate.

This has been changed on the upcoming Craft 2.3 release such that if the system status is set to off, account verification and set/forgot password logic will still run.


Creating a sitemap/index page, ordered by A-Z and 0-9 I'm created an Index like page (like at the back of a book) for entries within a certain section, ordered alphabetically with the letter proceeding it.

My code below seems like a tedious way to do it, is their an easier way?

How would I handle the entries with a number as the first character (0-9) of the title?

A

      {% for entry in craft.entries.section('artists').search('title::A*').order('title').find() %}

...

        {% endfor %}

B

      {% for entry in craft.entries.section('artists').search('title::B*').order('title').find() %}

...

        {% endfor %}

C

      {% for entry in craft.entries.section('artists').search('title::C*').order('title').find() %}

...

        {% endfor %}

The way to do this is with the group filter. You want to group the entries by the first character of the title.

Get the entries as an actual array

{% set allEntries = craft.entries.section('artists').order('title').find %}

Group them by first letter of title. first will return the first character of a string. upper converts a string to uppercase.

{% set groupedEntries = allEntries|group('title|first|upper') %}

Now you can loop through them:

{% for index, values in groupedEntries %}

{{index}}

    {% for e in values %}

...{{e}}...

    {% endfor %}

{% endfor %}

See also this question.


Set the application name for Craft in New Relic Like many of you, we've started to use New Relic to deep dive into performance of our websites.

Right now, we have a client's production server that has a version of Craft, ExpressionEngine and Wordpress.

Right now WP and Craft get lumped together as a 'PHP application'. Is there any config setting to allow us to set 'Craft CMS' as a thing to differentiate?

We've been able to do this with EE.

This method uses New Relic's PHP API, rather than php.ini, and is working well for me. It seems to be catching everything that I need to monitor. Any applications I've not done this for remain in the default application.

Just stick this in Craft's index.php file:

if (extension_loaded('newrelic')) {
    newrelic_set_appname('NAME OF SITE');
}

I haven't tried it with ExpressionEngine or Wordpress, but the principle would be the same?


How do I get entries of a child category, related to a parent category, defined in a URL segment? My entry url structure looks like this:

http://site.com/section/category/subcategory/entry_slug

I'm trying to drill down to specific entries by using the url structure and I'm currently having trouble getting the following to work:

{% set secondSeg = craft.request.getSegment(2) %}
{% set subCategories = craft.categories.group('section').level(2) %}

{% for cat in subCategories.relatedTo(secondSeg).slug(lastSeg) %}
    {{category.title}}
{% endfor %}

Currently nothing is returned. If I remove the .relatedTo(secondSeg) parameter in the cat loop, I'm properly getting all of the entries in child category that match the slug. But, the problem is that there is a possibility of certain entries having the same slug under different child categories. I'm not sure if I'm using the relatedTo parameter properly or not.

I don't think that there's a "relation" between categories and their sub-categories.
But that's what you currently have as a parameter on craft.categories.
Use the ancestorOf() parameter instead to filter your subcategories:

{% set mainCategory = craft.categories.group('section').level(1).slug(secondSeg).first() %}
{% set secondLevelCategories = craft.categories.ancestorOf(mainCategory).slug(lastSeg) %}


Craft 3 upload path on webserver My hoster has i public html folder where all websites are lying. Different Websites are separeted by subfolders. Should i upload all Craft3 installation files to this public html folder and point the webserver to the /web folder?

Or should i upload only the /web folder to my webhoster's public html folder and place all other files ABOVE, like it's explained in the Craft 2 installation guide?
If yes, how do i configure the craft path in the index.php file?

Thank you very much for a explanation!

Only upload the /web folder to the /public_html folder.

All other folders should be one level lower so they're not publicly accessible.

Personally, I'm also wondering why not everything resides in a nice clean /craft folder anymore. Now the craft directories are listed amongst a bunch of other stuff on a lowerlevel directory. It's probably the only one really strange architectural choice. I guess P&T is not using WHM/Cpanel etc.

Anyway: do not upload anything except /web in your public folder.

If you do it like this, the index will work correctly out of the box, since it'll be looking for the /app and all folders one level lower then the /public_html by default.


Using multiple sections VS a single section with entry types I'm just planning ahead for a project and was hoping for a second opinion.

I'm going to be making a site that will have about 7 different types of entry - all of which have different fields/URL's; however on the front-end they will all behave as if they are part of one channel. I will have a single page that lists all of the entries and I will also be giving end-users the ability to perform searches/filtering.

For the sake of easy dashboard management I have currently set them up as separate sections instead of one section with multiple entry types (because using individual sections gives me a nice separated 'Entries' page in the dashboard - it's hard to sort/view by entry type at the moment).

Question: Seeing as I can get the site to work the same regardless of which method I use, is there a dramatic difference between pulling out entries from multiple sections VS pulling out entries from one?

For this example lets just say we are dealing with around 100,000 entries total.

It's hard to answer without examples of your content types.

I would suggest that if you would ever need deliberately relate one Entry to another using the Entries field type, then making use of separate Sections for each type of content would be the way to go.

e.g. If an "office location" entry is the parent to multiple "services"

A more obvious factor is when an entry type needs to be a Channel vs a Structure. This can only be set at the Section-level

Hope that helps


Plugin Controller Ajax Request I've got a custom controller in my plugin that checks whether or not the request is ajax or not, using craft()->request->isAjaxRequest()

In the event that it is, I just want it to return a partial. First though, I'm trying to just get it to return a string but seem to be having issues getting something as simple as that to work (I'm pretty new to PHP). The code I have on the condition of it being an ajax request is:

$path = craft()->path->getSiteTemplatesPath();
craft()->path->setTemplatesPath($path);
$temp = craft()->templates->render('notifications/_test');
echo $temp;

I'm logging the response in javascript but keep getting a 404. If I try to open the link (custom controller url) in a new tab (so not and ajax request) it correctly executes the non ajax condition.

The GET request looks like this: $.get($(this).attr('href'), function(data)...
where the href is the controller action url.

Does anything look amiss? Am I perhaps missing a step to allow for this to work? I've tried $allowAnonymous on the controller to no avail.

You can't echo out of the controller function. Though, you can send back the rendered template via a convenient controller function.

$this->renderTemplate('notifications/_test');

To add variables for your template to access (because it's not automatic for security reasons). You can do this.

$this->renderTemplate('notifications/_test', array(
    'message' => $message
));


What's the difference between a Component and a Model in Craft 3? I'm trying to familiarize myself with the Craft architecture and I can't understand whether I should be extending craft\base\Component or craft\base\Model for my business logic models. Component seems like a pretty lean class that only adds a few initialization events to Model.

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

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


Datagrab style plugin for importing CSV data to sections (Channels) I use Datagrab on an EE site to import data to a Channel/fields and category assignment – is there an equivalent plugin or approach for Craft CMS, typically I want to allow the editor to import wine lists and display as listing pages (category title via EE e.g Burgundy) and click throughs from here to entry pages

I'm not familiar with Datagrab, but from your description it sounds like the Import plugin might work for you.


Troubleshooting Slow Craft Website - New Relic I am troubleshooting a client website and I have installed new relic on VPS.

Summary:
RESP. TIME = 12,300ms
USER CPU BURN = 7,000ms (56.9%)
SYSTEM CPU BURN = 115ms (0.935%)

Slowest components  Count   Duration    %
YiiBase::autoload   116     2,570 ms    21%
Craft\ElementsService::buildElementsQuery   175 1,960 ms    16%
Craft\ElementsService::findElements 175 1,690 ms    14%
Craft\BaseElementModel::setContent  153 1,300 ms    11%
__TwigTemplate_8a189a6b8bb1cda953a4a38f8aa3c4ccaccd30c1b5a2b790673a05284bb0de6b::block_menu 1   519 ms  4%
Composer\Autoload\includeFile   19  432 ms  4%
Remainder   1   3,840 ms    31%
Total       12,300 ms   100%

I have attached a trace.

It looks like a lot of time is spent on autoload. Any ideas what will cause this? Or what should I be looking at to fix this issue?

I don't know where the first set of data you posted is coming from, but in the attached stack trace autoloading is only .54% of the total request.

Whatever template(s) you're rendering account for 65% of the request (for a total of 8 seconds), so I'd start inspecting there.

Loading all of the plugins you have installed is about 10% (which accounts for about 1.3 seconds of the request), so I'd investigate those as well.


How to structure data: Solo Events (Lectures) and Group of Events (Conferences) I am working on my first craft project and am wondering how to create the following data structure:
I have a page with a large archive of solo-events (lectures, discussions etc). I think I will use a channel with categories for this.
In addition, there is a second content type: a conference. A conference is a group of solo-events. For example, several lectures and discussions.
The conference as a container has certain fields (picture, text) and the solo-events have other fields (speakers for example).
I wonder what is the best way in Craft to enable this form of container.
Example:
Solo-Events:

Event 1 with Speaker a
Event 2 with Speaker b

…
Conferences:

Conference A

-- Event A1 with Speaker c
-- Event A2 with Speaker d

Conference B

-- Event B1 with Speaker e
-- Event B2 with Speaker f
…
In the Frontend I would like to have:
Speakers-Archive:
I think this will be the easy one. For the speaker I would like to work with a channel and link them to the events.
Solo-Events and Conference-Archive:
A list with all solo-events and all conferences but without the sub-events.
So, this list should contain: Event 1, Event 2, Conference A, Conference B (A1, A2, B1, B2 should be excluded)
I am wondering how to deal with this idea of grouping the events to conferences:
I was thinking:

Two channels, events and conferences.
All events (solo and conference-related) are in one channel. For a conference (second channel) I can select the events which I want to include. For the archive list I need to exclude all the solo-events that are part of conferences.
This may not be optimal in terms of performance and user experience in the backend

Structure for Confernces and a Channel for Solo-Events
The conferences are the parent elements, the solo events are the child elements.
But how can I create different fields for the parents and children?

Structure with Entry Types:
I wonder if i can work with entry type here as well.
But But how can I bring the Entry Type together with the Hierarchy? So that Parent is always a conference and a children is an Event?

Matrix Field:
The Conferences has a matrix field to store the individual events. But I dont like this approach because I think it would be hard to get all the speaker from a conferences matrix field and combine them with the speaker from the solo-events to get one list with all speaker

Categories.
all events are stored in one channel and I create a Categorie for the Conferences.
It feels kind of wrong-headed because the Conference (in my understanding) is the parent of the event rather than the category.

What do you think?
At the moment I am trying the second approach:
{# get all conferences (parents) (level =1 )  from a structure and merge with all solo-events from a channel#}

{% set entriesConferences = craft.entries.section('conferences').level(1).ids() %}
{% set entriesEvents = craft.entries.section(['events']).ids() %}

{# Combine those IDs #}
{% set entryIdsCombined = entriesConferences | merge(entriesEvents) %}

{# Get all entries (so, no IDs this time), using your IDs, order by date#}
{% set allEntries = craft.entries.id(entryIdsCombined).order('datumUhrzeit desc') %}

Is there a better (in terms of performance, scalability and user experience in the backend) way to archive this?
I asked this question Oli from the craft team and he gave me an answer that he will hopefully add here as well.
Thanks!

My approach:

Create one channel for events with different entry types (solo-events, conference-events)
Create one channel for conferences
Re-use the date fields in both channels
That way you can fetch and order events by the re-used date fields from both channels limiting to the entry types of solo-events and conferences with one query. That makes listings, filtering and paging easy.
Conference-events can be eager-loaded with the query as well
The entry type for conference-events has a mandatory entry field for the conference
In the control panel you can show the related conference by adding the field as a column in the overview
Speakers is another channel or structure being linked from within the conference-events

Why I would not use:

Matrix: can be easily queried but can not eager load the entry it belongs to
Category: feels wrong to always add categories for new conferences
Structures for events: Structure are not 100% user friendly when adding new entries, as they always need to be sorted manually (though there are some improvements in 3.7 coming up)


Newbie: Trying to understand includeCssFile I'm a newbie to Craft and am working with a raw version of Craft CMS 2.6.2903 on localhost and am trying to understand some of the basics. The problem that I am encountering at the moment is to do with the Twig includeCssFile command.

I want to create a folder that will contain all my CSS details, so I went to _layout.html and moved all the CSS script from between the
style tags into a new script which I saved at craft/templates/styles/index.css. I then deleted the style tags from _layout.html.

I added this line to the <head> section of the _layout.html script:

{% includeCssFile "styles/index.css" %}

So that the <head> section looked like this:

<head>
<meta charset="utf-8" />
<title>{% if title is defined %}{{ title }} - {% endif %}{{ siteName }}< /title>
<link rel="home" href="{{ siteUrl }}" />
{% includeCssFile "styles/index.css" %}
</head>

and once again the Home page worked perfectly.

The problem occurred after I moved the whole styles folder up one level (i.e. to the same level as the templates folder).

I changed the calling code to
{% includeCssFile "../styles/index.css" %}
and refreshed the home page and had lost all the page styling. I played around with removing the '../' and changing it to './' and even '/' but it still didn't work. When I returned the styles folder to the templates folder, it all worked okay again.

There have been a couple of similar questions already posted on this group, but they haven't resolved my problem (link 1, link 2)

Can someone please tell me what I need to do?

Whenever Craft receives an URL request, it tries to figure out what resource to serve the client. Among other things, it'll look inside your templates folder and try to find the requested resource there – which is why a request to styles/index.css works if that file exists inside your templates folder. However, Craft only looks at files in your templates folder when it evaluates the request URL, nowhere else – which is why ../styles/index.css doesn't work.

In any case, it's usually a bad idea to serve external resources (CSS, JS files etc) from outside your public web root. If you can, put your CSS and JavaScript files somewhere in your public root directory, and make sure you're not using relative URLs for {% includeCssFile %} – i.e. you should use {% includeCssFile '/styles/index.css' %} if you have a folder called styles in your public web root (alongside your index.php file).

Another option is to inline your CSS files, in which case you can put the files whereever you want. I recommend the Inlin plugin for all your inlining needs:

<head>
    <style>
        {{ craft.inlin.er('styles/index.css') }}
    </style>
</head>

If you want to inline files without a plugin, you can use the Twig source function – outlined in this answer.


How to link to an anchor on an entry page from within Rich Text editor I need to link to a particular #anchor on a page from within the WYSIWYG editor.

However, if I start by using Link to Entry in the Rich Text editor, Redactor adds its own 'anchor' (with the same syntax as the Reference Tag for the entry page), and any additional anchors I add to the URL using the Edit Source functionality are ignored.

How would you suggest creating enabling users to create links to specific parts of Entry pages from within the Rich Text editor?

As of Craft 2.5.2759 this is now possible.

  It is now possible to include custom URL fragments in links to entries within Rich Text fields, alongside the entry's reference fragment (e.g. href="my-entry#custom-fragment#entry:123").


Get the Sub-Category Link from Category field in a Structure (output with Nav tag) I am creating a Structure for the main navigation that has two possible choices for the Link: Entries field or a Categories field. The answer I received here showed me how to setup the basics but if the Category page I want to link to is a Sub Category, it will only link to the Parent.
{% set menu = craft.entries.section('navDropDownMenu').all() %}

    {% nav link in menu %}

        {% if link.entriesURL|length %}
            {% if craft.app.request.absoluteUrl ==  link.entriesFieldURL[0].url %}
                {{ link.title }}
            {% else %}
                {{ link.title }}
            {% endif %}
        {% else %}
            {% if craft.app.request.absoluteUrl ==  link.categoryFieldURL[0].url %}
                {{ link.title }}
            {% else %}
                {{ link.title }}
            {% endif %}
        {% endif %}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

So what I'm trying to figure out is, if I have a category setup like this:
-Shoes
    -Tennis

in the context of using the Nav Tag (as above), how do I get the link to 'Tennis' and not 'Shoes'?
I know you can output a nav of Categories, but I wanted to use a Structure if possible because the navigation has a mixture of categories and links to internal pages, and they are mixed together in the navigation as far as sorting goes.

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

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

{%- for item in menu -%}

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

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

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

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

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

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

            {%- endfor -%}

        {%- endif -%}

{%- endfor -%}

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

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

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

{%- for item in menu -%}

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

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

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

            {%- endfor -%}

        {%- endif -%}

{%- endfor -%}

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


Redactor plugin Code Mirror read only I have redactor with plugin code mirror installed
however i want to put code mirror read only.

How can i do that the read only?
Thanks in advance.
Carlos Vieira

This is the solution

$('.CodeMirror > div > textarea').attr('readonly','readonly');

in init{} redactor calback


Using ImageOptimize, how do you loop through photos? I'm stumped on a basic concept for looping images. I'm using the plugin ImageOptimize with Imgix and Amazon S3. The code below works but only shows one image (when there's more for that field).

For the code below, how are you suppose to loop through the assets without showing the different srcset image sizes?

{% set optimizedImages = entry.clientWork.one().imgixTransforms %}

    <picture>
        <source srcset="{{ optimizedImages.srcsetWebP() }}"
            sizes="100vw"
            type="image/webp" />

        <img src="{{ optimizedImages.src() }}"
            srcset="{{ optimizedImages.srcset() }}"
            sizes="100vw" />
    </picture>

So the OptimizedImages field in ImageOptimize is added to your asset as a field (just like Entries can have fields), because it's added to your Asset Volume layout.

So you'd iterate through the images the same way you would iterate through any assets in Craft. I'm a little unclear on what part you're stuck on here? If you could clarify, I could help you more.

So let's say we have an Asset's field with a handle of heroImages, to output all of those images we'd do:

{% for heroImage in entry.heroImages.all() %}

{% endfor %}

So then let's say you have an OptimizedImages field with a handle of optimizedImages that's in your Asset Volume's layout, so it becomes a field that's in your Assets. Then we could just do:

{% for heroImage in entry.heroImages.all() %}

{% endfor %}

And it'll output all of the same images as in the previous example, but using an optimized srcset of the images.