FreeForm and HubSpot - Current Page We are looking to place a contact form across all pages and want to integrate HubSpot. I noticed that there was the ability to match up the fields with HubSpot - which is great - my question is how do we pass through the current page's Title and URL the form is shown on?

Is there a way of matching the field that or is it done a different way?.

Thanks in advance.

It would be fairly easy to create a hidden field and read the page URL into it.
As for the title, is your form an embed inside the channel entries call? Then it's pretty easy to get the title as well. If not you may have to be a bit creative.

Check the hidden field config, it even tells you how to pull in the current url.


Force redirect from HTTP to HTTPS via htaccess with multisite installation I'm using Craft CMS 3 multisite installation with more than 20 website based on subdomains.
There are websites:

website.com
one.website.com
two.website.com

with identical url paths but different content.
I need to redirect each website from http to https.
Root website htaccess:

<IfModule mod_rewrite.c>
    RewriteEngine On

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

    RewriteCond %{HTTP:X-Forwarded-Proto} !=https
    RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]

</IfModule>

But this adds index.php to URL while redirects. So http://one.website.com/test become into https://one.website.com/index.php?p=test

move these lines

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

to the end of the file


Using redirectInput {id} parameter I have a public registration form and want to redirect to a payment page where I will need some details about the newly created user. I tried doing this in my form:

<input type="hidden" name="action" value="users/save-user">
{{ redirectInput('join/payment/?user={id}') }}

I have set a custom route to allow for the query parameter:

   if url = join/payment/*  load template join/payment

but the resulting url does not include the query string, just the first two segments, 'join/payment'.

Am I doing something wrong here?

Thanks!

Sorry, false alarm. My template file was not syncing with the server. To recap, this works like a charm:

{{ redirectInput('join/payment/{id}') }}

This results in a redirect that includes the ID of the entry or user that was just created!


Using a variable that was set in a previous include By base.html:

{% block searchLogic %}
{% endblock %}

{% block meetingDisplay %}
{% endblock %}

My index.html:

{% extends "base.html" %}

{% block searchLogic %}
{% include 'logic/anonVisitor.logic' %}
{% endblock %}

{% block meetingDisplay %}
Some html code
{% for meeting in meetings %}
{% endfor %}
{% endblock %}

My anonVisitor.logic file:

{# More code that works, I just removed it for clarity #}
{% set meetings = craft.entries.section('meetings').address(params).limit(25).order('distance').find() %}

I try to use the variable meetings in the block "meetingDisplay" in the index.html file. For some reason the variable "meetings" is no longer available.

I am trying to seperate my logic blocks and my html blocks into separate files for manageability and reuse.

All this logic worked before I broke the code and html using the extends and includes.

Is there a way to make variables set in an include be available in a block?

So what you're running into is Twig scoping rules, which is discussed at length in the article Twig Processing Order & Scope

The TL;DR is that a variable is only available in the context in which it is defined. Since you're setting the meetings variable in a file you included, that variable exists only in the context of the anonVisitor.logic file.

Additionally, variables defined in a parent context are available to any child templates that are included, but you can't change the values in the child templates, because you're given a copy of the context that goes away when the child templates are done rendering.

What you can do is leverage extends and embed, because templates that extends other templates have the same context as the parent that they extends.


Enironment Variable being rendered literal OK,
So created 2 variables in my local .env file
ASSET_BASE_URL="https://mysite.local/resources"
ASSET_BASE_PATH="/Volumes/yada/yada/yada/resources"
Then in the CP, created a new Asset volume and punched in
Base URL = $ASSET_BASE_URL/gallery
File System Path = $ASSET_BASE_PATH/gallery
Then front end renders an entries asset as:
<img src="$ASSET_BASE_URL/_480x480_crop_center-center_80_none/doddle-01.jpg" alt="Doddle 01" width="480" height="480">
THEN it creates a new folder named '$ASSET_BASE_PATH' at public site root.
I'm familiar with V2 it appears V3 has stepped up a bit. Could it be a Mamp issue with paths or somesuch trickery? Works if I hard code the paths as listed initially. All help greatly appreciated.

You can't append anything to the value if you use environment variables. You need to use aliases for this.
In you config/general.php, add this:
'*' => [
    'aliases' => [
        'assetBasePath' => getenv('ASSET_BASE_PATH'),
        'assetBaseUrl' => getenv('ASSET_BASE_URL'),
    ],
],

Then in the asset volume settings, use the aliases in the Base URL & File system path:


Front end Entry form with validation error support? The official example ( https://craftcms.com/docs/templating/entry-form ) seems to assume that the form itself is not already on a page which is an Entry. Dropping this form into a template that has an entry loaded already spits out that entry's entry.title or entry.body.

How should this work? We want the "new entry form" to live on a page that the client controls the content for.

The saveEntry controller used by the default example returns an entry variable with the newly created item and the applicable error messages. This could be a potential cause of conflict if you have another variable called entry, which is by default pre-loaded in entry templates.

I think you could create a (for example) product.twig template and manually set an entry variable (via ID or slug) called anything else than entry.


Managing sections and field updates between environments What is the best practice for the following:

Client site running CraftCMS (v3) is in production. Updates are needed which require additions or modifications to the data structure / schema of the site (new sections, fields, etc.). Taking a remote dump of the database for local development is not a realistic option as the client makes regular updates to the website in production. Particularly for new additions, is there a way to easily make those updates in production after I've completed them in my development environment?

Real scenario: I'm adding a new section (a blog) to add to an existing Craft site. I will be working in the development environment for several days, making many additions to the data structure / schema, which I'd prefer not to have to replicate via the admin UI in production once I'm ready to deploy.

Note: I do not want to sync the entire databases - just the structure.

You could use https://github.com/Pennebaker/craft-architect to export your new sections/entry types/fields from your development environment once you're done, and then import them (without content) to production.


Live preview not automatically updating any help would be much appreciated.

I have Live Preview working on my entries ie. I can see and use the button, but the live preview won't update as I manipulate the content? It was working before so it is baffling me as to how it could stop working.

The only change I think I have made in that time is removing the open_basedir settings in my php.ini, but I wouldn;t imagine that would affect it?

Thanks,

Dc

UPDATE::

This is the htaccess code:

<IfModule mod_rewrite.c>
    RewriteEngine On

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

There is a known issue where if you use a variable name 'entry' in any template involved in a Live Preview request (including layout templates), then it can cause the behavior you're seeing.

Some examples are:

{% set entry = craft.entries. ... .find() %}

or

{% for entry in craft.entries. ... .find() %}

The workaround is to rename that variable to something else.  myEntry, for example.


How can I save matrix order via plugin? I am able to add/delete matrix blocks from within my plugin without any problems. I would like to give the user the ability to drag & drop any field just as you can within the CP.

I can use jQuery UI Sortable to create the functionality no problem. I am curious what/how to call within Craft that manages order so that it is saved.

Thank you for any suggestions!

Matrix blocks are saved in the order they appear in the POST data when saving the "owner" element (the entry, or whatever). So just adding jQuery Sortable to your front-end form will be enough.


Importing images from external url and saving to entry using plugin I'm looking for the correct way to import an image from a url and save it to an entry and in the correct subfolder (uploads/images/{id})

I've created a resource pointing to uploads/images
and the entry field will upload to resource/{id} by default.

As I understand the file also needs to be indexed in the database for it to be visible in the file browser so I can't just save it straight to the file system.

Here's how I did it in a recent project:

    $fileIds = array();

    // get remote image and store in temp path
    $imageInfo = pathinfo($data['image_url']);
    $tempPath = CRAFT_STORAGE_PATH . 'runtime/temp/' . $imageInfo['basename'];
    file_put_contents($tempPath, fopen($data['image_url'], 'r'));

    // insert the file into assets
    $response = craft()->assets->insertFileByLocalPath(
      $tempPath,
      $imageInfo['basename'],
      $myAssetFolderId, // notice, this is the id of the folder you want to upload to
      AssetConflictResolution::KeepBoth
    );

    // if the response is a success, get the file id
    if ($response && $response->isSuccess()) {
        $fileIds[] = $response->getDataItem('fileId');
    }

    // create a new entry
    $entry = new EntryModel();
    $entry->sectionId = $mySectionId;
    $entry->typeId = $myEntryTypeId;
    $entry->authorId = 1;

    // set your content, including image field by id
    $entry->getContent()->title = $data['title'];
    $entry->getContent()->mainImage = $fileIds;

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

I included the entry saving part of it to show how the response is used to get the file id(s) and so on.

Whether this is the "correct" way to do it or not, I don't know. :)


"Service Unavailable" I have installed WampServer in Windows machine.
WampServer services (PHP, Apache and MySQL) started successfully.
When I am trying to access public folder (http://localhost:8080/CraftCMS/public/) from CMS project through web it is showing an error:

  Our site is temporarily unavailable. Please try again later.

The contents of the "public" folder are supposed to be in your web root. So you're probably better off with a separate virtual host instead of accessing your Craft site in a sub folder for that reason. You can also move the contents of the public folder to the web root for localhost. Just change the path to the craft folder in index.php in that case.

I created an instruction on how to install Craft's demo site on Wampserver some time ago. Although that's not exactly the same as installing Craft, you should be good to go after following "WampServer setup" and "Virtual host setup".

If you're still having trouble after that, then it's probably worth taking a look in either the server logs or the logs at craft/storage/runtime/logs to see what's wrong.


Archive page date logic stopped working Edit: This is confirmed as a bug in Craft, that will be fixed in its next release. If you're running into this, please see the temporary fix over at GitHub: https://github.com/craftcms/cms/issues/3772

I'm leaving up the original post for posterity.

--

I'm running into an issue with the recent update for Craft 3.1. I've not changed any of my code on the archive pages, but the list of entries on my archive pages stopped showing up.

Here is the code I use to set up the date ordering.

{% set firstEntryEver = craft.entries.section('posts').orderBy('postDate asc').one() %}
{% set lastEntryEver = craft.entries.section('posts').orderBy('postDate desc').one() %}
{% if craft.app.request.getSegment(2) is null %}
    {% set year = 2018 %}
{% else %}
    {% set year = craft.app.request.getSegment(2) %}
{% endif %}
{% set archiveBlurbs = craft.entries.section('archives').type('yearBlurb').archiveYear(year) %}
{% set monthBlurbs = craft.entries.section('archives').type('monthBlurb').archiveYear(year) %}
{% set entriesInYear = craft.entries.section('posts').limit(null).after(year).before(year+1).all() %}

And the call I use is {% for month, entriesInMonth in entriesInYear | group("postDate|date('F')") %}. The content is then separated by month over a single year.

The logic I use here generally follows the official docs with some light modifications. I find that the content for all years shows up if I remove the before.

Any idea what might be at play here?

It seems that before and after() don't work with the year as an int, if instead of '2018', you use '2018-01-01', your code works again. Check this.

Basically, use a DateTime object
:)


How to list out entry types in a section Something like craft.entrytypes.section('sectionHandle') and then loop through them to list out their names.  I'm looking through the docs and can't see how to do this with just the craft.entries code.

Take a look at the sections documentation: https://craftcms.com/docs/templating/craft.sections

The following code lists all entrytypes of all sections.

{% set sections = craft.sections.getAllSections() %}

{% for section in sections %}

{{ section.name }}

    {% set entryTypes = section.getEntryTypes() %}

        {% for entryType in entryTypes %}

{{ entryType.name }}

        {% endfor %}

{% endfor %}

If you like only to show used entry types:

Loop trough all entries
Collect all entry types in a array
Now, you can loop trough the entry types array


Can the “Commerce Products”-field allow for selection of variants? The client wants related products on individual product pages.

Is it possible to have the “Commerce Products”-field allow for selection of variants rather than products as a whole? Or is there another way to achieve this functionality?

If not, I was thinking about letting the client paste the variant ids into a table field or something, then pull the variants onto the product page with ajax. Seems quite hacky though, so any alternatives are most welcome!

Thank you kindly

At the moment there is no Commerce variants field type unfortunately.   It comes up a lot, someone should post it here: https://github.com/craftcms/commerce/issues.

Edit - I've gone ahead and posted this here - https://github.com/craftcms/commerce/issues

In the meantime yes a text or eg table field could store variant IDs...which I suppose is ultimately what a proper field type would do basically.


Upload assets to location based on category if entry isn't saved yet? I'm building a gallery system and on the entry page I have fields for gallery category (category field) as well as gallery photos (assets field). When creating this entry, I would like to upload the assets field to something like:

images/galleries/category/slug

However, because the category is still being defined in the same entry as the assets are being uploaded, my images aren't put into a folder based on the category.

Is what I'm trying to do possible? What's the best way to approach it? I'm currently using this for my assets file path:

images/galleries/{galleryCategory.first.slug}/{slug}

I've ran into something similar, although it was using the entry ID. If you set the category and save the entry, and then upload an asset to that field on the entry does it save into the location you have set?

Also if the assets field is within a matrix you'll need to use owner

{owner.galleryCategory.first.slug}


Variables not iterating in for loop I am trying to use the Placid plugin to retrieve track-names from an external service, and having problems. I have the following code:

{% for song in craft.entries.section('music') %}
  {% set params = { 'id' : song.itunesId } %}
  {% set lookup = craft.placid.get('itunesMusic', { params : params } ) %}

  {% for track in lookup.results %}
    {{ track.trackName }}
  {% endfor %}
{% endfor %}

The values of song.itunesId and params seem to be set correctly, however lookup.results is returning the same track.trackName on each iteration of the loop.

Thanks for giving Placid a try, sucks you have had issues using it. I understand you're using Guzzle now, but for future reference I think I know what was going on.
Caching
In this case you would need to turn caching off for the Placid request, this is due to you needing a new request for each iteration, I will be looking to improve the caching in the near future to be more intelligent but in the meantime just setting { cache: false } should fix this:
{% for song in craft.entries.section('music') %}
  {% set params = { 'id' : song.itunesId } %}
   {% set lookup = craft.placid.get('itunesMusic', { params : params, cache: false } ) %}
   {% for track in lookup.results %}
    {{ track.trackName }}
  {% endfor %}
{% endfor %}

I've set up an example so you can see it in action here
I hope that helps if you choose to use Placid again in the future!


Specify a field dynamically using section handle I'm using a single template to display entries from several structures. Each structure has a cooresponding global field that is an entries field. I use this to display related entries as a sidebar. These fields are named sidebars.[structure handle]Sidebar, so fore example my blog sidebar global field would be sidebar.blogSidebar.

Coding the sidebar manually works fine, like this:

{% for block in sidebars.blogSidebar %}
    ...
{% endfor %}

But I'm trying to dynamically set the related entries field, and it isn't working:

{% set sidebar = "sidebars." ~ entry.section.handle ~"Sidebar" %}
{% for block in sidebar %}
    ...
{% endfor %}

This code doesn't output anything. If i just output {{ sidebar }}, it shows what I expect, ex: sidebars.blogSidebar.

And if I manually add it to the for loop {% for block in sidebars.blogSidebar %}, it works as expected.

Is there a different way to concatenate the name to make this work?

I don't think your approach makes sense but you can use twigs Attribute function

{% for block in attribute(sidebar, entry.section.handle ~"Sidebar") %}


Selecting categories by first letter I'm attempting to pull out a list of categories starting with certain letter(s).

What I've come up with so far seems a little excessive and I'm wondering if I've missed something obvious.

Can it all be done with just the 'craft.categories...' line?

{% set allCats = craft.categories.group('listingCategories').order('title').limit(null).find() %}
{% set allCatsByLetter = allCats|group('title | first') %}

{% for letter, allCats in allCatsByLetter if letter == "A" %}

        {% for cat in allCats %}

{{ cat.title }}

        {% endfor %}

{% endfor %}

If you don't mind using the search parameter you could add it like this:

{% set beer = 'a' %}
{% set allCats = craft.categories.search('title:' ~ beer ~ '*').limit(null) %}


Specify Redactor config in migration is it possible to specify the Redactor config file when creating a Redactor field programmatically?

I was hoping I could do something like the following but have had no success:

$bodyField = $fields>createField([
    'type' => 'craft\\redactor\\Field',
    'groupId' => 1,
    'name' => 'Body',
    'handle' => 'body',
    'settings' => [
       'redactorConfig' => 'Simple.json'
    ]
]);

$fields->saveField($bodyField);

Maybe you should take a look what the function createField does

Creates a field with a given config.
return    craft\base\FieldInterface  The field

It only creates a PHP object but does not save the field at all.
Craft::$app->getFields()->saveField($field);

is what you want
This is what the FieldsController does to store a new field
public function actionSaveField()
{
    $this->requirePostRequest();

    $fieldsService = Craft::$app->getFields();
    $request = Craft::$app->getRequest();
    $type = $request->getRequiredBodyParam('type');

    $field = $fieldsService->createField([
        'type' => $type,
        'id' => $request->getBodyParam('fieldId'),
        'groupId' => $request->getRequiredBodyParam('group'),
        'name' => $request->getBodyParam('name'),
        'handle' => $request->getBodyParam('handle'),
        'instructions' => $request->getBodyParam('instructions'),
        'translationMethod' => $request->getBodyParam('translationMethod', Field::TRANSLATION_METHOD_NONE),
        'translationKeyFormat' => $request->getBodyParam('translationKeyFormat'),
        'settings' => $request->getBodyParam('types.'.$type),
    ]);

    if (!$fieldsService->saveField($field)) {
        Craft::$app->getSession()->setError(Craft::t('app', 'Couldn’t save field.'));

        // Send the field back to the template
        Craft::$app->getUrlManager()->setRouteParams([
            'field' => $field
        ]);

        return null;
    }

    Craft::$app->getSession()->setNotice(Craft::t('app', 'Field saved.'));

    return $this->redirectToPostedUrl($field);
}


Setting a field search variable after main entries variable changes values Kind of hard to explain but here's an example:

{{entries.all()|length}} {# outputs 88 #}

{% set hasTopic = entries.search('dataTable_topic:*').all() %}
{{entries|length}} {# outputs 7 #}

How can I keep entries the same below the search variable.

This is because of the way Element queries are in Craft 3.

In Craft 2, each time you called a setter method (search() here) it would clone your ElementCriteriaModel, use that value on the clone and return the cloned object leaving the original alone.

In Craft 3, when you call a setter method, it gets set on the current element query.

So if I understood correctly, you should use clone (docs):

{% set entries = craft.entries().section('yourSection') %}
{{entries.all()|length}}

{% set hasTopic = clone(entries).search('dataTable_topic:*').all() %}
{{entries|length}} | {{ hasTopic|length }}


Issue accessing single entry from within category template I've got a product section on a website where individual product entries are categorised. On the section landing page all the products are listed organised by category. On the individual category pages only the product entries relevant to that category are shown.

The issue I’m having is that for the category landing page I want to pull in the Section landing page content. However when I try the following:

{% set entry = craft.entries.section(‘productsAndMarketsLandingPage’).first() %}

{entry} returns empty. Any thoughts why this isn’t being pulled into this particular page/template? I can access it just fine from within the

The section, template and URL structure is as follows:

Section landing page
url: /products-and-markets
template: /products-and-markets/index
section: productsAndMarketsLandingPage

Category landing page
url: /products-and-markets/{slug}
template: /products-and-markets/_category
section: productsAndMarkets

Product entry page
url: /products-and-markets/{slug}
template: /products-and-markets/_entry
section: productsAndMarkets

Cheers in advance,

Cole

Okay, solved.

Was an idiot and wasn't using the right tag to output the results of the query.

Sorry and thanks!


6 month old site is suddenly throwing 404s http://denizen.tv/work/2011-kca-image-campaign

http://denizen.tv has been up and running well since June, but it's suddenly throwing 404s. It looks like the same /index.php/ problem I was recently having with my own Craft install. The coincidence makes me think it must be a bug with a recent release.

Anyone else getting this error?

Since files that begin with a dot are hidden by default in Unix-based systems like OS X, Craft ships with a “htaccess” file rather than “.htaccess”. If you are using Apache and want to use this file, you need to rename it to .htaccess when you upload it to your web server.

Not sure why suddenly your site stopped working, but I can tell you that Craft auto-updates will only ever touch files within the craft/app/ folder, so if your .htaccess file was misnamed, it’s definitely not due to a Craft auto-update.


Are there any plugins for Craft 3? Are there any Craft 3 plugins yet? They would be useful as examples for porting/writing other Craft 3 plugins.

Here are some.

Store Hours (P&T)
match input
Mandrill (P&T)
Entry Count
Minify (9/17/2016)
MN Twig Perversion (9/19/2016)
Stamp (9/21/2016)
Inlin (9/21/2016)

Mention more in the comments, and I will add to this list.


400 Bad Request on account or admin login On attempting to login into either a front-end account or admin account I'm hit by:

400 Bad Request
Request Header Or Cookie Too Large
nginx/1.8.0

It's only happened recently but running the latest Craft CMS v2.5.2757 and from looking at the cookies created during login I think it's possibly related to CSRF protection as deleting the top cookie in the list below fixes the issue until you log in again.

Running a few other Craft sites on the same staging nGinx server without the same issue, and even the same codebase is running another site without issue.

Any thoughts please?!

Add this to your nginx server block:

server {
  ...
  large_client_header_buffers 4 16k;
  ...
}

and restart nginx. The default is 8k. If you have a lot of headers, beefing that value up should resolve it otherwise you may want to play with client_header_buffer_size as well.


Is it possible to get all elements in a Matrix field by type or field name I found a way to do something like this

 {% set allBlocks =  craft.entries.matrixes %}

Which seems to return all the matrix blocks.. or at least I think it is?

But if try to filter down like:

  {% set allBlocks =  craft.entries.matrixes.type('document') %}

I get nothing.

Any ideas how to get all the Matrix blocks by type or better still all the Matrix blocks in a particular field?

Would i need to setup a plugin for this?

There is no craft.entries.matrixes variable available natively in Craft.

(craft.entries returns an ElementCriteriaModel, which does not have a matrixes property explicitly set.)

So, craft.entries.matrixes is actually looking for ElementCriteriaModel->matrixes(), which could implicitly exist if:

You have a field called matrixes, or
There's a plugin in the mix that is changing functionality

You'll need a plugin to run these custom queries. Luckily Craft's MatrixService has plenty of methods that would be helpful.

Also, Low created a plugin (LowBlocks) to do this sort of thing, which might fit your need, or at least offer a helpful starting point.


How to speed up a single entry page with Eager Loading This is a single entry page. I have an assets field of imageGallery which allows multiple images to be uploaded but it could also be empty. I want to use the first image at the top of the page (if one exists) then show the rest of the images (if there is more than one) excluding the first one after the bodyText field. I'm also loading a transform named 'gallery' if the original image is larger than the transform. This is the code I have now (simplified for clarity):

{% set titleImage = entry.imageGallery[0] ?? null %}

{% if titleImage|length %}
    {% if titleImage.getWidth()>titleImage.getWidth('gallery') %}
        <img src="{{ titleImage.url('gallery') }}"
    {% else %}
         1 %}
    {% for image in entry.imageGallery.offset(1).all() %}
        {% if image.getWidth()>image.getWidth('gallery') %}
            <img src="{{ image.url('gallery') }}"
        {% else %}
            <img src="{{ image.url }}"
        {% endif %}
    {% endfor %}
{% endif %}

How could this be impoved on for faster loading?

Disclaimer: While eager-loading will almost always bring down the total number of queries executed, it's important to note that having less queries won't always equal better performance. When optimising a page with eager-loading, you should take care to observe the actual time Craft spends on database queries – which is the metric that matters.

For Craft 3, you should enable the Debug Toolbar, which will tell you exactly how many milliseconds Craft is using for database queries. Eager loading is not a silver bullet, and you should note the time spent on database queries with and without eager loading, to determine if it's actually increasing performance or not. You can enable the debug toolbar from your Craft user's profile page inside the Control Panel.

For Craft 2, you'll need to enable devMode, crack open your browser's dev tools console and expand the *Profiling Summary Report*. Unfortunately, AFAIK there's no record of the time spent on queries specifically, but you can gauge it by looking at the Time property (which will report the total time Craft spent resolving the request, including database queries). Obviously, the lower this number is, the better.

Furthermore, before worrying about eager loading, you should make sure that your template is properly optimised without it. The most important thing is to make sure that you're not doing multiple, redundant queries.

In the code example above, you're first executing two queries on the entry.imageGallery() field outside the {% for %} loop, and then 1 additional query per image inside the {% for %} loop. In other words, if you added 100 images to the galleryImages field, you'd execute a total of 102 queries – which is totally unnecessary.

By caching the array of Assets returned by .all() to a variable, you can get away with a single query:

{# Get all images in the field #}
{% set galleryImages = entry.galleryImages.all() %}

{# Set the `titleImage` to the first image #}
{% set titleImage = galleryImages[0] ?? null %}

{% if titleImage %}
    ...
{% endif %}

{{ entry.bodyText }}

{# Use the |slice filter to remove the first image – i.e. the title image – from the Assets array, and then print the rest of the images #}
{% set galleryImages = galleryImages|slice(1) %}

{% if galleryImages|length %}
    {% for image in galleryImages %}
        ...
    {% endfor %}
{% endif %}

Note the use of the |slice filter – this is used to remove the first index (i.e. the first image) from the array, after caching it to a variable titleImage. Don't worry, the |slice operation won't throw an error, even if the galleryImages array is empty.

With the above optimisation, your X number of queries have been reduced to a single query – and at that point, you probably wouldn't see any performance improvements by adding eager loading.

But, if you wanted to try it – here's how it could be done (this would replace the first line in the above example):

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages']
) %}

The above statement should go at the very top of your template – and if you do this, make sure to remove the reference to .all() in the first line of the first example (by eager loading the Assets field, the entry.galleryImages property is already an array and hence has no all() method).

Again, the above is probably not useful if you do the optimisations to bring down your query count to 1 – but, it could be useful if you had multiple relational fields you wanted to query, i.e.

{% do craft.app.elements.eagerLoadElements(
    className(entry),
    [entry],
    ['galleryImages', 'entriesField', 'categoryField']
) %}

For more info on eager loading, check out this excellent article.


How to find number of assets inside a matrix block? I have a matrix block which has an asset field inside of it. I want to know how many assets are inside the block, is there a way to do so?

Yeah you should be able to do something like

{{ block.assetField|length }}


Craft templates in sub directory We want to add a little more structure to our templates directory by adding folders to group templates files.

For example:

templates
--_macros
--_views
--_layouts

In general this works fine but we encountered a problem with the index pages of sections.
All pages are grouped in the views directory, so in views we could have a folder "articles" and within that a file "_entry.twig" and "index.twig".

For the entry to work we change the template path of the section in the backend.
But there is no place to this for the index file.

Anybody an idea how best to handel this?
Is there a way to tell craft to also look in de _views folder?

It sounds like you're wanting to move templates around like this:

articles/index.html
articles/_entry.html

To this:

_layouts/articles/index.html
_layouts/articles/entry.html

There are three basic ways Craft figures out what template to use based on the URL:

Element routing like articles/_entry.html (matches a URI in an element's settings, e.g. section or category)
dynamic routes and URL Rules
Template path routing like articles/index.html

(Craft 3 docs on routing)

To get a URL like http//example.com/articles to use the template _layouts/articles/index.html, you have two options:

Set up a dynamic route or URL rule.
Create a Single with the URI set to articles.

Personally, I often create a Single for this like a Blog index page. Then it's easy to control parts of the index page like a header image or custom SEO tags.

A dynamic route would look like this:

A URL rules would work something like this in config/routes.php:

'articles' => ['template' => '_layouts/articles/index'],

A third option that I don't recommend is if you have a structured section called something like "Pages" (or Static Pages or Landing Pages), you could create different Entry Types called "Page" and "Articles Index" just for this.

├── About Us (Page)
│   └── Our Team (Page)
├── Articles (Articles Index)
├── Services (Page)
└── Contact (Page)

I'm not a fan of this for a few reasons, but the main one is that you can't point entry types to different templates in Craft so you'll probably have to use Twig includes to create a "routing template" that points the Article Index entry type to a different template. Also,  chances are you will never need more than one Articles index page, and you won't want to drag and drop it's location around the structure because the URLs will become out of sync with the child Article entries.


How can I best extend TagModel to add a `count` property? I'm attempting to write a plugin to extend tags by adding a count property that'd be useful identifying popular tags, making a tag cloud, and anything else where a count would be useful.

The Goal

What I'd like is to neatly extend TagModel so that interacting with these new count tallies  would be straightforward and as similar as possible to working with tags. For example, pretend superTags is my count-appended set and I'm getting the top ten tags for a site across sections:

{% for tag in superTags.limit(10).order('count desc') %}
    {{ tag.name }} has been used {{ tag.count }} times.
{% endfor %}

...or getting the top 10 tags by a blog author:

{% for tag in superTags.channel('blog').relatedTo(author).limit(10).order('count desc') %}
    {{ tag.name }} was born in {{ tag.dateCreated | date('Y') }}.
{% endfor %}

The Problem

I humbly admit that I'm struggling to see the big picture. For example, this works fine (my plugin's called Taggregate):

{% set tags = craft.tags.find() %}
{% set superTags = craft.taggregate.appendCounts(tags) %}
{% set superTags = craft.taggregate.sortByCount(superTags) %}

{% for tag in superTags %}
    {{ tag.name }} has been used {{ tag.count }} times.<br>
{% endfor %}

I've got a TaggregateModel that extends TagModel only to merge in a count Number to defineAttributes(). My Service takes the tags array, then spits out a new one with TaggregateModel objects that include the count property. (Each count is just a tally from craft_relations with no regard for other parameters like section or author—later I intend to use an aggregate table as Brad suggested, even though that's irrelevant here.)

TaggregateService

...

public function appendCounts($tags)
{
    $superTags = array();

    new TaggregateModel($tags);

    for ($i=0; $i < count($tags); $i++)
    {
        $superTags[$i] = new TaggregateModel($tags[$i]);
        $superTags[$i]->count = $this->getTagCount($superTags[$i]->id);
    }

    return $superTags;
}

public function getTagCount($tagId)
{
    $q = craft()->db->createCommand('SELECT count(*) as count FROM craft_relations WHERE targetId = '.$tagId)->queryAll();

    // TODO: get stored aggregate if it exists, otherwise count and store

    return $q[0]['count'];
}

public function sortByCount($tags)
{
    usort($tags, function($a, $b)
        {
            return $a->count < $b->count;
        }
    );

    return $tags;
}

...

While this works, it's clearly bad design:

The Twig interface is specific to the plugin's weird version of non-native methods.
This superTag array isn't smart enough to do any of the cool things that TagModel can.

The Question

Is there a more sensible way to build this so I can hit my ideal usage outlined in "The Goal" above? I'm not looking for somebody to write this for me, just some big-picture guidance since I suspect I'm making this harder than it should be.

...or is my seemingly-simple objective actually complicated?

Before worrying about how templating should work, let’s just get one thing out of the way: Computing this data every time it’s requested is horribly inefficient, and could easily take a site down. You’ll absolutely need to find a way to store the tag counts in a more permanent location, and calculate it when entries are saved rather than when the template requests it. (Even if you wrap the template in a {% cache %} tag, you’re still forcing a couple people to experience slow page load times for no good reason.)

You have multiple options on how to store the data, but giving it its own table is probably the most obvious/reliable. I’d call it something like tagcounts, and give it tagId and count columns. tagId should be a FK to the tags table, set to cascade delete.

Then you’d want to listen to the entries.onSaveEntry event. When it fires, loop through all the entry’s Tags fields, and each of their selected tags. For each one, get the total count of rows in the relations table where the targetId column is set to the tag’s ID. Use DbCommand::insertOrUpdate() to save the value in your table.

craft()->db->createCommand()->insertOrUpdate('tagcounts', array(
    'tagId' => $tag->id
), array(
    'count' => $count
));

You’ll also need to loop through all existing tags and populate this table when the plugin is first installed.

With the tag count data in place, next up is templating. Unfortunately I don’t have a good answer for you there. It’s a complicated problem.

I think what I would do is, create a Variable class which accepts an ElementCriteriaModel, passes that off to craft()->elements->buildElementsQuery() which will take most of the parameters into account, then make some additional modifications to the query – join in the tagcounts table and set the ORDER BY.

Next up you would basically have to copy a ton of code from ElementsService::findElements(), which is totally lame. I’m going to see what I can do to make it much easier on you going forward. Ideally at this point you would be able to just do something like:

return craft()->elements->findElementsUsingQuery($query);


How can I ensure certain items always display at the end of a list? I have a website where I want to show Power Coat (-PC) options at the end of a list. The data goes into Craft in an unpredictable order, from a third-party service, so I am responsible for organizing it in the front-end.
Is there a way I can split out or force the -PC items to always appear at the end of the list, in my template?

How would you like to identify that particular entry? If you're happy to hardcode its id, then I'd do it like this with the filter filter and the without filter:
{% set allEntries = craft.entries.section('products').all() %}
{% set pcEntry = allEntries|filter(item => item.id = 1234) %}
{% set entriesWithoutPC = allEntries|without(pcEntry) %}

You can now output those however/wherever you like, e.g.

  {% for product in entriesWithoutPC %}

{{ product.title }}

  {% endfor %}

{{ pcEntry[0].title }}


Craft Rules and Validation Some of the changes in craft 3 have been killing me. I know Yii does validation using the public rules function. Here is a rules function I grabbed from the MatrixBlockType model.

function rules()
{
    return [
        [['id', 'fieldId', 'sortOrder'], 'number', 'integerOnly' => true],
    ];
}

My question is simple. I for the life of me can't find where the validator number is defined. I'm assuming it validates using Yii's NumberValidator.php function but can't verify that. Any ideas on where I can find the number validator?

I just figured out the answer so I'm going to post it if anyone else is asking this question. Yii accepts aliases as well as function/class names when evaluating the rules function. When using number you're really using an alias that points to the yii\validators\NumberValidator class. See yii2/validators/Validator.php to see a list of default aliases created by Yii.


How do you pull out second level structure entries based on their parent? I have a structure as follows:

Parent 1

Child 1
Child 2
Child 3

Parent 2

Child 1
Child 2
Child 3

Parent 3

Child 1
Child 2
Child 3
etc...

On my Child entry pages I want to pull out the other child entries under that parent to use as navigation. I think this should be fairly straight forward but I can not find any documentation on it. So far I have the below but this pulls out all level 2 child entries and not just the entries for the specified parent.

Any help much appreciated.

{% for subnav in craft.entries.section('mySection').level(2).find() %}

{{ subnav.title }}

{% endfor %}

Ok I've worked this out from above and adding some other code and now it works as below:

{% set parent = entry.getAncestors().first() %}
{% for subnav in craft.entries.section('mySection').descendantOf(parent).descendantDist('1') %}

{{ subnav.title }}

{% endfor %}

Hope this assists someone else.


Order by score and another field Currently I am sorting a category template with this:

'featured desc, postDate desc'

Works as expected. But I would like to sort it first on the featured field, then on the score. Such as

'featured desc, score'

But this throws an error. Can someone explain why that is and how I might achieve what I'm looking for? The first search is good for bringing featured posts to the top, but if there are none or maybe one, the rest of the results are not all that relevant. Ideas?

Thanks in advance.

I assume you're using .search() – a common mistake is to try to combine orderBy('score') with custom fields, which doesn't work because the score attribute isn't an actual field, but a computed value that Craft "injects" into the element model.

If I understand you correctly, you want to render any "featured" entries at the top of the search results. You could achieve this by doing two separate search queries, before merging the results, with the featured entries at the beginning of the entry results array. Assuming featured is a Lightswitch field, something like this should work:

{% set searchQuery = craft.entries.search('foo').orderBy('score') %}
{% set featuredEntries = searchQuery.featured('1').all() %}
{% set notFeaturedEntries = searchQuery.featured('not 1').all() %}

{% set allEntries = featuredEntries|merge(notFeaturedEntries) %}

{% for entry in allEntries %}
    ...
{% endfor %}

If you need to use pagination, the above won't fly – in which case you could opt to just collect the entry IDs and do a third query to pull the full entry models for a paginated result set:

{% set featuredEntryIds = searchQuery.featured('1').ids() %}
{% set notFeaturedEntryIds = searchQuery.featured('not 1').ids() %}
{% set allEntryIds = featuredEntryIds|merge(notFeaturedEntryIds) %}

{% paginate searchQuery.featured(null).limit(10).id(allEntryIds).fixedOrder(true) as pageInfo, pageEntries %}

An alternative approach to the above is to just have a single query, and use the group filter to sort out the featured entries from the non-featured ones:

{% set entries = craft.entries.search('foo').orderBy('score').all()|group('featured') %}
{% set featuredEntries = entries['1'] ?? [] %}
{% set notFeaturedEntries = entries[''] ?? [] %}

Note: If you're using Craft 2, be sure to replace the orderBy parameter with order. Using order in Craft 3 will still work, but the parameter is deprecated and will not work in Craft 4.


Use only the sub categories from a category input I have a category input. The category group has two levels.

When accessing the category input via Twig I am trying to only grab sub categories the user selected.  However when I use

{% set firstCat = entry.categoryInput.first %}
{% set cats = firstCat.getDescendants() %}

or children it grabs all the descendants from Categories > Group not just from the structure that was selected from the input.

You could set the level parameter according to your requirements:

{% set cats = craft.categories({
    relatedTo: {
        sourceElement: entry,
        field: 'categoryInput'
    },
    level: 2,
    limit: null
}) %}


Tag to fetch URL and Title of a entry when supplied it's ID I have a number of places in my templates where a link to a particular entry is needed to be hardcoded into the template, but we still want that links URL and title to be dynamic, so if the URL or Title of the entry is updated, this is reflected.

Is there a nice lightweight simple snipped of code we can use to fetch the URL and Title of an entry when supplied with a valid entry ID? I've checked through the documentation but can't see anything obvious.

Particularly after something lightweight that isn't going to add significant numbers of DB queries to a page load.

This is all you need:

{% set linkedEntry = craft.entries.id(42).first() %}
{{ linkedEntry.title }}

If you use this in many places you can also make a macro.

{% macro linkToEntry(entryId) %}

    {# Get the entry with the selected ID #}
    {% set linkedEntry = craft.entries.id(entryId).first() %}

    {# Make sure the entry exists and output the link #}
    {% if linkedEntry %}
        {{ linkedEntry.title }}
    {% endif %}

{% endmacro %}

It's nice to have macros in a separate file and import it into your templates. I really love using macros for this kind of code snippets, very useful and DRY.

{% import "macros.html" as macros %}

{{ macros.linkToEntry(42) }}

{{ macros.linkToEntry(17) }}

{{ macros.linkToEntry(20) }}


How to extend Craft.BaseElementIndex for a custom Element Type I have a custom Element and need to modify the Element Index page. I'm attempting to extend Craft.BaseElementIndex and register the extended class on my Element Index Page. I'm working on a plugin for Craft 3. Something similar seems to be working fine in Craft 2, but I'm not sure if this is really a version issue or just an issue with my implementation.

Something like this:

(function($){
    Craft.MyCustomPlugin.MyElementIndex = Craft.BaseElementIndex.extend({
      getDefaultSort: function() {
          return ['elements.dateCreated', 'desc'];
      }
    });

    Craft.registerElementIndexClass('mynamespace\\elements\\MyElement', Craft.MyCustomPlugin.MyElementIndex);
})(jQuery);

The javascript file seems to load however doesn't have any effect on the Element Index page.

If I add an init method with a console.log() statement, a message gets logged but then the results on the Element Index page don't load anymore.

(function($){
  Craft.MyCustomPlugin.MyElementIndex = Craft.BaseElementIndex.extend({
    init: function() {
      console.log('Who cooks for you?');
    },
    getDefaultSort: function() {
        return ['elements.dateCreated', 'desc'];
    }
  });

  Craft.registerElementIndexClass('mynamespace\\elements\\MyElement', Craft.MyCustomPlugin.MyElementIndex);
})(jQuery);

Any ideas on what I'm missing?

Not really an answer to your question but some thoughts..
I've tried your code with my form builder and I noticed two things (the first is really obvious)

When you overwrite the default init function everything will (of course) break because all the important staff happens there, you can make your calls in the afterInit() function. Craft.js Line 3573

// Give sub-classes a chance to do post-initialization stuff here
this.afterInit();

This function handles the sort for Craft. Craft.js line 2721 link to git

setStoredSortOptionsForSource: function() {
    // Default to whatever's first
    this.setSortAttribute();
    this.setSortDirection('asc');

    var sortAttr = this.getSelectedSourceState('order'),
        sortDir = this.getSelectedSourceState('sort');

    if (!sortAttr) {
        // Get the default
        sortAttr = this.getDefaultSort();

        if (Garnish.isArray(sortAttr)) {
            sortDir = sortAttr[1];
            sortAttr = sortAttr[0];
        }
    }

    if (sortDir !== 'asc' && sortDir !== 'desc') {
        sortDir = 'asc';
    }

    this.setSortAttribute(sortAttr);
    this.setSortDirection(sortDir);
},

The important part is: var sortAttr = this.getSelectedSourceState('order'), (line 2726) and since sortAttr (at least for me) was never null in my tests - the sortAttr = this.getDefaultSort(); is not triggert. This is because Craft caches the sort order for the user but I don't know how/when this happens. However: when I overwrite line 2729

if (true || !sortAttr) {
    // Get the default
    sortAttr = this.getDefaultSort();

    if (Garnish.isArray(sortAttr)) {
        sortDir = sortAttr[1];
        sortAttr = sortAttr[0];
    }
}

And use

getDefaultSort: function() {
    return ['dateCreated', 'asc'];
}

I was able to change the default sort. Hope it helps a little bit

Note: this will break the default Craft caching. Normally the default sort options runs only once, after that is keeps the sort order that the user specified. You could overwrite the function for your tests and remove the always true condition when it goes live for a reliable way to get your function triggert.


What's the correct way to relate element types to a custom element type? I'm working on a custom stock management plugin for a client's Craft Commerce site, and I need to have relations from my custom element type (used to keep a detailed log of stock changes) to the products and variants, and the user or order that modified the stock.

I've looked at the Events plugin, as well as Craft & Commerce's source code, but I'm still struggling to write my modifyElementsQuery in such a way that allows me to access the content of these other elements without directly joining from the content table (which seems like a terrible way of going about it).

What's the right way of relating two element types together? Is there any example code I can look at (either in Craft core, or an open-source plugin)?

One or more Entries Fields might help you establish the relationship between your custom element and the other elements - after that, you should be able to call setContentFromPost() on the Entries in that field to change the content of related elements.


What is the best way to generate email messages with attachments from Twig files? I am coming from a .net/C# background and we have recently moved to a Craft/Twig platform.  What is the best way to do this: Have a visitor come to a Craft webpage (Twig file), enter their email address in a text box, hit a button, and have an email message sent to them containing a PDF attachment that they selected from that page?

Is this functionality built-in to Craft or do I need a plugin?

You can do this with a simple Craft plugin.  You can generate the boilerplate plugin code here.

Your form on the front-end will set its hidden action input to your plugin's controller's action.

From there, you can use Craft's EmailModel (along with addAttachment()) and EmailService's sendEmail() to send whatever email contents you wish.


Updating User Photo from Front-End I have this form, there's no errors getting thrown and the User photo field is not updating via this form.

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

          {% if currentUser.photoUrl|length %}

          {% else %}

          {% endif %}
          Profile Picture
          <input type="file" name="fields[photo]" class="form-control-file upload">

        <input type="submit" value="Save Profile">

      </form>

I'm unsure why it's not working, as it's fairly identical to some questions on SO.

Im my form, I also have a hidden field for the user photo:

<input type="hidden" name="photo" value="{{ currentUser.photo }}">.

I have {% if currentUser.photo %} instead of {% if currentUser.photoUrl|length %}.

Also,  instead of . This should display the current photo.

EDIT:

File input field name should be photo: <input type="file" id="photo" name="photo">


Craft login problem with memcache and ubuntu? session_regenerate_id(): Session object destruction failed is the error i'm receiving after attempting to log in.

I just updated to Ubuntu 16.04LTS using PHP7 and php-memcached.

Is there a fix for this in a craft version? I'm on version 2.6.2791 and this behavior is still broken. I cannot seem to find a workaround besides overwriting Yii with a workaround myself.

I saw a few work arounds for this here, hopefully it helps:
https://github.com/yiisoft/yii/issues/2376


Loading javascript on specific sections/pages What  is the recommended way to add section specific javascript to entry pages?
I need to make some 3rd party api calls front end for currency conversion but I want to only use it on a specific section entry.

A safe way to add JavaScript resources via the frontend, is to use the {% includeJsFile %} Twig function in your template. The nice thing about the includeJsFile function is that it doesn't matter where in your template you call it; the file(s) added will always be output just above your </body> tag (or wherever else you put your {% getFootHtml() %} call). Also, the function makes sure that no duplicate resources are requested, even if you have multiple calls to includeJsFile using the same URL (or filepath, for local resources).

You're not being specific about why the JavaScript should only be loaded for a specific entry, so it's difficult to advise about the optimal way to achieve this – but there's a few different approaches that could work nicely:

For one, you could add a conditional to your template, where you hard code the ID to the entry in question:

{% if entry.id == 100 %}
    {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
{% endif %}

Of course, you can have the conditional look at other attributes, as well:

{% if entry.section.handle == 'awesomeSection' %}
    {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
{% endif %}

If the JavaScript should e.g. be loaded whenever a certain Matrix block type is output, you could do something like this:

{% for block in entry.matrixField %}
    {% switch block.type %}
        {% case 'someBlockType' %}
            ...
            {% includeJsFile('https://code.jquery.com/jquery-3.0.0.js') %}
    {% endswitch %}
{% endfor %}

Remember, includeJsFile handles duplicate requests for you, so it doesn't matter if there's more than one someBlockType block – the actual external JS resource will only be requested once.

Of course, the most flexible option – and the one I would recommend – would be to add a custom field to your entry type, where you can add URL(s) to external scripts that should be loaded. This makes it easy to add external JavaScript resources to any entry, via the regular editing form in the CP. For this, the Table fieldtype will do nicely (the following assumes a table field with the handle externalScripts and a single column called url):

{% for row in entry.externalScripts %}
    {% if row.url %}
        {% includeJsFile(row.url) %}
    {% endif %}
{% endfor %}

Finally, another approach would be to add a PlainText field to your entry type (multiple lines, i.e. a textarea), where you can paste in a full <script> tag, e.g.:

    <script src="https://code.jquery.com/jquery-3.0.0.js"   integrity="sha256-jrPLZ+8vDxt2FnE1zvZXCkCcebI/C8Dt5xyaQBjxQIo="   crossorigin="anonymous"></script>

If go down this path, you can't use includeJsFile and will have to output the string "manually" – making sure to add the |raw filter to prevent Twig from escaping the HTML (the following assumes your plaintext field is called scripts):

{{ entry.scripts|raw }}

For the latter option, you might want to add a {% block scriptsInFooter %} to your base layout, in order to have the value for the scripts field render in the appropriate place:

{# Entry template #}
{% block scriptsInFooter %}
    {{ entry.scripts|raw }}
{% endblock %}

{# Base template #}
    ...
    {% block scriptsInFooter %}{% endblock %}
</body>


Dynamic upload location for Super Table within a Matrix field? I'm trying to set dynamic upload locations for my asset fields that are in a Super Table field within a Matrix field. So it's Matrix > Super Table > Asset field. I'm getting the following error when I save an entry, though. Could not resolve the subpath “{owner.section.handle}/{owner.slug}”.
Omitting the owner part doesn't work either.

Any ideas? Thanks!

Have you tried using {owner.owner.slug}? If you've got Matrix > Super Table > Asset, and you're trying to get an attribute on the Entry/Element, you'll need to go two level out from the Super Table field.

Entry
  Matrix
    Super Table
      Asset Field

The owner of the Super Table field is the Matrix field. The owner of the Matrix field is the Entry.


Need to access each item's converted price from payment gateway I am trying to implement multi currency to my payment gateway plugin.

I need to get converted price of the line item. Each item from Omnipay\Common\Item has the price of non converted, main price of the item.

This cause trouble because my payment gateway adds the line items and matches sum of all individual items to total sum of paid amount.

At the moment there is no multi-currency support built into Commerce.

Meaning, all prices in the system are stored in a single currency. This includes products, shipping, taxes, sales, discounts.

We DO have a multi-currency payments feature that allows a customer to pay in another currency (so they are charged an expected amount and get no surprises with their banks own conversion ratio).

The issue you are hitting above is that the price of the products is never converted. The items in the 'item bag' can only exist in the primary currency.

Your best bet is to not send the item bag to the gateway and only have them charge the amount. You can do this with the setting: sendCartInfoToGateways https://craftcommerce.com/docs/configuration#sendcartinfotogateways

If we were to try and get clever and convert the line items prices to the differing payment currency, the amount to be paid would work out to be different to the converted total, due to rounding.

When we move to full multi-currency support, this issue would go away since the line items would be converted first (along with discounts etc), and the total would be a sum of those amounts.

Hope that helps.


What is the typical owner:group for Craft files and folders? Using cpanel, apache. All requirements are met for Craft. On a typical default set up I believe that the public_html is user:nobody. What should the ../craft folder owner and group be? With what permissions? What about sub folders?

I  getting 403 forbidden with 0744 and 0774 permissions.

It really depends on your hosting environment, but the article Hardening Craft CMS Permissions might be useful to you.


How to duplicate a page within a Structure? Most of the pages in my Craft site are contained in one big Structure. There are a couple of pages whose content needs to exist in two locations within the structure. I'm not sure how best to do this.

I could probably hack something together with a bespoke route that loads a template which sets variables related to the navigation, then loads the content from the Entry defined in the CMS... but that seems like a horrible hack, and at that point I'd start to think I should just manually copy and paste the content between the two Entries in the CMS.

Any other ideas? Ideally I'd like it to be manageable in the CMS so it's not too hidden away from the client.

There are two easy ways to avoid copying and pasting or having duplicate entries.

First, you can use Globals to store the shared information.

Alternatively, your second entry/template can just ask for the data from the entry of the first entry.

{% set shared_information = craft.entries.slug('my-first-entry-slug').first() %}

<p>{{shared_information.customFieldWithSharedInformation}}</p>


Organize singles in Entries tab Looking to build a largish site with Craft and I need a way to organize the entries for content editors/creators. Adding headers down the side will help for channels/structures, but all singles seem stuck in the predefined singles tab.

I've tried adding a custom field to each page but it doesn't seem possible to sort by a custom field from within the entries view, which makes this rather useless.

Is there anything built in that I'm missing or perhaps a plugin that can help me to group together related content on this page? You can imagine this becoming hard to navigate with dozens or even hundreds of pages.

Doesn't the Expanded Singles plugin do what you're looking for? Best of luck.


how to get request url? I'm trying to get url from request,
 {{ craft.app.request.url }}

but the uri is chinese, like "localhost/測試",
it print out "http://localhost/����"
did i miss some setting in craft CMS ?
Thank you.

This isn't really an answer, but my investigating was too long for a comment.
Ultimately, craft.app.request.url gets routed through Yii's resolveRequestUri() and likely gets pulled from $_SERVER['REQUEST_URI'].
Anything coming from $_SERVER['REQUEST_URI'] is always going to be URL encoded so using this in a template:

I get this URL encoded output in a browser:

Unfortunately, Twig doesn't have a |url_decode filter, so you'd need to write a quick custom Twig filter that uses PHP's urldecode() method.
But it actually looks like you're having a character encoding issue first because of the ���� and I'm not exactly sure what's causing that.
My guess is its environment configuration related (I'm using https://getnitro.sh in a fairly default setup for testing).


What's the difference between Neo and Matrix fields? Im a bit new in Craft CMS
But so far to me, seems like both allow the user to create multiple blocks of content

On first blush they are very similar. I think the Craft Plugin Store description of Neo sums it up nicely:

Neo is a field type that builds upon the concept of the Matrix field type with a number of very useful features.

Neo solves one of the biggest issues people have with Matrix and adds Oreo features: no blocks within blocks. Sometimes you need this feature, other times you can get away without it.
Matrix

Built-into Craft CMS / first party support
Blocks use their "own" fields
No inception (child / nested / hierarchical) support (Matrix block within another)

Neo

3rd party plugin / extra license cost / another dependency in the stack
Uses existing Craft CMS fields
Can clone/copy/paste blocks
Blocks can be nested inside each other (inception style)
Blocks can be organized in groups / tabs / drop-downs for better authoring experience

Summary
Neo is like Craft's own Matrix field but a different and arguably more flexible take on it. However, it comes with all the risk/reward of using 3rd party plugins.
As an aside, after Craft 3 shipped, it took awhile for Neo to come over to Craft 3. I think this was partly to blame because Neo was offered as a free plugin for Craft 2 and with Craft 3's extensive changes, it's not surprising that the Craft 3 version of Neo is a paid version—3rd party developers have to eat too!
Alternatives
As an alternative to Neo, there's another plugin called Spoon which supplies some of Neo's organizational features and supercharges the built-in Matrix. That's a little bit more "future-proof"—so even if you decide to remove the plugin, your content will stay in place.
Using Super Table, you can get some of the inception level magic that Neo offers.
FWIW the plugin store allows you to try all of these plugins out on a dev instance and see for yourself which methodology you prefer.


Why are my profile pages not generating which I click on 'submit'? does anyone know what I am doing wrong here? I am trying to create profile pages for each user, but when I click the submit button, it doesn't take me to the user's page.

This is my form code:

<form method="get" accept-charset="UTF-8" class="form"    action="/profile/{{ user }}"> <input type="hidden" name="action" value="users/login">

<input id="loginName" type="text" name="loginName" placeholder="username"
    value="{{ craft.session.rememberedUsername }}">

<input id="password" type="password" name="password" placeholder="secret password">

<input type="submit" value="Login" class="login_enter">

    <input type="checkbox" name="rememberMe" value="1" checked>
    Remember me

{% if errorMessage is defined %}

{{ errorMessage }}

{% endif %}

I have a profile folder and an _profile template. I also added a custom route in the admin panel with the following URI

    profile/*

And a link to the template

    profile/_profile

The profile index file looks like this:

{% set users = craft.users %}
{% for user in users %}
{{ user }}
{% endfor %}

And the _profile file looks like this

{% extends "_account_register_layout" %}
{% set title = "account" %}
{% set user = craft.users.username( craft.request.segment(2) ).first() %}

Try setting the action and redirect as hidden inputs, see below:

<form method="post">
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="/profile/{{ currentUser.username }}">


ElementAPI: Error's out if entry doesn't have assets These keeps erroring out if any of the entries' do not have any assets in the 'listingPhotos' field. However, IF all entries have at least 1 photo in the 'listingsPhotos' field, it works.

The Error Message: Trying to get property of non-object

namespace Craft;

return [
    'endpoints' => [
        'trucks.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'trucks'],
            'paginate' => false,
            'transformer' => function(EntryModel $entry) {
                return [
                    'ID' => $entry->id,
                    'Year' => $entry->year,
                    'Manufacturer' => $entry->manufacturer,
                    'Model' => $entry->model,
                    'Category' => (string)$entry->category[0],
                    'Pics' => $entry->listingPhotos[0]->url,
                ];
            },
        ],
    ]
];

Why don't you just check if there is at least one photo? Something along the lines of

'transformer' => function(EntryModel $entry) {
    return [
        'ID' => $entry->id,
        'Year' => $entry->year,
        'Manufacturer' => $entry->manufacturer,
        'Model' => $entry->model,
        'Category' => (string)$entry->category[0],
        'Pics' => !empty($entry->listingPhotos) ? $entry->listingPhotos[0]->url : null,
    ];
}


Category structure with multiple groups I need only 2 main categories, A and B, and both can have unlimited subcategories. Ideal would be to split these into groups but how can an editor choose between groups AND only select or create a category?

I could setup a checkbox field which asks is this A or B but this then needs to be linked to the category groups and might make the template tags to call the data unnecessary complicated.

What's the craft-way todo this?

A rather sneaky solution to your issue could be to create a matrix field that has one block type per category group. Each of those block types then could contain a single category field with the category source set to the corresponding category group. Limit those category fields to 1 category each and then limit the matrix field to one matrix block.

This way your editors will be able to select only one of the matrix block types and that block type will limit the categories to the selected group.

If you need this for some custom markup wizardry in your templates, make sure you understand variable scoping in Twig loops if you're trying to set some variable value while looping through your matrix data.


Hiding Field on Parent Entry So, I'm building a portfolio site for a client, and I'd like to know if it's possible to hide fields on a parent entry. Essentially, I've created a structure for portfolio items, and they are all children of the main "Works" page. I've built a set of fields for each portfolio item, but I don't want those fields to show up on the parent entry, as they are unnecessary and therefore distracting. Is there a way I can do this?

Thanks in advance!

You can create two different Entry Types for your Structure section, and use one Entry Type for parent entries, and a different entry type for child entries. Entry Types have their own field layout, which makes it possible to have different fields for different kinds of entries, within the same Section. Then, it's simply a matter of selecting the right Entry Type when you create/edit your entries.

If that isn't dynamic enough (it isn't possible to assign entry types automatically based on whether an entry has children or not), you could possibly use the CP CSS plugin (perhaps in combination with the CP JS plugin) to hide the relevant fields for the parent entries.

I realize that neither of these solutionals are ideal – however, if you only have a single parent (i.e. "Works") for all your portfolio entries, I think a better approach would be to create a separate "Portfolio" Structure section limited to a single level, to hold all your portfolio entries. Set the URL format for this section to "works/{slug}". Under /templates/works you can add two templates, index.html and _entry.html. The former will render for the URL example.com/works and can be used for your portfolio section's listing page (i.e. it'd replace the current "Works" parent page), and the latter template's path (i.e. works/_entry) should be added to your portfolio section's Entry Template setting.

If you do need some fields for the listing page, you could create a Single called "Works" and set its URL Format and Entry Template path to just "works". A setup like this would circumvent your issue completely (and also avoid the problem with content editors getting your current solution wrong; adding new portfolio entries to the top level).


Call a Craft variable inside array I'm currently trying to call variables called {{entry.title}}, {{entry.latitude}} and so on in an array.

This is what it looks like:

{% set markerArray = [] %}
{% for entry in craft.entries.section('xSpots') %}
    {% set tempMarkerArray = [
    {'name':'{{entry.title}}','url':'{{entry.Url}}','lat':'{{entry.latitude}}','lng':'{{entry.longitude}}'}
    ] %}
    {% set markerArray = markerArray|merge(tempMarkerArray) %}
{% endfor %}

When calling {{markerArray[0].name}} afterwards I am expecting it to return the proper title of the entry in Craft, instead it only returns "{{entry.title}}", as if the variable is not properly recognized while filling the array.

Any help? Am I doing something fundamentally wrong?
Thanks in advance.

To output variables inside an array like that you'd simply omit the twig braces.. at the moment the ' are telling whatever is inside them to output as a string.

UPDATE: try adding parentheses around each variables like so

{'name':(entry.title),'url':(entry.Url),'lat':(entry.latitude),'lng':(entry.longitude)} ] %}


Channel not showing all items? We have a channel on the following page that shows 'Issues' of our magazine: http://ambitmagazine.co.uk/issues

We have issues going all the way back to issue 1, but the channel page currently only shows issues back as far as issue 32:
http://ambitmagazine.co.uk/issues/32 (displaying in the channel feed)
http://ambitmagazine.co.uk/issues/31 (not displaying but the URL returns the issue information, and no other settings are different in the backend).

Does anyone know why this page might not be showing everything? Thanks!

Set a limit of nulll on your entry query which means no limit. If you do not specify a limit, you will only see 100 entries.

.limit(null)


AJAX page transitions with history.pushState I'm a new craft user (previous EE user). trying to follow Zack Spear's directions (https://designbycosmic.com/journal/craft-cms-ajax-page-transitions-with-history-pushstate) for how to setup Ajax page transitions.

The final javascript example (the last code block) the new "loadPage" functions doesn't appears to have any line that actually loads the new content into $main. So when I implement the scripts as per those instructions, the fade in and out work, but the content that fades in is the same content from the previous page rather than the new content that should have replaced it.

Sorry if I'm being thick here, as I don't have a lot of Ajax experience. What do I need to add to the loadPage function to get this to work?

So I just went through my article step-by-step and I indeed missed adding the new content into $main. I think there may have been a versioning mistake in the article's code as I definitely tested it.

Anyways, here's an updated loadPage function for you. Which I will be adding to the article tomorrow. I've added a few extra things to ensure that there's no content (like the footer if you include it in layout.twig) jumping when the content switches out, so feel free to modify that.

loadPage = function(href) {

  $main.wrapInner('
');

  /* ----- Get height of new container inside results container and to ensure the footer doesn't jump up -----  */
  var newResultsHeight = $('.new-results-div').outerHeight();
  $main.height(newResultsHeight);

  $('.js-ajax-wrapper').velocity('transition.fadeOut', {
    /* ----- Upon completion of animating out content put user at top of page. ----- */
    complete: function(){
      $('html').velocity("scroll", {
        duration: 0,
        easing: "ease",
        mobileHA: false
      });
    }
  });

  $.ajax({
    type: 'POST',
    url: href,
    data: {},
    success: function(result){
      /* ----- HERE'S WERE THE CONTENT GET'S ADDED ----- */
      $main.html(result);

      /* ----- Wrap content in div so we can get it's height ----- */
      $main.wrapInner('
');

      /* ----- Get height of new container inside results container and set $main to it so there's no content jumpage -----  */
      var newResultsHeight = $('.new-results-div').outerHeight();
      $main.height(newResultsHeight);

      /* ----- Bring In New Content ----- */
      $('.js-main .js-ajax-wrapper').velocity('transition.fadeIn', {
        visibility: 'visible',
        complete: function() {
          /* ----- Removes the temp height from $main ----- */
          $main.css('height', '');
          ajaxLoad();
        }
      });
    },
    error: function(){
      console.log("error.");
      location.reload();
    }
  });

};

Apologize for any trouble due to the missing code. Feel free to let me know if you have any other questions.


Does Craft have an installer error log I can check? I've tried to install Craft on a variety of systems, and it seems that no matter what I try, I cannot get all the way through the installation process. In most cases, my install hangs on the "Oops" screen.

I've learned not to trust this screen, because if I immediately close the window and cancel my installation, the installer screen continues to show up when trying to access the admin login /admin/.

Instead, if I just let it sit for a few minutes then close the screen, it seems like the install actually works as expected. Visiting /admin/ in my browser has the desired affect, and I'm able to use the CMS as expected.

My thought is that it might be something related to the install cleanup process - but I'd like to take a peek at the install log file to see exactly where things went wrong.

I've checked system requirements, although on some systems, I'm unable to personally verify all of the requirements are met. But I'd like to know why I got that "Oops" screen. It's obviously a non-critical error, or else the db and system would not function properly - which it does.

Typically the Craft logs are stored here:

/craft/storage/runtime/logs

I don't know how much logging the installer does, but if it does any at all, that's where you'll find the log data.

In the meantime, you can also try this script by Ben Croker which will check your server configuration to make sure it has everything it needs to proceed.


How do I resolve dependency conflicts in Composer? I'm new to using Composer and I'm having trouble deploying to Laravel Forge. I am getting an error message that says:

  Your requirements could not be resolved to an installable set of packages.

  Problem 1
      - Installation request for illuminate/support v5.5.44 -> satisfiable by illuminate/support[v5.5.44].
      - don't install tightenco/collect v5.5.33|don't install illuminate/support v5.5.44
      - Installation request for tightenco/collect v5.5.33 -> satisfiable by tightenco/collect[v5.5.33].

I didn't add these packages, they are dependencies of something I have added. So I have a few questions:

First, how do I resolve this? I am thinking that I should not go in and try to change the version numbers on anything because that would break things most likely, correct? Also, since they are not in my composer.json file, I'm not sure how I would do this.

Second, how do I determine what package I am installing uses this as a dependency?

Third, I have a couple of plugins that I have uninstalled in the CP that are still showing up in the composer.json file.Do I need to go back into my composer.json file and remove them? I thought this was done automatically when a plugin was uninstalled, but that may be my mistake. I am wondering if one or more of those plugins might be the culprit.

Thanks,

Brian

I was able to take your composer.json file, run composer update from it without any issues, do an install of Craft from that and update Craft/plugins and install/uninstall Craft/plugins from the Control Panel without any issues.

symfony/yaml v4.1.0 requires php ^7.1.3 -> your PHP version (7.2.14-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.0) does not satisfy that requirement.

For that one, you've got this in your composer.json file:

  "config": {
    "sort-packages": true,
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },

Change it to this:

  "config": {
    "sort-packages": true,
    "optimize-autoloader": true,
    "platform": {
      "php": "7.2.14"
    }
  },

And it will go away.


Conditionally Applying CSS to Element on Active Page Without Using URL or ID Logic I want to conditionally add some CSS to a subnav element if that page in the subnav is currently active. However, I can't add the CSS based on any slug / URL / getSegment logic, as that will likely be changed down the road. I also can't use the ID of the page.

The pages in this subnav are part of the same structure and it seems to me the best way to set the rule would be based on the order of the page in the structure. Something like if page 2 in craft.entries.section('') is active then apply CSS to target element.

Is this possible in Craft? If so, how would I do that? If not, other ideas for how to approach it?

The craft_structureelements table contains the data you need to determine the exact position & level of each entry in your structure. But you'd need some fancy plugin logic to attack that data and use it to your advantage.

In all honesty, I really feel like you're going the wrong way on this, and you're better served trying to find a way to make the slug or id work for you. The sole purpose of a slug is to identify a specific page.

How about this...

When you dynamically generate your nav, add a CSS class with slug of that nav item. Then, you can verify that against the slug of the page which is being loaded. Even if the slug changes, it'll change in both places simultaneously.


Navigating through entries within a category when they belong to multiple I need some advise on the best way to achieve this.

I have entries within a section which could belong to category A, B, C, D. Any of these entries could also belong to a Featured category.

Each category has it's own page, and from an entry you can go to the next or previous entry (within that category).

I can't see how I can do this for the Featured entries as they also belong to another category.

I'm thinking I'll have to do something with the URLs so the entry knows its been clicked on from the 'Featured' category page rather than 'B' so the Previous and Next buttons stay within 'Featured'.

This is my Next and Previous buttons code on the entry template:

{% set params = craft.entries.section('galleries').relatedTo(categories.galleries) %}
{% set nextEntry = entry.getNext(params) %}
{% set prevEntry = entry.getPrev(params) %}

    {% if prevEntry %}Prev |{% endif %}

    {% if nextEntry %}Next
    {% else %}
        Next
    {% endif %}

I think you are on the right track, in that you will likely need to create a separate route for the entries when they are 'featured', so that you can configure the nav properly in the template. I can think of a few ways to do this (and I'm sure there are more).

Add a custom route, adding a '/featured/' segment to the uri. Then in the entries template test for the segment, and modify the entries ('params') and the nav accordingly.

{% set isFeatured = (craft.request.getSegment(2) == 'featured') ? true : false %}
{% if isFeatured %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.featured) %}
    {% nextUrl = siteUrl ~ '/featured/' ~ entry.getNext(params).slug %}
    {% prevUrl = siteUrl ~ '/featured/' ~ entry.getPrev(params).slug %}
{% else %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.galleries) %}
    {% nextUrl = entry.getNext(params).url %}
    {% prevUrl = entry.getPrev(params).url %}
{% endif %}

Add a parameter to the uri (i.e. ?v=featured and test for the parameter in the template. Then pass the parameter on in the navigation.

{% set isFeatured = (craft.request.getParam('v') == 'featured') ? true : false %}
{% if isFeatured %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.featured) %}
    {% nextUrl = entry.getNext(params).url ~ '?v=featured' %}
    {% prevUrl = entry.getPrev(params).url ~ '?v=featured' %}
{% else %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.galleries) %}
    {% nextUrl = entry.getNext(params).url %}
    {% prevUrl = entry.getNext(params).url %}
{% endif %}

Abstract the relationship by creating a new 'featured' entries channel, with an entries field that links to the actual entry. Then the 'featured' category can link to the 'featured' entries (which are subsequently linked to the real entries). The featured template can then just include the normal entry with a variable isFeatured=true or something.

// In 'featured' entry template
{% include 'mychannel/_entry' with { entry: entry.myEntriesField, isFeatured: true } only %}

// In native entries template
{% if isFeatured %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.featured) %}
{% else %}
    {% set params = craft.entries.section('galleries').relatedTo(categories.galleries) %}
{% endif %}

I'm sure there are more but one those might work.


P&T Contact Form plugin : how can I dynamically add multiple email recipients inside the form config file? I don't want to show up the email recipients in the source code using this :

<input type="hidden" name="toEmail" value="{{ 'me@example.com,me2@example.com'|hash }}">

I want to manage multiple emails dynamically from the contactform.php config file in my craft/config folder.

<?php

return array(
    'toEmail' => (hash('firstemail@domain.com, secondemail@domain.com') ?: null),
);

This config file is not working and don't override the plugin settings in the CP. What would be the best way to achieve this ?

[UPDATE]

I ended to this, but while it is working fine in the front end, this is causing PHP errors in the CP :

<?php

return array(
    'toEmail'  => array(
        ('firstemail@domain.com' ?: null),
        ('secondemail@domain.com' ?: null)
     )
);

This is how to achieve this :

<?php

return array(
    'toEmail' => ('firstemail@domain.com,secondemail@domain.com' ?: null),
);


What's the best way to set up a content-manageable 404 page? I'd like to make my 404 page editable through Craft, but when I create a single for it, a URI is required.

Is there a way to make a single with no URI, or is the best route to setup globals for managing this content? Or is there a better way that I don't know about?

I would create a Single with the URI set to "404", and also set its Template to "404". That entry will automatically get loaded if you go to http://example.com/404, and load your 404.html template, so at the top of the template you should add this to it:

{#
 #  Fetch the 404 Single entry, if we don’t already have it.
 #  (requests to /404 will already have it.)
 #}
{% if entry is not defined %}
    {% set entry = craft.entries.uri('404').first() %}
{% endif %}

Craft 3 note: As of Craft 3 the 404.html template is only loaded if devMode is disabled in the current environment. If devMode is enabled, you'll continue get a Yii error message.


Automatically create users from http header Bit of an awkward one.

The client wants a system where they send us a link e.g. mycraftsite.com?userid=abc123 and from there we need to populate the user table.

I am new to craft but I am assuming the correct way is to use a plugin, grab the header data and somehow insert it using a hook, but I don't see any available for before the site renders.

Can anyone help point me in the right direction?

You would most likely want to add a controller to your custom plugin, with an 'action' method designed to handle the url request and generate a user; using 'post' or 'get' to pass parameters to the controller action.

In the controller action, you can access your parameters using:

$username = craft()->request->getParam('username');

You can then populate a new User Model using the passed params and save the model.

$user = new UserModel();

$user->username   = $username;
$user->email      = $email;
$user->firstName  = $firstName;
$user->lastName   = $lastName;
$user->getContent()->setAttributes([
    'customField' => $customFieldValue
]);

craft()->users->saveUser($user);

// We now have a user Id, so assign user to a group
craft()->userGroups->assignUserToGroups($user->id, $groupId);

// or to multiple groups
//craft()->userGroups->assignUserToGroups($user->id, [$groupId, $otherGroupId]);

However, by default, controller actions are only accessible to logged-in users. If you want to allow anonymous access you would need to specifically allow it using the $allowAnonymous property. This definitely introduces some security issues however, so proceed with caution. For example: definitely do not just assign user group(s) blindly from passed parameters or someone might be able to give themselves admin access!


Display field content inside a matrix from a different locale I am building a site with 2 different languages - English and Chinese. Is it possible to retrieve only one field inside a matrix in English while I am in Chinese site? But the rest of the matrix fields, I want them to be kept in Chinese.
Below is an example snippet from retrieving the field inside the matrix. Is it possible to force translate it directly to English regardless of the current locale the site is in?
{{ globalMatrixTable.globalPresenceItem }}

You should be able to query a global set in a different site:
{% set englishMatrixTable = craft.globalSets()
    .handle('globalMatrixTable')
    .site('yourEnglishSiteHandle')
    .one() %}

{{ englishMatrixTable.globalPresenceItem }}


Element Type: Edit Page fields I'm currently working on creating a full-sized Edit Page for my own Element Type.

I created a elementSelectField and wanted to know if you guys have some advise or good articles to read on that matter. Right now I'm crawling my way through the craft code for reverence and i am not sure if I'm doing this correctly :)

{% set section = craft.app.sections.getSectionByHandle('days') %}
{% set elementType = craft.app.elements.getElementTypeByRefHandle('Entry') %}

{{ forms.elementSelectField({
        label: 'Day'|t('app'),
        instructions: 'The day the cookie belongs to'|t('app'),
        id: 'day',
        name: 'day',
        elementType: elementType,
        selectionLabel: "Choose a day"|t('app'),
        sources: ['section:'~section.id],
        criteria: '',
        elements: elementType,
        viewMode: 'list',
        limit: 1,
    })
}}

I think this is Ok? Sending the form to my controller and dumping it there, the selectfield's value array contains only the choosen entry's id.

Yes this is correct. The best documentation you can find is the source code, so looking at it is usually the way to go. Craft stores all relations with an array of element ids.

When you have a BaseRelationField in your elements field layout you'll store the value - even if it's a single value - like

$element->setFieldValue('day', [1]); //<- note, always pass an array

(or the faster variant)

$fieldsLocation = Craft::$app->getRequest()->getParam('fieldsLocation', 'fields');
$element->setFieldValuesFromRequest($fieldsLocation);

If you don't use a field layout and store your relations in a custom table/column you'll have to find a way that fits your requirements


Get categories ordered by the associated entries' postDate I'm looking to show recent categories ordered by their associated entries' postDate.

Is this possible?

I don't want to list the entries within the category
I simply want to list 4 categories that have recently updated related entries.
Entries from any section can be associated to my site's global categories.

You could technically do this with a lot of custom SQL, but it would be messy. I think your best bet would be to create a custom Date field on your categories called “Last Used”, and then to write a module that keeps its value updated as entries are saved.

The default Craft 3 project comes with a module file out of the box, so you can use that as a starting point.

First, add this to the top of the module file, after the namespace line:

use Craft;
use craft\elements\Category;
use craft\elements\Entry;
use craft\events\ModelEvent;
use yii\base\Event;

Then in its init() method, add this after the parent::init() line:

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

    if ($entry->enabled) {
        // Loop through the related categories
        foreach ($entry->myCategoriesField as $category) {
            /** @var Category $category */
            // Is this entry's post date more recent than the current Last Used value?
            if ($entry->postDate > $category->lastUsed) {
                $category->setFieldValue('lastUsed', $entry->postDate);
                Craft::$app->elements->saveElement($category, false);
            }
        }
    }
});

You can get Craft to re-save all of your entries by re-saving each of your sections’ settings. (You don’t need to change anything.)

With that in place, you can start sorting by that custom field in your templates.

{% set categories = craft.categories()
    .group('myCategoryGroup')
    .lastUsed('not :empty:')
    .orderBy('lastUsed desc')
    .limit(4)
    .all() %}


Is there an easy way to reset user permissions back to usergroup settings? Is it a matter of clearing the userpermissions_users table?

Background: After initial authoring, we've cleaned up permissions for our usergroups, but the existing users have accumulated manually-added permissions as sections got added.  Would be nice to be able to blanket-remove all the custom permissions.
(Also, "Deselect All" in the User Settings' Permissions tab is doing a select-all instead.)
Thanks.

I found that turning on Admin (and saving) and then turning it off will reset the user's permissions to their group defaults.  It's not the fastest, but faster than going through all the checkboxes.


Is there a way to generate a url to an image in the craft/storage/myplugin directory? I am generating dynamic images to a directory in craft/storage. I need to be able to use these generated images on the front-end inside templates. Is there a helper method for this, or some way to use these images in my templates?

Since craft/storage/ is not publicly accessible, your only real option here is to serve them through Craft as Resource Requests. (This is the vehicle through which Craft serves up all of the CP’s front end resources, which live in craft/app/resources/.)

The actual resource URLs will depend on the site’s resourceTrigger config setting, so to generate the URLs you should use URLHelper::getResourceUrl():

$url = UrlHelper::getResourceUrl('myplugin/some/path.jpg');

Your templates can call the corresponding resourceUrl() function as well:

{{ resourceUrl('myplugin/some/path') }}

Then you will need to add a getResourcePath hook method to your primary plugin class, which would detect incoming resource requests and resolve them to the actual server path in craft/storage/.

public function getResourcePath($path)
{
    // Does this path start with "myplugin/"?
    if (strncmp($path, 'myplugin/', 9) == 0)
    {
        // Return the path to the file in craft/storage/
        return craft()->path->getStoragePath().'myplugin/'.substr($path, 9);
    }
}

It’s worth mentioning that you’re always going to get worse performance out of serving files through PHP than you would if they were located somewhere that’s publicly accessible. So you might just want to have the user create a new folder somewhere under their web root, and have them specify the path/URL to that folder, just like local asset sources.


Add a field to a global set is there a way to add a field to a global set by code ? I figured out how to create a global:

$global = new GlobalSetModel();
$global->name = 'GlobalName';
$global->handle = 'globalHandle';
craft()->globals->saveSet($global)

But I can't figure out how to add a field to this newly create global.

See here for how to add a field to a user's field layout.

Users, Globals, Tags, Categories, etc. are all elements in Craft so they behave very similarly.

You can also check out Craft's own InstallService's private _createDefaultContent() method for examples on how Craft creates the default content on a fresh install of Craft.


Craft not generating language links correctly {{siteUrl}}, {{category.url}}, {{product.url}}, etc. is not outputting any language.

The main language is Norwegian. I created a folder for English (/en/) with define('CRAFT_LOCALE', 'en_us');

Navigating to site.com/en works fine, and all the english content shows as expected. However any link generated by craft simply omits "/en/", thus throwing me back to Norwegian. I don't get it.

Anything in particular I should look into? Thanks a lot!

In a multilingual site, your siteUrl config setting in /craft/config/general.php needs to be an array where the keys correspond to your installed locales:

return array(
    // ...
    'siteUrl' => array(
        'no' => 'http://example.com/',
        'en_us' => 'http://example.com/en/',
    ),
);


Hiding my plugin table columns for mobile My custom plugin uses a table to display each of my results, works as intended. However, on the mobile device the table does not layout properly as the table has 6 columns.

I know this is a rather simple task that can be handled with media queries, but is there a way to use the native CSS/tools that craft provides?

I have never used it, but there is a method craft.request.isMobileBrowser().

{% if not craft.request.isMobileBrowser() %}
    non-mobile browser column
{% endif %}

or even better, you could give that column a class, and then include a mobile css file to layout the table for mobile:

{% if not craft.request.isMobileBrowser() %}
   {% includeCssFile "/assets/css/mobile.css" %}
{% endif %}


Parse a line of Markdown, without Is there a way to parse a line of Markdown within Twig – without the surrounding
<p> tags?

I see there is a StringHelper method called ParseMarkdownLine that does exactly what I'd like, but I haven't found a way to invoke it in my templates.

Have a look at the Parsedown plugin by P&T, it provides a line mode to not output any wrapping <p> tags.

{{ entry.title|parsedown('line') }}


When onAfterElementSave is called check for save as draft or publishing? Is there a way to detect if a entry is being saved as a draft vs being published so when onAfterElementSave is called, so I don't save data to the database when it is a draft.

Actually, onAfterElementSave doesn't get called at all when saving a draft, so there's nothing to worry about.

When you load a draft in the CP, your field type will be passed in a $value based on the POST data for the field back when the draft was last saved (which is the same thing that happens when saving an entry fails due to validation errors).