Images much larger on server and page than the local version I am trying to bring image file sizes down as much as possible, but the images on the server turn out to be quite a bit larger than the same images I have saved locally.

For example, I have one local image that is 70KB. When I upload it into Assets it‘s 180KB. On the page itself it is being transformed like so:

{% set imgSize = {
    mode: 'crop',
    width: 960,
    height: 450,
    quality: 75,
    position: 'center-center'
} %}

That transformed image on the page is then 208KB.

So rather than optimising file sizes as I thought it did, my set up is making the files 3 times larger.

I have checked the server with phpinfo, and I can't see Imagick installed, but GD v2.1.0 is.

What can I do to prevent the images from becoming larger?

This is likely to be a combination of factors.

Firstly; GD isn't all that great, so if you can get ImageMagik installed it's possible you'll get better results.

Secondly; This can depend on the image format too. PNGs for example are far more complicated to save optimised and it's unlikely that a PNG generated by a server is going to match the level of optimisations you can get locally through tools like TinyPNG and ImageOptim. PNGs have many more options for quality control than JPG's simple slider. Try to avoid transforms on anything other than JPGs.

Thirdly; check you're uploading an image that's larger than the crop you're creating. Craft has a horrible behaviour of blowing up images to match the crop. It's not really cropping, it's just taking any image and making it the size requested. That can mean 'cropped' images larger in filesize and dimension than the source.


Sprout Forms `onSaveEntry` event I need to add an event handler for the onSaveEntry event in order to integrate with another system. In the admin screens for the form where and how do I add this event handler?

Adding an event handler is not something you do through the control panel.

What you need to do is create a plugin (pluginfactory.io makes this fairly easy), and in your plugin's main class, you have an init() function that looks like this:

public function init()
{
    craft()->on('sproutForms.onSaveEntry', function (Event $event) {
        $entry = $event->params['entry']; // fetch the new entry
        ... do things with $entry ...
    });
}

If you structure your plugin properly, you will "do things with $entry" by calling a Service.


Problem uploading JPG in MAMP Pro 4.2 (9213) I use MAMP Pro for a few years in combination with Craft CMS, but since the new upgrade to version 4 I cannot upload JPGs anymore. Dit anybody had the same issue and how to fix this?

In the PHP7.0.20.ini there's a line says:

MAMP_Imagick_MAMPextension=imagick.so

And these are the settings for resource limits:

max_execution_time = 240
max_input_time = 240
memory_limit = 1024M
upload_max_filesize = 32M

But it's different from earlier versions, so it looks like ImageMagick is loaded?

Thanks in advance.

Cheers, Martijn

I found the answer: in the main window of MAMP Pro there's a sidebar with a sub heading Languages > PHP. When you click that and check the option under Extensions: Imagick / ImageMagick, all my problems disappear and I can upload JPG and PNG.


pass data to _layout? I have a field call "scripts" to house scripts like a marketo form script. This gets added in an entry template, but I need to pass this to the layout (if there is something in the field) and render in the footer.

Is this possible? I'm open to ideas or suggestions.

Are you on Craft 3 or 2? In 3, you can use the built-in {% js %} ... {% endjs %} tag to inject scripts into tags named {{ endBody() }} or {{ beginBody() }} that you place wherever you like in your layout.

When outputting from the entry, also be sure to use the |raw filter.

https://docs.craftcms.com/v3/dev/tags/js.html

Craft 2 had a similar function: https://docs.craftcms.com/v2/templating/includejs.html

...Or you can just do it all manually with a Twig block - one thing that's a bit annoying about Craft's built-in tags is that they automatically include the
{% endblock %}

{% block extraFootData %}

    {{ entry.scripts ? entry.scripts|raw }}
{% endblock %}

Edit to add: I forgot to mention the one big advantage of using Craft's built-in methods over native Twig blocks is that they can work anywhere in the template regardless of the nesting level or scope of your blocks. For this reason it's usually preferable. (Even if you start with a simple inheritance model where each template @extends the layout, when the site grows and you start using shared intermediary templates to keep the code DRY, you can start running into very fiddly scope issues).


Tried to duplicate site in local environment but loading blank I'm trying to duplicate an existing Craft CMS site by moving it from an online server to a local installation using MAMP. I have copied the /craft folder and all files in the root of /public_html (including the htaccess file). I have exported and reimported the database using PHPMyAdmin.

But now when I go to localhost:8888 I get a "server not found" error because I've been redirected to www.localhost — is this the issue? I tried swapping out the htaccess file to the default one from the craft installation packet but then instead of getting a server not found I get blank pages.

Any ideas? I'm pretty sure the database imported correctly because I could login to /admin before I moved the /craft folder to the local server.

I ended it up fixing the issue by replacing the /craft folder with the original installation folder and then just replacing /craft/templates and /craft/plugins from the existing site.


Smart Map cluster marker I use Smart Map for a project, but I have a question for this plugin.

Is it possible group the markers per cluster or I need see other options.

Tks

Yes, it's definitely possible to cluster your markers with Smart Map.
In fact, anything that you can do with the Google Maps API can also be done with Smart Map:

Manipulating the map in JavaScript

I'd recommend adding the Marker Clusterer JS library to your project.


Testing database credentials Craft 3 Setup When i try setup db in craft 3 at windows with composer using php craft setup/db command it give me
Which database driver are you using? [mysql,pgsql,?]: pgsql
Database server name or IP address: [127.0.0.1]
Database port: [5432]
Database username: [root]
Database password:
Database name: cmsdb
Database schema: [public]
Database table prefix:
Testing database credentials ... failed: could not find driver
Database server name or IP address: [127.0.0.1]```

This might be the problem with the pgsql driver.
You need to install and activate postgresql extension in PHP
You can use below command to install it.
[sudo] apt-get install php-pgsql

For activating it, uncomment pgsql and pdo-pgsql extensions in etc/php/$PHP_VERSION/apache2/php.ini file.
After all this you need to restart you apache server and the try to connect again.


How do I optimise this colossal query? This complex query makes the server cpu run at 100%.

{% set entries = craft.entries({
      section: sectionParam,
      search: searchParam,
      relatedTo: relatedToParams,
      condition: conditionParam,
      price: [
          'and',
          '>= ' ~ pricesParam|split(';')[0],
          '<= ' ~ pricesParam|split(';')[1]
      ],
      priceOffer: [
          'and',
          '>= ' ~ pricesParam|split(';')[0],
          '<= ' ~ pricesParam|split(';')[1]
      ],
      specsMtplm: weightParam,
      specInternalLengthFeet: lengthParam,
      priceOffer: '',
      specsBerthSleeps: [
          'and',
          '>= ' ~ berthsParam|split(';')[0],
          '<= ' ~ berthsParam|split(';')[1]
      ],
      spectransmission: transParam,
      seatbelts: seatbeltsParam

}).order('dateCreated desc').limit(null) %}

How can I optimise this twig so it doesn't kill the server each time it runs?

This is really difficult to provide a proper answer for in its current form, so I'll give some general advice when troubleshooting things like this.

Try to limit the complexity of the Twig code building the query.  It might help to break it up into multiple, smaller queries instead of executing everything as one monolithic query.
Don't do this in Twig. Break out into a plugin/PHP using a template hook and grab only the data you need using query builder. Again, it might help to break things up into multiple, smaller queries even from PHP.
Enable devMode and find the resulting SQL that is generated.  Use standard MySQL slow query debugging techniques to see where the bottleneck is and optimize from that information.
Finally, you can try to throw more resources at your server and brute force your way though it.


Error sending email: Process could not be started [The system cannot find the path specified. craft cms I'm testing my email and I'm seeing the following error in the web logs:

  "Error sending email: Process could not be started [The system cannot find the path specified. craft cms"

Does anyone know what that means?

In my local environment I am not seeing what exactly causes this error.
I've tried following this article on Craft but it seems like this is not relevant to the error I am receiving?

https://craftcms.com/guides/troubleshooting-email-errors

Also, I don't see the file structure they mention on this article, I found the error log on storage/logs/web.txt.

I've tried also changing my email to SMTP with Outlook credentials to no avail.

The images show the directory structure I'm seeing: https://i.stack.imgur.com/yvDex.png

Error sending email: Process could not be started

That error means that you've got sendmail selected as the mail driver for Craft under Settings->Email in the Control Panel, but the sendmail executable is either not installed or configured properly on your server.

  Also, I don't see the file structure they mention on this article, I found the error log on storage/logs/web.txt.

That's correct... the article was written for Craft 2 and you're using Craft 3. The log paths changed a bit between the two versions.

  I've tried also changing my email to SMTP with Outlook credentials to no avail.

I'm guessing you got a different error then?  I'd suggest setting up Craft with a transactional email provider like https://postmarkapp.com/ or https://sendgrid.com/.

There are Craft plugins for each (https://plugins.craftcms.com/sendgrid and https://plugins.craftcms.com/postmark), they'll be more reliable than sendmail and easier to setup than SMTP.


How to display a flash message in a template I have a plugin that accepts a form post. I need to return a notice or error, plus the original data. Starting with the notice/error first, I have tried this:

if (craft()->broadbean_jobs->createJob())
{
    craft()->userSession->setNotice(Craft::t('Job created.'));
}
else
{
    craft()->userSession->setError(Craft::t('Unable to create job.'));
}

$this->redirectToPostedUrl();

How can I display the notice or error in my template?

You can use the setFlash function in the userSession Service like this:

In your Controller:

craft()->userSession->setFlash('yourVariable', "Something happened yo!");

In your template (that the user gets redirected to):

{% set message = craft.session.getFlash('yourVariable') %}

After that just run an if-statement to see if the message is set or not.

EDIT:
In Craft 3 controller:

Craft::$app->session->setFlash('yourVariable', "Something happened yo!");

In template:

{% set message = craft.app.session.getFlash('yourVariable') %}
{% if message|length > 0 %}
    {{message}}
{% endif %}


Laravel Homestead installation nightmare I'm running Vagrant/Virtual Box on a Windows 10 host.

I originally installed Craft on a Vagrant Scotch Box (https://box.scotch.io/). The admin panel was running a little slow so I tried installing in on a Laravel Homestead box after reading that many developers were using this solution.

I had many problems getting this to work, and when I did get it working the performance problems were worse than with my original installation.

First problem was the missing mcrypt extension in PHP 7. If you Google for a solution, you will see this:

sudo apt-get install php7.1-mcrypt

This command, although it runs ok does not result in the extension actually being installed. phpinfo shows that the extension is still not available.

I tried enabling Apache using the Homestead Yaml settings to see if that made any difference. It did not.

After doing an update and an upgrade in the Ubuntu shell, I was finally able to get the mcrypt extension running with a slightly different command:

sudo apt-get install php-mcrypt

After this I was able to run the Craft installer, but the site was running even slower, CSS files for the admin panel were intermittently failing to load, and database requests were extremely slow.

I started seeing weird MySQL errors, which were apparently a result of an incompatibility with the latest version of MySQL. This problem was resolved by adding the following to the my.cnf file in Ubuntu:

sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

This change did not improve the performance issues however.

I reverted back to Nginx to see if that would fix the problem. It did not. I then destroyed the vagrant box and started again with a brand new box.

This time I was not able to get the mcrpyt extension running at all, using either form of the Ubuntu package installer commands. It kept hanging at one of the "processing triggers" steps.

Homestead works great for Laravel and the performance is snappy, but for me getting it to play nice with Craft has been a disaster.

I am going to stay with Scotch Box for now, which runs on PHP 5.6 & MySQL 5.0.

Note: The "nfs" setting is enabled for both of these vagrant boxes, and vagrant-winnfsd (1.3.1) is installed.

I would be interested to know if anybody else had a similar experience and managed to get everything working?

If you follow the instructions here: Local Development with Vagrant / Homestead and can't get it working, let me know.

That's the exact procedure I use whenever I set it up; I just did it 3 weeks ago to set up a new machine running Homestead without incident.


Commerce 1 create a new order programmatically How can this be done in PHP?  I can't find anything in the docs.

To add orders programmatically, you can do so by using the Commerce_OrderModel class.

Like so:

$order = new Commerce_OrderModel();
$order->email = 'test@example.com';

// Add your products here and other order info...
// .................

$success = craft()->commerce_orders->saveOrder($order);


Set a user's group on a registration form using a hidden field I am looking to have two separate front end registration forms for adding users to either the partners user group or the members user group. These have been created in the back end with the following user group handles: members and partners.

I have added the following hidden field to the partners registration:

<input type="hidden" name="userGroup" value="partners">

and the following hidden field to the members registration:

<input type="hidden" name="userGroup" value="members">

I have then created a plugin with the following code:

public function init() {

   parent::init();

     craft()->on('users.saveUser', function(Event $event) {

      // only fire if new user
      if ($event->params['isNewUser']) {

          // retrieve the userModel from the event
          $user = $event->params['user'];

          // check for presence of 'type' POST field
          $userGroup = craft()->request->getPost('userGroup');

          $userGroups = array();

          if ($userGroup == 'partners') {
              $userGroups[] = craft()->userGroups->getGroupByHandle('partners')->id;
          }

          if ($userGroup == 'members') {
              $userGroups[] = craft()->userGroups->getGroupByHandle('members')->id;
          }

          if (count($userGroups))
          {
              // assign the user to the groups
              craft()->userGroups->assignUserToGroups($user->id, $userGroups);
          }
      }
  });
}

This code is not adding the user to either of the groups but the user is created with no problem.

There's a couple of problems you're probably running into.

By default, assigning user permissions (either directly or via groups) requires the the currently logged in user to have the assignUserPermissions permission. It sounds like you're doing this from a front-end request, where I'm guessing there is no authenticated session in place.
User groups and permissions are applied in Craft after the user has already been saved, so even if you got by #1, your changes would probably be overwritten.  The events you should be listening for are probably onBeforeAssignUserToGroups and onAssignUserToGroups.

Of course, you can always write a custom plugin that has a controller action, point your form to it, and do whatever custom user saving logic your situation requires as well.


Security Headers in htaccess Don't Work We have an issue on our server when our Security Headers are not working. We added the following to our htaccess file after installing Craft CMS: -

<IfModule mod_headers.c>
    Header always set X-Xss-Protection "1; mode=block"
    Header always set X-Content-Type-Options "nosniff"
    Header always append X-Frame-Options ALLOWALL
    Header always set Strict-Transport-Security "max-age=31536000"
    Header always set Referrer-Policy no-referrer
</IfModule>

These settings worked on our previous CMS which was completely developed in house. We have recently upgraded our server to PHP 7 and Apache 2.4. We have been using https://securityheaders.io to check our results.

Any help trying to get this to work would be really appreciated.

I'm assuming mod_headers is installed & active? Otherwhise I can't say why the .htaccess rules are not applied (devOps is not my forte) but you could set them through the twig template.

See here for the tag to use. Basically it comes down to something like this (untested):

{% header 'X-Xss-Protection "1; mode=block"' %}
{% header 'X-Content-Type-Options "nosniff' %}
{% header 'X-Frame-Options ALLOWALL' %}
{% header 'Strict-Transport-Security "max-age=31536000"' %}
{% header 'Referrer-Policy no-referrer' %}

You can make those in a block and just include the block on all the relevant pages.


Is there an API for modals? I’m looking to hook into existing modal functionality, if any exists.

Is there any way of doing this?

If there is, what’s the advised approach and considerations required to ensure responsiveness?

In the CP you can generate a modal using craft's 'garnish' js as explained in this answer. On the front-end I believe you would need to develop you own solution.


Checking permission for editing entries from inside template How do I check permission for editing entries belonging to a specific section?

When I try {{currentUser.can('editEntries:'~entry.sectionId) }}, it returns false - and I am sure that currentUser can edit entries from this section.

edit:
Its craft 3.1

In Craft 3.1, permissions checks are done based on uid now, not id.

This should work:

{{ currentUser.can('editEntries:'~entry.getSection().uid) }}


Charge/Stripe and "Missing required param: exp_month." I'm working on getting charge to take donations and have set up my Expiration date field the same as in the demos.

    Expiration Date
    <input type="text" class="form-control" data-stripe="exp"  id="cardExpiry" placeholder="mm / yy" required>

However on form submission (in test mode) I see this error.

  Missing required param: exp_month.

Not sure how to resolve this. Please advise

I got this resolved by official support.

When using the combined date input you'll need to include the exp_month and exp_year inputs as hidden fields in the form.

And here's the working hidden fields:

  <input type="hidden" name="cardExpMonth" value="" data-stripe="exp_month">
  <input type="hidden" name="cardExpYear" value=""data-stripe="exp_year">


Eager Loading Relatedto & Target Elements I have quite a substantial amount of queries heading out for this bit of code below. I've tried quite a few things to get it down, but I need to eager load some things just to try and reduce the overhead of this, but I still think it won't do enough. Is there anything I can look at to optimise this?

    {% set brandIds = craft.entries().section('brands').relatedTo({ targetElement: category }).ids() %}
    {% set offers = craft.entries().section('offers').relatedTo(brandIds).limit(6) %}

    {% for entry in offers %}

              {% for asset in entry.relatedBrand.one.brandLogo.all() %}

              {% endfor %}

{{ entry.title }}

{{ entry.body }}

              {{ entry.relatedBrand.one }}

  {% endfor %}

First of all just a few ideas about best practices

Don't

{{ entry.relatedBrand.one.url }}
{{ entry.relatedBrand.one.title }}
{{ entry.relatedBrand.one.size }}

Do

{% set relatedImage = entry.relatedBrand.one() %}
{{ relatedImage.url }}
{{ relatedImage.title }}
{{ relatedImage.size }}

Furthermore your code with eager loading

{% set brandIds = craft
    .entries()
    .section('brands')
    .relatedTo({ targetElement: category })
    .ids()
%}
{% set offers = craft
    .entries()
    .section('offers')
    .with(['relatedBrand.brandLogo'])
    .relatedTo(brandIds)
    .limit(6)
    .all()
%}

{% for entry in offers %}

    {% set relatedBrand = entry.relatedBrand? entry.relatedBrand[0] : null %}

          {% set logos = relatedBrand? relatedBrand.brandLogo : [] %}
          {% for asset in logos %}

          {% endfor %}

{{ entry.title }}

{{ entry.body }}

          {{ relatedBrand.title?? '' }}

{% endfor %}


How to check variable type? How do I check what type my variable of (string, integer, boolean, array, dictionary,  etc)?

To my knowledge this is not possible natively in Twig. Depending on your situation / template needs here are some useful tests

{% if foo is iterable %}

Array or object

{% if foo is same as(true) %}

Basically identical to using === in php


Searching for item SKU in Commerce orders I'm trying to show some Commerce 2 order information on the front-end. I can't work out the correct syntax. I'm trying to list orders that include a specific product.

I have orders for item SKU "abc123" but this is returning no results.

{% set myOrderQuery = craft.orders()
    .relatedTo("abc123")
    .limit(10)
    %}

{% set orders = myOrderQuery.all() %}

{% if orders|length %}

    {% for order in orders %}
      {% for item in order.lineItems %}

{{ item.sku }}

      {% endfor %}
    {% endfor %}

{% else %}

No results

{% endif %}

If I remove the .relatedTo parameter I get results including orders for that item. How do I just return orders that include that item?

I've tried various permutations of relatedTo and search but haven't found anything that works yet.

Use the hasPurchasable order query param:

https://docs.craftcms.com/commerce/v2/dev/element-queries/order-queries.html#haspurchasables

{% set myOrderQuery = craft.orders()
    .hasPurchasables(product.defaultVariant)
    .limit(10)
%}


How do I import data into Craft? What's the best known way to import masses of data into Craft?

Are there tools that support the migration of content/users from say XML, JSON etc.

There is craftimport which is an 'unsupported' starting point for importing entries from an XML source.

https://github.com/clearbold/craftimport

There is also Import:

https://github.com/boboldehampsink/import

which can import from CSV sources.

Check out http://straightupcraft.com/craft-plugins for a list of current Craft plugins.


How to install cURL on Ubuntu 14.04 to run Craft CMS? I'm in the process of installing Craft on my Ubuntu 14.04 server and ran into an issue.

When I run the installer at http://example.com/admin, I get the "Can't run Craft" error message:

Craft requires cURL in order to run

I have these packages installed using sudo apt-get install:

curl
libcurl3
libcurl3-dev
php5-curl

No clue what's going on. Could be a configuration issue? or are my packages not properly installed?

Thanks for the help!

You likely need to go to /etc/php5 and either make a link or move curl.ini from the mods-available folder to mods-enabled. (Just did this myself on Ubuntu 14.04 server)

Also, be sure to restart apache:
    su apache2ctl restart


“Service Unavailable” message when not logged as admin I am junior web developer I am setting up my first website with Craft CMS. I have been getting the "Service Unavailable" error message on my site every time I try to enter not logged in as admin. I've done some searches on this StackExchange site and tried setting again the permissions for craft/app/, craft/config/, and craft/storage/ as told in the installation docs, but didn't work. I've also tried modifying the .htaccess as told in other thread, but still didn't work.

Any help would be very appreciated. And forgive my ignorance since I'm very new to this CMS :D.

Make sure your site is enabled under Settings ➞ General ➞ System Status.

Also, check your craft.log files under /craft/storage/runtime/logs/craft.log.


Pass Controller Variables into a Model I am using a Controller to get Variables from a field in my Plugin.
How and what would be the best way to pass and use them in other classes or my main plugin file.

I thought about using Sessions or passing them via URL Parameters, but i am not sure if thats the most convenient way.

Thats my controller:

use craft\web\Controller;

class SetUserController extends Controller {
    public function actionSubmitUser() {

        $request = \Craft::$app->getRequest();

        $dateTime = $request->getParam('dateTime');
        $user = $request->getRequiredParam('user');

    }
}

e.g. in my main plugin file i would like to pass the variable to a function:

// check if commerce record for craft user exists
public function checkCommerceRecord($user) {
    return $this->customers->getCustomerByUserId($user);
}

Update:

I figured that i need to setup a module, however i cant save the variables into the module, getting Setting unknown property: wewereyoung\wfwplugin\models\WFWPluginModel::userId

Module:

namespace wewereyoung\wfwplugin\models;

use craft\base\Model;
use craft\validators\ArrayValidator;

class WFWPluginModel extends Model {

    public $setUser = [
        'userId',
        'timeDate'
    ];

    public function rules() {
        return [
            [
                [
                    'setUser'
                ],
                ArrayValidator::class
            ]
        ];
    }
}

Updated Controller:

namespace wewereyoung\wfwplugin\controllers;

use craft\web\Controller;
use wewereyoung\wfwplugin\models\WFWPluginModel;

class SetUserController extends Controller {
    public function actionSubmitUser() {

        $request = \Craft::$app->getRequest();

        $dateTime = $request->getParam( 'dateTime' );
        $userId   = $request->getParam( 'user' );

        $setUser            = new WFWPluginModel();
        $setUser->userId   = $userId;
        $setUser->dateTime = $dateTime;

    }
}

To simply pass the variables to your plugin or module use:

MyPlugin::getInstance()->checkCommerceRecord($user, $dateTime);

To pass to a service (see the Creating a Service section of the docs) use:

MyPlugin::getInstance()->myService->checkCommerceRecord($user, $dateTime);

To pass it with your model use:

$model = new WFWPluginModel(['setUser' => [$userId, $dateTime]]);

MyPlugin::getInstance()->myService->checkCommerceRecord($model);


Multiple contact forms - Different recipients I'm creating a website that has a contact form on two different pages.

I am using the Pixel & Tonic ContactForm plugin and currently have a working contact form on one page - This one requires the user to provide their name, email, telephone, company name and message.

On the other page, the contact form is different as the user needs to select which department they would like their message to be sent to. For example:

  <div class="select-wrapper">
   <select name="department" id="department">
    <option value="">- Please Select -</option>
      <option value="one">Business One</option>
      <option value="two">Business Two</option>
      <option value="three">Business Three</option>
      <option value="four">Business Four</option>
   </select>
 </div>

In the README document for this plugin, I can see that it is possible to programatically add email recipients by adding a hidden input field named “toEmail” and changing the craft/config/contactform.php config file

But, is it possible to do this when there is another contact form on the site?
If so, what do I need to add to the department dropdown code?

But, is it possible to do this when there is another contact form on the site?

Yes?

  If so, what do I need to add to the department dropdown code?

The dropdown code shouldn't have anything to do with it, if I'm following you correctly.

Both forms just need to have a toEmail hidden input as specified in the docs: https://github.com/pixelandtonic/ContactForm#dynamically-adding-email-recipients-requires-craft-25


Odd behaviour when uploading .svg Assets Running 2.6.2983 on OS Sierra.

I'm noticing that some of my SVG files when uploading are going from 50kb to 1kb and then appear completely blank when trying to view them. Does anyone have a clue why this would be happening?

Thanks,

Half-bug, half side-effect/undesired behavior for SVG sanitization that got added in Craft 2.6.2982 for SVGs that use embedded data.

The next release of Craft (post 2.6.2983) adds a sanitizeSvgUploads config setting (true by default) that you will be able to set to false to disable SVG sanitization.


How to manage different templates for a structure i am trying to figure out the right way to display elements on a page.
Its about a website for a fashion designer. There will be parent elements like :

Parent X
Parent Y

both of those elements use the same template and i used structure for it. i figured structure is the right choice because of the ability to sort them in the panel etc.

It should be possible to add child elements to the parents like

Parent X

Item a
Item b

Parent Y

Item c

etc..

those elements are using a different template:

Like
- ParentTemplate/

and
- ParentTemplate/ItemTemplate/

how can i structure them in the craft panel without making them a new structure, because the new structure isnt related to parents then anymore , what they have to be ... ot is it the wrong approach here ?

thanks a lot guys

Your approach looks good to me. There are different ways you can make it happen:

If you set up your structure in the CP you can decide how many levels you want to allow for that structure. (By default the number of levels is not limited.) If you have entered at least one parent entry in your structure, you can assign child entries in two ways:

1 – When you create a new entry you can choose a parent for that entry.

2 – If you miss that step or you change your mind later, you can move your entries around in the structure entries list: Choose your structure under „Entries“, klick and hold the cross in front of the entry you want to move and then drag it to the desired location. (So it´s possible to move a child entry from one parent to another later on.)

As for the templates for this set up, you have different options as described here:
How to load a different template for parent page

Another possibly interesting solution would be „Entry types“.

If you find that your parent entries would also use different fields than your child entries it could make sense to define a second entry type for the children in that section (https://craftcms.com/docs/sections-and-entries). When you define the „child" entry type, you assign fields to that just like for the first (parent) entry type. If you now enter a new entry for the section you can choose between the entry types and then are presented with the different field sets.

Regarding the templates you can still use the first solution but now you could change the layouts based on entry types as well:
In your template for single entries you could something like this

{% if entry.type == "child" %}
    {% include "sectionTemplateFolder/_types/child" %}
{% else %}
    {% include "sectionTemplateFolder/_types/parent" %}
{% endif %}

(This example assumes that you have an actual entry type called „child“, replace the „child“ in the if statement with your desired name.)

An elegant solution how to change layouts between several entry types is given here:
https://craftcms.com/support/entry-type-templates

Whatever approach you take you do not need to structure your templates like your entries. Within the Craft templates folder, the templates can live where it makes the most sense to you. For the entry-type example it could be

sectionName (folder)

index.html (for listing)
_entry.html (for the single entries)
_types (folder)

child.html
parent.html

Hope this helps?


Upgrade failed - what needs to be restored? Unfortunately I tried to (auto)upgrade to v2.5.latest on a live site (after testing on another development (but different site)) and it failed resulting in the site being down. What is the best way to restore the site to pre-upgrade and working state? I plan to

Remove the existing database and replace with the one created by the
backup process - that part seemed to go OK.
Replace the /craft/app directory from the version that matches the database backup.

Are there other files/things I need to do to recover the situation?

That should do it!

Auto-updating to 2.5 is causing a few people headaches, mainly because people are bumping up against their php.ini setting limitations. It's a pretty significant update, requiring pretty significant server resources to handle the transition.

Once you've successfully rolled back, I'd recommend performing a manual update. This takes a lot of pressure off of your server, and only leans on your server resources to run the database migrations (which definitely shouldn't cause any overloads).


Unable able to update Freeform Pro from 2.2 to 2.5 I continue to get this error each time I try to update Freefrom.
I don't was to alter the table structure since data exists.

Solution: Instead of using the Craft updater, execute a composer require composer require solspace/craft3-freeform-pro


Routing: ignoring a segment from the URL I am trying to configure my routes so that the last segment of the URL is ignored and can be used as parameter in the twig file.

for example, the following URL should ignore the city-segment

/services/name-of-the-service/city

and should be routed to

/services/name-of-the-service

I have currenty set up the following routing-rule

'services/<service:{slug}>/<city:{slug}>' => 'service/<service>'

Which results into a 404 and says
Unable to resolve the request "services/name-of-the-service".
Which is the exactly the URL that I want to get parsed...

When I am trying to route to the template

'services/<service:{slug}>/<city:{slug}>' =>  ['template' => 'services/_entry']

Which seems to load the correct template but the entry can not be parsed...

Any ideas how to solve / work around this problem?

I did something similar for a site that showcased projects.

In the top of my entry page, I had code like this:

{% set entrySlug = craft.app.request.getSegment(2) %}
{% set entry = craft.entries.section('services').slug(entrySlug).one() %}

{% if entry is not defined or entry is null %}
    {% exit 404 %}
{% endit %}

And then I've got two routes:

services/<slug>/* which routes to services/_entry

services/<slug> which routes to services/_entry

Might not need both, but for me, when I didn't have both, I'd get a 500 error when the second segment was broken.


Get all variants from multiple products I need to get a list of variants from multiple products, but in a way that allows us to show the results in Craft's handy {% paginate %} tags.

So far we have this less-than-appealing markup:

{% set firstProduct  = craft.products.relatedTo(category).one() %}
{% set results = craft.variants({product: firstProduct}) %}

{% set products  = craft.products.relatedTo(category).all() %}

{% for product in products %}
    {% set results = results|merge(craft.variants({product: product})) %}
{% endfor %}

However, because we're using merge it's turning our ElementCriteriaModel into an Array. Is there a way to use the {{ craft.variants({product: product}) }} tag and pass it multiple products?

(Craft3 and Commerce2)

Thanks

EDIT: Final markup that ended up working:

{# All products within this category #}
{% set products = craft.products.relatedTo(category).all() %}

{# Empty variant id array #}
{% set variantIds = [] %}

{# Populating variant id array #}
{% for product in products %}
    {% set variantIds = variantIds|merge(craft.variants({product: product}).ids()) %}
{% endfor %}

{# Get all variants from the variant id array #}
{% set results = craft.variants.id(variantIds).orderBy('title asc') %}

The "variant" method can receive multiple ids using the following: craft.variants().id([1,2,3]).

Following that, you can easily populate an array while looping through your (specific) products, and then use that array to fetch the variants.

Official documentation


How should a multi-stage editorial process be implemented in Craft? I'm building an editorial system on Craft which has 6-8 editorial stages, such as Assignment, Initial Proofing, Secondary Proofing, etc.  It seems that the simplest solution would be to have the current stage be a custom field.  I'd like to build this system entirely using Craft's backend so I don't have to reinvent all of the niceties Craft provides.

The fuzzy part, however, comes when I'd like to be able to have a "Send to Next Stage" button.  For instance, if the article is done with its initial proofing, the proofreader should be able to mark it as done and automatically send it to the Secondary Proofing step.  I realize that I could just have a dropdown where the user changes the status and saves it, but that feels cumbersome.  Stage 1 should only be able to send entries to Stage 2.  Stage 2 should only be able to send entries to Stage 3.  Things should never skip steps or move backwards.

My current thought is to hook into the entries.onSave event and have a switch or something to automatically change the status.  Then, I suppose that within a stage, all versions would have to be saved as drafts rather than entries, as saving would have that side-effect of essentially marking the entry as complete.

Is there a simpler, more foolproof, or more intuitive way to walk an article through an editorial process like this?  I suppose I could use categories rather than a custom field type, but the entries.onSave hook would still have to be the mechanism I'd use to automatically send the article to the next stage of the editorial process.

Have you already seen the workflow plugin? Maybe it could give you some inputs for your further development: https://github.com/engram-design/Workflow.


frontend editing, show selected category I have this in my edit form

{% set categories = craft.categories.group('jobCategory') %}
    <label for="fields[jobCategory]">Job Category:</label>
    <select id="jobCategory" name="fields[jobCategory]">
        {% for category in categories %}
            <option value="{{ category.id }}">{{ category.title }}</option>
        {% endfor %}
    </select>

but can't for the life of me, show select as 'selected' for the category the entry belongs to.

Missing something simple I'm sure.

Something like the following should work. This assumes that your category field handle is 'jobCategory', and has a limit set to 1.

{% set categories = craft.categories.group('jobCategory') %}
{% set entryCategory = entry.jobCategory.first %}
<label for="fields[jobCategory]">Job Category:</label>
<select id="jobCategory" name="fields[jobCategory]">
    {% for category in categories %}
        <option value="{{ category.id }}" {% if category.title == entryCategory %}selected{% endif %}>{{ category.title }}</option>
    {% endfor %}
</select>


Password validation for resetting password I have the following code to further validate passwords when creating/registering an account which is working fine.

However, when trying to use this same validation for resetting a password I am not getting any errors back?

Can anyone point me in the right direction...?

public function onBeforeSetPassword(Event $event)
{
    $user = $event->params['user'];
    $password = $event->params['password'];

    if (mb_strlen($password) < 8)
    {
        $user->addError('password', 'Sorry but your password must be at least 8 characters.');
        $event->performAction = false;
    }

    if (!preg_match('/(\d.*[A-Z]|[A-Z].*\d)/', $password))
    {
        $user->addError('password', 'Sorry but your password must contain at least one uppercase letter and one number.');
        $event->performAction = false;
    }
}

On the template:

{% if account is defined and account.getErrors('password') %}
    {% include '_includes/formError' with { error : account.getErrors('password')|join('<br>') } %}
{% endif %}

Thanks.

I wasn't validating againts the field newPassword, only validating against password. Hence why I wasn't getting any feedback. Duplicating the validation for newPassword seems to have resolved this.


Plugin development - How to access actions? I have a simple controller in /craft/plugins/craft-dns-notifier/src/conrollers/DnsNotifierController:
namespace kokesjan\dnsnotifier\controllers;
use craft\web\Controller;

class DnsNotifierController_DbController extends Controller
{
    public function buu() {
        echo "tradada";
    }
}

I would like to access the buu() action from src/templates/index.html twig file via Ajax.
I've had no luck for three days, unable to find any hint anywhere. Nothing I have tried worked. It seems like very easy task to me, but I just can't make it work.

I'd suggest generating the code via pluginfactory.io and if you have code comments enabled, it'll give you the URI that you need to trigger your action in the example code.
But essentially it's going to be a kebab-case version of your controller route, with a kebab-case version of your method name (but removing the action preface).
For you, first you should rename your method thusly:
    public function actionBuu() {
        echo "tradada";
    }

And then your URI would be something like:
/actions/dns-notifier/dns-notifier-controller-db-controller/buu

See here for more on controller actions


How do i get variables from general.php Within the config folder there is a general.php file with various vars which are site specific.

how do i get at these from within a plugin?

Thanks for your help.

For Craft 3:

Craft::$app->config->general->{var name}


Links breaking with double domain When calling my links, they're appearing and trying to link like so:

  testurl.com/university/testurl.com/university/arizona-state/

Really it should just be

  testurl.com/university/arizona-state/

The line that is generating a category URL:

        <a class="university-widget w-inline-block" href="{{ category.url }}">

and my general.php:

return array(

  '*' => array(
  ),

  'localhost' => array(
    'devMode' => true,
    'siteUrl' => 'http://localhost:8888/',
    'server' => 'localhost',
        'enableCsrfProtection' => true,
        'defaultWeekStartDay' => 0,
        'omitScriptNameInUrls' => 'auto',
        'defaultSearchTermOptions' => array(
            'subLeft' => true,
            'subRight' => true,
        ),
        'cpTrigger' => 'admin',

    'environmentVariables' => array(
      'baseUrl'  => 'http://localhost:8888/',
    ),
    'testToEmailAddress' => 'dev@email.com',
  ),

  'testurl.com' => array(
    'siteUrl' => 'testurl.com',
    'server' => 'localhost',

        'enableCsrfProtection' => true,
        'defaultWeekStartDay' => 0,
        'omitScriptNameInUrls' => 'auto',
        'defaultSearchTermOptions' => array(
            'subLeft' => true,
            'subRight' => true,
        ),
        'cpTrigger' => 'admin',

    'environmentVariables' => array(
      'basePath' => '/var/www/html/',
      'baseUrl' => 'http://testurl.com/',
    )
  )
);

Fixed by changing the following line:

'siteUrl' => 'http://testurl.com',


Error: Invalid negative value for  attribute I'm trying to create a dashboard widget using the new Craft charting library.  I'm more or less copying the New Users widget however I'm running into an issue where my container does not seem to be behaving in the same way as the New User widget - it appears the container is getting a different width and no height.

Similar to NewUsersWidget.js I am using these three lines of code to set the container:

this.$widget = $('#widget'+widgetId);
this.$body = this.$widget.find('.body:first');
this.$chartContainer = $('

').appendTo(this.$body);

However, when I inspect this.$chartContainer in the NewUsersWidget.js it has a width and height whereas when I inspect this.$chartContainer in my own widget, the width is different and the height is not present. I don't see these values set explicitly in the New Users widget. It appears they may be set dynamically in craft.js, but I'm not sure. Both javascript objects extend Garnish.Base.

Understandably, someone helping troubleshoot this may need more context. I'm really not sure what more I should be sharing, so let me know if I can provide additional details to help narrow down what may be happening.

A more general question may be, how does width and height get set when creating a variable (this.$chartContainer) in an object that extends Garnish.Base? Why would two different widgets creating the same variable both end up with a different height and width?

Craft charts are taking the width and height of the container's
 as a basis for drawing the chart. So your JS is probably working but you need to define a width and height for the chart's div to make it work.

A basic implementation of the Area chart would look like this:

{% extends "_layouts/cp" %}
{% set title = "Area Chart"|t %}

{% includecss %}
    #chart {
        width: 400px;
        height: 300px;
    }
{% endincludecss %}

{% includejs %}

    var $chart = $('#area'),
        chart = new Craft.charts.Area($chart);

    var dataTable = new Craft.charts.DataTable({
        columns: [
            { label: "Date", type: 'date' },
            { label: "New Users", type: 'number' },
        ],
        rows: [
            ['2016-01-23', 5],
            ['2016-01-24', 15],
            ['2016-01-25', 10],
            ['2016-01-26', 13],
        ]
    });

    chart.draw(dataTable);

{% endincludejs %}

{% block content %}

{% endblock %}


How to query EntryQuery for multiple sections with varying types I think the best way to pose this question is by giving an example:
Given a variable $query of type craft\elements\db\EntryQuery, I'd like to get entries from 2 different sections: "people" and "news". Of the entries from the "people" section, I only want ones with entry type "Employees". How would I set this up so that the "type" filter only applies to 1 section? If I were querying them individually, they would look like this:
$query->section('people')->type('Employees');
$query->section('insights');

How can I do this in 1 query? Thanks!

I'm not sure you can achieve this in one query.
The easiest solution I can think of to your problem requires 3 queries:
{% set peopleIds = craft.entries().section('people').type('Employees').ids() %}
{% set insightIds = craft.entries().section('insights').ids() %}
{% set query = craft.entries().id(peopleIds|merge(insightIds))

The first 2 queries are executed and return the ids of the matching entries. You can then create  your EntryQuery using the ids as the only criterion.


Is there a way to delete all entries? Starting on a second site which is an almost like for like copy of the first, except it has different content. I cant use locales to manage it because there may be the possibility of multiple languages on the second site.

I have dozens of field & entry types I want to transfer over to the second site. Is there an automated way of deleting all the content?

You could also delete all rows in your craft_elements table, which have type set to Entry (or whatever ElementType you want to delete).


Payment Method and Discount elements query by ID in Twig In Craft 2, is it possible to query a specific element by ID in Twig?  They aren't mentioned in the docs.

I was trying things like these but without success:

{{ craft.commerce.paymentMethods.id(1).name }}

Commerce 1:

{% set paymentMethod = null %}
{% for pm in craft.commerce.paymentMethods %}
    {% if pm.id == 2 %}{% set paymentMethod = pm %}{% endif %}
{% endfor %}

{{ paymentMethod.name }}

Commerce 2:

{{ craft.commerce.gateways.getGatewayById(2).name }}


Commerce: Calendar to Product Quantity I'm working on a Commerce Grocery Store that allows users to select a day to have their order either picked up or delivered. Furthermore, some products will have a set quantity for each day of the week. As an example, Fresh Cinnamon Rolls may have 20 available on Thursday, and only 5 available on Friday. With users being able to make an order and then select 'Pickup on Friday', that would mean Friday's quantity for the product needs to be checked and adjusted.

This kind of thing is going to be a bit of work with a Craft Plugin. I've been struggling to come up with simply a concept/path for how I would go about this quantity-by-calander situation. The client is imagining the 'Quantity' field in variants being a calander, where he can define the quantity for each day of the month.

I know this isn't the most technical question as I'm not providing code. But it would be incredibly helpful to get some insight from some of you Craft/Commerce experts on just how you would go about something like this in a plugin. If you thought of an approach while reading this, I'd love to hear it!

Thanks in advance!!

Sounds like a fun project. :) My thoughts:

– I'd ditch using Commerce' stock management, and set all products to have unlimited stock.

– I'd build a plugin that has a field type that attaches to products/variants, that lets the client add stock to certain dates for that product/variant.

– I'd have template variable for getting stock for a given date and product/variant, and use it to show availability in the templates. If you need to show availability in product listings, I'd probably also create a custom template variable for getting products (instead of using craft.commerce.products directly), that extends the element criteria to add your custom stock availability to it (see this article, or my Similar plugin for examples).

– I'd listen for some Commerce events (commerce_orders.beforeOrderComplete and commerce_variants.onOrderVariant) to update the stock level when an order is placed (see the Stock Notifier plugin from P&T for examples)

To be honest, I think the biggest challenge is the second point, making the interface and database structure that lets the client update availability. A real simple solution where they add a date and a number for stock, is easy enough. But making a nicer calendar interface, and adding support for stuff like recurring dates ("we have 20 fresh cinnamon rolls every thursday"), gets pretty complicated pretty fast. But, it all depends on the use case how advanced it needs to be.

Anyways, that's my initial thoughts. :)


Replacing core services I'm relatively new to CraftCMS, so feel free to smack me upside the head if I'm missing something obvious.

We have an ElasticSearch provider that I'd like to use instead of Craft's default search.

The file at /app/etc/config/common.php appears to be a dependency injection system that should make replacing core components relatively easy, and
the class defined in /app/services/SearchService.php looks simple enough to replace with a custom solution.

Unfortunately I'm having trouble finding documentation around replacing core components, and I'm not having much luck finding any way to override the common config file from outside the core application.

It might be that I'm going about this the wrong way, and I'm totally open to suggestions. Either way, thanks in advance!

Currently not possible, but I really like the idea of a plugin being able to swap out what craft()->search points to, whether it's ElasticSearch, Lucene, etc.

I'll add it to our internal list, but you might want to submit a public feature request for this as well.


How to assign entries to static positions such as footer? The footer of my site has some links that can be considered "static" in the sense that they always should point to a specific entry. One for "acknowledgements", one for "cookie info" and one for "more contact info".

What is the recommended way to assign entries to these three "roles"? I need it to work in a multi-site envionment.

This sounds like a perfect use case for an Entries field in a Global.

I'd create a field called "Footer Links". At the bottom of the field settings page, expand the Advanced area and enable Manage relations on a per-site basis. This will allow you to have different links for each of your sites, if you wish.


ID of matrix printed instead of value I have strange issue and cannot find out the solution for that.
I have this field (matrix with some text values): https://imgur.com/a/KaFXubJ

Also I have this entry: https://imgur.com/a/cPMrGul

And this is how it rendered (it shows not value of fields but id of matrix block table): https://imgur.com/a/SR3HgQZ

Here is how it looks like in template: https://pastebin.com/viVbPLqj

I've tried multiple combinations but nothing was solution. Also other fields are works well (fields which not related to "companyInformation" matrix).

So what may I do wrong?

Technically the data you're seeking are under the first matrix block (not the first data of your .companyName - which is not valid)

{% set relatedCaseStudy = reviewFeatured.relatedCaseStudy.first %}
{% set firstCompany = relatedCaseStudy.companyInformation.first %}
{{ firstCompany.companyName }}

Note: If you plan to have only one company, think about a SuperTable field in 'static' mode (only one occurence).


Entries from previous year 2016 not displaying Ok, so this is pretty bizarre... Entries from 2016 are NOT displaying when searched for in the admin panel. Whether we search by the year, title, or part of the title, until they're edited (using the id to access them).

I see entries from 2015 and 2017 but only a few from 2016 which, as I said, are the ones we managed to edit.

This happens in the list of entries as well as on fields that link to them and we've got LOTS of entries...

UPDATE - Check this out:

Articles listed from December 2016:
https://www.dropbox.com/s/o0rmkiazm436etb/Screenshot%202017-10-22%2009.16.07.png
Searching for name of article:
https://www.dropbox.com/s/ydwilwz6pye1jb4/Screenshot%202017-10-22%2009.16.44.png
Searching for year 2016, bottom of results, all 2015 and 2017:
https://www.dropbox.com/s/w7imwnnfyrnjjri/Screenshot%202017-10-22%2009.17.15.png
If i access the article highlighted on screenshot 1, via URL:
https://www.dropbox.com/s/opdv12hpyz993z4/Screenshot%202017-10-22%2009.20.50.png

The articles are there, they're accessible from the user end, but for some reason they won't show up on the Admin side. Bizarre...

Sounds like your search indexes are corrupted. I’d try to run the “Rebuild Search Indexes” tool in CP > Settings.


Craft Commerce: fixed product variants/multiplier We have a client that is selling products with fixed rate variants. In other words so that the base cost is the only price defined whilst others are based on a globally defined multiplier, eg. 1.5x or 3x the base/defined price.

Is there a way (either baked in or via plugin) to have extra variants created or available based on a pre-defined criteria/multiplier? If necessary happy for this to be just in the add to cart/checkout process rather than explicitly defined in the product details/record.

Looking through docs only way could see something like this being possible would be via a plugin automatically adding/updating variants on a product creation/save eg the EVENT_BEFORE_SAVE_ELEMENT event.

I'm not sure if the base cost is global across all products, or varies between products - but either way you could use an Adjuster module or plugin to modify the price of line items in the cart.

That way you don't need to worry about creating any variants in the backend at all, and can store the price multipliers in Global fields if you want to.

To my knowledge there aren't any plugins that do this, but don't be put off my the thought of creating a plugin/module, I'm not much of a developer but have managed it myself : )

This proof-of-concept Adjuster gist should set you in the right direction, and here's another one for good measure.


disable guest accounts for commerce Is there a method to remove the ability for commerce to allow guest accounts? I want to allow only registered, logged-in users to be able to place orders.

I don't actually think Commerce has an option to disable guest checkout, no.

But Craft itself makes this, in effect, quite easy.  (In fact, Commerce's whole concept of customers is largely separate from the Craft concept of users.  A customer may be a user, and vice versa, of course, but they are really two separate things.)

In any case, you can hide all checkout access and pages behind {% requireLogin %} tags so those parts of your front end are simply then not reachable by customers who are not logged in users.

https://docs.craftcms.com/v3/dev/tags/requirelogin.html


Seomatic - show only global site title Right now my homepage title looks like:

Home page - SiteName

But i want it to look like this:

SiteName

How do i do this?

Did you remove the standard title tag placed in the _layout.html file by craft?

This line is probably breaking your SEO title: <title>{% if title is defined %}{{ title }} - {% endif %}{{ siteName }}</title> This is found inside the <head> tags

If not you should navigate to SEO > Site Meta and take a look in the settings there. The only problem then is that you could only disable the site name being placed not the title. But I guess its the line of code you still have in your _layout


How can i check an entry author's user group? I'm trying to check if a user is part of a user group but not having any success!
I tried this:

{% if entry.author.groups == 'authors' %}

But even though the user is definitely in a user group with that handle, the output inside that if statement doesn't show up.

I also tried this:

{% if entry.author.admin != 1 %}

That DID work, but unfortunately i don't just want to check if the user is not an admin, i want to specifically check their user group.

As Fabio pointed out, i'd managed to miss the isInGroup method. Slightly embarrassing!

So for anyone else looking to do what i asked, i changed my code to the following:

{% if entry.author.isInGroup('authors') %}

and it works perfectly now.


How to add/link an entry to an object using PHP? I'm building a plugin to add users to the system with set properties (like company) and permissions. The user form works with an "Entries" field and works with connected source section entries and works fine. Now when I receive the objects in my SiteAdministrator_UserService i'm trying to link the passed in companyId to the custom Entries field. Like this:

$lNewUser = new UserModel();
$lNewUser->status = UserStatus::Pending;
$lNewUser->firstName = $aUser->firstname;
$lNewUser->username = $aUser->username;
$lNewUser->lastName = $aUser->lastname;
$lNewUser->email = $aUser->emailaddress;

$lCompany = craft()->entries->getEntryById($aUser->companyId);
$lNewUser->getContent()->setAttributes(array(
        'companiesDropdown' => $lCompany,
    ));

return craft()->users->saveUser($lNewUser);

$lCompany holds the entry of the company, that works fine. Now how do I link the $lCompany to the first entry in the custom Entries (companiesDropdown handle) field?

Just to clarify. All the above has nothing to do with an actual dropdown field.
Thanks in advance

Ah got it :

$lNewUser->getContent()->setAttributes(array(
    'companiesDropdown' => array($aUser->companyId),
));


Progressive jpg image transforms? I want to use progressive jpg files and want to know if craft image transforms save jpg images as progressive, or can they be made to?

You can achieve progressive JPGs if your server has Imagick installed, but it doesn't look like the image processing library that Craft is using has added support for it, yet.


Self-hosting requirements/scaling Is there any reason the mySQL, CraftCMS, and assets/images/content can't all live on the same server, assuming the server is appropriately sized and backed up?

Are there any sizing/scaling guidelines?

No reason at all, that should work perfectly fine.

In fact, at least 90% of my projects keep files, database, and assets all on the same server. For the remaining 10%, I'm usually only moving the assets to Amazon S3. Everything else continues to live on the same server.


Editing a custom user field onBeforeSave When a user saves a front-end form, and has a custom field with a set value, I want to send an email - and set another field on the users profile to indicate a mail has been sent, so that if the form is saved again, another email will not be sent.

To do this I have a small plugin:

public function init() {
    craft()->on('users.onSaveUser', function(Event $event) {
        $user = $event->params['user'];
        $consentGiven = craft()->request->getPost('fields.consentGiven', 'no');
        $notificationAlreadySent = $user->notificationAlreadySent;

        if($consentGiven == 'yes' and $notificationAlreadySent != '1') {
            ... SEND EMAIL CODE ...

            // now set the notificationAlreadySent to '1' so we dont get in this conditional next time
                $userModel = new UserModel();

                // why we need to manually read these to write the same values I don't know
                $userModel->id        = $user->id;
                $userModel->username  = $user->username;
                $userModel->firstName = $user->firstName;
                $userModel->lastName  = $user->lastName;
                $userModel->email     = $user->email;

                // update the one field we actually wanted to update in the first place
                $userModel->getContent()->setAttributes(array(
                    'notificationAlreadySent' => '1'
                ));

                // Actually save it
                craft()->users->saveUser($userModel);
        }
    }
});

Problem: This ends up in a loop because it's watching the onSaveUser event, and inside that event it's calling saveUser. I figure I actually need the onBeforeSaveUser event, and I need to tweak the value of that field there so that it'll "just work" once it gets to the saveUser action.

That being the case I've tried this instead...

public function init() {
    craft()->on('users.onBeforeSaveUser', function(Event $event) {
        $user = $event->params['user'];
        $consentGiven = craft()->request->getPost('fields.consentGiven', 'no');
        $notificationAlreadySent = $user->notificationAlreadySent;

        if($consentGiven == 'yes' and $notificationAlreadySent != '1') {
            ... SEND EMAIL CODE ...

            // now set the notificationAlreadySent to '1' so we dont get in this conditional next time
                $user->fields['notificationAlreadySent'] = '1';
        }
    }
});

New problem: The syntax $user->fields['notificationAlreadySent'] = '1'; doesn't appear to be correct, and I can not work out how to reference that property...

Solution:

Instead of:

$user->fields['notificationAlreadySent'] = '1';

Use

$user->getContent()->setAttributes(array(
    'notificationAlreadySent' => 1
));

Of note: I find this sort of thing extremely hard to research. I know what I want to do (edit the value of a field in an event via the onBefore listener) but documentation on how to do that seems non-existent. I keep finding this sort of problem with developing Craft plugins - that unless you know the internals, you're really hard pressed to even articulate what you're wanting to search for in order to find a solution.


Has someone figured out Craft 3 content migrations? One of the big features for craft 3 is content migrations. Migrating fields and sections between environments (like deploying code to test or production).
I'm just having a hard time figuring out what options there are. I did find some simple examples, but they are a little limited...

https://craftcms.com/news/craft-3-content-migrations
https://docs.craftcms.com/v3/content-migrations.html

Since there is a separate documentation page which seems incomplete i created an issue. If anyone has some additional info i would like to make a pull-request to complete the docs.

This is a plugin I'm working on to do exactly what you are after.

https://m.youtube.com/watch?v=n6ko2PKUqAo&feature=youtu.be

The syntax to figure out how to create sections, elements etc is determined by reading through the craft service and model classes.


Why is the cpresources folder so big? I'm just wondering why don't you guys compile all the cpresources into 1 .js and 1 .css file?

Right now this folder is gigantic :D
cfr: https://i.imgur.com/Oksr5Kn.png

Craft CMS 3 uses Yii2 Asset Bundles for AdminCP resources. This lets it handle dependencies such as certain scripts not loading before jQuery, for example.

Remember that many Craft CMS 3 components need to publish JS/CSS resources to work, as do third party plugins. Some system needs to manage these things, and their dependencies.

Combining it all into one isn’t practical, since different pages require different resources, and plugins may add resources in arbitrarily. If you really did combine everything needed for the AdminCP backend, it’d be slow to build (and that build would have to be done dynamically as other components add/remove resources), and not very useful, especially with http/2 and multiple streams.

Note that the way it works now is a vast improvement over Craft 2.x, where every AdminCP static resource request went through the index.php, and this was slow to load, and could not be cached.

Just ignore the cpresources/ directory; consider it a cache that you don't need to worry about.


How to link to previous/next entries in a section? What would be the equivalent in Craft of ExpressionEngine's Next/Previous entry linking? I was looking at getNext() and getPrev() (and their aliases next and prev) (via the EntryModel docs), but when I try the obvious:

Previously: {{ entry.prev.title }}

I just get the current entry's data.

What piece am I missing here?

You are probably not using this within a craft.entries loop. Position it inside a loop or set custom parameters for your prev and next elements:

{# Set parameters for prev/next elements list #}
{% set params = craft.entries.section('blog').order('title asc') %}

{# Get the prev/next elements #}
{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}

{# And make sure to only output the links if the element exists #}
{% if prevEntry %}Previous{% endif %}
{% if nextEntry %}Next{% endif %}


Live Preview not working Live Preview isn't working for any kind of entry. Dev or production. I get the following error on chrome's console.

jquery-2.1.1.min.js?d=1409764106:4
POST http://undiario.dev/ 500 (Internal Server Error)

jquery-2.1.1.min.js?d=1409764106:4
k.cors.a.crossDomain.send

jquery-2.1.1.min.js?d=1409764106:4
n.extend.ajax

jquery-2.1.1.min.js?d=1409764106:4
n.(anonymous function)

craft.js:10520
Craft.LivePreview.Garnish.Base.extend.updateIframe

jquery-2.1.1.min.js?d=1409764106:2
n.isFunction.f

Anybody knows why this is happening?

Just want to mention for anyone running across this thread that if you're having a problem with live preview and seeing dev tools errors of the nature of cors or crossdomain then the first thing you might want to check is that if the domain you're serving the site (the control panel, specifically), is the same as what you have set in "Settings | General Settings" (or in Craft 3, "Settings | Sites")

For example, if you serving the site from a example.com (root domain), and you have www.example.com in the settings, your live preview will bonk because it's a different domain and the live preview is being served via ajax.


How to access a digital products information on the products page in Craft Commerce? I have created a digital product type and a digital product but strangely on the digital products template I can't access any information regarding the product like for example, entry.title. I'm getting a Variable "entry" does not exist. error. Any Ideas?

Instead of entry use product variable. For example, {{product.title}}.


ElementAPI -> Find entry template name I'm using many "entry type" templates as described here: http://buildwithcraft.com/help/entry-type-templates. I'm using ElementAPI to render full entries as HTML embedded into JSON. I'm using this transformer method:

craft()->templates->render('path/to/template/template-name', [
    'entry' => $template
])`

This works fine. But I need to assign the corresponding template to each entry-type. I have not found a solution. I can't seem to access the name or path of the assigned template. I don't really need the path, but need the name. The following seems right, but doesn't work:

'path/to/template/' . $template->getTemplateName()

Any ideas??

Thanks!

Perhaps instead of trying to get a template name, use the entry type as the template name, similar to the method that you linked to. In the link, it doesn't check which template is assigned to an entry, but instead, uses the entry type to load a template with the same name. In your example that might look like this:

craft()->templates->render('path/to/template/' . $entry.type, [
  'entry' => $entry
])

Where your template would be named the same as the handle for your entry type. Does that make sense?


How do I set my siteURL instead of having http://localhost:8888/? I downloaded and installed Craft Personal on my computer and choose /websitetest/ as my website name. I used MAMP and phpMyAdmin to create a database.

Still to access my website the url is http://localhost:8888/ and when I try to access http://localhost/websitetest/ I get the following error message: Forbidden
You don't have permission to access /websitetest/ on this server.

Moreover in my index.html file, when I call for an URL entry:

href="{{ entry.url }}"

by default it redirects towards /websitetest/_entry , which displays me the same error message, while localhost:8888/_entry works when I test it manually!

Some ideas where can this come from?

Thanks!

Unless instructed otherwise, MAMP uses port 8888. You can tell it to use the "default" ports, which will mean the site gets served over port 80, and your URLs no longer contain :8888.

As for the other issue, it sounds like you haven't set up your site's document root correctly. Either way, it's a MAMP configuration issue, not a Craft issue.


Filter channel entries by slug Is there any way to output the content of a channel entry by their slug?

For example, say I have an asset field called "image" in each channel entry, I want to output the content of that field only for the channel entry filtered by the slug "home", I've tried both:

{% for item in craft.entries.section('images').slug('home') %}
    {{ item.image.first() }}
{% endfor %}

and

{% for item in craft.entries.section('images').find().slug('home') %}
    {{ item.image.first() }}
{% endfor %}

but neither work...

The second example won't work since .find() should be at the end of the ElementCriteriaModel. But since you treat the CriteriaModel like an array, you don't need to add it at all.

Your first code looks correct, but you should check if the loop found an entry:

{% for item in craft.entries.section('images').slug('home') %}
    ....
{% else %}
    No entry found
{% endfor %}

Also your current code is only outputting the title of the AssetFileModel:

  Outputting an AssetFileModel object without attaching a property or
  method will return the asset’s Title

That's why you should add the "url" property, and also check whether the field contains an asset:

{% for item in craft.entries.section('images').slug('home') %}
    {% set asset = item.image.first() %}

    {% if asset %}
       {{ asset.url }}
    {% else %}
        No asset added to the field
    {% endif %}
{% else %}
    No entry found
{% endfor %}


How would I pass and entry's field value to an include? I have this:

{% include "partials/includes/page-header" with { 'title' : '{{ entry.heading }}' } %}

But it seems that nothing I do will actually pass {{ entry.heading }} as 'title' in the include.

You'll never need to put Twig tags within other Twig tags... Try it like this:

{% include "partials/includes/page-header" with { 'title' : entry.heading } %}


Template cache table growing very big, best way to keep it in line? So we have built a rather large site for a client, which has multiple regions, locales, user privileges, etc.
Some time ago the default cache of Craft couldn't cope anymore with keeping track. The cache clearing tasks always stalled so cache wouldn't be deleted anymore.

This triggered us to change the way we cache our pages. Unfortunately, the template cache table in the database is getting to its limits as we haven't found a good way to clear the old caches.

How it works:

We set 'cacheElementQueries' => false,

Every page gets its own cache (unique cachekey) which consists of:

Is the user logged in yes or no?
Which region is the user in? (one of 3 possibilities)
Which user type does the user have? (any combination of 3 types possible)
The page url
The last updated date of the entry (not always used)

We cache everything globally and cache some parts of pages separately, for example: the sidebar of a product page remains the same but the content changes.

We use a combination of coldcache and cacheflag plugins.

Issue:

As we create a lot of caches and a lot of them with a certain date in the key, the database table gets cluttered and grows to big in size (max limit for our DB is 1GB and the cache table is reaching 500MB).

The question

How can we delete old caches from the DB table?

The only two options I can think of now are:

Set cache duration to a certain time interval (but than all caches are deleted which will make the site slow every interval).
Create a plugin that runs every month with a CRON job and checks all of the cache keys and deletes everyone but the latest.

Any other ideas out there?

In addition to what Brad suggested, I'd also do some auditing to see what kind of benefit you're getting out of your caches. You could, for instance, use the for parameter to cache only for 24 hours or such. No reason to keep a stale cache around that isn't getting hit -> https://docs.craftcms.com/v3/dev/tags/cache.html#for

e.g.:

   {% cache using key cacheKey for 1 day %}

Let unused caches naturally expire after a reasonable period of time.

If you do it this way, all caches will not expire at the same time. In an ideal world, Craft's {% cache %} tag would allow for incrementing the cache duration based on hits, so things that are getting lots of hits would say in the cache (until otherwise busted), and unused cache entries would expire.

I don't think there is any way to do that currently, tho. So at least using for, it isn't an all or nothing proposition, and caches will expire individually, 24 hours after they are created.

I will also say that you may consider using another method of caching, such as FastCGI Cache or Varnish


Getting image url error code: Impossible to access an attribute ("url") on a null variable My site just suddenly broke down on a certain page with the following error code, (see screenshot).

It is occuring for every image on this page and really confusing me.

Any quick suggestions?

For whatever reason, your site isn't able to find the image. And since your Twig code isn't being defensive, it's failing ungracefully.

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

This first part is fine... I'm assuming that media is an Assets relationship field. You're attempting to fetch the first asset, and set that to image. Here's the kicker... when no assets are found, image will be set to NULL.

This next part is where your problem is...

{{ image.url }}

That'll work great assuming an asset was found. But when no assets were found, this will trigger an error. Because image would be set to NULL, and NULL doesn't have an attribute of url. (This is exactly what the error message is telling you.)

Instead, you should write that line more defensively...

{{ image ? image.url }}

This technique uses the ternary operator to first check "if image is truthy" before attempting to output image.url. In other words, if image contains a valid asset, output the image URL.

That way, if no asset is found, you won't get a big nasty error message.

On a separate note... You seem to be expressing some urgency that your site has gone down. But the screenshot you showed is clearly a byproduct of being in devMode. For the record, you never want to have devMode enabled in a live production environment.


Recommended CPU/RAM VPS settings to query 50,000 entries I'm running a very simple query on a text field...

{% set query = craft.request.getQuery('email') %}

Locally, with one entry on my machine, I'm getting a response time of 332ms. We were assuming around 3,000 total entries, but 3 days in, I'm at 15,000 and climbing by hundreds per hour.

What would be a good starting point for CPU/RAM on a VPS if I assume that we could hit 50,000?

The CPU won't be the issue more the RAM if you expect to pull in all those results. But it's not much anyways.... A 1 CPU/1GB RAM on Digitalocean will be enough.


Plugin FieldType giving error on live server - fine locally I have a plugin with a FieldType - I used the CocktailRecipes plugin as a template.

It extends BaseFieldType; it has 3 methods (getName, defineContentAttribute [AttributeType::Mixed] and getInputHtml)

It it working fine on a local PHP install.

However, on the server, when I create a new field, the plugin's custom field type isn't listed in the drop-down; this works fine on my local PHP install.

If I use my local install connected to the server's database, I can add the field type - but if I look at the field list in the admin back on the server, the field Type isn't the string returned but the getName function in the FieldType model (as it usually is) - it's the full class name, highlighted in red (it has a wrapping element with a class of "error").

I can't see anything in the log files about why - even in dev mode.

The only differences I can think of between my local and the server setups is that the PHP version is higher on the server - and the server OS is case-sensitive for file names.

I've checked the casing used, and it looks correct based on the CocktailRecipes plugin example.

It feels like the issue is that the class can't be found on the server, despite it being there; and perhaps a casing issue, which is being masked on my local machine, is the reason the issue isn't occurring locally.

Has anyone encountered this issue before? With no error messages being logged, I haven't had much luck digging out the issue.

What I'm basing it on:

<?php

namespace Craft;

/**
 * Ingredients Fieldtype
 *
 * Allows entries to select associated ingredients
 */
class CocktailRecipes_IngredientsFieldType extends BaseFieldType
{
    /**
     * Get the name of this fieldtype
     */
    public function getName()
    {
        return Craft::t('Cocktail Ingredients');
    }

    /**
     * Get this fieldtype's column type.
     *
     * @return mixed
     */
    public function defineContentAttribute()
    {
        // "Mixed" represents a "text" column type, which can be used to store arrays etc.
        return AttributeType::Mixed;
    }

    /**
     * Get this fieldtype's form HTML
     *
     * @param  string $name
     * @param  mixed  $value
     * @return string
     */
    public function getInputHtml($name, $value)
    {
        // call our service layer to get a current list of ingredients
        $ingredients = craft()->cocktailRecipes->getAllIngredients();

        return craft()->templates->render('cocktailrecipes/_fieldtypes/ingredients', array(
            'name'      => $name,
            'options'   => $ingredients,
            'values'    => $value,
        ));
    }
}

What works fine locally:

<?php
namespace Craft;

class ECOffers_OfferPeriodFieldType extends BaseFieldType {

    public function getName() {
        return Craft::t('Offer period');
    }

    public function defineContentAttribute(){
        return AttributeType::Mixed;
    }

    public function getInputHtml($name, $value) {
        $offer_periods = craft()->eCOffers_offerPeriods->getOfferPeriodsForLocale($this->element->getContent()->getAttributes()['locale']);
        $options = array();
        if ($offer_periods) {
            foreach ($offer_periods as $offer_period) {
                $options[] = array(
                    'label' => $offer_period->name.': '.$offer_period->fromDate->format('H:i D jS M Y').' - '.$offer_period->toDate->format('H:i D jS M Y'),
                    'value' => $offer_period->id
                );
            }
        }
        return craft()->templates->render('ecoffers/_fieldtypes/offerperiods', array(
            'options' => $options,
            'value' => ((!is_null($value)) ? $value:craft()->eCOffers_offerPeriods->getCurrentOfferPeriod($this->element->getContent()->getAttributes()['locale'])->id)
        ));
    }
}

I think you're on the right track with the case-sensitivity check.

Make sure that not only the class names match up case-wise, but the file names on the file system match case-wise as well.


Filter entries in CP by Author How can you filter entries in the CP by Author? I assumed entering something like author:tdavis (where tdavis is my username) would do it, but no results returned. I also tried substituting id for username.

For Craft 3, at least for now.

1) Make a custom plugin
2) Add event to modify the query in control panel

// Register element query prepare event
Event::on(ElementQuery::class, ElementQuery::EVENT_BEFORE_PREPARE,
    function(Event $event)  {
        if (Craft::$app->getRequest()->getIsCpRequest()) {
            if ($event->sender->elementType === 'craft\elements\Entry') {

                if(isset($_POST['criteria']['search'])&&strpos($_POST['criteria']['search'],'author')!==false)
                {
                    $email = explode(':',$_POST['criteria']['search']);
                    if(isset($email[1]))
                    {
                        $user = User::find()->email($email[1])->one();

                        if($user)
                        {

                            $event->sender->query->andWhere(['authorId'=>$user->id]);
                            $event->sender->subQuery->andWhere(['authorId'=>$user->id]);
                            $event->sender->search = null;
                        }
                    }

                }
            }
        }
    }
);

So when you type author:[Email] it can fetch in the CMS.


How to add multiple performers to event schema with seomatic I am adding event schema to an entry page. I have offer and date properties working well based on https://nystudio107.com/blog/tips-for-using-seomatic-effectively

This is working for offers

{% if entry.soldOut == '1' %}
  {% set availability = 'http://schema.org/SoldOut' %}
{% else %}
  {% set availability = 'http://schema.org/InStock' %}
{% endif %}
{% set offersJsonLd = seomatic.jsonLd.create({
    'type': 'Offer',
    'price': entry.eventPrice,
    'priceCurrency': 'GBP',
    'validFrom': entry.postDate|date("Y-m-d"),
    'url': entry.url,
    'availability': availability,
}, false) %}
{% do mainEntity.offers(offersJsonLd) %}

I can't work out the correct approach for performers though. I have a Matrix field for performers with two fields performerType and performerName

I have tried this

{% set performerJsonLd = seomatic.jsonLd.create(
  {% for block in entry.performers .all() %}
    {
    'type': block.performerType,
    'name': block.performerName,
    },
  {% endfor %}
  false) %}
{% do mainEntity.performer(performerJsonLd) %}

and

{% set performersAndTypes %}
  {% for block in entry.performers .all() %}
    {
      '@type': '{{ block.performerType }}',
      'name': '{{ block.performerName }}',
    }{% if not loop.last %},{% endif %}
  {% endfor %}
{% endset %}
{% set performerJsonLd = seomatic.jsonLd.create(
  performersAndTypes,
  false) %}
{% do mainEntity.performer(performerJsonLd) %}

but get errors for both.

What would the correct approach be to get this working?

I hadn't seen those examples but it is bookmarked now.

I've adapted your example as below and it's all working. Thanks @andrew.welch

{% set performersArray = [] %}
{% for block in entry.performers .all() %}
  {% set performersArray = performersArray | merge([seomatic.jsonLd.create({
      'type': block.performerType,
      'name': block.performerName,
  }, false)]) %}
{% endfor %}
{% do mainEntity.performer(performersArray) %}


Is it possible to display another column in Entries type field? I would love to be able to show another column inside Entries type field. Specifically, Image field. Basically,the same functionality as on the Entries list. Is there a plugin or another way of implementing this.

Nope, not out of the box – but being able to display fields in addition to the entry title for selected entries being displayed in an Entries field, in an easy-to-use interface like the Customizable Element Index, sounds like a killer feature request.

For now, your best (albeit not super easy, I suspect) bet would be to create a custom plugin that adds a custom FieldType extending the EntriesFieldType class.

By overriding the BaseElementFieldType's $inputTemplate property (i.e. by adding an $inputTemplate property to your custom FieldType's class, pointing to a different template) you might be able to display entries in a different manner compared to the vanilla Entries field.


Group entries by category than by month based on Date/Time field I would like group entries first by what category they are in, than group by month based on a Date/Time field like this for example:

Category 1

February 2017

Event 1

March 2017

Event 4 (in all categories)

Category 2

February 2017

Event 2
Event 5

March 2017

Event 4 (in all categories)

Category 3

March 2017

Event 4 (in all categories)

Here is what I'm currently using:

{% set eventCategories = craft.categories.group('events').find() %}
{% set eventEntries = craft.entries.section('event').order('dayStart asc').limit(null) %}
{% for category in eventCategories %}

{{ category.title }}

        {% for eventDate, entries in eventEntries | group("dayStart|date('F Y')") %}

{{ eventDate }}

                {% for entry in eventEntries.relatedTo(category).find() %}

{{ entry.title }}

                {% endfor %}

        {% endfor %}
{% endfor %}

Instead the output I'm getting is this:

Category 1

February 2017

Event 1
Event 4 (in all categories)

March 2017

Event 1
Event 4 (in all categories)

Category 2

February 2017

Event 2
Event 5
Event 4 (in all categories)

March 2017

Event 2
Event 5
Event 4 (in all categories)

Category 3

February 2017

Event 4 (in all categories)

March 2017

Event 4 (in all categories)

Is there a way to stop the duplicates?

Thanks in advance.

In your code, within the {% for eventDate, entries in eventEntries | group("dayStart|date('F Y')") %} loop, in the sub-loop, you are looping over eventEntries.relatedTo(category).find() rather than restricting the entries in that loop to the ones you have already grouped to the date, i.e. in the entries array. That is why you are getting all the entries related to the category under each date heading, instead of just the ones falling under that date.

This should work:

{% set eventCategories = craft.categories.group('events').find() %}
{% set eventEntries = craft.entries.section('event').order('dayStart asc').limit(null) %}
{% for category in eventCategories %}

{{ category.title }}

        {% for eventDate, entries in eventEntries | group("dayStart|date('F Y')") %}

{{ eventDate }}

                {% for entry in entries if (category.id in entry.categoriesField.ids()) %}

{{ entry.title }}

                {% endfor %}

        {% endfor %}
{% endfor %}


Filter assets by a single category? Is there a way in Craft to filter assets by an associated category?

In asset settings, one of our asset sources has been given a category field, and those assets have been given a category.

ie; asset source "documentLibrary" has category field "documentType"
and asset "documentOne" has documentType "sitePlan".

I have tried the following variations below:

craft.assets({documentType: "sitePlan"})
craft.assets({documentType: "contains, sitePlan"})
craft.assets({documentType: "LIKE '%sitePlan%'"})
craft.assets({documentType: array('sitePlan')})
craft.assets({count(documentType): '> 0'})
craft.assets({relatesTo: "sitePlan"})

You first have to get the CategoryModel of that category you want to filter by. Use slug as a parameter and the first() method to get the first and only category matching that criteria.

This CategoryModel is the target element of your relation. Set your craft.assets ElementCriteriaModel using the relatedTo parameter to filter by your category and also set the relation's field name here (not necessary if you don't have other relations set on your assets).

If you really have the need to further filter by an asset source (don't get the assets which match the other criteria but are in a different source folder), you (currently) can only do this by looking up that asset source's ID in the database and filter by that sourceId. Set all other parameters to your needs.

{% set categorySlug = 'sitePlan' %}

{# Get the CategoryModel #}
{% set category = craft.categories.slug(categorySlug).first() %}

{# Get the assets related to this CategoryModel #}
{% set assets = craft.assets({
    relatedTo: {
        targetElement: category,
        field: 'documentType',
    },
    sourceId: '1',
    limit: null,
    order: 'dateUpdated desc',
}) %}


Which is best practice, SET or FOR? On my home page template I include a couple of extracts from single entries and I'm not sure which is the best/most efficient way to call them.

{% for entry in craft.entries.section('information').slug('about') %}

{{ entry.title }}

    {{ entry.summary }}
{% endfor %}

or

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

{{ entry.title }}

{{ entry.summary }}

They both generate the same amount of queries in the Chrome dev tools profile summary report, but I don't understand why, as the second looks like it's more specific and not a loop.

Regardless of the number of elements involved, Craft will return an iterable ElementCriteriaModel whenever you query for content (e.g. via craft.entries, or using relational FieldTypes like Assets, Entries or Categories).

This means that even if you know that there'll only be a single element returned (e.g. when you query for a Single section entry, or have a relational field restricted to a single element) using a for loop to actually access that element is totally viable and whether to actually use a loop or not in such cases, is mostly a matter of personal preference.

Looping on single-element query results may seem counter-intuitive, although you're not actually looping on a single element, but the ElementCriteriaModel (which just happens to "contain" a single element and not several). Personally I tend to only use loops when I actually need loops (i.e. there is or could be more than one element returned), but its up to you.

In any case, beyond personal preference there are a few minor differences to each approach.

Using a {% for %} loop, it's easy to render alternative content if the query doesn't return anything, by adding an {% else %} statement:

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

{{ entry.title }}

{% else %}

Sorry, the entry wasn't found!

{% endfor %}

Using .first() and {% set %}, you should – in most cases – add an {% if %} statement testing the value returned, to avoid template errors if the query doesn't return a valid element:

{% set entry = craft.entries.section('mySingleSection').first() %}
{% if entry %}

{{ entry.title }}

{% endif %}

Also using .first() and {% set %}, it's easy to declare fallback data if the query doesn't return anything, using the |default filter – this may negate the need for an {% if %} statement:

{% set imageUrl = entry.assetsField.first().url|default('/assets/fallback.jpg') %}

Performance-wise, I doubt there'll be any real-world difference between the two methods, with only a single element involved.

As for the query part of your question; even if you're using a for loop, Craft won't run the craft.entries query in your example more than once – which is why you're seeing the same amount of queries in your profiling report. When talking about queries and performance, it's however worth noting that both the amount of queries and the efficiency of those queries are relevant. In your example, the first query will probably be a tiny, tiny bit faster than the second (Gustavs' answer explains why).


'Variable "assetSourceOptions" does not exist' after updating to Craft 2.6 When I try to add another field, suddenly I get this error:
"Variable "assetSourceOptions" does not exist"

This started after I updated to Craft 2.6

It looks like the Redactor I plugin was incompatible with Craft 2.6... Fortunately, Brandon fixed this last night!

Update your version of Redactor I, and the problem should be fixed.


Get next entry based on entry type As an extension of this question
How to link to previous/next entries in a section?

If my page is set to automatically provide a entry var in my template.
And I can simply access a field like this

entry.title

Which means I don't need to do something like this

{% set entry = craft.entries.section('blog').first() %}

If I want to get the next entry and previous entry based on this entry's entry type. Is it possible?

No, you still have to set the parameters by your own:

{# Get this entry's entry type #}
{% set type = entry.getType() %}

{# Set parameters for prev/next elements list #}
{% set params = craft.entries.section('blog').type(type) %}

{# Get the prev/next elements #}
{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}

{# And make sure to only output the links if the element exists #}
{% if prevEntry %}Previous{% endif %}
{% if nextEntry %}Next{% endif %}


Find entries related to user and display field name If I’m finding all the entries that are related to a user, how could I get the field handle that the found user is referenced from?

{% set events = craft.entries.section('events').relatedTo(user) %}
{% for event in events %}

  {# What goes here? Hypothetical code based on non-existent method would be: #}

  {% set field = craft.fields.relatedTo(user) %}
  {{ field.title }}

{# Obviously this isn't possible. Any way to accomplish something like this? #}

{% endfor %}

There are multiple users fields in the found entries, and there will be different logic depending on which field the user is found.

What could work for you is to get the events for each field separatly:

{% set firstEvents = craft.entries.section('events').relatedTo({
    element: user,
    field: 'firstEntriesField'
}) %}

{% set secondEvents = craft.entries.section('events').relatedTo({
    element: user,
    field: 'secondEntriesField'
}) %}

If you need them combined in one loop, I can't think of another way other than to query x + 1 times:

{% set allEvents = craft.entries.section('events').relatedTo({
    element: user,
}) %}

{% set firstEventsIds = craft.entries.section('events').relatedTo({
    element: user,
    field: 'firstEntriesField'
}).ids() %}

{% set secondEventsIds = craft.entries.section('events').relatedTo({
    element: user,
    field: 'secondEntriesField'
}).ids() %}

{% for event in allEvents %}
    {% if event.id in firstEventsIds %}
        {# Event related through firstEntriesField #}
    {% elseif event.id in secondEventsIds %}
        {# Event related through secondEntriesField #}
    {% endif %}
{% endfor %}


Keep translation files in sync? I've set up multiple translation files (de.php, fr.php, es.php etc.) in craft/translations/ to translate static text.

While my site is in development, I am trying to keep these lang.php files in sync, so that they all contain at least the strings of the primary locale as array keys.

But the more strings are added or changed, the more annoying this undertaking gets. Any idea on how I could make this more simple and efficient?

You could manage all your translations in one csv file. There's another Q/A about translation files, where @Bill Criswell explains how you can use csv files for translations. I added some variables to his script to make it well adaptable to multiple locales.

Set up your new csv file with a column for each locale. Then add the script to each of your lang.php files and configure $this_locale_column according to the file's locale.

<?php

$path = $_SERVER['DOCUMENT_ROOT'].'/../craft/translations/translations.csv';
$delimiter = ';';
$skip_rows = 1; //skip header rows
$primary_locale_column = 0; //set primary locale column
$this_locale_column = 1; //set secondary locale column for this `lang.php` file

$translations = array();
$translations_file = fopen($path, 'r');

if ($translations_file) {
    while(($translation = fgetcsv($translations_file, 1024, $delimiter)) !== FALSE) {
        if($skip_rows != 0) { $skip_rows--; continue; }
        $translations[$translation[$primary_locale_column]] = $translation[$this_locale_column];
    }
}

return $translations;


Can a Table Column be Rich Text / WYSIWYG? The only types in the list are Single-line text, Multi-line text, Number or Checkbox.

I think that's actually a table field type you are referring to, not a Matrix Field Type.

Matrix field types can indeed have Rich Text. There are a lot of instances where a Matrix field can be used in place of a table field.


Fields (Matrix) side by side? In ExpressionEngine it was possible to have fields side by side.

So when creating a entry you had all options (for example for an image) in one row.

I can't figure out how to do that in Craft

I think the easiest way to replicate this behaviour, is to use the Super Table plugin. It lets you create all of Craft's fields within table rows.