Set Locale in template I was wondering if there 's a quick way to just set a locale in your template for example:

{% set locale = 'en' %}

and then use that locale to get the correct content. I know that Craft automaticly uses the right locale based on the url, but I'm importing some templates from Craft with curl into another site and so the Craft template is unaware of the locale. That's why I would like to set it, if possible without the use of an extra plugin.

You can’t set the craft.locale from the template. You can set the locale for your Element Criteria though.

{% set entry = craft.entries.id(14).locale('en').first() %}


When I try to edit an entry: "Unable to find 'craft\services\EntryRevisions'" I have just moved my site onto the live server and imported my local db. It is a multi-site setup.

In the Entries section of the CP, when I click on an entry to edit it I get the following error page:

  Unknown Class – yii\base\UnknownClassException
  Unable to find 'craft\services\EntryRevisions' in file: /home/careacas/vendor/craftcms/cms/src/services/EntryRevisions.php. Namespace missing?

Any ideas?

Try to replace or upload all the files again. A file is not fully uploaded and the reason of this error is that.


Multiple domains for a single locale Hi I'm creating a site that will be used in 4 locales which each have their own domain.

Australia: project.com.au
New Zealand: project.co.nz
South Africa: project.co.za
USA: project.co

In short, from a content management perspective I only want two locales. English AU and English USA. However, I need the content on the au locale to be accessible from the au,nz,za domains.

Is it possible to have an array of URL for one locale config?

Use a Multi-Environment configuration to set the siteUrl for your two locales, en_au and en_us, independently for each domain like so:

'project.com.au' => array(
    'siteUrl' => array(
        'en_au' => 'http://project.com.au/',
        'en_us' => 'http://project.co/',
    ),
),

'project.co.nz' => array(
    'siteUrl' => array(
        'en_au' => 'http://project.co.nz/',
        'en_us' => 'http://project.co/',
    ),
),

'project.co.za' => array(
    'siteUrl' => array(
        'en_au' => 'http://project.co.za/',
        'en_us' => 'http://project.co/',
    ),
),

'project.co' => array(
    'siteUrl' => array(
        'en_au' => 'http://project.com.au/',
        'en_us' => 'http://project.co/',
    ),
),

You can also set additional environment / domain specific variables in the config file. You could set the currency or the timezone for each domain:

'project.com.au' => array(
    'currency' => 'AUD',
    'timeZone' => 'UTC+10',
    'siteUrl' => array(
        'en_au' => 'http://project.com.au/',
        'en_us' => 'http://project.co/',
    ),
),

This is how you access such a variable in your templates:

{{ craft.config.currency }}


Serialization of 'Closure' is not allowed when upload image I built up a form at the frontend to allow users to upload their avatars,my code looks like below

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="users/save-user">
    <input type="hidden" name="redirect" value="users/{{ currentUser.username }}">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">
    ...some other fields
    <input type="file" name="photo">

    <input type="submit" value="upload">
</form>

But I got error 'Serialization of 'Closure' is not allowed' from '/Users/rain/dev/valet/tr3ndsideas/vendor/yiisoft/yii2-queue/src/serializers/PhpSerializer.php' . Any idea please

I found the problem which is because of a package called "Scout". I just update it and everything seems to be fine now.


Craft can't connect to db.php on live server My Craft files are structured correctly, I have the Craft file level with the public_html file on the server (which contains the index.php file), within index.php I have set my $craftpath correctly to $craftPath = '../craft';.

But when I go to my live url I get a Craft styled error of:

Service Unavailable
Our site is temporarily unavailable. Please try again later.

When I try to reach my admin I get an error of:

Error error
Craft can’t connect to the database with the credentials in craft/config/db.php.

If it helps, my general.php file looks like this:

return array(
    '*' => array(
        'omitScriptNameInUrls' => true
    ),

    // development
    'example.dev' => array(
        'environmentVariables' => array(
            'devMode' => true,
            'siteUrl'  => 'http://example.dev/',
            'assetPath' => 'http://example.dev/assets/'
        )
    ),

    // production
    'example.com' => array(
        'environmentVariables' => array(
            'devMode' => false,
            'siteUrl'  => 'http://example.com/',
            'assetPath' => 'http://example.com/assets/'
        )
    )
);

And the db.php file is as such:

return array(
    '*' => array (
        'tablePrefix' => 'craft',
    ),
    'example.dev' => array (
        'server' => 'localhost',
        'user' => 'root',
        'password' => 'root',
        'database' => 'localdatabase',
    ),
    'example.com' => array (
        'cooldownDuration' => 0,
        'server' => 'server',
        'user' => 'user',
        'password' => 'password',
        'database' => 'database',
    )
);

I hope you can help becuase I'm lossing my mind as to whats wrong, but I'm sure it's something minor that I'm overlooking.

The cooldownDuration setting should go in your general.php config file, not in your db.php config file. On your server, is the db on a separate server or is it on the same server? If so, the value for server in example.com should be localhost not server.


postDate keeps jumping ahead when editing an entry When I edit an existing entry the post date jumps ahead by an hour meaning I have to manually remove it before saving the changes.

I thought it may have something to do with the timezone but this is set to the correct timezone.

Has anyone come across this?

Adding as an official answer since we've had a handful of reports about this.  Best we can tell it's a bug in Firefox that happens when you live in a non-UTC timezone.  There are several Date related bugs in Mozilla's bug tracker, but this one looks to be the most relevant: https://bugzilla.mozilla.org/show_bug.cgi?id=1227499


Can't view image assets in web browser (403 error) after uploaded in Craft CMS Dashboard Can't view image assets in web browser (403 error) after uploaded in Craft CMS Dashboard.

I've checked permissions according to previous thread:
403 Forbidden Assets

Help please!

Fixed the image issue. Such a simple oversite.

I just needed to change the Asset Source settings and change the URL to include :8888 since I was running a local build with MAMP Pro.


Update Search Index on Entry Save Wondering if there is any way to force Craft to update the search index for an entry when it is saved.

Reason I ask is that on our site we have a Location entry type with lat/lon inputs that we use to maintain store locations and plot them on a map. However, when we update the lat/lon coordinates, it does not update the search index and continues to plot the old location on the map even though it is displaying the new address in the text.

We can force it to update by rebuilding the search indexes, the only downside is that it takes a few minutes and renders the site search functions useless until it is done. If there's some way for the entry to automatically update the index when lat/lon coordinates are changed, that would be awesome. Any ideas?

You can do a task resave after elements are entered:

public function resaveElements()
{
    // Queue up a new ResaveElements task
    craft()->tasks->createTask('ResaveElements', null, array(
        'elementType' => ElementType::Entry,
        'criteria'    => array('section' => 'search', 'limit' => null, 'status' => null,'localeEnabled' => null)
    ));

    // Start running tasks
    craft()->tasks->runPendingTasks();
}


User-selected Image Transform I've set up four custom image transforms on the page and would like the content editor to be able to select which size they want the image to be from a drodown field preconfigured with the transformation names. This is all within a Matrix field, btw. This answer was close, and helped me put .value on the end of my dropdown field variable, but it must only work with pre configured image transforms in Craft's settings.

Here is the code (simplified):

{# medium 16:9 #}
{% set landscapeMd = {
  width: 439,
  height: 247,
  quality: 80,
} %}

{# medium 9:16 #}
{% set portraitMd = {
  width: 278,
  height: 494,
  quality: 80,
} %}

{% for block in entry.productCollage %}
  {% switch block.type %}
    {% case "digitalProduct" %}
      // selected via dropdown field
      {% set transformType = block.imageAspectRatio.value %}

        {% for image in block.image %}

        {% endfor %}

  {% endswitch %}
{% endfor %}

What I get with this code is an error that says the selected image transform is not available. However, if I type in that image transform verbatim, it works fine.

landscapeMd and portraitMd are variables... they would need to be strings (or array keys) for this to work.

Try something like this:

{# medium 16:9 #}
{% set landscapeMd = {
  width: 439,
  height: 247,
  quality: 80,
} %}

{# medium 9:16 #}
{% set portraitMd = {
  width: 278,
  height: 494,
  quality: 80,
} %}

{% set transforms = {
  'landscapeMd': landscapeMd,
  'portraitMd': portraitMd
} %}

{% for block in entry.productCollage %}
  {% switch block.type %}
    {% case "digitalProduct" %}
      // selected via dropdown field
      {% set transformType = transforms[block.imageAspectRatio.value] %}

        {% for image in block.image %}

        {% endfor %}

  {% endswitch %}
{% endfor %}

This maps the transforms with the transforms object, then references the key in transforms[block.imageAspectRatio.value].


Enupal Backup not backing up assets I am testing Enupal Backup.
In the settings, I can choose to back up assets, templates, etc. But when I run the backup, only the database is acutally backed up.
What am I missing here?
I submitted an issue regarding this at the repo, in case it's a bug.

Glad to know that it is working on your server. On Windows, you may need to add the paths manually. Please follow our docs about how to add the paths on Windows.


Image transforms returning cpresources url I'm trying to get Craft to render an image transform defined in the control panel. No image is added to the "filelocation/_transformhandle" folder and returns the url "/cpresources/transforms/98" where 98 is the transform index.

I have tried clearing the cache and db table already as well as updating the asset index. I have double checked the sources paths and it is not a file permission issue.

Code example as a matrix block:

{% elseif block.type == "slideShow" %}
{% if block.galleryImages|length>0 %}

{% for image in block.galleryImages %}
    {{ image.aboutText }}
    <img src="{{ image.getUrl('galleryHorizontal') }}">
{% endfor %}
{% endif %}

I tried using the other methods on this page in the docs with the same result. http://buildwithcraft.com/docs/templating/assetfilemodel

Thanks!

That’s what getUrl() returns if the transform hasn’t been generated yet. When the browser requests that URL, Craft will generate the transform, and respond with a 302 redirect to the actual image URL.

Update: As of Craft 2.2, even if the transform generation URL doesn’t get directly requested (e.g. if it’s a social media image, or a srcset size that doesn’t apply to the browser), it will still get generated automatically as a background task as soon as Craft is done serving the page.

The next time getUrl() gets called (after the transform has been generated), the image URL will be returned directly.

If you would prefer that getUrl() actually generates the transform itself and immediately returns the image URL (perhaps because the output is getting cached by Varnish or something), you can open up craft/config/general.php and add this to your config array:

'generateTransformsBeforePageLoad' => true,

(See http://buildwithcraft.com/docs/config-settings#generateTransformsBeforePageLoad for details.)


Form question - freeform /mailchimp Looking at this plugin.
https://solspace.com/craft/freeform

Need a form to do this, any help would be pic guys.

Fill in form - sends email to nominated email with enquiry

If sign up to newsletter is chosen then the name is added to mailchimp list and opt in email sent

If sign up response is negative form still sends email to us, but the users email is not added to the mailchimp list or is added with a status of unsubscribe.

Freeform includes mail list integration for MailChimp, Constant Contact (pro only) and Campaign Monitor (pro only).

As per their documentation, form fields can be mapped to your mail list. You can include a checkbox so visitors can choose to subscribe when submitting a form. If they do tick the checkbox, they will be sent a double opt in email (if this is enabled).

Do bear in mind though that MailChimp is rolling out single opt-in from 31st October 2017 unless you're within the EU.


validationKey on load balanced enviornments In the Craft docs for validationKey config settings, it states that validationKey should be used in load-balanced environments.

I'm curious on how to set this up for a load-balanced site. Does each  server need a different key, or should they all share the same setting in the config?

It should be the same for every server in the load balanced environment.

You should also set the appId config setting to a consistent value for every server in the cluster as well.

I've updated the documentation for those config settings to clarify.


How to Render a State Abbreviation in Craft CMS? Folks,

Is there a way to render a state abbreviation in a front end template on Craft CMS? Currently, I have a plain text field that has the full text of a state and I would like to render the standard two letter abbreviation.

Here is my current code:

{% if eventType.eventState | length %}{{ eventType.eventState }}{% endif %}

I would be open to changing the field type (or downloading a plugin) if that makes things easier but don't see an address field or something that on the surface would be conducive to easily filtering down to an abbreviation.

I don't think there's anything native (and haven't seen a plugin) that does this, but one way to do it is to create a macro where you add all the states and their abbreviations to a map. Something like this should work:

In a file called templates/_macros/helpers.html or the like (abbreviations map shortened in example; you can find a full list here, just need to convert it to Twig object syntax):

{% macro abbreviateState(stateName) %}{% spaceless %}

    {% set abbreviations = {
        'Alabama': 'AL',
        'Alaska': 'AK',
        'Arizona': 'AZ',
        'Arkansas': 'AR',
        'California': 'CA',
        'Colorado': 'CO',
        'Connecticut': 'CT',
        ...
    } %}

    {{ abbreviations[stateName|trim] ?? stateName }}

{% endspaceless %}{% endmacro %}

In your template (i.e. /templates/entry.html):

{# Import macro at the top of the template #}
{% import '_macros/helpers' as helpers %}

{% if eventType.eventState | length %}

    {{ helpers.abbreviateState(eventType.eventState) }}

{% endif %}

Of course, this solution hinges on the state names being typed properly (exactly the same way as they appear in the macro); if somebody were to write "New york" and you've got "New York" in the macro, a proper abbreviation would not be found and the state name "New york" would simply render as-is.

To mitigate this, you might consider opting for a different input field type other than Plain Text, e.g. a Dropdown where you set up all the states as options.

If you're sticking with a Plain Text field, you could also circumvent the specific issue of capitalisation being off by making the state names in the macro map all lowercase, and applying the |lower filter to the state name when you try to pull the abbreviation:

{% set abbreviations = {
    'alabama': 'AL',
    'alaska': 'AK',
    'arizona': 'AZ',
    'arkansas': 'AR',
    'california': 'CA',
    'colorado': 'CO',
    'connecticut': 'CT',
    ...
} %}

{{ abbreviations[stateName|trim|lower] ?? stateName }}


Installing Craft without MAMP I want to install Craft in home directory in mac. I don't like to use MAMP as local server.

Is to possible to install without using MAMP? I use gulp and webpack in home directory.

It depends what you are most comfortable with. PHP and Apache are shipped with macOS by standard but you'd still need to install and configure MySQL (or MariaDB etc), along with manual virtual host configuration.

MAMP makes it much easier but sandboxing it all in one easy to install package with a GUI so if you're not comfortable with the command line and the manual configuration then it's a good option.

If you are a little comfortable with the command line and want a minimalist setup then Laravel Valet could be worth a try. It is a wrapper which orchestrates installing the required components via Homebrew which enables you to just create a new folder in your web root folder with a .dev extension and then be able to view it in the browser. This can be a nice in between.

For more of an isolation you can opt for virtual machines and Vagrant images for example which run a virtual OS with all pre-requisites installed. It can be a little resource hungry however. Alternatively there is docker which provides a containerised environment (much the same but without the full OS layer).

It really goes down to what you're more comfortable with but any of the above will get you up and running with Craft.


Installing Craft in sub directory I need to install Craft under a laravel sub-directory http://example.com/corp/ where example.com is a laravel site.

Does anyone have a clean way to install craft in a directory below an existing app?

Here is my config from /corp/public/index.php

// Path to your craft/ folder
$craftPath = '../../../craftsite/craft';

// Do not edit below this line
$path = rtrim($craftPath, '/').'/app/index.php';

With $craftPath you set the path to the craft/ directory (containing the app/ folder etc.) whereby your index.php is the starting point if you set this as a relative path:

// Path to your craft/ folder
$craftPath = '../relative/path/to/craft_dir/';

As narration_sd pointed out, the craft/ directory should be above the web root for security reasons. But this doesn't mean that you cannot have your index.php at http://example.com/corp/index.php. Just configure $craftPath accordingly. For example:

Laravel at web root:
/var/www/laravel-site/public/index.php

Craft in a subdir:
/var/www/laravel-site/public/corp/index.php

Craft app above web root:
/var/www/craftsite/craft/app/index.php

Craft's path config:
$craftPath = '../../../craftsite/craft';

Remember to also update the paths to your assets in the Control Panel and the paths to your files linked to in your templates.


Filter users by a custom field? From within a plugin, I’m trying to filter users by a custom field.

An external post request will supply a variable which I want to match the custom field to. I then want to respond to that request with other user custom fields as JSON.

For example the incoming post contains customHandle1=A, I then find all the users where customHandle1=A and return customHandle2 and customHandle3 data.

How would I do that?

To get a user by a custom field, you would need to create a ElementCriteriaModel like this:

$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->fieldName = craft()->request->getPost('fieldName');

$users = $criteria->find();

you could then loop over $users and use getAttributes() to get the user data, and if you need the attribute names use attributeNames() if you need the users fields.


How do I call a service from my controller in a plugin? I'm writing a plugin, and used plugin.io to generate my scaffolding.  In my controller I am attempting to call a service, and getting an error.

This is my service code from my generated plugin it lives at fulcrumdonation/services/FulcrumDonation_FulcrumCyberSourceService.php:

class FulcrumDonation_FulcrumCyberSourceService extends BaseApplicationComponent
{
    /**
     *
     * From any other plugin file, call it like this:
     *
     *     craft()->fulcrumDonation_FulcrumCyberSource->exampleService()
     */
    public function exampleService()
    {
    }
}

And just as the scaffolding suggests, I'm attempting to call this function in the controller:

craft()->fulcrumDonation_FulcrumCyberSource->exampleService();

But when I add that line of code in the controller I get the following error:

  Property "Craft\WebApp.fulcrumDonation_FulcrumCyberSource" is not
  defined.

What am I missing here?

Try it with a lowercase f in the middle...

craft()->fulcrumDonation_fulcrumCyberSource->exampleService();


How to get absolute path to asset file? I have some csv files uploaded as assets and now I need to fopen() them from my plugin.

I have an AssetFileModel but I have not been able to work out how to construct a full path to the file.

I can access the filename like: $asset->filename which gives me my_csv_file.csv but this is not enough for fopen() to find it.

How can I get the absolute path to the asset file?

Or at least a path that I can use with fopen() to find the file?

You can get the rest of the path from your asset's source and folder, I think something like this should do it:

$source = $asset->getSource();

if ($source->type != 'Local')
{
    throw new Exception(Craft::t('Paths not available for non-local asset sources'));
}

$sourcePath = $source->settings['path'];
$folderPath = $asset->getFolder()->path;

$assetFilePath = $sourcePath.$folderPath.$asset->filename;


Emails not being sent when transaction complete Folks:

I'm wondering if this is a bug or something else. Essentially, test emails from the system work fine but emails that are supposed to be sent when the order moves to "Processing" do not. The log file from yesterday states: 2016/03/17 14:31:52 [info] [plugin] [Forced] Can't send email if no status or emails exist.

But there is a status (processing) and an email for that status ({{ order.email }}). I have attempted several dummy transactions today as well but the emails don't come through and the logs don't update either. And no, there's nothing in the spam folder. Or error messages sent back to the host.

I even tried to have the order emails sent to a specific email address instead of {{ order.email }}. No joy.

Finally, I am using the default commerce templates so I'm pretty sure the issue isn't there.

Does anyone have any ideas?

The error is not telling you that the email address is missing, I think, but rather that the email itself to send is missing.

Have you assigned an actual email to send for that particular status?

Commerce->Settings->Order Statuses - check the column 'Has Emails' has a value of 1 or more in it.

(To actually assign one, create it first in the email section, and then in this section click on the order status and in the bottom field 'Status Emails' you'll then be able to choose your created email).

Based on the error and the code generating it (in Commerce_OrderStatusesService.php) - I would say you've set up a status but not actually assigned the email you've made to it.


Author List, Only Users With Entry I am trying to show a list of users but only if they have created a post in a certain section... the code I am using isn't working as expected. Perhaps I have the syntax wrong when it comes to the user model

Help would be greatly appreciated.

{% set entries = craft.entries.section('news') %}
{% set authorList = craft.users.relatedTo(entries) %}

{% for author in authorList %}

{{author.fullName}}

{% endfor %}

This should do it:

{# Grab all the entries for the section #}
{% set entries = craft.entries.section('news').find() %}

{# Group by the authorId #}
{% set entriesByAuthor = entries|group('authorId') %}

{# Grab all of the users with the userIds in entriesByAuthor #}
{% set authors = craft.users.id(entriesByAuthor|keys) %}

<ul>
    {% for author in authors %}
        <li>{{ author.username }}
    {%  endfor %}
</ul>


How to create a migration for the main Craft DB? Let's say we add a section or other elements (field, category, tags, assets, etc) in the CP on our dev servers and want to roll that change out to a stage or production environment, is there a way to capture the changes we've made through the CP as a migration, or is there some other recommended way to reverse engineer that into a migration?

I have checked out the documentation on creating plugin migrations and a couple of questions here and here, but nothing addressing creating a migration for the craft DB itself.

You're looking for the answer to a complicated problem. :)

What you're thinking of I would describe as "content migrations" or "content model syncing".

There is currently nothing in Craft out-of-the-box that will do what you're looking for, although we've got some ideas on how we'd like to approach the sharing/syncing of content between environments/installations in the long term.

If you need something before then, you'll have to write a plugin that rolls its own solution.


How can I get the count of entries in a structure? I'm using this in the root of a structure to try and get the count of entries in another part of the structure.

{% set count = craft.entries.section('hotelDetails').descendantOf('oakview-hotel').level(3).type('review').total() %}
        {{ count }}

But it's including entries from other hotels, I hoped descendantOf('oakview-hotel') would restrict the count to only oakview-hotel. When I replace escendantOf('oakview-hotel') with descendantOf(17) 17 being the ID oakview-hotel the count is restricted to oakview-hotel and the entry count is correct.

Ca anyone please telly me why descendantOf('oakview-hotel') isn't working for me or suggest a better way to do this?

There may be a better option, but off the top of my head, you could do:

{% set countParent = craft.entries.slug('oakview-hotel').first() %}
{% set count = craft.entries.section('hotelDetails').descendantOf(countParent).level(3).type('review').total() %}
        {{ count }}


How to reference the current entry via twig in the control panel? I'm trying to write a general use plugin for a calculation fieldtype that evaluates a twig expression (defined in the field settings) to display additional information about the current record in the CP (i.e. price * qty = amount). So far, everything is working perfectly — the generic expression 1 + 1 is evaluated and the result is properly displayed in the field.

The problem is, I don't actually know how to reference the current entry in the CP from within the CP via twig, to get access to the entry field values. Looking for something like {{ entry.price }} * {{ entry.qty }}, but don't know what to use instead of entry. Does anyone know a twig expression that I can use?

As far as I know. The variable {{ entry }} is not available to custom field plugins through inheritance and must be explicitly set and returned as a variable in the getInputHtml method within the class definition file.

See this question for details on how to set this variable and things to be aware of.


Debugging a Failed Custom Task in Craft CMS I am trying to debug a failed task in craft.  However I'm not really sure what I'm looking for.  I've dug though the log files and found traces of the task but no real errors to speak of.  I have set:

'runTasksAutomatically' => false,

in my general.php file so that when I create my task:

craft()->tasks->createTask('WassermanNews_SocialTask');
craft()->end();

it will become a pending task rather than run automatically. That part seems to work as I end up with a pending task in my control panel.

So I think I've got the process up to this point.  From here I'd simply like to kick off that pending process which I am attempting to do by though cURL.

curl -H "X-Requested-With: XMLHttpRequest" myurl.dev:32769/actions/tasks/runPendingTasks

I know that this is firing because the tasks moves from a pending state to a failed state:

However as I previously mentioned I have no idea why the task is failing and the logs do not seem to be my friend today.

Any ideas on what I could be doing wrong/where I could look for errors?

Below is my task which should be firing (it fires 1 subTask):

<?php
namespace Craft;

class WassermanNews_SocialTask extends BaseTask
{
  $TWITTER = 1;
  $INSTAGRAM = 2;
  $VINE = 3;

  public function getDescription()
  {
    return 'Social Grab';
  }

  public function getTotalSteps()
  {
    return 3;
  }

  public function runStep($step)
  {
    WassermanNewsPlugin::log("Social Grab stepz izz happening",LogLevel::Info);

    switch($step){
        case TWITTER:
            return $this->runSubTask('WassermanNews_TwitterTask');
        case INSTAGRAM;
            return $this->runSubTask('WassermanNews_InstagramTask');
        case VINE:
            return $this->runSubTask('WassermanNews_VineTask');
    }
  }
}

All the sub tasks look more or less identical to this:

<?php
namespace Craft;

class WassermanNews_TwitterTask extends BaseTask
{
  public function getDescription()
  {
    return 'Twitter Task';
  }

  public function getTotalSteps()
  {
    return 1;
  }

  public function runStep($step)
  {
    return "twitter step";
  }
}

Any help figuring this out would be much appreciated!

UPDATE:

I just attempted to run the an example and it failed as well.  Do certain settings affect how tasks are run?
Installed PixelAndTonic's Power Nap and it failed as well!  I did however find a log for this example saying:

Encountered an error running task 95 (PowerNap): Could not find the task component type.

This makes me wonder what the type of the task has to be!  I took a look in TasksService.php and saw that the error is derived from not having a type so what type do tasks need to have?

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

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

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


Why are my SEOmatic Entry Metas not overriding Sitewide SEO? SEOmatic is working as normal locally, but since I put the site up on production the Meta Entry fieldtype isn't overwriting the Site Metas.

I have my

{% hook 'seomaticRender' %}

set up in my head as normal. I've created my Meta fieldset and added it to each entry type. I've set up SEOmatic before and never seen this issue, so I assume I missed something while bringing the site onto the hosting.

If you added the SEO Meta FieldType to existing entries, you'll need to re-save each section in order for it to start pulling content for you. I'm assuming that's what is going on here; see for more details:

https://github.com/nystudio107/seomatic/wiki/05.-SEO-Entry-Meta


Rounding issue with Craft Commerce We've had this problem for a while now and it's largely gone un-noticed but I'd like to raise it.

We have a bunch of products that are discounted when you buy them in bulk. E.g. 12 products for 69.99.

In order to achieve this we calculate what the price should be for each product, by dividing 69.99 / 12, which is 5.8325.

We put this in the database as the product price and I can see it is stored in the database correctly.

However when you add 12 items to the cart, the total is 69.96 - anything past 2 decimal places is being rounded off prior to multiplication.

I've managed to work out a fix for this, but its not ideal as it will get wiped out if anyone ever updates the LineItemModel.

Here is my solution to change the calculation:

public function getSubtotal()
{
    // The subtotal should always be rounded.
    return $this->qty * CommerceCurrencyHelper::round($this->salePrice);
}

to

public function getSubtotal()
{
    // The subtotal should always be rounded.
    return CommerceCurrencyHelper::round($this->qty * $this->salePrice);// Modified: JL
}

and change

public function fillFromPurchasable(Purchasable $purchasable)
{
    $this->price = $purchasable->getPrice();
    $this->taxCategoryId = $purchasable->getTaxCategoryId();
    $this->shippingCategoryId = $purchasable->getShippingCategoryId();

    // Since sales cannot apply to non core purchasables yet, set to price at default
    $this->salePrice = $purchasable->getPrice();
    $this->saleAmount = 0;

    $snapshot = [
        'price'         => $purchasable->getPrice(),
        'sku'           => $purchasable->getSku(),
        'description'   => $purchasable->getDescription(),
        'purchasableId' => $purchasable->getPurchasableId(),
        'cpEditUrl'     => '#',
        'options'       => $this->options
    ];

    // Add our purchasable data to the snapshot, save our sales.
    $this->snapshot = array_merge($purchasable->getSnapShot(), $snapshot);

    $purchasable->populateLineItem($this);

    //raising onPopulate event
    $event = new Event($this, [
        'lineItem' => $this,
        'purchasable' => $this->purchasable
    ]);
    craft()->commerce_lineItems->onPopulateLineItem($event);
    // Always make sure salePrice is equal to the price and saleAmount
    $this->salePrice = CommerceCurrencyHelper::round($this->saleAmount + $this->price);
}

to

public function fillFromPurchasable(Purchasable $purchasable)
{
    $this->price = $purchasable->getPrice();
    $this->taxCategoryId = $purchasable->getTaxCategoryId();
    $this->shippingCategoryId = $purchasable->getShippingCategoryId();

    // Since sales cannot apply to non core purchasables yet, set to price at default
    $this->salePrice = $purchasable->getPrice();
    $this->saleAmount = 0;

    $snapshot = [
        'price'         => $purchasable->getPrice(),
        'sku'           => $purchasable->getSku(),
        'description'   => $purchasable->getDescription(),
        'purchasableId' => $purchasable->getPurchasableId(),
        'cpEditUrl'     => '#',
        'options'       => $this->options
    ];

    // Add our purchasable data to the snapshot, save our sales.
    $this->snapshot = array_merge($purchasable->getSnapShot(), $snapshot);

    $purchasable->populateLineItem($this);

    //raising onPopulate event
    $event = new Event($this, [
        'lineItem' => $this,
        'purchasable' => $this->purchasable
    ]);
    craft()->commerce_lineItems->onPopulateLineItem($event);
    // Always make sure salePrice is equal to the price and saleAmount
    $this->salePrice = $this->saleAmount + $this->price;// Modified: JL
}

Can anyone tell me if this is a known issue and whether there is any reason why the code is not like this to begin with? Why store values at 4dp if it's always rounded off to 2dp when calculated?

It is stored in 4 decimal places because some currencies have more than 2 decimal places.

We round before multiplication because we need don't store any value on the line item in a number of decimal places larger than the base currency. This allows us to add up line items without creating new cents.

As you suggest this could be changed to CommerceCurrencyHelper::round($this->qty * $this->salePrice); but this would be a breaking change for other users. We will consider it for Commerce 2.

I don't recommend using > 2 decimal places to accomplish your "12 for 6.99" offer, rather make a discount adjuster that reduces the regular price of line item with a discount if qty modulo 12 = 0.


How delete a user session with the element api? I need a function to logout a craft user and delete the session of that user. This must take place in the element API plugin as an endpoint. Something like this:

function userLogout(){
    if (craft()->userSession->isLoggedIn()){
        // if user loggedin
        // how to logout?
    }
}

'api/logout' => array(
    'elementType' => 'User',
    'criteria' => ['id' => craft()->userSession->user->id, 'limit' => 1 ],
    'paginate' => false,
    'transformer' => function(\Craft\UserModel $user) {
        userLogout();
    }
),

You can end a user's session with the craft()->userSession->logout(), method, which the UserSessionService class inherits from the CWebUser class.

So, your userLogout function would look like this:

function userLogout(){
    if (craft()->userSession->isLoggedIn()){
        craft()->userSession->logout(false);
    }
}

Additional information

Passing false to the logout method tells Yii not to "destroy" the session, and mimics the call in Craft's UsersController::logout method.

According to the Yii documentation, destroy "frees all session variables and destroys all data registered to a session." I'm unclear why Craft chooses not to destroy the session.

The UsersController::logout method also includes a few cleanup tasks, but those seem to be duplicates of the tasks performed in the UserSessionService::afterLogout method.

The afterLogout method is called from the craft()->userSession->logout() method, so you shouldn't have to worry about this manual cleanup.


Matrix | Craft 3 Element API / Scout Plugin I am trying to grab the contents a matrix field (Redactor).

Here is the section of code I am struggling with:

$bodyBlocks = [];
foreach ($entry->getFieldValue('pageBuilder')->all() as $block){
   switch ($block->type->handle) {
      case 'blockText':
      $bodyBlocks = $block->blockTextPara;
      break;
   }
}

// Begin defining the response data for this entry
$data = [
  'title' => $entry->title,
  'slug' => $entry->url,
  'status' => $entry->status,
  'textArea' => $bodyBlocks,
];

It is submitting to Algolia but the contents of the matrix block is empty.

{
  "title": "Transport",
  "slug": "http://xxxxx/boarding-at-bruern/the-london-link",
  "status": "live",
  "textArea": {},
  "heroBanner": "http://xxxx/images/uploads/banners/_algoliaTransform/ASC7795.jpg",
  "objectID": "1_408"
}

For reference here is my entire scout.php config file:

<?php

    return [
        "sync" => true,
        "application_id" => "xxx",
        "admin_api_key" => "xxx",
        "mappings" => [
            [
                'indexName' => 'xxx',
                'elementType' => \craft\elements\Entry::class,
                'criteria' => [
                    'section' => 'websitePages',
                    'type' => 'websitePages'
                ],
                'transformer' => function(craft\elements\Entry $entry) {

                    Craft::$app->getConfig()->getGeneral()->generateTransformsBeforePageLoad = true;

                    $bodyBlocks = [];
                    foreach ($entry->getFieldValue('pageBuilder')->all() as $block){
                        switch ($block->type->handle) {
                            case 'blockText':
                                $bodyBlocks = $block->blockTextPara;
                                break;
                        }
                    }

                    // Begin defining the response data for this entry
                    $data = [
                        'title' => $entry->title,
                        'slug' => $entry->url,
                        'status' => $entry->status,
                        'textArea' => $bodyBlocks,
                    ];

                    // Get the first asset in a "heroBanner" Assets field (if there is one) and then add it to the data array.
                    $heroBanner = $entry->heroBanner->one();
                    $data['heroBanner'] = $heroBanner ? $heroBanner->getUrl('algoliaTransform') : '/images/site/search-default.jpg';

                    return $data;

                },
            ],
        ],
    ];

The first code section looks correct, other than that you're first creating a bodyBlocks array and then assigning a string to it, but that's not really consequential and not the issue behind this failing.

Do yourself a favor and set up PHPStorm + xdebug, you'll find the issue very easily. I suspect you might have some mixed up identifiers (field names, block handles) etc.


Sprout Email trigger when entry goes live In Sprout Email is it possible to set a notification trigger to be when an entry goes live?

I'd like to create entries ahead of time and post date them so that they go live on the specified date.  I'd like the Sprout Email notification to get triggered when the entry is live (rather than when it is saved).

The docs state that the following events are available from Sprout Email:

When a new entry is created
When an existing entry is updated
When a new user is created
When a existing user is updated
When a user is activated
When a user is deleted
When a user logs in

I think changing the status of an entry would trigger the "existing entry is updated". Not tested though.


Get user data in Craft CMS Personal edition Like I am stating in the title, I am using the free Craft Personal edition which is perfect for my portfolio.

I already (and obviously) have an account and only one.
So I cannot have access to craft.users but this account already have my Full Name and Email written in it and I want to use those in my website without having to redo them as Globals.

Is that possible in Craft Personal?

I thought I will be able to use {{ account }} but it is only accessible in the Registration Form as I can see.

Thanks for your time.

Should be possible with a simple plugin that registers its own Twig extension.  Head over to https://pluginfactory.io/ and check the "Twig Extensions" option to have it generate the boilerplate code for you.

100% untested, but in your PluginNameTwigExtension.php file, add a getGlobals() method that does something like this:

public function getGlobals()
{
    $criteria = craft()->elements->getCriteria(ElementType::User);
    $criteria->admin = true;
    $user = $criteria->first();

    return array('adminAccount' => $user);
}

Then every template should have a global adminAccount variable available to it that's a UserModel object, so you can do things like {{ adminAccount.firstName }}.


List subfolders of a specific asset folder Is it possible to list subfolders from a specific folder?

Context:
I'm printing out hundreds of icons which are maintained by moving a directory structure directly over to my public assets folder. Currently, I grab and list all icons by looking at the parent folder for icons:

{% for image in craft.assets.source('iconLibrary').limit(null) %}
   <li>...</li>
{% endfor %}

I'd like to call and list them by their individual folder names though. Is there a way to take a specific folder and return a list of subfolders?

Update:
Brad's solution works! Though it's somewhat awkward having to call an image first to start at AssetFileModel. Hopefully this can be optimized as I'm running through a loop like
 the one above for each child folder now—

<!--find image in parent icon folder to access folder via AssetFileModel.-->
{% for image in craft.assets.id('9328') %}
   <!-- get children of that asset's folder -->
   {% for subfolder in image.folder.getChildren() %} //
      {{ subfolder }}   //prints each child folder name
   {% endfor %}
{% endfor %}

Not a complete answer, but in your example image if going to be an instance of AssetFileModel.

AssetFileModel has a getFolder method that returns an instance of AssetFolderModel.

AssetFolderModel has a getChildren method you could loop through to get all of the subfolders for the given folder.

Depending on how numerous your file/folder structure is, though, it might be more efficient to do this from PHP in a custom plugin rather than to do it from Twig.


How can I import a large number of new entries into Craft 3 I need to create a few hundred entries at once.  I used the Import plugin for Craft 2 to create these entries from a CSV file.

How can I do the same for Craft 3?  I do not see a plugin for this capability on the Craft 3 plugin page.

Thanks,

One option is to create a Craft 2 site, import the entries there, and then upgrade that site to Craft 3.


FieldType's element attribute is null I am trying to create a new entry via a form post that will come from a third party, by doing this in my plugin's service class:

$entry = EntryModel::populateModel(array(
    'sectionId' => 1,
    'typeId' => 2
));

$entry->getContent()->setAttribute('reference', craft()->request->getPost('someReferenceField'));

craft()->entries->saveEntry($entry);

The reference field is a custom FieldType (https://github.com/fuel-digital/Craft-Unique-Text-FieldType/blob/develop/uniquetextfield/fieldtypes/UniqueTextField_UniqueTextFieldType.php) where I am validating the submitted value is unique for this EntryType (in this case an Entry rather than a User/Asset/etc).

That FieldType works fine in the control panel but I'm getting an error when submitting via my plugin as $this->element is null within the FieldType's valueExists() method.

I can get around this by creating a new EntryModel like so:

/**
 * Checks if another entry exists with the given value
 *
 * @param  string $value The value to check
 * @return bool
 */
private function valueExists($value)
{
    if ( ! $this->element)
    {
        $this->element = new EntryModel();
    }

    $existing = craft()->elements->getCriteria($this->element->elementType)->first(array(
        $this->model->handle => $value
    ));

    return ($existing && $existing->id != $this->element->id);
}

But that means the FieldType will only work with Entry elements, and not Users, Assets etc.

As the plugin works fine in the control panel, I assume I'm missing something in my plugin service?

Found a solution by how Entry Form handles it.

Assuming you've posted fields with names such as jobData[reference]:

$fieldsLocation = craft()->request->getParam('fieldsLocation', 'jobData');

$this->entry->setContentFromPost($fieldsLocation);

The setContentFromPost() method of the EntriesController class sets the ElementType.


Custom plugin log not logging I'm having this weird issue that both of my custom plugin logs are not working but all other third party ones including craft.log work fine. By 'not working' I mean the log file is generated, but empty.

Another weird thing is the issue only happens on production environment. Tested on local environment and staging environment, they all work fine.

I believe I got the code right?

MyPlugin::log("Errors:\n\n" . print_r($fieldsData, true), LogLevel::Error);

It's Craft 2 by the way.

Anything ideas?

Put the force parameter to true

MyPlugin::log("Errors:\n\n" . print_r($fieldsData, true), LogLevel::Error, true);

Custom Log in Craft


How do you only show children of "active" parent in a Structure section's nav? I've got a Structure section where the top level is the main menu. The submenu consists of the children of the active main menu item. This works well.

For the submenu, I'm using this code:

{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry) %}

{% nav page in subnav %}

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

        {% children %}

    {% endifchildren %}

{% endnav %}

...which shows all children of each page.

How can I only show the children of the active parent? I've tried to wrap the ifchildren block inside another if statement (the same I used to set the class="active" to the
), but that results in a Template error:

  Unexpected tag name "ifchildren" (expecting closing tag for the "if" tag defined near line x)

Putting that if statement inside the ifchildren block also throws a template error.

PS. With the current HTML output, I could also just use CSS to hide/show the
s based on the .active class, but I'd still like to know how to generate that tree without the need for  a CSS workaround.

A recursive macro will help you get around the limitations of ifchildren (which P&T will hopefully resolve soon), as follows:

{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry).level(2) %}

{% macro recursiveChildren(page) %}
  {% if page.hasDescendants and page.slug == craft.request.getSegment(page.level) %}

      {% for subpage in page.children %}

            {{ subpage.link }}
            {{ _self.recursiveChildren(subpage) }}

      {% endfor %}

  {% endif %}
{% endmacro %}

{% for page in subnav %}

    {{ page.link }}
    {{ _self.recursiveChildren(page) }}

{% endfor %}

More on macros here.


How can i get API-Response that includes localized data using json_expand? My index.html endpoint in the templates folder looks like this:

    {% header "Content-Type: application/json" %}
    {% set basics = craft.entries.section('basics').find('') %}
    {{ basics | json_expand | raw  }}

I did enable the fields and put some localized strings inside,
still json returns this:

[
 {
"id": "261",
"enabled": "1",
"archived": "0",
"locale": "de",
"localeEnabled": "1",
"slug": "wimpern-richtig-tuschen",
"uri": null,
"dateCreated": {
  "date": "2015-11-26 12:08:01",
  "timezone_type": 3,
  "timezone": "UTC"
},
"dateUpdated": {
  "date": "2015-12-07 15:03:51",
  "timezone_type": 3,
  "timezone": "UTC"
},
"root": null,
"lft": null,
"rgt": null,
"level": null,
"sectionId": "7",
"typeId": "9",
"authorId": "153",
"postDate": {
  "date": "2015-11-26 12:08:00",
  "timezone_type": 3,
  "timezone": "UTC"
},
"expiryDate": null,
"parentId": null,
"revisionNotes": null,
"title": "Wimpern richtig tuschen",
"basics_text": "Wimpern richtig tuschen", (etc...)

is there a way to make an endpoint just for the english version, like basics_en ? Is there even any way to get the localized data using this method? The CMS is for a mobile-app, so i just need the raw data from the endpoint.

It was pretty easy :)

{% header "Content-Type: application/json" %}
{% set basics = craft.entries.section('basics').locale('en').find('') %}
{{ basics | json_expand | raw  }}

all it needed was: .locale('en')


How do you set an "If" option on an entry that includes "contains" I am trying to set an if statment that will show a li if there is only one entry displaying. The issue I am having is that this entry is put into two different places via checking if it contains a checkbox.
I can only seem to managed to get it to display all the time or not at all

The code I have at the moment is this
    {% if entry.ENTRYNAME.contains('CHECKBOX OPTION') == 0 %}
CONTENT
 {% endif %}

But that does not seem to work.
I am using the Check box contains option else where and it works fine. It's  just the value check that I cannot seem to get to work. I've also tried adding both .length and |length but neither of those seem to work.

OKay so the solution I found is this. It was much more complicated than I wanted it to be but it works.

{% set VARIABLE = 0 %}
{% for entry in craft.entries.section('ENTRY') %}
    {% if entry.FIELDNAME.contains('CHECKBOX OPTION') %}
        {% set VARIABLE = VARIABLE + 1 %}

CONTENT

    {% endif %}
{% endfor %}
{% if VARIABLE <= 1 %}

CONTENT

{% endif %}


Using DreamObjects to store assets Has anyone used Dreamhost's cloud service: DreamObjects, an Object-Based-Storage to host their assets? If so, how do you configure this with Craft 2.6.2911?

If I'm understanding you correctly, it sounds like you're trying to add another Assets Source Type.

Unfortunately, this isn't possible in Craft 2. This feature is expected to be introduced in Craft 3.

  Volume Types

  Asset Sources have been renamed to “Volumes” in Craft 3, and their API has been dramatically simplified. In addition to Craft’s built-in Local, S3, Google, and Rackspace Volume types, plugins are now able to supply their own. There’s even a base Volume class that makes it really easy to implement Flysystem-based Volume types.


Listing related entries to a section I have two sections: 'reviews' and 'games'.
Games has an field called 'GamesReviews' which is type entries and points to 'reviews'.
An example of a games entry is located at:
http://www.colorcomputergames.com/games/donkey-king

Towards the bottom, I link to the related reviews for this entry.
That sends me to:
http://www.colorcomputergames.com/reviews/1983-06-01/donkey-king

At the bottom of the review, I want to link back to the related entry of that review.

I am able to display the name of the game 'Donkey King', but the URL is not pointing to:
http://www.colorcomputergames.com/games/donkey-king

But instead:
http://www.colorcomputergames.com/reviews/1983-06-01/donkey-king

The code I am usinng in the template (reviews/_entry.html) is:

{{ entry.title }}

    {% if entry.ReviewsAuthor|length %}
Reviewer: {{ entry.ReviewsAuthor }}
{% endif %}
    {% if entry.ReviewsMedia|length %}
Media: {% for category in entry.ReviewsMedia %}{{ category.title }}{% endfor %}
{% endif %}
    {% if entry.ReviewsDate|length %}
Date: {{ entry.ReviewsDate.format('F Y') }}
{% endif %}
    {% if entry.ReviewsRelatedLink|length %}
Related Link: {{ entry.ReviewsRelatedLink }}
{% endif %}

{{ entry.body }}

{% set entries = craft.entries.section('games').relatedTo(entry) %}

Info:

{{ entry.title }}

You are returning an elementCriteriaModel (which always returns an array-like object regardless if there is one or more than one result), which you either need to loop over or just grab the first entry (because in this case there can only be one).

{% set gameEntries = craft.entries.section('games').relatedTo(entry) %}

Info:

{% for gameEntry in gameEntries %}

{{ gameEntry.title }}

{% endfor %}

or

{% set gameEntry = craft.entries.section('games').relatedTo(entry).first %}

{{ gameEntry.title }}


Create Solspace Calendar Event on Commerce onOrderComplete I'd like to create a Solspace Calendar Event on Commerce onOrderComplete. I've done this with Charge where on Charge Success an event was created however I know that I did that in a less than ideal way so hopefully the answer to this allows me to both achieve what this question is asking as well as fix my previous plugin (that works but just seems less than ideal).

I'd need to pass some of the fields from the Order Fields such as the Start Date, End Date, Products Purchased.

I know i need to create a plugin for this, i'm just not quite sure how to call the Solspace Calendar plugin onOrderComplete and send it the appropriate data to create said event. Any help (with examples if possible) would be greatly appreciated.

To clarify: I am not looking for someone to write a plugin for me. I am simply looking to be put on the right track in terms of connecting to Solspace Calendar and sending it the appropriate data on completion of a commerce order.  I can write the code myself once pointed in the right direction.

To listen to Craft Commerce order save event, you must make a new plugin (or use an existing one) and in it's ::init() method, listen to the commerce_orders.onSaveOrder event:

class TestPlugin extends BasePlugin
{
    public function init()
    {
        parent::init();

        craft()->on(
            "commerce_orders.onSaveOrder",
            function (Commerce_OrderModel $order) {
                // Create the event
                $event = new Calendar_EventModel();

                $event->getContent()->title = "New Event Title";
                $event->slug                = "new-event-title";

                // Any custom fields go through the ::getContent() model
                $event->getContent()->body = "This is a custom rich text field";

                // Do whatever you need to do with the order data
                // By using the $order OrderModel
                // For example:
                //
                // $event->getContent()->body = "Order total: " . $order->totalPrice;

                // Mandatory fields
                $event->calendarId = 1;
                $event->authorId   = craft()->getUser()->id;
                $event->startDate  = new DateTime();
                $event->endDate    = new DateTime();

                $event->allDay = true;

                // Save the event using Calendar Events service ::saveEvent() method
                craft()->calendar_events->saveEvent($event);
            }
        );
    }
}


Is it possible to display additional fields on the entries list in admin? For example, in addition to the auto-generated title for an entry is it possible to display another column alongside with another field? I would like data input be as easy as possible for the client. The more information available on this page to view and sort by the better.

Unless there is another way to approach this I am not aware of? Would a plugin be required for example?

Yes, since Craft 2.3 you can edit the CP's index views for entries, assets, etc. from a plugin.

Have a look at the documentation for the hooks defineAdditionalEntryTableAttributes and getEntryTableAttributeHtml to see some sample code. Making a little plugin for this is easy, simply copy and paste the above sample code into your primary plugin class and then edit the parameters.


Automatically Log in User In my Controller I created a script to add a user to the database, is there a way I can automatically:

1) Log them in and
2) Set a permanent session cookie or similar?

I basically don't want the user to have to ever log in and we will be creating the accounts for them.

You're probably looking for a combination of:

craft()->userSession->login()

or

craft()->userSession->loginByUserId()

along with setting the userSessionDuration config setting to a really high value.


Multiple categories filter I have a channel section called Members. I have 2 category groups (categoriesMembres & cantons).

My goal: show entries only related to a specific category in categoriesMembres and loop through the cantons:

Canton1

entry 1
entry 2
etc.

Canton2

entry 3
entry 4
etc.

Right now the code below display it like that:

Canton1

entry 1
entry 2
entry 3
entry 4

Canton2

entry 1
entry 2
entry 3
entry 4

The code (I stripped out html for clarity)

{% set membersCat = craft.categories.group('categoriesMembres').title('Membre').first() %}
{% set entries = craft.entries.section('listeMembres').relatedTo(membersCat) %}
{% set cantonsCat = craft.categories.group('cantons').relatedTo(entries) %}

{% for canton in cantonsCat %}
   {{ canton.title }}
   {% for row in entries|batch(3) %}
    {% for entry in row %}
     {{ entry.title }}
    {% endfor %}
    {% endfor %}
    {% endfor %}

What am I overseeing or doing wrong?

You missed to filter for entries related to your "Canton" category only within your cantons loop.
Add another ElementCriteriaModel and get entries related to both membersCat and canton:

{% for canton in cantonsCat %}
    {% set entriesInCanton = craft.entries.section('listeMembres').relatedTo('and', membersCat, canton) %}
    {% for row in entriesInCanton|batch(3) %}
        ...
    {% endfor %}
{% endfor %}

Another approach (only works if there's one "Canton" max per entry!) would be to make use of Craft's group filter. This is probably the better way to solve your problem, because it doesn't add extra DB queries for each "Canton" iterated over in your loop.

{% set membersCat = craft.categories.group('categoriesMembres').title('Membre').first() %}
{% set cantonsCats = craft.categories.group('cantons') %}
{% set cantonsCatsInUse = craft.categories.group('cantons').relatedTo(entries) %}

{% set entries = craft.entries.section('listeMembres').relatedTo('and', membersCat, cantonsCats) %}
{% set entriesByCanton = entries|group('myCantonCategoryField.first()') %}

{% for canton, entriesInCanton in entriesByCanton %}
    {% for row in entriesInCanton|batch(3) %}
        ...
    {% endfor %}
{% endfor %}

This probably won't output the cantons in the sort order you whish, but this fortunatelly can be solved easily.

{% set entriesByCanton = entriesByCanton|supersort('ksort') %}


Performance hit from Entry Url Format with multiple {% if %} clauses? With help from this answer, I've got an Entry Url Format that can include top, 2nd, or 3rd-level categories.  It works for any of these situations:

top-level-category/entry.slug
top-level-category/second-level-category/entry.slug
top-level-category/second-level-category/third-level-category/entry.slug

{% if object.mainCategory.last().level == 3 %}{mainCategory.last().parent.parent.slug}/{% endif %}{% if object.mainCategory.last().level > 1 %}{mainCategory.last().parent.slug}/{% endif %}{mainCategory.last().slug}/{postDate.year}/{slug}

It's ugly, but it works. But I'm wondering if it is slowing things down a bit.  Does anyone have any knowledge in this area?

As far as Craft is concerned whatever is in the Entry URL Format field is just another Twig snippet of code.  It gets rendered down super fast just like any other Twig code.  A few if conditionals aren't going to have any measurable impact on that process.


How can I use categories to filter entries? It's a pretty basic question, but for some reason all of the possible solutions do not work for me.

I tried this: https://craftcms.com/docs/relations#the-relatedTo-param
And also this (which I really expected to solve my problem): https://craftcms.com/support/entries-related-to-category

I'm pretty sure I may have overlooked something, but I can't see what.

I made this:

{% set lastSeg = craft.request.lastSegment %}
{% set meubels = craft.entries.section('meubels').relatedTo(lastSeg) %}

And use this as a test:

{% for meub in meubels %}
test

{{ meub.title }}

{% endfor %}

According to every answer to related questions this should work, but unfortunately it returns nothing. But lastSegment does return the required string from the URL. (At least, I'm assuming this must be a string)

I made a list of categories which all seem to route just fine, no problems there.

The relatedTo parameter requires one of the following as an argument:
- AssetFileModel
- CategoryModel
- EntryModel
- UserModel
- TagModel
- An element’s ID
- An array of element objects and/or IDs

Passing in a string from the URL will not work. If you are not on a template that is the result of a category route, you need to fetch the category first.

{% set thisCategory = craft.categories.handle(lastSeg).first() %}

You can then use thisCategory as your argument in the relatedTo parameter.

{% set meubels = craft.entries.section(‘meubels’).relatedTo(thisCategory) %}


How to track entry visit? how do I able to track the visit number of entry?
Something like track view in Expression Engine.

I have try to find but don't have any source.

Check out the Craft Entry Count plugin by Ben Croker...

  https://github.com/putyourlightson/craft-entry-count

Counting entry views is exactly what that plugin does.


How to use a plugin to add own fields, values, forms,...? in short:
Can you please point to some (working?) sample of implementing a barebone default / dev setup (css, js, basic templates, custom fields, groups, users, matrix forms, front-end forms,...) using a plugin?

Also: Is there a way to "enforce" presence (installation and activation) of "related" plugins ("must use" plugins) so I can develop a theme with functions/features related to other plugins I do not own?

Background:
I am starting over (again) with craft, simply as I am fed up managing plugins (i.e. with wordpress). One thing that I am really missing - which may be due to limited coding experience with craft - is a simple way to add my "defaults" (css, js, fields, forms, groups & related (test)users,...) to the system to proceed creating templates (internal as well as customers). In wordpress I could simply extend the functions.php or use a custom site or template related plugin providing me the basics I want/need to proceed developing themes or plugins. In craft I don't get the point / simply don't understand where to start just to add custom fields and relations. I also don't see how I could use a plugin to create t theme / copy the related files and have them "managed" by my plugin.

I'll try and cover as much as I can:

Can you please point to some (working?) sample of implementing a barebone default / dev setup (css, js, basic templates, custom fields, groups, users, matrix forms, front-end forms,...) using a plugin?

I don't think there would be anything where this is implemented with a plugin (unless i'm mistaken), but P&T have an installation of Craft you can either clone on Github or generate from their website called HappyLager, this contains a bunch of boilerplate to you get you started including sections, entry types, matrix fields, relations, assets.

I don't think there is anything with users on there though due to licencing, Craft personal only allows one user and Client 1 Admin and 1 Client account : http://buildwithcraft.com/pricing

Generate a site for you to log in to: https://demo.buildwithcraft.com/
Download the Repo and install it to your own server: https://github.com/pixelandtonic/HappyLager

Is there a way to "enforce" presence (installation and activation) of "related" plugins ("must use" plugins) so I can develop a theme with functions/features related to other plugins I do not own?

There is sort of a way to do this I believe, you would need to have a set of dependancies you could define as an array in your main plugin class, then when your plugin's CP/settings page is loaded, do the checks through a controller to see if the correct plugins are installed and proceed with notifications, errors when conditionals are met etc.

An example of a plugin i've seen that has done this is the Twitter plugin from Dukt, its free so you should be able to download it and find what you need. TwitterPlugin.php is where the logic is (from what I can see) then controllers/TwitterController.php to put it all together and then  templates/settings/_dependancies.html is how it's dealt with in the front end.

https://dukt.net/craft/twitter

It might be worth having a read about plugin development: http://buildwithcraft.com/docs/plugins/introduction

But I think in your themes readme, a simple list of required plugins with links on how to get them would be good enough for most situations.

In craft I don't get the point / simply don't understand where to start just to add custom fields and relations

This should be solved or become apparent in the HappyLager demo? if not the documentation is quite helpful with this:

http://buildwithcraft.com/docs/sections-and-entries
http://buildwithcraft.com/docs/fields
http://buildwithcraft.com/docs/relations

I also don't see how I could use a plugin to create a theme / copy the related files and have them "managed" by my plugin.

I think the problem with building a theme is there are so many factors involved with regards to how someone might have their backend set up (if retro fitting a theme) as you if you had something like craft.entries.section('news') in one of your templates but the section is called blog your theme isn't going to work.

For a clean install your problem might be with licensing, I'm not an expert on it by any means so if anyone else knows more information please edit this answer, but I would assume you would need to be careful how you add sections and users at the least.

Your plugin could generate sections on it's install, it could even generate users but I would probably check with Craft directly with this or read their license to be sure, but the methods to create such things are there in the internal API, you could take a look at the full class reference to see whats going on and whats available: http://buildwithcraft.com/classreference

With regards to template files, you can change the location of these file, see Custom template location, but I don't think you can get your plugin to do this, unless i'm mistaken.

As for theme files etc you could have a set directory structure when people install your theme and then use something like the File class to interact with these files http://buildwithcraft.com/classreference/etc/io/File

I hope that helps you get off to a start with building on Craft


Custom Environmental Settings Is it possible to use custom environmental settings with Craft?

I have separate web services that I use in production and development environments. I would like to programmatically point to the appropriate service based on my environment. If I am in development, I should always point to the dev service...production...to the production service.

The documentation leads me to believe that I can only use the settings that Craft provides.

How can I use custom environmental settings within Craft?

Yes it's absolutely possible, and available out of the box with craft.

In your public/index.php file you specify the different environments based on your server name.

With the environment set, inside your craft/config/db.php and craft/config/general.php files, you can create different configurations for each environment.

This article in the craft documentation goes over how to configure it. Let me know if you have any trouble, it's really just modifying those three files.

http://buildwithcraft.com/docs/multi-environment-configs


How can I return HTTP 403 from a template? I'm building a rough JSON API using normal Craft templates (i.e. rendering the JSON with Twig) but would like to be able to return HTTP 403 to unauthenticated requests.

For example:

{% if not user %}
    {% respond 403 %}
{% endif %}

Is something like this built in?

Exit tag is what you're looking for.

{% exit 403 %}


Grabing data from another channel associated to an entry displayed using category I have a page that shows a listing of entries (called products) by category. Those product entries have related content (reviews) stored in another channel that are tagged using a relations field.

On the category page, I want to show the overall rating (the sum of all ratings)for each individual product shown.

I'm calculating and showing the overall rating currently on the product profile page with no problems. But on the category page, I'm having trouble showing that overall rating also. I think my problem is where I'm using the relatedto field (in my queryParams variable) to associate the reviews to the product entry associated with the category.

Any help is appreciated.

<!-- get category from URL -->
{% set category = craft.categories.group('productCategories').slug(craft.request.lastSegment).one %}

<!-- display craft product entries related to category-->

{% set entries = craft.entries.relatedTo(category)
    .limit(30)
    .orderBy ('dateCreated desc')
    .all() %}

<!-- set variable to grab the associated reviews -->

    {% set queryParams = {
        section: 'userProductReviews',
        relatedTo: 'entry'
    } %}

{% set reviewQuery = craft.entries(queryParams).all() %}

<!-- overall rating code -->

{# set sum of product ratings per entry#}

    {% set sumOverallratings = 0 %}

    {% for entry in reviewQuery %}
        {% set sumOverallratings = sumOverallratings + entry.overallRating %}
    {% endfor %}

{# the actual number of reviews related to product entry #}

  {% set reviewCount =  craft.entries(queryParams).total() %}

{# set the average for the rating #}

    {% set productOverallAverage = sumOverallratings / reviewCount %}

You nailed it! relatedTo: 'entry' is indeed your issue. Two problems I see with it: 1) you're checking for things related to the string entry, which doesn't do you a lot of good, and 2) even if it wasn't a string you're not setting the entry variable anywhere.

Here's what you need to do:

{% set category = craft.categories.group('productCategories').slug(craft.request.lastSegment).one %}

{# we should only continue if we actually have a category #}
{% if category %}

    {# let's call this products to keep things simpler #}
    {% set products = craft.entries
        .relatedTo(category)
        .orderBy('dateCreated desc')
        .limit(30)
        .all() %}

    {# we need to loop over our products before we even start worrying about the reviews #}
    {% for product in products %}

        {# obviously here is where you'd add your html markup to display the products #}
        {{ product.title }}

        {# we now have a `product` variable to use as our relatedTo param #}
        {% set productReviews = craft.entries
            .section('userProductReviews')
            .relatedTo(product)
            .all() %}

        {# we can use the already existing query to get the total count (as opposed to sending off a whole new query) via the `| length` filter #}
        {% set reviewCount = productReviews | length %}
        {% set sumOverallRatings = 0 %}

        {# I've also renamed these variables to keep things easy to understand #}
        {% for review in productReviews %}
            {% set sumOverallratings = sumOverallRatings + review.overallRating %}
        {% endfor %}

        {% set productOverallAverage = sumOverallratings / reviewCount %}

        {# and now you have your average rating! #}
        {{ productOverallAverage }}

    {% endfor %}

{% endif %}

For bonus points, you could tidy up the part where you're querying and calculating the ratings (as long as you're on Twig 2.10+) using the reduce filter.

With reduce you could replace everything inside the {% for product in products %} ... {% endfor %} loop with this (and whatever html markup you're using):

{% set productReviews = craft.entries
    .section('userProductReviews')
    .relatedTo(product)
    .all() %}

{{ productReviews | reduce((totalSum, review) => totalSum + review.overallRating) / productReviews | length }}

The reduce filter here is taking your array of product entries and basically adding up the value of all the overallRating fields, which we then divide by the length of the productReviews array.


How do I add a favicon I'm a newbie to Craft so apologies if this has been answered or is too simplistic for the forum but how do I change my site's favicon? Thank you.

Just like you would add a regular favicon just in your head.
If you want it to be an uploaded picture I would say:

Make a global and add a field like "favicon" to it and upload your image there and display it like:

{% for image in favicon.fav %}
<link rel="icon" type="image/png" sizes="16x16" href="{{ image.url }}">
{% endfor %}

But what I always do is just go to a favicon generator like:
http://www.favicon-generator.org/

And upload your logo and copy paste that code in your <head> tags in your _layout.html file


Create different types of Donation purchasable? (for Gift Aid etc) The new donations purchasable looks super handy for charity websites, thank you for this :)

In the UK we have a thing called Gift Aid that allows charities to claim an extra 25% on donations/purchases if the customer opts into the scheme.

Is there any way you could modify the new Donation purchasable so that two (or more) kinds of donation can be logged in Craft?

Eg something like craft.commerce.donation.type(normal) and craft.commerce.donation.type(giftaid) - and then ideally a way to export a CSV of each donation type via the control panel?

Maybe a bit late but we've implemented gift aid for a client's donations site and whilst in Craft2 and using the Charge plugin it might help a bit.

We added a field to the Charge order which is a lightswitch of GiftAid on or off. As August suggested this could be done in the line item as an options[giftaid] value of Craft Commerce

We then created a couple of twig templates restricted to admin users only. The first one is an index file that lists the calendar months as links to another twig template that lists the details of that months orders as a CSV file for GiftAid reporting.

The code for the css twig template looks like this:

{% set month = craft.request.getParam('d') %}
{% set year = craft.request.getParam('y') %}
{% set firstDay = date(year ~ '-' ~ month ~ '-01') %}
{% set lastDay = firstDay|date_modify('first day of next month') %}
{% header "Content-Type: application/csv" %}
{% header "Content-Disposition: attachment; filename=" ~ month ~ "-" ~ year ~ "-GiftAidReport.csv" %}
{% set postDateParam = ['and', '>= ' ~ firstDay|date('c'), '< ' ~ lastDay|date('c')] %}
{% set charges = craft.charge.charges({
    giftAid: 1,
    dateCreated: postDateParam,
    refunded: false
})%}
CharityNumber, CharityName, ProjectName, FundraisingCampaign, DonorTitle,DonorFirstName,DonorLastName,DonorAddress,DonorPostcode, Description, DonatonDate, DonationAmount, DonationCurrency, GiftAidValue
{% for charge in charges %}
{% set thisName = charge.customer.name|split(' ') %}
<this is your list of CSV fields>
{% endfor %}

I'm sure there is a much nicer way of doing this all in a plugin within the backend but this was a nice quick and easy way to do it.


Checking for existence of a field within a Matrix block In trying to test for the existence of a field within a Matrix block I think I may have stumbled upon a bug, or I'm missing something and approaching this the wrong way.

I've setup a simple test using a fresh, standard Craft install with a very basic Matrix setup. I've pasted the Matrix template code below.

    {% if entry.matrix is defined and entry.matrix|length %}

        {% for block in entry.matrix %}

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

                {{ block.richText }}

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

                {{ block.plainText|markdown }}

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

                {% if block.test is defined %}

Uh oh! This field doesn't actually exist.

                {% endif %}

{{ block.quote }}

                    – {{ block.attribution }}

            {% endif %}

        {% endfor %}

    {% endif %}

Within the blockquote block I am checking if block.test is defined, this check always evaluates to true despite the fact that it doesn't exist and if I add any additional checks it bombs out the template.

Any insight is greatly appreciated!

Use brackets instead of dot notation for the field handle when you test for defined:

...
{% if block['test'] is defined %}
    ...
{% endif %}


No live preview & SEO plugin cannot find content on page When I try to live preview my craft site the content of the live preview is blank:

This is happening for all pages.
I have set the template file for the page to use:

I am running Craft Solo 3.6.12
Something that is also kinda odd is that the SEO plugin I am using cannot seem to detect the content on the page, my suspicion is that these two things are linked:
SEO plugin:

I get an odd error when trying to use the SEO plugin for key words:

I have looked at some of the issue on github but have not been very successful finding a solution so if anyone has come across this before and could offer some dev wisdom that would be great.
Please ask any questions you might have,
all the best - W

Pretty simple answer - the .env file was not showing the correct primary site i.e.
PRIMARY_SITE_URL=https://www.XXXXXXX.com

http:// XXXXXX

should have been
https:// XXXXXX

very embarrassingly for me, this error was clearly displayed in the console log of the live preview site i.e.

navigate to the live preview page
enter dev tools
view console for the log errors

There is also another post of this issue as well:
Live Preview not loading - https / http conflict
(I'd like to suggest this post be left open as I had previously seen that post but did not attribute it to this issue - possibly due the double digits spent infront of the screen...)


$event->isNew not working as expected after Craft 3.2 update Pre Craft 3.2, you could do something like this if you wanted to perform an action in the event you just saved a new entry:

use craft\elements\Entry;
use craft\events\ModelEvent;

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function(ModelEvent $event) {
        $entry = $event->sender;
        $isNew = $event->isNew;

        if ($isNew) {
            // do something...
        }
    }
);

However, after the update, this code doesn't work as it used to. $isNew always gets evaluated to true whether resaving a pre existing entry or editing a yet-to-be-saved entry (the autosave kicks in after a couple of seconds while you're editing).

I've tried doing something like this to check if the entry is being resaved but it still gets evaluated to true:

$isBrandNew = false;
if ($event->isNew && ! $entry->propagating && ! $entry->resaving) {
    $isBrandNew = true;
}

if ($isBrandNew) {
    // do something
}

How do I fix this so that my code only runs after a brand new entry was just created, like it did before Craft 3.2?

We just released Craft 3.2.5 which should fix this for you.

For more context about why this happened in the first place, see https://github.com/craftcms/cms/issues/4589.


How can I safely identify a single asset-folder? Background

I'm writing a plugin that will function as a document-archive with access-rights to different folders set based on user-groups.

In addition to folders which are restricted, there is also one folder in the asset-source which is "open" to everyone.

I have the full plugin working; or at least so I thought until one of the test-users moved the "open" folder inside the asset-source trough the CP.

Suddenly the "open" folder (and it's contents) were no longer displayed anywhere.

I was fetching this folder based on it its ID.

Why you should not rely on folder-ids in Craft

Basically - folder-IDs are dynamic, which means that you cannot safely look up a folder by ID!

Let's do a little experiment.

Create an asset-source named My assets, and under it create two folders: Test and Test2

Now - if you look at your craft_assetfolders database-table, you'll see something akin to:

ID - parentId - sourceId - name        - path
77 - NULL     - 4        - "My-assets" -
78 - 77       - 4        - "Test"      - "Test/"
79 - 77       - 4        - "Test2"     - "Test2/"

Note that id, parentId and sourceId might be different numbers in your example - they depend on how much your craft_assetfolders database-table contained before you started this example.

So far this all makes perfect sense - until you move a folder! Per example, drag and drop Test into Test2, then reload the view of your database-table

It will now read

ID - parentId - sourceId - name        - path
77 - NULL     - 4        - "My-assets" -
79 - 77       - 4        - "Test2"     - "Test2/"
80 - 79       - 4        - "Test"      - "Test2/Test/"

What happened to id 78? It's gone! However the folder Test still exists, it still contains all of its assets etc - it just has a new ID.

Now - for the sake of experimenting, let us drag and drop Test back to the root of our asset-source and reload our view of the database-table

ID - parentId - sourceId - name        - path
77 - NULL     - 4        - "My-assets" -
79 - 77       - 4        - "Test2"     - "Test2/"
81 - 77       - 4        - "Test"      - "Test/"

Basically - whenever you move an asset-folder, rather than simply update the path and parentId values of the associated database-row, the old row is deleted and a new one is created.

Summa summarium - having a plugin or template reference a folder by its ID is hardly safe!

What other options do we have?

Well, in addition to ID folders also have a UID. But, since that is set on row creation, that also changes when a folder is moved. So that's another no-go.

We could look it up by name - but names can be changed, so that's as unreliable as looking it up by ID (or UID).

Even if you were to write up a plugin-setting that allows you to pick the desired folder, that would - given that you move (or - if your plugin stores name rather than ID - rename) the folder - contain a null-reference.

So how can we - safely - identify a single asset-folder in a plugin, and know that it will always point to said folder and subsequently its contents?

Moving a folder is a pretty complex operation. You have to move all the files contained in the folder, all of the subfolders and all of the files contained in the subfolders. Another thing to consider is that a move is essentially a copy+delete.

So, how Assets goes about all of this is that firstly it mirrors the subfolder structure to be moved in the target destination. It then moves the files one by one. After that, it deletes all of the old folders.

Dividing the operation into many steps accomplishes several things:
1) It allows for displaying the progress bar.
2) It divides the processing time and memory needed across multiple requests, helping prevent timeouts
3) If the user closes the browser window, there is at least fault tolerance and no files are lost - you just get duplicates of some files and you can retry the same operation using "replace" instead of trying to figure out which files were moved and which were not.

So, the folder ID changes, because it's not the same folder anymore. Theoretically, it would be possible to manually adjust the folder IDs afterwards so that they remain unchanged, but I don't think that's a good precedent.

I could argue that folder IDs are a Craft internal thing and relying on them is not encouraged, however, I would just offer a better solution UX wise - just use an Asset source type drop down selector and a text box for the relative path. Not only it would be less amibigious than a magical ID, it would also be more consistent with user experience of addressing folders while also pointing to a specific spot, instead of an entity, which is definitely better for long-term maintenance.


How to find the block type of Super Table field that is inside a Matrix field I'm making a front-end entry form with a Super Table field that is inside a Matrix field. Super Table docs at https://verbb.io/craft-plugins/super-table/docs/template-guides/front-end-form have an example with the following code to figure out a block type of Super Table field:

{% set fieldHandle = 'mySuperTableField' %}
{% set field = craft.fields.getFieldByHandle(fieldHandle) %}
{% set blocktype = craft.superTable.getSuperTableBlocks(field.id)[0] %}

If in my case I have a Matrix field with handle myMatrixFeild that contains mySuperTableField, how do I find out the block type of mySuperTableField?

That's more complicated, because fields in a Matrix are scoped to the Matrix field, which is why you can't just go:

{% set field = craft.fields.getFieldByHandle('superTableFieldInMatrix') %}

You'll need to loop through the Matrix's fields to find the Super Table field, then carry on as normal.

{% set matrixField = craft.fields.getFieldByHandle('myMatrixField') %}

{% for field in matrixField.getBlockTypeFields() %}
    {% if field.handle == 'mySuperTableField' %}
        {% set blocktype = craft.superTable.getSuperTableBlocks(field.id)[0] %}


Internal Server error during install I've done a few installs of Craft and never had a problem. I'm currently trying to do an install on a new server under a subdmomain and getting the following results…

This results in 404
http://staging.example.com/admin

Using /index.php/admin or /index.php?p=admin results in Internal Server Error 500.

In case it helps someone, my issue was the permissions for the root index.php file...It was 666 (writeable by group) and when I switched that file permissions to 644, the installation was able to move forward.


Missing javascript .map files When I view the browser console whilst viewing the Dashboard for instance, I get a whole load of 404s for Javascript .map files. For example on a fresh update to v2.3 I get this lot reported as missing:

/admin/resources/lib/garnish-0.1.min.js/garnish-0.1.min.map/
/admin/resources/js/craft.js/craft.min.map/
/admin/resources/js/cp.js/cp.min.map/
/admin/resources/js/QuickPostWidget.js/QuickPostWidget.min.map/
/admin/resources/js/RecentEntriesWidget.js/RecentEntriesWidget.min.map/
/admin/resources/js/GetHelpWidget.js/GetHelpWidget.min.map/
/admin/resources/js/UpdatesWidget.js/UpdatesWidget.min.map/
/admin/resources/js/FeedWidget.js/FeedWidget.min.map/

It just looks like the paths a wrong, if I look in the /js/ folder, the .map files do actually exist.

Is it something I should be concerned about? Everything seems like it's all working ok, so it's not a show stopper at all. I just find it a bit annoying to be honest, so if I can do something to turn off the requests that'd be nice.

EDIT: Solution

As per Jason's answer below, I had the following rule in my .htaccess file to add trailing slashes:

RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]

I removed that and it has cured the issue. I have subsequently put the rule back in and the problem hasn't returned so it must have been cached somewhere.

If you are hosting on an Apache server, check your rewrite rules. The output provided appears to be appending a / to the end of the URL - which would most likely return a 404 error as it thinks the file is actually a directory.

To be more specific, check for any rewrite rules that add a trailing slash to directories (or in general). That is most likely the culprit.

Hope that helps.


How to filter entries by checkboxes using Sprig I am using the Sprig plugin to filter news entries on a news overview page. I have three checkboxes for the categories related to the news entries.
I have the page working for the basic functions by adapting code used on the Sprigboard.
But the page won't let me select multiple checkboxes. I can't figure out how to make Sprig respect all checkboxes and push the selection to the url.
I have previously done this using vanilla javascript, but I wonder if such a feature could be solved elegantly using Sprig.
Category checkboxes:
  {% for category in craft.categories().group('news').all() %}
  <li class="filter--content--item {{ category.id in newsCat ? 'selected' : '' }}">
      <input sprig type="checkbox" class="filter_checkbox" name="newsCat" id="checkbox_{{ category.id }}" value="{{ category.id }}" {{ category.id in newsCat ? 'checked' : '' }}>
      <label id="label_{{ category.id }}" class="newsCatLabel" for="checkbox_{{ category.id }}">
          {{ category.title }}
      </label>
  </li>
  {% endfor %}

Search query:
  {% set newsCat = newsCat ?? '' %}
  {% set relatedTo = newsCat ? relatedTo|merge([newsCat]) : relatedTo %}

  {% set entryQuery = craft.entries
    .section('news')
    .limit(10)
    .relatedTo(relatedTo)
    .search(search)
  %}
  (...)
  {% do sprig.pushUrl('?' ~ {page: page, newsCat: newsCat}|url_encode) %}

Checkbox input field names should be in array format (not specific to Sprig), so I expect this should work.
<input sprig type="checkbox" class="filter_checkbox" name="newsCat[]" id="checkbox_{{ category.id }}" value="{{ category.id }}" {{ category.id in newsCat ? 'checked' : '' }}>


How to display payment gateway error message only I am trying to display the error message coming from the payment gateway ONLY.
I know I can use

{% set message = craft.app.session.getFlash('error') %}
{{ message|length ? message }}

but commerce returns to me a vague error like this

  Unable to update cart.

If anything happens to the cart, even if it is not the payment. I don't know what the error is, nor does the customer. So is there a way to catch payment errors of the cart only?

When submitting a payment form to the commerce/payments/pay controller action there are three potential sources of error messages.

If you are submitting via a normal form submission (not ajax) you will be able to get access to the errors in the following manner from your template.

General Errors

{% set flashError = craft.app.session.getFlash('error') %} For general errors e.g. requireBillingAddressAtCheckout is set to true and there is no billing address on the order.

Order Save Errors

{% set orderErrors = order.getErrors() %} The order is recalculated and saved during the pay process to make sure something has not changed elsewhere. The order is validated and therefore errors will be returned if there are validation issues.

Payment Form Errors

{% set paymentFormErrors = paymentForm.getErrors() %} The payment form errors will contain any errors related to the payment form and, dependant on gateway, may also return payment gateway errors.


Craft Commerce 1 - Stripe payment intents SCA ready I am using Craft CMS 2 with Commerce 1.
I want to update to the new SCA ready (3d secure) Stripe integration.
Has anyone made this already?

The Stripe for Commerce 2 plugin has been updated for SCA, but I'm not aware of any solution for Commerce 1.

https://github.com/craftcms/commerce-stripe


Import Plugin date format (Post Date postDate) Having much success with the Import Plugin

I've also raised this here, but thought this forum perhaps better.

I'm trying to force through a Post Date on my imports, but nothing is being respected, also, doesn't map automatically. All other fields have imported flawlessly, but PostDate seems to stick with the current date (not the date from years ago I want to be the postDate.

Can I check please?

I have CSV column titled tried a few but thought "postDate" would work best.
Date format, matched "31/07/2014" to the field, and "31/07/2014 00:00" but can't get anything to stick though any method (append, or replace)

Thanks in advance.

I haven't yet used the plugin, but I'd try to import the dates into another, custom datetime field (e.g. myImportDate) to see if it's a problem with postDate being a special field (also goes into other tables in the DB, as far as I know). This would be for testing purposes only...

Another hint that might help:
Craft usually saves a datetime in a format like so: "2014-07-31 12:00:00". I've no idea if this is relevant for your plugin though. Same applies for the timezone, as Craft saves a datetime in UTC. As the plugin uses the saveEntry API, you probably don't have to care about the timezone, but the string format could break it for you.

Edit:

OK,postDate should be possible and the timezone defined after Craft install should be used to save datetime values. I'd bet it's the unusual "31/07/2014 00:00" format, Simon!


Image Transforms not generated - permission problem? Since I installed my Craft based website on the production server the image transforms are no longer generated. The tasks runs through more than 5000 images but doesn't generate new ones.
There have been other issues with permissions on this server we solved but we can't figure out what the problem is now, since there are no errors about this.
Does Craft use any temp folders or so when generating the image transforms? When I know which folders are affected I can check the permissions again.
PHP version                 7.4.10
OS version                  Linux 4.9.0-9-amd64
Database driver & version   MySQL 5.5.5
Image driver & version      Imagick 3.4.4 (ImageMagick 6.9.7-4)
Craft edition & version     Craft Pro 3.5.11.1
Yii version                 2.0.38
Twig version                2.12.5
Guzzle version              6.5.5
Imagine version             1.2.3-dev

Craft will store any temporary files it generates into storage/runtime/temp by default, but both Imagick and GD will also likely write to the system's temp folder (likely /tmp but could vary depending on OS and distro).


CP transform renders image 404 I have a transform in my CP called detail large.
IN my template the image will render normally.

Wen i want to use the transform like below:

I get a 404.

The image path created for the transformed asset is:

/webroot/assets/images/_detailLarge

but not folder or assets is ever created there.
Permissions and aliases are fine.


Title Format - Auto Generation via linked entry Finally hopping back into Craft to finish a large project, and am loving so many of the new features added! One thing I am using extensively is the Title Format feature. For one of my entry types, my Title Format field looks like so:

{songTitle} - {{ performedWith.entry.title }}

performedWith is the name of a field that links to an entry. I assumed I could do entry.title to pull the title from the linked entry, but it is simply showing up blank. Any ideas? Thanks!

Lindsey's answer is correct when outputting to a template, however, from within the title field of an Entry Type you would use the following:

{songTitle} - {performedWith.first.title}

entry is not needed, and only need single brackets.


How do I build a LIKE query with DbCommand/Query Builder? I'm trying to construct a fairly simple LIKE query using the Query Builder, and I'm struggling. Here's the SQL that I want:

SELECT `id` FROM `craft_somecustomtable` WHERE ((`somecolumn` LIKE '%foo%') OR (`somecolumn` LIKE '%bar%'))

I've ran the above query in Sequel, with results.

For the Query Builder, here's what I've got so far:

$query = craft()->db->createCommand();
$query->select('id');
$query->from('somecustomtable');
$query->orWhere(array(
    'somecolumn' => 'LIKE %foo%',
));
$query->orWhere(array(
    'somecolumn' => 'LIKE %bar%',
));

This produces the following query, which obviously doesn't work as intended:

SELECT `id` FROM `craft_somecustomtable` WHERE ((`somecolumn`='LIKE %foo%') OR (`somecolumn`='LIKE %bar%'))

I've also tried adding the LIKE directive like this:

$query->orWhere(array(
    'somecolumn LIKE' => '%bar%',
));

This produces an error, however.

Just before posting the question, I had the good mind to read the Yii CDbCommand docs again, and I figured this out myself:

$query->orWhere(array(
    'like',
    'somecolumn',
    '%foo%'
));