Composer require looking to craft/plugins/[plugin] directory but throws runtime error? I've got Craft 3.1.32 up and running on dev machines and we're ready to get it into our test/stage enviromnments, which are built through a GitLab CI/CD. While doing this, we noticed some plugins wouldn't install and would throw a composer error:

  [RuntimeException]
  craft/plugins/[plugin-name]/ does not exist and could not be created.

Now, craft/plugins is the Craft 2 location for plugins, and that directory doesn't exist in Craft 3, right? I see there's a file that gets created called /vendor/composer/installers/src/Composer/Installers/CraftInstaller.php that has a reference to craft/plugins/{$name} so I'm guessing that this file is being invoked to do some quick stuff to clean  the plugin name. But I'm not sure what the directory is really doing.

Any ideas?

EDIT:
It looks like there's a nice file within the composer/composer repo that dates back to Craft 2: See CraftInstaller.php in GitHub that is pointing at old directories

I found the real root cause. A internal business plugin which I migrated from Craft 2 to Craft 3 had a composer.json file which required composer/installers and that little bugger was mucking up the whole thing.
So if you find that in your composer.lock file for Craft 3, go in deep and find it!


See the SQL query that gets executed when saving entry I'm creating a pretty specific entry with some fields. And I want to create the from a third party app. For that, I'd like to see the SQL query that get executed.

I've tried it with events, entries.onBeforeSaveEntryand content.saveContent but I cannot get the query itself.

If you add the devMode setting to your config, you should then be able to view the Javascript Console in your browser to see the SQL Queries being run.

In particular you're looking for the Profiling Summary Report.

Also, you can view the Craft Logs at /admin/utils/logs, when you are logged into the Control Panel.


Remove related / suggested videos from the end of an embedded YouTube video I'm using the Dukt Videos plugin v1.2.5 on Craft v2.7.2. Is there a way to control or remove the video suggestions that are displayed once my video has played through to the end. Or perhaps have the video restart once it reaches the end ?

This answer isn't specific to the Dukt plugin, but I was going to suggest that passing in the parameter of rel with a value of0 would be the solution. Looking at the docs for YouTube embed shows this is no longer good as of Sept 25, 2018 though:

https://developers.google.com/youtube/player_parameters#rel

Basically, you used to be able to shut off related videos, but YouTube has removed that ability. You're stuck with them if you choose to use YouTube as your video provider.

  After the change [made on Sept 25, 2018], you will not be able to disable related videos. Instead, if the rel parameter is set to 0, related videos will come from the same channel as the video that was just played.


URL structure for structure section This seems like it should be straight forward. I need to set-up a structure section  with a parent page which uses the same section entry and same template. So the parent would have 'parent' as the slug and the children would have 'parent' as the first segment of the URL ie parent/children. Under the site settings in the section page I can include 'parent' before the slug, but this means the parent page gets the URL parent/parent. How do I get the parent page to keep the URL parent/?

If you do this:

{parent.uri}/{slug}

You should get URLs like this:

site.com/parent
site.com/parent/child-1
site.com/parent/child-2

Does that make sense?


Can I make the front-end entry form send an email to a user group? I've used the front-end entry form in the docs to build a Q&A portal, and it's working great. But I'd like to extend the functionality once the new entry is saved.

I've set the entries up to not be enabled when saved so that a moderation team can later approve them. Is there a way for members of the moderator user group to receive an email every time someone publishes a new question via the front-end form?

You can write a simple plugin that listens for the onSaveEntry event.

When that event fires, you plugin could check the $isNewEntry param to make sure it's a new entry being saved and also check the entry's section to make sure it's the front-end section you're expecting and might as well check craft()->request->isSiteRequest() to make sure it's a front-end request.

If all of those match, you would get the users in a group, then loop through all of them sending an email with craft()->email->sendEmail() for each user.

Something like (pseudocode):

$element = craft()->elements->getElementType(ElementType::Users);
$element->group = 'groupHandle';
$users = $element->find();

foreach ($users as $user)
{
    // compose email body, header, etc.
    $success = craft()->email->sendEmail($email, $variables);
}


How to save a matrix content of a new entry in my plugin? I have a section of type channel with a matrix field. I want to know how I would save the matrix content while I save the entry as well. I know I can save the entry as follows:

    $entry = new EntryModel();
    $content = array('productName' => $data[0]['Product'][0], 'productQuantities' => $data[0]['Product'][1]);
    $entry->sectionId = 10;
    $entry->typeId = 10;
    $entry->postDate   = date('Y-m-d');
    $entry->authorId   = 1;

    $result = $entry->setContentFromPost($content);

    $entry->getContent()->title = "Fancy Title";

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

The content variable above stores the content matrix block for this entry should have. So the Matrix has two fields within it one is of entry type and the other is numerical. I want to set these two fields before "craft()->entries->saveEntry($entry);". Please someone tell me how this is possible. I know for the entries type field I have to create a relation but please help me by letting me know how to do that as well as how to create this new matrix block containing that relation etc.

Ok there are two parts to this question - how to save relationships and how to save matrix blocks whilst saving an entry.

How to save relationships

To deal with the first, it is my understanding that the entries need to exist first so you may need to create them if they aren't already. Then all you need to do is pass an array of entry ids to the relevant field:

$entry->getContent()->entriesField = $targetEntryIds;

How to save matrix blocks whilst saving an entry

Bryan is correct in that you can create and save blocks all by themselves, however if all you want to do is add some blocks to a new entry then the following setup will work just fine:

$matrixData = array();

$matrixData['new1'] = array(
  'type' => 'blockType',
  'enabled' => true,
  'fields' => array(
    'fieldOne' => 'Some string or data',
    'fieldTwo' => '12'
  )
);

// You can repeat this part for each block you want to add, just increment the newN number.
$matrixData['new2'] = array(
  'type' => 'blockType',
  'enabled' => true,
  'fields' => array(
    'fieldOne' => 'Some more text',
    'fieldTwo' => '16'
  )
);

// set matrix field to contain those blocks before saving the entry
$entry->setContentFromPost(array('matrixField' => $matrixData));

This gist from Brandon explains all on the Matrix front, I am merely repeating most of it here for your benefit.

Best of luck!


Front-end link to Clear Cache? I currently implemented a fixed position edit button in the front-end when a user is logged in based on this " Get Entry Edit Link in Twig " Is there a version of this link, but to Clear Cache?

Please read this to get to know how to create a basic ajax request

And change the route to

action: 'utilities/clear-caches-perform-action',
caches: '*'


Multiple dropdown filters interfering with each other I have a multiple dropdown filters that lets users pick the category that they want to display results for below. See my previous question Search entries by location or name for screenshot.

So I have one working, but I need some guidance on how to do the code for the other filters as well, as currently my code for linking up to the second filter is stopping the first filter from working correctly. So clearly I'm doing it wrong.

So I have four dropdown filters, but I'll simplify it to two filters for this example. The filters are named name="county1" and name="development1" in their respective  tags.

And then I'm using the following to access them:

{% set query = craft.request.getParam('county1') %}
{% set query = craft.request.getParam('development1') %}
{% set queryFilter = craft.categories.group('developments').search(query).order('title asc') %}

{% for category in queryFilter %}

....markup...

{% endfor %}

Can someone tell me what i need to do to fix this so that the filters don't interfere with each other?

If your goal is to filter by one drop-down value at a time then you could use an if statement to check if the passed value is set for each drop-down.  This will only work if each drop-down has an option that is blank or it submits on select so that the other drop-down is not set.

{% set query = "" %}
{% if craft.request.getParam('country1') and
      craft.request.getParam('country1') is not empty %}
    {% set query = craft.request.getParam('country1') %}
{% elseif craft.request.getParam('development1') and
          craft.request.getParam('development1') is not empty %}
    {% set query = craft.request.getParam('development1') %}
{% endif %}

{% for category in queryFilter %}

....markup...

{% endfor %}


How to automatically redirect a url based on dynamic content We have a some conditional logic for a dashboard style setup. We have urls like :

neptune/{id}/details
neptune/{id}/options
neptune/{id}/confirm

etc..

The actual urls accessible depend on the status of the elements in question, and the whole process has a flow setup - the user has to go through each part in turn, ie. details > options > confirm, however they can go back and revise and drop out entirely and pick up where they left off later.

This all works fine, but to smooth out things we'd ideally have a way to automatically force a redirect from a urls based on the current state. If this were ExpressionEngine we'd have a tag like :

{redirect="neptune/{id}/confirm"}

What's the equivalent Craft/Twig setup? Or is there an alternative better setup.

Note : this isn't for the main flow of the user, only needed for the actual edge cases where a user may revisit (ie. manually) an out of flow url somehow, so isn't related to the core logic.

Take a look at Craft's redirect function:

{% redirect '/' %}

In your case it would look like this:

{% redirect 'neptune/' ~ id ~ '/confirm' %}


Not showing the entry somewhere else on the same page In the footer there is a column showing the images of the most recent entries. How do you prevent the image from the main entry itself to be shown?

Do you test an url segment against the title or slug?

This cannot be too complicated, but I am not able to find an example to get me started.

Added Code (thank you Robin)

{% set recents = craft.entries.section('sectionName').id('not ' ~ entry.id).all() %}
{% for entry in recents %}

{% endfor %}

One more question:
How do you limited the output using the elementCriteriaModel? Invoking Limit(x) on the array is not possible.

You can exclude the current entry from your query

{% recents = craft.entries.id('not ' ~ entry.id).find() %}


Live Preview only works for Entry variable? Is there an undocumented shortcoming of Live Preview? Seems to only work where the entry variable is concerned.

I'm using a Structure section to create pages with "Chapters". The section (let's call it Areas) has a Max Level of 2. The idea is that level 1 entries  load a template that calls the content from all of that entry's children.

For instance, Areas looks like this in the CP:

Learning
-- Our Approach
-- Design Patterns
-- etc.

The front-end works just fine. /areas/learning loads the areas/_entry template where I call all of the entry's children and output their content to the page.

The issue is in Live Preview when editing a child entry, such as Our Approach. It looks like Live Preview only likes using the provided entry variable, but will not update anything nested, found in a loop, or otherwise loaded into the template's context.

For instance, this simplified template code, while rendering as expected, does not update in Live Preview:

{% if craft.request.isLivePreview %}
    {% set myEntry = craft.entries.slug(craft.request.getSegment(2)).first() %}
{% endif %}

{% set chapters = myEntry.children %}

{{ myEntry }}

{% for chapter in chapters %}

{{chapter}}

{% endfor %}

I renamed the entry variable as per this answer. Thoughts?

We just changed this behavior in Craft 2.3.2616:

  Live Preview and Share links will now show the unpublished entry/category changes wherever the entry/category are being referenced in the templates (even areas where the entry/category was fetched from the database).

So now Live Preview (and Share links) should work as expected for you.


Specify template directory in config Is there a way to specify a different template directory from the general config?

Not in the config file, but you can from index.php using the CRAFT_TEMPLATES_PATH constant:

define('CRAFT_TEMPLATES_PATH', '../templates/');


How can I display second level children only from a specific parent structure item? I'm trying to display a list of child structure links, but only from a specific parent. The template I'm working on isn't for the parent in question so I don't think I can use 'entry.'

My structure is set up like this

Parent 1
--Child One
--Child Two
--Child Three
Parent 2
--Child One
--Child Two

I only want to display the children of Parent 1. What I have so far is

{% set pages = craft.entries.section('visit').level('>1') %}
{% nav entry in pages %}

{{ entry.title }}
    {% ifchildren %}

           {% children %}

     {% endifchildren %}

{% endnav %}

Using this outputs all of the second level children instead of just the children from Parent 1. Is there any way to specify that the only children I want to display must come from Parent 1? Can I specify a slug somehow?

Any help much appreciated

yes you can!

You may search for a slug craft.entries.slug('slug-of-first-parent'), select the first result .one(), and then the children by .getChildren(). Now you can proceed as you already did and limit your result to only elements with a level greater than 1 .level('>1') and list.

{% set pages = craft.entries.slug('slug-of-first-parent').one().getChildren().level('>1') %}

I am not sure whether this is the best and most effective solution, but it should definitely do the job.

Tip: You can display information about an entry and the methods and variables available by dumping them either by using var_dump($variable) in php code or {{ d($variable) }} (by using this free plugin) in your twig template. This can help a lot when dealing with entries and finding children or parents.


Sensible way to have different number of entries on page one of pagination? I have a blog where page one has a big "feature" thumbnail and after that each subsequent thumbnail is half the size.
I want that to only happen on page one, which i have done using:

{% if paginate.currentPage == 1 and loop.index == 1 %}

That works perfectly fine.

The problem is that because of this design choice, page one shows 13 entries, but page two onward needs to show 12, otherwise it will look wonky! Any ideas on how i could achieve this?

There's an offset parameter that allows you to skip the first entries from your ElementCriteriaModel.

You would set up two nearly identical ElementCriteriaModels, one exclusivly for your featured entry, using the first() method to only query for the first entry, and to the second one you'd add offset(1) as a parameter, to get all the other entries for your pagination.

{% set params = { section: 'blog' } %}

{# Get the featured entry #}
{% set featuredEntry = craft.entries(params).first() %}

{# Get all the other entries #}
{% set entries = craft.entries(params).offset(1).limit(10) %}

{% paginate entries as entriesOnPage %}

    {# Show featured entry on page one #}
    {% if paginate.currentPage == 1 %}

    {% endif %}

    {% for entry in entriesOnPage %}

    {% endfor %}

{% endpaginate %}


Filtering entries by multiple categories with multiple filters I'm trying to build a category filter on a page that lists houses that are for sale. The idea of the filter is to make it possible to select houses which, for example, are for sale or rent, have a certain amount of rooms, a minimum/maximum price and eventually a search option to search at location, postal code or street address.

I first built one filter, which filters if a house is for sale or for rent. This filter works with two anchor buttons in a list. I now want to add the next filter, which is the amount of rooms. This filter should be a dropdown (a select tag with options in it).

I got both filters to work, but I want them to stack upon each other. So when the houses that are for sale are being shown and the user clicks on houses with 4+ rooms, it shows the houses that are for sale AND have 4+ rooms.

What I came up with so far

The filter for sale/rent houses

 {% for offerCategory in craft.categories.group('offerTypes').find() %}

   {{ offerCategory.title }}

 {% endfor %}

The filter for the amount of rooms

<select onChange="window.location.href=this.value">
 {% for offerRooms in craft.categories.group('offerRoomTypes').find() %}
  <option value="{{craft.request.url}}/?category={{ offerRooms.slug }}" name>{{ offerRooms.title }}</option>
 {% endfor %}
</select>

And the rest

{% if craft.request.getParam('category') is not null %}

 {% set offerCategory = craft.categories.slug(craft.request.getParam('category')) %}
 {% set offerRooms = craft.categories.slug(craft.request.getParam('category')) %}

 {% set offers = craft.entries({
    section: 'offers',
    relatedTo: [
        'and',
        { targetElement: offerCategory },
        { targetElement: offerRooms }
    ]
 }) %}

{% else %}

 {% set offers = craft.entries.section('offers').find() %}

{% endif %}

The URL that's being fetched is now: .../?category=forsale and when selecting rooms .../?category=4rooms. What I want to achieve is something like .../?category=forsale,4rooms (I'm nog sure if that's the right way).
If someone also can tell me directly how the search should be implemented that's welcome as well ;). Thanks in advance!

Passing the category as a comma delineated string and using craft.request.getParam('category') the second time will not grab the second variable 4rooms.  First you need to parse that string into an array. This will create an array ['forsale','4rooms']. Use the parts of that array to assign to your other variables.

{% set params = craft.request.getParam('category')|split(',') %}
{% set offerCategory = craft.categories.slug(params[0]) %}
{% set offerRooms = craft.categories.slug(params[1]) %}


Loop through both category group and tag group in single loop Is is possible to loop through both a category group and tag group in a for loop?

Categories: blue, red, orange
Tags: basketball

Loop displays: basketball, blue, orange, red.

Something like this may work for you (untested).

{% set categories = craft.categories.group('myCategoryGroup').find %}
{% set tags = craft.tags.group('myTagGroup').find %}
{% set elements = categories|merge(tags) %}

    {% for element in elements %}

{{ element.title }}

    {% endfor %}

Sorting them alphabetically is a little more difficult. For that you may want to try twig's sort filter or, failing that, the supersort or craft-twig-better-sort plugins.


Plugin for entries table field In Craft we have the table field type and each column can have a type. This field type is restricted to only text, number and checkboxes. Is there a plugin to add entries field type to the column types?

And if there isn't, can someone guide me to the proper files which I should look into to modify and add the field types myself by making a new plugin.

This question is from a long time ago, but nowadays there's a great 3rd-party plugin that lets you do this: https://github.com/engram-design/SuperTable


Three duplicated guest entries posted on form submision I was doing some design tweaks to the form today, barely touched coding parts and than I went for a test run to see if it submits an entry.
Everything run as it was on the front end except on the back end I got 3 same entries created with ascending IDs every time an entry is posted.

I was going through and through the form for hours, but ... aaargh!

If anyone has a theory of the issue without seeing the code, post it here please. Otherwise I will submit the code. It's extensive thought.

The site is running through CodeKit compiler connected to MAMP server. This was odd because it has never happened before with same configurations but When I run the site directly from MAMP server the problem disappeared.

But I have no idea why compiler was causing that.


Remove the anchor in nav loop based on another field conditional I'm using this solution to output the children within a current structure entry.  Unfortunately I need to take out the anchor on some entries that don't yet have content, but still include the (unlinked) title.

I'm trying the following

{% nav page in subnav  %}
  {% if page.id != entry.id %}

{% if page.pageIntroText|length %}{%endif%}{{ page.title }}{% if page.pageIntroText|length %}{%endif%}

  {%else%}

{{ page.title }}
{%endif%}
{% endnav %}

.. but it removes the anchor regardless of whether there is any content in pageIntroText field?

Any ideas?

Many thanks

Martin

Instead of using {% if page.pageIntroText|length %} have you tried

{% if page.pageIntroText is not empty %}


How to override the Craft forgot password email Struggling to find any documentation on how to override Craft's HTML for the forgotten password email.

The documentation can be found here:
https://craftcms.com/docs/templating/forgot-password-form

Part of the full templating documentation that starts here:
https://craftcms.com/docs/templating/global-variables

The actual HTML side of things is determined by the template you're using, which you can specify in the control panel -> settings -> emails.  I believe these settings are considered 'self documenting' in that there are explanations on that page as to what they do.

One thing worth noting is that IIRC you can't extend a layout template with that template, which is a little unfortunate.  So I have one general layout for all my general emails and duplicate that fully into the system email template.


Prevent change field in user profile edit Is there a way to prevent the current user from changing fields in his profile? Currently i've attached a customfield "company" to the user object. I only want the site admin to set this field once and the only one allowed to change this. Where can I inject/override/overload the behavior of the saveUser method? Or is there a way to allow a different validation function or to disable a certain customfield during edit/save?

Thanks in advance....

There isn't anything to do this out-of-the-box in Craft.

I believe the proper way you'd want to approach it would be to write a plugin that has it's own field type that takes into account user permissions.

An admin would get a normal text input, for example, and any other user would just see read-only text.


Allow editors to create pages (singles) Seems like a very obvious (and missing) feature, but maybe I'm missing something. If we have a generic "page" template how could an editor (as in someone not confident with using settings) just create a new single page?

E.g they may have singles for about, history, faq's etc but then want to add a new "page" for a one-off thing. Right now the developer has to create a new single in settings for them which is really clunky.

Just make a channel for your generic pages, and set the route to {slug}, that way your editors can create, delete, edit and disable any generic template pages without needing to touch the more involved areas of the Control Panel


How do I properly use Twig syntax in dynamic title/URL fields? I have an idea to create urls for entries that can't be guessed, but are automated without any extra effort from the content creator/editors. The intention is for the URL not require any authentication, but not be "guessable" just because you have another similar URL.

My thought was to use the Entry URL Format field to automate this. I tried the following but it didn't work as expected:

documents/{ (id * 1234567) | number_format(0, null, '-') }

I assumed I could use any twig syntax here due to the description/label for the input field:

  What the entry URLs should look like. You can include tags that output entry properties, such as {slug} or {postDate|date("Y")}.

So, is it possible to do what I'm trying? What's the correct twig syntax here?

After chatting with The Honorable Brad Bell I learned that the sample tags in the field's label are showing some shorthand references to a few variables. (The {slug} reference for example.)

All I needed to do was use the object object to fully utilize twig tags/filters/etc. Here are a few ways to achieve what I was aiming for:

{% set num = (object.id * 1234567) | number_format(0, null, '-') %}documents/{{ num }}

or slightly more concise code:

documents/{{ (object.id * 1234567) | number_format(0, null, '-') }}

Also, thanks to carlsc for sharing the documentation on this feature. Reference: https://craftcms.com/docs/sections-and-entries#dynamic-entry-titles.

Happy Dynamic Titling and URLing.


Eager loading of reverse related elements? Is it possible to load reverse related elements? I mean if the elements I’m querying are the target elements?

Example:

I’m setting up a criteria model to get some categories and I also want to load the entries related to each category. I’m using a Categories field, so my categories are the target elements of those relations.

{% for category in craft.categories.group('news').all() %}
    {% set query = craft.entries.relatedTo({
        targetElement: category,
        field: 'myCategoriesField',
    }) %}

    {# Oh no, a N+1 query problem... #}
    {% set entries = query.all() %}
{% endfor %}

I could probably do it the other way around, query for the entries and eager load the categories. Then use the group filter to order everything by category. But that approach is awkward and has limitations, e.g. doesn’t play well with pagination.

Isn't eager loading the wrong idea here, since categories do not have a property anyway, which automatically points to entries assign to this category?

Let's take 2 samples:

Sample #1: behavior like lazy loading (one entry query per category)

{% for category in categories %}
{% set entries = craft.entries...relatedTo(category)
{% endfor %}

Sample #2: behavior like eager loading (one entry query for all categories)

{% set entries = craft.entries...relatedTo(categories)

Now the only trick is to sort the entries in a way that they are easy accessible from each category in the {% for category in categories %} loop.

Or should't Craft automatically cache the loaded categories and therefor make accessing them from the entry fast after having executed the Sample #2 query?

What I mean is that it would not become faster, only more comfortable if this eager loading was possible.

Only ideas...


How to display all entries within a given category I've got a category group called allcategories, inside of this is two categories called design and photo.

I'm trying to filter all entries in the section projects by the category `photo' but none of my permutations are working :(

    {% set category = craft.categories.group('allcategories').find('photos') %}
    {% set projects = craft.entries.section('projects').relatedTo(category).find() %}

    {% for entry in projects %}

{{ entry.title }}

    {% endfor %}

Your mistake is in getting the category. Instead of what you have try:

{% set category = craft.categories.group('allcategories').slug('photos').find() %}

Getting elements in Craft use ElementCriteriaModel and find(), first(), last(), &c. do not accept any parameters (though nth() is an exception to this). So you need to search by other fields in the element as per the docs.

You may also want to make sure that the slug of the category group is not camel case (allCategories as opposed to allcategories).


Craft as a CMS for mobile app content We're just looking at potentially using Craft as a CMS to serve up content to a mobile apple/android app. Ideally content would be delivered as JSON and there be some sort of authentication from the app side (like an api key) as some of the content isn't intended to be publicly accessible. Can craft do this?

Many thanks!

This is most likely possible by serving up restful resources that refer to Craft data with some sort of PHP API that you'll need to write. The APIs you write will just need to grab data using Craft's API

As for hiding certain content for mobile (or whatever frontend platform), I'd create a Lightswitch field for section that you can use to signify content that is "mobile only" or whatever you'd like.

BTW - your API doesn't even necessarily need to be in PHP - You can probably use AngularJS or some other JS server-side framework and use Twig templating. Someone correct me if I'm wrong about that... The great thing about Craft CMS is it's frontend-agnostic


List Only Child Categories Related to Entries I need to show a list of Child Categories which only have Entries attached.

From about 6 different solutions here, I have assembled the following. It works perfectly on a Section that has < 200 Entries with a Category Group that contains 50 Parent Cats that each may have up to 10 Child Cats.

My concern is that with a larger Section (3,200 entries, yet to be imported into Craft) it will break down, timeout, etc. because in order for this to work, ALL the Entries from a Section must be present in the Array for the Categories to check Relations against.

For brevity and clarity, the following URL structure is required by the client for several reasons...

URL = /alpha/yadda/news
syntax = /[parent-category]/identifier/[section]

Section = News
Category Group = 1
Category Examples =
alpha
    alpha-1
    alpha-2
    alpha-3
beta
    beta-1
    beta-2
    beta-3
    beta-4
etc....

Based on that, here is what I've assembed that works great for 200 entries in News. It outputs a list of Child categories that only have News entries, based on the Parent's Category Slug in segment 1:

{# 1. find ALL the entry ids for a channel #}
{% set entryIds = craft.entries.section('news').limit(null).ids() %}

{# 2. find all the cats in Group 1 related to those entries #}
{% set categories = craft.categories.relatedTo({ sourceElement: entryIds }).groupId(1).limit(null).find() %}

{# 3. set var from URL seg1 and use to get CatModel Object: catParent #}
{% set parentSlug = craft.request.getSegment(1) %}
{% set catParent = craft.categories.slug(parentSlug).first() %}

{# 4. using catParent, get child cats #}
{% set subCategories = craft.categories.descendantOf(catParent) %}

{# 5. loop through cats found matching entries in step 2
        then subloop through this Parent Cat's descendants for match #}
{% for category in categories %}
    {% set currentCat = category.title %}
    {% for subCat in subCategories %}
        {% if subCat.title == currentCat %}
            <li>{{ subCat.title }}</li>
        {% endif %}
    {% endfor %}
{% endfor %}

Again, this all works...for 200 entries in News. But I don't see how it's scalable for the 3,200 blog entries that will be imported.

Just seems like there must be a better, more efficient way to display a list of Categories (or only descendants of a specific Parent Cat) that have Entries attached?

Having the need for a similar setup to yourself, I came up with a more efficient example below.

{% set entryIds = craft.entries.section('news').status('live').limit(null).ids() %}

{% set parentSlug = craft.request.getSegment(1) %}
{% set catParent = craft.categories.slug(parentSlug).first() %}

{% set categories = craft.categories.relatedTo({ sourceElement: entryIds }).groupId(1).limit(null).descendantOf(catParent).find() %}

{% nav category in categories %}

        {{ category.title }}
        {% ifchildren %}

                {% children %}

        {% endifchildren %}

{% endnav %}


Create a field group in a plugin I'm trying to create a field group in a plugin that fires onAfterInstall. I'm getting the error below but after install the field group does exist and seems to have been created successfully.

2015/10/21 21:57:17 [warning] [application] [Forced] Failed installing XXXXXX: An exception was thrown: CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`craft`.`craft_fieldlayoutfields`, CONSTRAINT `craft_fieldlayoutfields_fieldId_fk` FOREIGN KEY (`fieldId`) REFERENCES `craft_fields` (`id`) ON DELETE CASCADE). The SQL statement executed was: INSERT INTO `craft_fieldlayoutfields` (`required`, `uid`, `layoutId`, `tabId`, `sortOrder`, `dateUpdated`, `dateCreated`) VALUES (:yp0, :yp1, :yp2, :yp3, :yp4, :yp5, :yp6). Bound with :yp0=0, :yp1='b68bdc0b-647d-45fd-afa1-dbadffb973b8', :yp2=427, :yp3=263, :yp4=2, :yp5='2015-10-21 21:57:17', :yp6='2015-10-21 21:57:17'

Here is what the code look like which is creating the field group:

// XXXXX field group
Craft::log('Creating the XXXXX field group.',
 LogLevel::Info, true, 'application', 'XXXXX');

$group = new FieldGroupModel();
$group->id   = '';
$group->name = 'XXXXXXX';

if (craft()->fields->saveGroup($group))
{
  Craft::log('XXXXXX field group created successfully.',
   LogLevel::Info, true, 'application', 'XXXXXX');
}
else
{
  Craft::log('Could not save the XXXXXX field group.',
   LogLevel::Warning, true, 'application', 'XXXXXX');
}

Just a hunch and not tested, but don't do this:

$group->id   = '';

My guess is by explicitly setting that to an empty string, Craft thinks it's dealing with an existing record and not a new one.


Updating Craft 3 from ver. 3.0.28 10/23/2018 I have to update Craft 3 from ver. 3.0.28 10/23/2018, but i got this message:
You’ve reached a breakpoint! More updates will become available after you install Craft CMS 3.0.40.

How can i fix this problem?
Updating from the Terminal is no available with my version.
https://docs.craftcms.com/v3/updating.html

You need to manually update to the latest version of Craft 3.0.x, then update to Craft 3.1.x:

In your composer.json, change your Craft package to "craftcms/cms": "3.0.40",
Run composer update
Then in your composer.json, change your Craft package to "craftcms/cms": "^3.0.40",
Run composer update again


Get current date / time in specific timezone? How can I get the current date / time for specific timezones?

My local time is easy:

{{ now|date("H:i") }}

So how can I get this for New York? or Singapore?

{{ now|date("H:i", "Europe/Paris") }}

As per: http://twig.sensiolabs.org/doc/filters/date.html


Combine two almost identical sidebar templates, used for blog index and category index pages I'm struggling to combine two almost identical sidebar templates.

I’m working on a site that has:

a blog channel section with an index template that ‘includes’ a ‘sidebar-main.html’ template
a structure section with a page template that ‘includes’ the same ‘sidebar-main.html’ template
a category template that lists blog posts for a single category, but which ‘includes’ a different ‘sidebar-category.html’ template

The ‘sidebar-main.html’ and ‘sidebar-category.html’ templates are almost identical. Their main function is to offer the user a choice of an 'All categories' menu sorted by category, or a 'Top categories' menu sorted by number of posts, selectable in the entry control panel.

The 'sidebar-main.html template starts:

    {% if entry.sidebarContent is defined %}

        {% for block in entry.sidebarContent %}

            {% if block.type == "sidebarWidget" %}
                {% if block.widget.contains('topCategories') %}

Top categories

                    {% set entryIds = craft.entries.section('blog').ids() %}
                    {% set allCats = craft.categories.relatedTo(entryIds).level(1).find() %}
                    {% set catArray = {} %}

                    {% for category in allCats %}
                      {% set catArray = catArray | merge({(category.slug):craft.entries.relatedTo(category).total() }) %}
                    {% endfor %}

                    {% set catArray = catArray|sort|reverse %}

                    {% for catSlug, entryCount in catArray | slice(0,3) %}
                    {% set category = craft.categories.slug(catSlug).first() %}

                    {% if loop.first %}

                    {% endif %}

                                        {{ category.title }}&nbsp;

{{ entryCount }}{% if entryCount == 1 %}&nbsp;post{% else %}&nbsp;posts{% endif %}

And the 'sidebar-category.html' template is identical to this, except that entry.sidebarContent is replaced by category.sidebarContent. This works fine, with no errors or problems (except it's not DRY). However, if I can eliminate the use of 'category.sidebarContent', then I can split up the combined template to enable its use in 404 and search etc pages.

I hope all that makes some sort of sense, and thanks for any suggestions!

You could pass the content to the sidebar include, as follows:

{% include 'sidebar-template' with {
    content: entry.sidebarContent
} only %}

The sidebar template would then use content, rather than entry.sidebarContent.

It's also worth taking a look at Twig embeds, which can be very useful in situations such as this.


Is there a JavaScript event that is triggered when a field type's settings html is displayed within Matrix? Google Maps for Craft has a settings page that uses JavaScript that aids the user in setting up their Google Maps field. So the user can set a default center and zoom for the map, and they do this by manipulating a map in the settings page. All works fine when creating a standard field. I used the $(document).ready() method to trigger my code, but since Matrix creates these fields after the DOM has already triggered that event, my code isn't getting instantiated. Matrix for EE has a similar callback function that is triggered, so I assume Matrix for Craft has the same thing.

Any code examples for listening for when new Matrix fields are created? I tried browsing through the existing field type code and MatrixConfigurator.js but couldn't find any examples yet.

There’s no event for it, but any JS you include using craft()->templates->includeJs() from your field type's getSettingsHtml() method will get fired each time a new Matrix sub-field is created, so if you code your field type correctly with properly namespaced inputs] IDs/names, no event will be needed.

The thing about Matrix is, there’s no way to predict what the actual input IDs/names are going to be when they are added to the DOM, as they will be run through TemplatesService::namespaceInputs() with the namespace blockTypes[__BLOCK_TYPE__][fields][__FIELD__][typesettings], and those “__BLOCK_TYPE__” and “__FIELD__” placeholders are replaced dynamically by MatrixConfigurator’s Javascript before adding the settings HTML to the DOM.

Regular field settings get namespaced too, but in a more predictable way (their namespace will always be types[FieldTypeClassHandle]), so it can be tempting to just hard-code the namespaced IDs directly into your Javascript, like this:

$js = "\$('#types-FieldTypeClassHandle-myInputId')" // ...

Matrix’s unpredictability shows why it’s important to not do that, and instead always use TemplatesService::namespaceInputId() and namespaceInputName() whenever you need to reference an input’s ID or name from your Javascript:

$namespacedId = craft()->templates->namespaceInputId('myInputId');

$js = "\$('#{$namespacedId}')" // ...

When you let TemplatesService generate the namespaced IDs/names for you, you can be sure that it will always give you an ID/name that will match whatever the actual ID/name will be in the DOM.


How can I change the rich-text editor to remove the "Heading 1" option I want to remove the option to add a H1 from the dropdown in the Redactor rich-text component. I have edited the Standard.json file in craft>config>redactor to the below but it still hasn't done the job:

{
    "buttons": ["format","bold","italic","lists","link","horizontalrule"],
    "plugins": ["source","fullscreen"],
    "formattingTags": ["h2","h3","p","blockquote"]
}

I followed instructions from this page, but it looks like "formattingTags" doesn't work. Anyone know how to fix this?

formattingTags is not the correct syntax.

You should be using formatting instead, as per my answer on this question.


Best way to programmatically create categories? We're working on an XML import plugin to migrate content from another CMS.

What's the best way to create a new category (with a name, slug etc.) and assign it to the entry when running
$entryModel = new EntryModel(); ?

To create a category, you'd have to use the craft()->categories->saveCategory() method, and feed it a CategoryModel. Having done that, you can use the ID of your new category to create an array for the entry's category field (in this example its handle is categoryFieldHandle):

$category = new CategoryModel();
$category->groupId = 2; // Or whatever ID your new category's group has.
$category->getContent()->title = 'My new category title'; // Slug will be automagically created

if(craft()->categories->saveCategory($category)) {
    $entryModel = new EntryModel();
    $entryModel->title = 'My entry's title';
    $entryModel->categoryFieldHandle[] = $category->id;

    if(craft()->entries->saveEntry($entryModel)) {
        ...
    }
}


Retrieving an entry by ID in ALL locales I've been looking at How can I build a language switcher? but I don't to hit the DB for each entry in the loop, just to get the entry's localised slug.

However I can't see a way to get an entry by ID with anything other than the current or a specific locale.

So assuming I'm on a template where we have an entry defined, this returns 1 entry in current locale:

craft.entries.id(entry.id);

And this returns 1 entry in a different locale:

craft.entries.id(entry.id).locale('es');

How can I get entries for ALL locales so I can do one DB query rather than one for every locale that's enabled on the site?

I don't think this is possible witout the use of a plugin. The craft.entries tag works on an entry basis. The slug is saved in the table that houses the localized data for an element, craft_elements_i18n. When you request an entry, (in theory) the craft_entries table is joined with the craft_elements table (based on id), which is then joined with the craft_elements_i18n table (based on locale). There's no way you could join in data from several different locales this way.

What you have to do is query the craft_elements_i18n directly, and return all rows based on the entry id (elementId in that table is the entry id), and then you'd get locale, slug, and url. This table isn't exposed in any way to the templates, so you'd need to do it with a small plugin. It will still be one query to do this, though.

I think maybe this is more work than what it's worth, unless you have loads of locales, the difference in performance will be very, very small. Also, you could cache this in your templates, which would make it even less of an issue.


Get entries relatedTo multiple categories I have searched and tried a few different ways but none have worked so not sure what is wrong.

Example say I have a few categories case studies, featured, articles, videos...

I have tried this way

{% set category = craft.categories.group('resource').relatedTo(
    'and',
    { targetElement: featured },
    { targetElement: case studies }
) %}
{% set entries = craft.entries.relatedTo(category).limit(3).find() %}

I have tried this way

{% set category = craft.categories({
    group: 'resource',
    relatedTo: [
        'and',
        { targetElement: featured },
        { targetElement: case-studies }
    ]
}) %}
{% set entries = craft.entries.relatedTo(category).limit(3).find() %}

I am wanting to find entries that use two categories together example case studies, and featured category.

The relatedTo parameter's targetElement property has to be an ElementCriteriaModel or a single category model:

{% set featured = craft.categories.group('myCatGroup').slug('featured').first() %}
{% set caseStudies = craft.categories.group('myCatGroup').slug('case-studies') %}

{% set entries = craft.users({
    group: 'resource',
    relatedTo: [
        'and',
        { targetElement: featured },
        { targetElement: caseStudies }
    ]
}) %}


How do I eager load a dropdown field? I'm going through my current project and making my loops more "eager". It's working great in several areas and improving performance massively but for some reason I can't get it to work when the entries I'm asking for have a dropdown field. "newsType" is the name of the field. Am I missing some obvious mistake here or are dropdowns a special case somehow?

The error:

Array to string conversion
echo twig_escape_filter($this->env, $this->getAttribute($context["article"], "newsType", array()), "html", null, true);

The code:

{% set latestNews = {
    section : 'news',
    with : ['title', 'body', 'newsType'],
    limit : '6'
} %}

{% if latestNews|length %}
{% for article in craft.entries(latestNews) %}

{{ article.newsType.label }}

{{ article.title }}

           {{ article.body|striptags|slice(0, 150) ~ '...' }}

        Read More &rarr;

{% endfor %}
{% endif %}

Dropdowns are not relations, and therefore they don't need to be eager loaded (and indeed can't be eager loaded).

Here's an explanation of what's going on under the hood with eager loading: Speed up your Craft CMS Templates with Eager Loading

TL;DR only things that are relations, which are other Elements are candidates for eager loading. Other fields like Dropdowns, etc. are loaded as part of the content already.


Should I use cache on data pulled from within files? I've read documentation and it says, that We shouldn't use cache tags on static text.

I have a files, that are static in that way, that the data are pulled from within a file, or in some case, data are pulled from outside a file, where cache tags are.

For example - language and territory data, static navigation.

Within cache tags I have pretty computationally statements and looping, where documentation says, that it's exception.

The reason the documentation says to not use it on static text, is because the cached data will be saved to the database, resulting in at least one database query (two if it needs to update the data). Database operations are fairly expensive compared to reading data from files, or running twig code, so in many cases this will be slower than just showing the text.

There's no way to know for sure if using cache tags will be a benefit in your case. It really depends on what exactly you're doing in your template, and where the bottlenecks in your system is. The only way to know, is to test it. If you turn devMode on, reload your page with and without the cache tag enabled, you could compare the response time shown in the console output under "Profiling Summary Report". This is the time it takes for the page to be generated by craft, which is what you'd seek to minimize using the cache tag. Remember to reload the page several times for each case and do an average, since the result will vary somewhat depending on what else is going on in your system.


Plugin eager loading not loading relations I have a plugin with two records with the relationships as follows:

Placid_EndpointRecord

public function defineRelations()
{
    return array(
        'resource' => array(static::BELONGS_TO, 'Placid_ResourceRecord', 'required' => false, 'onDelete' => static::SET_NULL)
    );
}

Placid_ResourceRecord

public function defineRelations()
{
    return array(
        'endpoints' => array(static::HAS_MANY, 'Placid_EndpointRecord', 'resourceId'),
    );
}

In a service class I have (options being an empty array at this point):

return Placid_ResourceRecord::model()->with('endpoints')->findAll($options);

When I dump the response from the service method i'm getting back is:

Craft\Placid_ResourceModel Object
    (
        [classSuffix:protected] => Model
        [strictAttributes:protected] => 1
        [_classHandle:Craft\BaseModel:private] =>
        [_attributeConfigs:Craft\BaseModel:private] => Array
            (
                [id] => Array
                    (
                        [maxLength] => 11
                        [min] => -2147483648
                        [max] => 2147483647
                        [decimals] => 0
                        [type] => number
                        [unsigned] =>
                        [length] => 10
                        [column] => integer
                    )
                [name] => Array
                    (
                        [type] => string
                    )
                [handle] => Array
                    (
                        [type] => string
                    )
                [host] => Array
                    (
                        [type] => string
                    )
            )

        [_attributes:Craft\BaseModel:private] => Array
            (
                [id] => 1
                [name] => Foo
                [handle] => Bar
                [host] => Bar
            )

        [_extraAttributeNames:Craft\BaseModel:private] =>
        [_errors:CModel:private] => Array
            (
            )

        [_validators:CModel:private] =>
        [_scenario:CModel:private] =>
        [_e:CComponent:private] =>
        [_m:CComponent:private] =>
    )

There doesn't seem to be any hint of the endpoints relation, there is definitely a row in the related table but even if not i'd expected to see an empty array of some sorts.

Is there anything i'm missing or doing wrong? I looked at some of the core files and it seems the records are set up the same way for similar relations and I get no errors so i'm a bit clueless as to what's going wrong. Any help would be awesome, thank you!

What strikes me as interesting here is your dump contains a Model instance.

For example you said:

  When I dump the response from the service method i'm getting back is:
  Craft\Placid_ResourceModel Object

When I query findAll through a CActiveRecord derived class I get an array of Records. In order to populate this into models, the populateModel(s) methods are typically used.

If you have a relation at the ActiveRecord level, it is a pseudo-attribute and will only be carried through to the model if the attribute is defined as defined attributes can only be mass assigned. Yii also supports rules definitions to mark attributes as safe, but this is almost entirely optional.

The question is really why you have a model being output.

E.g. for me the following code:

$records = SomePlugin_ProductRecord::model()->with('pricing')->findAll($criteria);
var_dump($records[0]);

Results in:

object(Craft\SomePlugin_ProductRecord)#179 (14) {

Do you have any code which is auto inflating into a model? or are you calling populateModel(s)?

If so, then you have made the correct call of creating the attribute in your model if you want to access it from there, as far as I've experienced.


Assets are not loading anymore (maybe an update) I just noticed that I can't see my files if I go into the assets section.
An Error blinks up and says "An unknown error occurred". In the front-end, I see every file and I can upload files to an asset too and see there uploaded files and selecting it.

The log file says nothing.
I use for Image Transforms Imager without imgix.
If i want to edit an Image i get a error too:

  Getting unknown property: aelvan\imager\models\ConfigModel::imgixEnableAutoPurging

It has always worked.

I can only imagine that an update has changed something?!

Thanks for any help. Really big problem

Solved the complete error with a reset of the imager config file.


Displaying images from a matrix field from a related field I have a section that is a single type. On this page there is a relation ship ('entries') field where the user can select a related photo gallery. Photo gallery is its own section with a matrix field on it that contains image files and image names. How when I am displaying the single page pull in the matrix field to display an image gallery. This is what I have tried but not with much luck.

I have tried

  {% if entry.associatedGallery is not null %}
    {% set theGallery = craft.entries.section('bb').relatedTo(entry.associatedGallery) %}

        {% for matrixBlock in theGallery.albumImages %}
          {% set asset = matrixBlock.imageFile.first() %}
            {% if asset %}

            {% endif %}
        {% endfor %}

    {% else %}

 Apparently its null

  {% endif %}

and

  {% if entry.associatedGallery is not null %}
    {% set theGallery = entry.associatedGallery %}

        {% for matrixBlock in theGallery.albumImages %}
          {% set asset = matrixBlock.imageFile.first() %}
            {% if asset %}

            {% endif %}
        {% endfor %}

    {% else %}

 Apparently its null

  {% endif %}

I think I am missing something fundamental about how relationships are defined.

Relationship field is defined like:

{% for relatedItem in entry.relatedItemField %}
  {{ relatedItem.someField }} {{ relatedItem.someOtherField }}
{% endfor %}

So maybe:

{% if entry.associatedGallery | length %}
    {% for theGallery in entry.associatedGallery %}
        {% for matrixBlock in theGallery.albumImages %}
            {% if matrixBlock.imageFile | length %}
                {% for asset in matrixBlock.imageFile.first() %}

                {% endfor %}
            {% endif %}
        {% endfor %}
    {% endfor %}
{% endif %}


Get entry by value from custom field I have a field defined in my plugin called video with AttributeType::Mixed where I store a video_id and a title of a video. I need to look up the entry by the video_id (I can't do it via the the entry ID).

$entry = craft()->elements->getCriteria(ElementType::Entry);
$entry->section = 'video';
$entry->search('video: video_id=' . $videoID);
return $entry->first();

This works, but there has to be a better solution?

It's actually not SQL friendly at all to store multiple values (Title and Video ID) in a single column. The data is stored as a serialized string and all you can do is to use the pattern matching operator LIKE to get the row you're after.

For best performance you should refactor your fields and store each of them individually. If all the data has to be in one field, store the field in its own table (like Matrix fields do).

If this is no option for you, I would recommend to not use the search parameter with your ElementCriteriaModel, but to prepare a DbCommand object using buildElementsQuery and add your "Video ID condition" using the LIKE operator I mentioned above, so you don't rely on up-to-date search indexes.

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

$query = craft()->elements->buildElementsQuery($criteria);
$params = array(
    ':video_id' => '%video_id='.$video_id.'%',
);
$query->andWhere('entries.video LIKE :video_id', $params);
$result = $query->queryRow();

return EntryModel::populateModel($result);


Is there a way to re-order states in Craft Commerce? I'm setting up a Craft Commerce site and for some of the countries the user must specify a State. However, the order of states appears to be alphabetical.

The problem is that the site's traffic comes mainly from 2-3 states so it would be much easier for the vast majority of users to find those states if they appear at the top.

Craft Commerce seems to allow custom ordering for countries. Is there a way to do the same for States?

Not at the moment, you would need to manually put the states at the top of your select box in the front-end. There is no harm if you have a duplicate select option in your form, so you could list the popular ones first, then list all of them.

We will look to add sorting of States in a future release of Craft Commerce. I have added it as a feature request and can follow progress there: https://github.com/craftcms/commerce/issues/1284


Connect to an external database from a Craft 2.x plugin I recently saw a very helpful post about how to connect to an external database from a Craft plugin and I wanted to confirm I understood the implementation correctly.

On this response the author recommended a way to leverage Yii's Query Builder on external databases. Is the following snippet the way to properly implement this in a service? Do I need to manually "close" this connection or is this alone the way to implement this?

<?php

// Connect to an external database
$db = Craft::createComponent([
    'emulatePrepare'    => true,
    'charset'           => 'utf8',
    'class'             => 'Craft\DbConnection',
    'autoConnect'       => true,
]);

$db->connectionString = 'mysql:host=localhost;dbname=MY_DB;port=3306';
$db->username = 'UN';
$db->password = 'PW';

// Use Query Builder to fetch data from the database
$data = $db->createCommand()
    ->select("*")
    ->from("TBL")
    ->queryAll();

// Pass along the data to be used in a template via variables
return $data;

If only the service will be connecting to it and only one method, then your example works fine.

If only the service will be connecting to, but you use it across multiple methods, then you might want to move the bootstrapping part to the service init() method and save the database connection as a private instance variable in the service so everything in the service can access it.

  Do I need to manually "close" this connection

I wouldn't worry about it.


Dynamic Reply-To In Sprout Forms Notification Is it possible to get Sprout Forms built in notifications to have dynamic reply to details? Or even from name etc?

I'm wanting my client to be able to respond directly to the client when Sprout Forms notifies them that a new submission has been posted.

Putting {{ formFieldName }} with the relevant field name in the "Reply To Email Address" field made the email not send (so obviously doesn't work).

Thanks.

It looks like you might need to update your dynamic values. Sprout Forms supports two types of syntax for dynamic information.

1) Shorthand syntax:

{formFieldHandle}

2) Object syntax:

{{ object.formFieldHandle }}

Submitted values from your form entry should be available in all of your notification fields:

Email Recipients
Subject
Sender Name
Sender Email Address (although you probably don't want to set this dynamically as it can affect deliverability)
Reply To Email Address


Add fields/custom fields to page in the admin page (backend) following situation: let's assume I have page with some ARTICLES (textfields): Article1, Article2, Article3, etc..

Now is there a module for CraftCMS that I can add textfields (articles) to a page directly in the backend (admin page)? So when I want to add a new article, then I don't have to do this with PHP or else.

Craft CMS is a full-featured CMS. You should not need to use PHP at all unless you need very custom functionality.

It sounds like what you should do is create an "Articles" Section, and add whatever fields you need for articles into that section's layout. Then you'll have a nice user-friendly way to enter content on the backend.

Please see: Sections and Entries


Use `onBeforeSaveEntry` event to update EntryModel properties? With my plugin I listen for onBeforeSaveEntry events and make changes to the $entry EntryModel. It works and I can change most properties from this function, but I have problems updating sectionId, typeId, authorId, postDate and expiryDate.

I looked up the relevant code in EntriesService.php and noticed that it might have something to do with a variable $entryRecord that gets saved to the DB separately (comment in the code: "Save the actual entry row").

Am I doing something wrong or is it simply not possible to set these properties from this function. As an alternative solution I could trigger a seperate saveEntry() from here, but this looks to be not the cleanest solution.

craft()->on('entries.onBeforeSaveEntry', function(Event $event)
{
    // Disable the entry
    $event->params['entry']->enabled = false;

    // Change the `authorId` (does NOT work!)
    $event->params['entry']->authorId = 1;
});

Just looking through the source file, it looks like sectionId, typeId, authorId, postDate and expiryDate are all set as properties on the $entryRecord before the onBeforeSaveUser event is fired. It also looks like $entryRecord is not accessible from the event, nor is it saved yet such that you could modify it directly. I suspect that you will need to modify these properties after the entry is saved (using the onSaveEntry event), and then resave the entry. You will also of course need to add conditionals (i.e. compare current authorId to target authorId) and only save the entry if needed, to ensure that you don't create an endless loop.


Can I change TEXT to MEDIUMTEXT/LONGTEXT in database? I have a text field in my database in which I'm going to index the contents of a PDF file. Right now the database column for that field is defined as "TEXT" but I need more space since my PDF files can be quite large.

Can I change this column in the database to MEDIUMTEXT or LONGTEXT or will this be a problem with Craft somehow?

The underlying database column for the plain text field type is defined by it's Max Length setting under it's field settings.

If you set that to something crazy high (like greater than 4294967295), it should use Long Text.

This means that Craft will adapt and change the column type dynamic from how much "data" you need to store/define for the field. Very powerful!

Note or warning (from Brad Bell at P&T support)
I'd make sure that you really need that much storage space (up to 4GB per row!). You can really start to choke MySQL by abusing that data type. Medium Text stores a very healthy 16MB, which is still a lot of data.


Using the CP login session expiration for the frontend I love the session handling on the backend CP. The prompts that come up on session expiration after setting 'userSessionDuration' => 'PT5M', in config/general.php are exactly what I want to use on the frontend website, (shown below).

I would like to use this logic on the frontend to force session-ends after x minutes. Doing some digging I can see the logic lies in UserController under actionGetAuthTimeout(), and this is polled while I'm on the CP every minute.
My question is whether I would have to manually run the controller constantly in the background and make the modal pop up? is there a more elegant method I've missed?

Thanks!

What you want is this:

// Returns how many seconds are left in the current user session.
// (int) The seconds left in the session, or -1 if their session
// will expire when their HTTP session ends.
craft()->userSession->getAuthTimeout()

You can then combine this with a Javascript setTimeout when the page loads so you can trigger whatever messages you need.

Edit: You can use this in your template files:

{% set authTimeout = craft.session.getAuthTimeout() %}


Get User Object for a given Entry I am trying to use the relatedTo parameter to get user details for a given entry with this code:

{% for entry in craft.entries.section('blog').limit(1) %}

    {{ entry.title }}

    {% set authorDetails =  craft.users.relatedTo(entry) %}

    {% for person in authorDetails %}
        {{ person.firstName }} {{ person.lastName }}
    {% endfor %}

{% endfor %}

The Title returns fine, but nothing else. First time I have used relatedTo and guess there is something I don't understand about usage. Any advice greatly appreciated!

Roi

If you're just looking to get the author of an entry, it's a simple as:

{% for entry in craft.entries.section('blog').limit(1) %}

    {{ entry.title }}

    {{ entry.author.firstName }} {{ entry.author.lastName }}

{% endfor %}

If you're looking to get every user associated with every Users field for an entry, your relatedTo syntax will work:

{% for entry in craft.entries.section('blog').limit(1) %}

    {{ entry.title }}

    {% set allRelatedUsers =  craft.users.relatedTo(entry) %}

    {% for user in allRelatedUsers %}
        {{ user.firstName }} {{ user.lastName }}
    {% endfor %}

{% endfor %}

The reason that returned nothing in your original question is because the "author" field isn't a proper Users field type - it's more of a special case user field.


Craft on Heroku with buckateer as a middleman for Amazon S3 We are using Craft on Heroku and wants to use S3. The problem is that we want to use a Heroku element (buckateer) as a middleman. Buckateer only gives you an IAM user without listbuckets permissions. So you get "S3::listBuckets(): [AccessDenied] Access Denied". Is there a smart and easy way to set the bucket manually without going into the core files?

I found a solution that lets you overwrites the core file S3.php without touching the core files.

By adding this snippet to config/general.php

// S3 override
const BUCKET_NAME = 'YOUR BUCKET NAME';
require_once('../craft/plugins/gm/S3.php');

return array(
   ...
);

And duplicate the S3.php file and add it to the plugins folder you can make the needed changes.


How do I access a specific element of a supersorted array? Let's say we have this setup:
{% set myArray = [9,3,5,7,2,1] %}
{% set mySortedArray = myArray | supersort() %}

It gives us:
myArray = array(6) {
    [0]=int(9)
    [1]=int(3)
    [2]=int(5)
    [3]=int(7)
    [4]=int(2)
    [5]=int(1)
}

mySortedArray = array(6) {
    [5]=int(1)
    [4]=int(2)
    [1]=int(3)
    [2]=int(5)
    [3]=int(7)
    [0]=int(9)
}

How can I access say the second element of mySortedArray?
If I do {{ mySortedArray[2] }} I get 5, but I want the 3.

If you run mySortedArray through the | values filter, it will reset the keys:
{% set mySortedArray = myArray | supersort | values %}

mySortedArray = array(6) {
    [0]=int(1)
    [1]=int(2)
    [2]=int(3)
    [3]=int(5)
    [4]=int(7)
    [5]=int(9)
}


Remove white space and parenthsis from global from entry variable I am using a phone number in a global variable called {{ global.phone }} with the format "(555) 555-5555". I'd like to use that same variable/string and remove spaces, dash, and parenthesis to use for the href tel link. I've tried a few different things from Twig and Craft documentation, but nothing is working. Here's what I have right now.

Ph: {{ global.phone }}

Is this possible to do? If so any advise how to accomplish this?

I haven't tried this but I think that you can use the twig replace function. Something like:

{{ global.phone|replace({"(":"", ")":"", "-":"", " ":""}) }}

Update In your case, since the prefix (1-) is required, and "-" are allowable, the replace string for "(555) 555-5555" would be:

{{ global.phone|replace({"(" : "1-", ") " : "-"}) }}


Get entries by category value from within plugin I need help.

I want to get entries based on multiple field search. It works for basic field types like selectbox or plain text but I can't get it to work with Categories Fields.

The field size is a selectbox field and works good.
The color is a Categories field and doesn't work.

The code:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = "houses";
$criteria->size = "big";
$criteria->color = "white"; // <== HOW???
$entries = craft()->elements->buildElementsQuery($criteria)->queryAll();

How do I get entries with a specific Categories Field value?

Thanks for any help.

Here's another solution which feels more correct. It uses relations and the relatedTo parameter.

// First get the all CategoryModels
$colorCriteria = craft()->elements->getCriteria(ElementType::Category);
$colorCriteria->group = 'colors';
$colorCriteria->slug = array("white");
$colorCategories = $colorCriteria->find();

// Then get the entries
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = "houses";
$criteria->size = "big";
$criteria->relatedTo = $colorCategories;//<= Here's the fancy part.
$entries = craft()->elements->buildElementsQuery($criteria)->queryAll();

Hopefully that helps someone else.


Limit the entries element API will return based on the post date I'm looking to only return entries that were published in the last 90 days.

Within the criteria for the endpoint, set

'postDate' => '>=' . date('Y-m-d', strtotime("-90 days"))

Of course you can adjust the date to suit your needs.


Twig include with noscript tag rendered as a string and not code So I have an include file.

I am including like standard:

{% include '_includes/partials/image-noscript' %

but for some reason it is generating the code like so…

  &lt;img
    src="http://plowmancraven-v4.loc/imager/uploads/images/general/3172/PC-Enviro-Generic-London-shutterstock_370946690_3488bcae28a5a46889970c4f238b0c7c.jpg"
    alt="PC Enviro Generic London"
  /&gt;

Edit: Here are some of the things I have tried but nothing has solved this issue yet.

{%- include '_includes/partials/image-noscript' -%}
{% autoescape false %}{% include '_includes/partials/image-noscript' %}{% endautoescape %}

inside the included file:

{% spaceless %}{% endspaceless %}

{% autoescape false %}

{% endautoescape %}

{% autoescape false %}{% endautoescape %}
{% autoescape false %}

{% endautoescape %}
{% autoescape false %}{% endautoescape %}

It's escaping the text in the default (html) context, which should not be happening for a template you include

I suspect this is due to a larger issue, as templates that are included should not be escaped in this manner.

You can change the escaping strategy using block tags around the code, though:

{% autoescape false %}
{% endautoescape %}

cf: autoescape


In entry.getPrev/Next navigation, show entries from a specific category only I have portfolio section that has a ‘portfolio’ category attached to it, which has categories ‘2D’ and ‘3D’.

There are 3 templates:

The index template shows a list of all the entries in the portfolio
section.
The categories template shows the entries within a specific category.
The entry template shows a single entry.

On the index page (/portfolio) you can click on 'All', '2D' and '3D' whereby 'All' takes you the index page, and 2D and 3D lead to /portfolio/2D and 3D (the categories template). Click on any item in the list and you go to the entry page.

On the entry template, I have a simple ‘previous entry’ and ‘next entry’  browsing navigation, using:

{% set params = {section: 'portfolio', orderBy: 'postDate desc', limit: null} %}
{% set entry_prev = entry.getPrev(params) %}
{% set entry_next = entry.getNext(params) %}

The thing is, this navigation always browses through all of the entries, regardless of what category an entry is in. And that's fine when you've reached the page from the index page, where all of the entries are listed. But I’m trying to make it so when you click an entry on the categories page, and you are then taken to this entry page, the browsing navigation (previous and next entry) takes into account what category you’re in. I use a simple cookie or getQuery() to set and get this information. That way, when you've clicked on an entry in the list with 2D items, you don't get entries from other categories in the prev/next navigation, but when you've clicked on the same item on the index page, you do get to navigate through all of the entries.

I’ve tried:

{% set params = craft.entries.section('portfolio').relatedTo('2d').orderBy('postDate desc').limit(10).all() %}

But this does not work: the navigation still includes entries that do not have the 2d category.

Anyone have any idea how to achieve this?

Try this

// Assuming you have named portfolio group for 2D and 3D as portfolio

// .first() if craft2, .one() if craft3

{% set category = craft.categories.group('portfolio').title('2D').first() %}
{% set params = craft.entries({
   section: 'portfolio',
   relatedTo: category,
   orderBy: 'postDate desc',
   limit: 10
 }) %}

Ref: https://docs.craftcms.com/v3/dev/element-queries/category-queries.html#example


How do I loop through and access all sections of returned entries? On my search results page I want to add a section filter depending on the different sections that are included in all of the returned entries.

I am getting all the sections like this:

{% set entries = craft.entries.section(['inspirationArticles', 'pages', 'pressArticles', 'products']).search(searchQuery).order('score') %}
{% set entrySections = entries.getAllSections() %}

And then loop through them:

{% for entrySection in entrySections %}
...
{% endfor %}

But when trying to access the sections’s names or handles via {{ entrySection.name }} or {{ entrySection.handle }}, I get a CException error:

Craft\EntryModel and its behaviors do not have a method or closure named "handle".

So it looks like it isn't actually accessing the SectionModel. Am I missing a step?

Entries to not have a getAllSections method. You can use the group filter to group your entries by their sections.

{% set entries = craft.entries.section(['inspirationArticles', 'pages', 'pressArticles', 'products']).search(searchQuery).order('score') %}
{% set grouped = entries|group('section') %}

{% for section, entriesInGroup in grouped %}

Section: {{ section }}

        {% for entry in entriesInGroup %}

{{entry}}

        {% endfor %}

{% endfor %}

Here's some documentation to help!


Is it possible to totally reskin the admin panel with a new template? Can the control panel have a skin or theme applied without it affecting automatic updates?

You can certainly override the admin css by using https://github.com/lindseydiloreto/craft-cpcss from Double Secret Agency. It's rather nice.

Lindsey also has a Admin JS plugin too: https://github.com/lindseydiloreto/craft-cpjs

Regarding actual admin template changes and their ability to survive an update, I'll have to defer that to somebody who know's more about it than myself.


Duplicating shipping details from an Order into a Cart Further from yesterday's Duplicate an existing Order as a new Cart in Commerce I need to step in front of MultiAdd to set up a couple of other things - such as to duplicate the Shipping details from the old order to the new cart.

I have been trying to do it as follows:

public function actionReorder()
{
    // basic security precautions
        $this->requirePostRequest();

    // get the current cart
        $cart = craft()->commerce_cart->getCart();

    // get the fields passed to us in the form
        $oldOrderNumber = craft()->request->getPost('oldOrderNumber');

    // get the 'old' order
        $oldOrder = craft()->commerce_orders->getOrderByNumber($oldOrderNumber);

    // set the shipping etc on the cart to the same as the old order
        $cart->shippingAddressId    = $oldOrder->shippingAddressId;
        $cart->shippingAddress      = $oldOrder->shippingAddress;
        $cart->shippingMethodHandle = $oldOrder->shippingMethodHandle;

    // ok now pass it all over to the multiAdd controller...
        craft()->runController('multiAdd/multiAdd');
}

This doesn't work because

  Property "Craft\Commerce_OrderModel.shippingMethodHandle" is read only.

I have also tried

if (!craft()->commerce_cart->setShippingMethod($cart, $oldOrder->shippingMethod, $error)) {
    $cart->addError('shippingMethod', $error);
    LogicPlugin::log("error adding shipping method to cart: " . $error, LogLevel::Error);
}

instead of $cart->shippingMethodHandle = $oldOrder->shippingMethodHandle;

But that doesn't appear to work either. It tells me that the Shipping method not available.

How should I go about doing this?

It's particularly problematic for me because my Commerce set up required the Shipping address to be set in order for the Product Options to work (the options are based on the address the cart will ship to).

Simple error on my part. You don't pass the old order's "shippingMethod" model to the new cart's 'setShippingMethod' function. You pass the old order's shippingMethodHandle to the setShippingMethod function.

The following works:

public function actionReorder()
{
    // basic security precautions
        $this->requirePostRequest();

    // get the current cart
        $cart = craft()->commerce_cart->getCart();

    // get the fields passed to us in the form
        $oldOrderNumber = craft()->request->getPost('oldOrderNumber');

    // get the 'old' order
        $oldOrder = craft()->commerce_orders->getOrderByNumber($oldOrderNumber);

    // set the shipping etc on the cart to the same as the old order
        $cart->shippingAddressId    = $oldOrder->shippingAddressId;
        $cart->shippingAddress      = $oldOrder->shippingAddress;

        if (!craft()->commerce_cart->setShippingMethod($cart, $oldOrder->shippingMethodHandle, $error)) {
            $cart->addError('shippingMethod', $error);
            LogicPlugin::log("error adding shipping method to cart: " . $error, LogLevel::Error);
        }

    // ok now pass it all over to the multiAdd controller...
        craft()->runController('multiAdd/multiAdd');
}


Where is the documentation for creating templates/themes? How do I find documentation explaining how to build a theme in Craft CMS? Where do I put my theme's assets, like my CSS and JS files, and how do I reference those assets in my Twig templates?

Each Craft install is typically considered a discrete site, with its own design, information architecture, assets, etc.

This is why you might not be seeing information about "theming," per se.

However! Everything you need to start will be in craft/templates and public.

craft/templates is how you generate HTML. Files in here often correspond to your sections and routes, but can also get rendered statically, just based on where you put them and what they're named. Check out the Routing documentation to decide how you want to set up your basic templates.
public is the only folder in the installation that is accessible to the web, directly. All your CSS, JS, fonts, static images (i.e. a logo, icons), etc. will go. You can reference those files the same way you would a regular HTML file. Craft has some tags to help you with generating the proper URLs.

These are two of the primary concepts that you'll need to grasp to get started displaying your content.

Be sure to check out the Templating Overview and click through the next few Docs pages. Once you understand where a template needs to be (and why), you can dig in to the expanded templating docs.

One last (rather granular) note: Each type of content you define (Sections) that has a URL will ask you for an Entry Template. That path is within your craft/templates folder, and it'll automatically load the file when you visit that Entry's URL. (i.e. my "News" section might have _news/post as its Entry Template, which corresponds to craft/templates/_news/post.twig. The underscore prevents it from being directly accessed/rendered via mydomain.com/news/post.


Order product without gateway I would like "buy" product without the use of a gateway. The reason for this is that the customer will have the option to apply for a loan at the bank and when the loan it approved we'll get a callback and then the order will be executed.

Does anyone have a good idea for this solution?

Seems like what you're looking for is under Commerce Settings->Payment Methods, set the "Credit Card Payement Type" to "Authorize Only (Manual Capture)", then set the "Payment Gateway" to "Dummy".


Decimal value for quantity I need to accept a decimal value for the quantity of a line item and for the total quantity. I understand this is not a normal request for most products but my client sells items by the foot and needs the flexibility to sell lengths in feet and inches (ex. 10 ft. 6 in. = 10.5 or 5 ft 6.5 in. = 5.541. I could probably hack this using JavaScript on the front-end but would like to do this the correct way. Any guidance is greatly appreciated. Has anyone achieved this?

You could build a plugin that listens to https://craftcommerce.com/docs/events-reference#commerce_cart.onbeforeaddtocart and translates the front end values of 10.5 or 10'6" or whatever into the number of inches (or, if you're working in a sane part of the world, even cm!).

Then on display of the cart or updates etc, you'll want to use some JS and/or twig maths to translate that back into those crazy feet/inch units you need there.

I honestly think trying to retro-fit in partial unit sales into Commerce as a whole would be quite a considerable challenge, so I think the best way to solve this is to use your smallest unit as the back end unit of quantity for the product, and do the magic in your plugin/and display.


How to get fields from another section? I need to get data from fields from another section.
My code is:

        {% for kontaktEntry in craft.entries.section('kontakt').entry.kontakter %}

                    {% set image = kontaktEntry.bilde.first() %}
                    {% if image %}

                    {% endif %}

{{ kontaktEntry.navn }}

                    {{ kontaktEntry.stilling }}

        {% endfor %}

kontakter is a matrix. I get nothing in output. What is wrong here?

I'm not sure that .entry is a valid parameter? I think that craft.entries.section('kontakt') contains an array with entries, so maybe you you could do .first on it, so basically I think you wanted to do this:

    {% for kontaktEntry in craft.entries.section('kontakt').first.kontakter %}

                {% set image = kontaktEntry.bilde.first() %}
                {% if image %}

                {% endif %}

{{ kontaktEntry.navn }}

                {{ kontaktEntry.stilling }}

    {% endfor %}


Enabling CSRF Protection for Mailchimp Subscribe plugin and other forms I'm using the MailChimp Subscribe for Craft plugin to embed several subscription forms on a website I'm building.

The following code appears via my master _layout.html file:

<form action="" method="POST">

    <input type="hidden" name="action" value="mailchimpSubscribe/list/Subscribe">
    <input type="hidden" name="redirect" value="successfully-subscribed">

    {# MailChimp List ID #}
    <input type="hidden" name="lid" value="XXXXXXXXXX">

    {% if mailchimpSubscribe is defined %}
        {% if (not mailchimpSubscribe.success) and (mailchimpSubscribe.errorCode!='1000') %}

An error occured. Please try again.

        {% endif %}
    {% endif %}

        Name
        <input type="text" placeholder="Name" name="mcvars[NAME]" value="{% if (mailchimpSubscribe is defined) and (not mailchimpSubscribe.success) %}{{ mailchimpSubscribe.values.vars.NAME }}{% endif %}" required>

        Email:
        <input type="email" placeholder="Email Address" name="email" value="{% if (mailchimpSubscribe is defined) and (not mailchimpSubscribe.success) %}{{ mailchimpSubscribe.values.email }}{% endif %}" required>

    <input type="submit" name="" value="Go!">

</form>

When I hit go, I get the following Bad Request error:

I've temporarily fixed the error via general.php by disabling CSRF Protection (not recommended).

How do I implement CSRF Protection on this form? I've followed this article, but replacing the name and value fields will surely disable the plugin's functionality?

Should I also implement the method shown here for other forms like Am Forms?

Update:
There's a pull request on the plugin git page regarding this.

Enable CSRF protection in your config again and add {{ getCsrfInput() }} right after the <form> opening tag on all forms on your site, regardless if they are amforms or mailchimp subscribe.  I can verify that it won't interfere with the mailchimp plugin as I am currently (and just recently) installed it on a project I'm working on and it works fine.


How can I embed Image into Craft Commerce 2 PDF Receipt How do I embed an image (PNG,SVG or JPG) into a CraftCMS Commerce 2 PDF receipt? I tried importing the svg using an includes. I tried using an img tag and referencing a local file. Nothing seems to work.

David

The PDF renderer uses DOMPDF, which expects a HTML document to be supplied. See the DOMPDF documentation to see what types of images are supported.

If you are linking images from a different domain you will need to set the commerce.php config setting of pdfAllowRemoteImages to true.

https://docs.craftcms.com/commerce/v2/configuration.html#pdfallowremoteimages


list available parameters of variable Is there a way to print all of the available parameters/handles when I set a variable?

For example if I put {% set orders = craft.commerce.orders.find() %} is there a way to list out the available parameters/handles depending on what I set, without having to go to the docs? So a way of checking that my code is right from the templates.

If you're looking for a purely Twig/template solution, then your best bet would be to either enable devMode and use Twig's dump() method or install something like the Craft Kint plugin.

Keep in mind that both of them are going to give you much more information than just attributes available on a model (like the array of OrderModel's your example is going to return), but that info will be included.


Enable plugin in devMode Is is possible to enable certain plugins only in devMode? (or via some other configuration option)?

I just was pointed to the correct solution (shame on me I did not find it myself):

There already is a config for this:
https://docs.craftcms.com/v3/config/config-settings.html#disabledplugins

To be used like this:

'production' => [
     'disabledPlugins' => ['cloner', 'cp-field-inspect', 'dumper', 'migration-manager']
],

Thanks gtettelaar for dropping me a hint! (https://github.com/craftcms/cms/issues/5107)


How to list the latest 3 entries per category per section? I'm trying to create a condensed overview of my website content on my homepage. I'd like that page to loop through all sections, in each section looping through the categories that apply to the section, and for each category to pull the title, uri, and excerpt of the newest three entries.

I'm having trouble wrapping my head around how I'd do that.

What I'm after might be seen as:

SECTION
  CATEGORY 1 [title, description, view category archive]
    POST 1 [title, excerpt, publication date, view entry]
    POST 2 [title, excerpt, publication date, view entry]
    POST 3 [title, excerpt, publication date, view entry]
  CATEGORY 2 [title, description, view category archive]
    POST 1 [title, excerpt, publication date, view entry]
    POST 2 [title, excerpt, publication date, view entry]
    POST 3 [title, excerpt, publication date, view entry]
SECTION 2
  CATEGORY 1 [title, description, view category archive]
    POST 1 [title, excerpt, publication date, view entry]
    POST 2 [title, excerpt, publication date, view entry]
    POST 3 [title, excerpt, publication date, view entry]

For the sake of simplicity, all my categories are currently under a 'global' group. They also map pretty much 1:1 to the EntryTypes available in each section. (I'm not entirely convinced I'm using Categories / EntryTypes correctly, given that 1:1 relation... in fact that's another question to ask).

You need to loop over the sections. In each section, you then loop over the categories, and display your entries inside them. Something like this.

{% set categories = craft.categories.group('groupHandle').find() %}
{% for section in craft.sections.getAllSections() %}
    {% if section.type == 'channel' %}

{{ section.name }}

        {% for category in categories %}

{{ category.title }}

            {% for entry in craft.entries.section(section).relatedTo(category).limit(3).find() %}
                {{ entry.title }}
            {% endfor %}
        {% endfor %}
    {% endif %}
{% endfor %}

This is a pretty quick and dirty example. I pull the categories ahead of time so I can reduce the number of database calls. I suggest using the cache to speed things up.

The template docs (especially the ElementCriteriaModel) are handy reading materials.


How to subscribe to an entry and get notified by email in case of new comments? I am thinking about a possibility to let members subscribe to a blog entry, and then get notified in case of new comments related to the respective entry. The comments are stored as entries in a Craft CMS channel.

My idea is to use the Like for Craft CMS plugin for the subscription to a blog entry. In a second step I would try to use the Postmaster for Craft CMS plugin to notify the subscribers by email. I hope that this will be possible using the Postmaster Developer API, but I am not sure.

What is your opinion regarding my idea? Do you know perhaps an easier approach.

I very much appreciate your help, thanks!

I really like the idea of using a simple plugin like Like to keep track of what entries users are interested in.

But instead of writing the code to integrate with Postmaster, I’d probably just use Craft’s API directly to send the mail after new entries are saved in your comments section.

The Like plugin and Craft API you need to look into:

entries.onSaveEntry event
getLikesByElementId()
sendEmailByKey()


How to display itemCount using the Shortlist plugin? I am using the Shortlist plugin as a rating system throughout the site and need to display the numeral for the total, with a very simple conditional.

{% set item = craft.shortlist.item('favourites') %}

{% if craft.shortlist.itemCount > 0 %}
    **{{ number }}**<i class="fa fa-large fa-heartbeat">
{% else %}
    <i class="fa fa-large fa-heart-o">
{% endif %}

I have tried {{ item }}, {{ count }}, {{ itemCount }}, but am unable to display a numeral.

Any suggestions?

From the documentation is looks like the correct syntax to use is:

{{ craft.shortlist.itemCount }}


getQuery() returns only one value I have a URL passing values from form checkboxes to a template. All the checkboxes are grouped with the same name= attribute. When multiple checkboxes are selected, the query string looks something like:

?checkValue=12345&checkValue=23456&checkValue=34567

However, craft.request.getQuery('checkValue') returns only the last value (34567 in this case).

How can I retrieve all the values so they can be used and manipulated?

EDIT: I've corrected the naming of the checkboxes from name="checkValue" to name="checkValue[]", so now my query string looks like this:

?checkValue%5B%5D=12345&checkValue%5B%5D=23456&checkValue%5B%5D=34567

Does that change what can be accessed using craft.request.getQuery('checkValue')?

This question is not really Craft related. Since you just don't send a valid request. You can't send one key multiple times unless you do it in an array.

The php $_GET is a simple array with all your values and you overwrite them again and again.

https://stackoverflow.com/questions/5098397/how-to-pass-an-array-in-get-in-php


How to return entries based on Checkboxes field criteria? Ok I'm building a plugin that needs to check for an id in an array and return only users that have the id in the checkbox array.

So this is what I have:

$user_criteria = craft()->elements->getCriteria(ElementType::User);
$user_criteria->interests = $interestId;
$users = $user_criteria->find();

interests is a dynamically created checkbox array which sits under the users profile. $interestId is the id I wish to look for in that array and return all users that have it.

Any help much appreciated.

The default Checkboxes field type stores its value to the database as a serialized PHP array. So for an entry with checkboxes "7", "12" and "32" checked, the value in the field_interests column is ["7","12","32"].

This is not query friendly at all, so the best solution would be to use a different field type.

But if you really want to use the checkboxes field, here's how you can query for your elements. Convert your criteria model to a DbCommand object and add a new WHERE clause with a LIKE condition to perform pattern matching. Include the quotes enclosing each ID in the pattern, this should make the query robust.

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

$query = craft()->elements->buildElementsQuery($user_criteria);
$params = array(
    ':interestId' => '%"'.$interestId.'"%',
);
$query->andWhere('field_interests LIKE :interestId', $params);
$results = $query->queryAll();

$users = EntryModel::populateModels($results);


Get different kind of entries relatedTo one asset (many to one)? I got an asset field called docs which is contained in 2 different entries.
Those entries are in different sections and they contain the docs field directly or through a matrix field called articleBody.

I made two queries relatedTo and merge them thereafter.
It works but would it be a better way by combining the two queries in one relatedTo call?

Query 1: pages section entries contain docs field inside a matrix field called articleBody
Query 2: library section entries contain docs field directly

        $criteria1 = craft()->elements->getCriteria(ElementType::Entry);
        $criteria1->section = 'pages';
        $criteria1->relatedTo = array(
            'targetElement' => $asset->id,
            'field' => 'articleBody.docs'
        );

        $criteria2 = craft()->elements->getCriteria(ElementType::Entry);
        $criteria2->section = 'library';
        $criteria2->relatedTo = array(
            'targetElement' => $asset->id,
            'field' => 'docs'
        );

        $criteria = array_merge($criteria1, $criteria2);

OK in fact it was very simple: criteria params accept arrays...

        $criteria = craft()->elements->getCriteria(ElementType::Entry);

        $fields = [
            'articleBody.efficyDocuments',
            'efficyDocuments'
        ];

        $criteria->relatedTo = array(
            'targetElement' => $asset->id,
            'field' => $fields,
        );


Is it possible to view entries in admin panel list view with specific field? I want to add a checkbox field to all my entries.

But the key factor being that if 3 entries from 100 have this checkbox enabled, the 3 entries will show in the list of 100+ entries with a specific colour/sign/ anything really that makes it stand out and shows that this entry has this field checked.

Im hoping I made sense!

Thanks

You can use the cog at the bottom of the panel to choose which columns to show in the entries table

This then highlights which entries have the checkbox enabled:

Unfortunately, I don't think you can sort on this sort of column with core.

Some plugins may help here, if you want more control, e.g.

https://github.com/mmikkel/CpSortableCustomColumns-Craft

Or for a lot more options/control in this area:

https://zenbustudio.com/software/zenbu-craftcms


Using relatedTo programatically? I'm trying to extend the ElementCriteriaModel using the guide here:

https://blog.tighten.co/craft-cms-building-complex-queries-by-extending-the-elementcriteriamodel

However I need to re-implement relatedTo keyword somehow. This is what I have so far but doesn't seem to work at all

    $criteria = craft()->elements->getCriteria(ElementType::Category);
    $criteria->slug = 'seasonal-event';
    $criteria->limit = 1;

    $category = $criteria->find();

    $this->criteria->relatedTo = array(
        'targetElement' => $category
    );

    return $this;

You're using $criteria, but attempting to set the relatedTo property on $this->criteria.

Assuming that's not the issue, have you tried using $criteria->setAttribute('relatedTo', ['targetElement' => $category])?

I've found setAttribute to be more reliable than the ElementCriteriaModel magic methods.


Category field in entry I am trying to show an image that is defined on a category - named photos. I have an entry page with a list of all category entries listed at the bottom. I'd like to show this image but I'm still green on Craft categories and I'm getting errors in dev mode. This is what I have so far:

{% set entries = craft.entries.section('sermons').find() %}
{% for category, catEntries in entries | group('series.first().title') %}

 {% if category.photos | length %} {# if a photo exists, show it #}
    {% for image in category.photos.limit(1) %}
    {% set params = { width: 300, height: 200 } %}

    {% endfor %}
  {% else %} {# if no photo exists, show a default image #}

  {% endif %}

{# output all category entries #}

   {% for entry in catEntries %}

{{ entry.title }}

   {% endfor %}

{% endfor %}

It wasn't really clear to me if you want to list only those categories that are related to the current entry
or if you want a list of all categories that are assigned to your sermons.

I dont't think the group filter helps a lot in either case and I'd get the catgories like this.

{% set sermonCategories = entry.series %}

In case you don't want them to be ordered by your manual sort order, you need to
get them using a craft.categories ElementCriteriaModel.

{% set sermonCategories = craft.categories.relatedTo(entry).order('title') %}

To get all the categories you'd query for all of your "sermons" entries first.

{% set sermons = craft.entries.section('sermons') %}
{% set sermonCategories = craft.categories.relatedTo(sermons).order('title') %}

The you can start with your loop. I did some small changes, so that only categories with entries related to it will be shown.

{% for category in sermonCategories %}

    {% set relatedEntries = craft.entries.relatedTo(category) %}

    {# Only show category if there are related entries #}
    {% if relatedEntries|length %}

        {% set image = category.photos.first() %}
        {% set params = { width: 300, height: 200 } %}

        {# If a photo exists, show it, otherwise show a placeholder #}
        {% if image %}

        {% else %}

        {% endif %}

            {% for entry in relatedEntries %}

{{ entry.title }}

            {% endfor %}

    {% endif %}

{% endfor %}