Matrix with an entries field and need to grab category title Any help would be greatly appreciated! I hope I explained my situation in enough detail to get the help that is needed.

Currently I have two channels that need to share information. This is going from one channel to an other.

Channel One is called Resellers
This information needs to be feed into my other channel called Products.
Reseller contains info about various resellers, places to purchase a product.
In this channel I have a field for Category. The category is actually a Country name. The rest of the fields are plain text.

Channel 2 is called Products
Products has various fields but I am interested in doing is pulling in info from Resellers and displaying it. I am able to pull in everything from Resellers except for the Category name.

In Products I have a matrix field that contains an entry field and a plain text field.
The entry field pulls in the information about each reseller.
The plain text field allows me to override a field from Reseller to display per product information. I got this part working without an issue.

What I am trying to create is the following structure:
Country name then under the country list out each reseller alphabetically.
You will see Country Name A, A means nothing it just shows alphabetical listing.

Country Name A

Reseller A
Reseller T

Country Name C

Reseller D
Reseller H
Reseller R
Reseller T

Below I have listed out my field handle names that are relevant to this issue.

From Resellers

rdCountry - field where category is selected from

I am able to pull in all other fields easily that are part of Resellers.

From Products

Matrix field - chooseResellers

Entries field - chooseReseller
Plain text field - customProductLink

Again I am able to display each reseller just fine. What I am having issues with is pulling in the Category/Country name. Once I pull in the country name I might need help with setting up my loop to display everything.

Thanks for your time and help, it is greatly appreciated!

EDIT:
So the below code seems to solve my issue listed above. Now I just gotta loop through everything correctly.

{% for entry in craft.entries.slug(entrySlug).find() %}
    {% for block in entry.chooseResellers %}
        {% for reseller in block.chooseReseller %}
            <h3>{{ reseller.rdCountry.first() }}</h3>
        {% endfor %}
    {% endfor %}{# /matrix #}
{% endfor %}{# /for product #}

EDIT TWO - the code solves part of the problem but I do not think will allow me to loop through everything as I was expecting. Help is appreciated!

To achieve structure:

Country Name A

Reseller C

Country Name C

Reseller B
Reseller D

With configuration:

Category Countries

Channel Resellers:

rdCountry (Country Categories) field

Channel Products:

chooseResellers (Matrix) field

block

chooseReseller (Reseller Entries) field

You gonna need code like this:

{% for entry in craft.entries.slug(entrySlug).find() %}
    {% set countries = {} %}
    {% for block in entry.chooseResellers %}
        {% for reseller in block.chooseReseller.with(['rdCountry']) %}
            {% set countryName = reseller.rdCountry[0].title %}

            {% if countries[countryName] is defined %}
                {% set temp = countries[countryName] | merge([reseller]) %}
                {% set countries = countries | merge({(countryName): temp}) %}
            {% else %}
                {% set countries = countries | merge({(countryName): [reseller]}) %}
            {% endif %}

        {% endfor %}
    {% endfor %}

    {% for countryName, resellers in countries %}

{{ countryName }}

        {% for reseller in resellers %}

{{ reseller.title }}

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

Because of the current section/field/relation configuration we need to use countries temporary array to store Country => Reseller structure.

.with(['rdCountry']) is what you call eager loading. It allows you to reduce sql queries, speed up the whole process. With eager loaded entries field you replace find() with index number.

countries looks like this at the end:

{
   "Country Name A":[
      {
         "title":"Reseller C"
      }
   ],
   "Country Name C":[
      {
         "title":"Reseller B"
      },
      {
         "title":"Reseller D"
      }
   ]
}


Filter by category and update URL This may be a simple question but I am not sure how to approach it - again trying to work out best practice for these things!

I have a "single" at /our-work, which among other things displays a projects listing - basically a list of links to the full entry for that project.

I now wish to filter that listing by the category they are in. I also wish to update the URL to reflect that filter e.g. /our-work/branding.

I have got the below code - listing out all the projects with their links, and also outputting the category links for the filter. When the links are clicked I currently I get an error - unsurprising considering the page doesn't exist.

How can I best achieve both the filtering and the required url change? Any help or pointers gratefully received by a craft beginner!

{% extends "_layouts/main" %}

{% block main %}

{% set categories = craft.categories.group('projectType').level(1).all() %}

{% for category in categories %}
  {{ category.title }}
{% endfor %}

{% for project in craft.entries.section('projects').all() %}

    {{ project.title }}

{% endfor %}

{% endblock %}

When setting up the category, you should be able to specify the URI Format which in your case would be "our-work/{slug}" then setting the template field to point where ever your category template is (You could point this at the same template as the overview and do a some checks but if you're beginner you'd probably better off having them in separate files).

Once you're loading in the new template, you need to get the projects that are related to the category by doing:

{% set projects = craft.entries.section('projects').relatedTo(category).all() %}


Search for non-existing tags shows all entries I have 3 groups of tags that redirect to the same template. tags/index.html. All the routing and linking those tags to their group page works well.

<a href="{{ siteUrl }}taggroup/{{ tag.slug }}"

The problem I have is that when I try to enter a tag that doesn't exist on the address bar (e.g., http://sitename/taggroup/unknowntag) I get all entries displayed.

Here's my tags/index.html code:

{% if not tag %}
    {% exit 404 %}
{% endif %}

{% set tag = craft.tags.slug(tag).first %}

{% set entries = craft.entries.relatedTo(tag).order('title').limit(null) %}

 {% if entries | length %}

  {% for entry in entries %}

    <!-- Code Here -->

  {% endfor %}

  {% else %}

   <!-- No Tag Code Here -->

 {% endif %}

What Am I doing wrong? Thanks in advance.

That is only logical. Your tag will be null so your query is actually
{% set entries = craft.entries.relatedTo(null).order('title').limit(null) %} and that results in
{% set entries = craft.entries.order('title').limit(null) %}
So in the end you will fetch all entries.
This is what you need

{% set tag = craft.tags.slug(tag).first %}
<!-- check if the tag exists -->
{% if tag %}
    <!-- the length filter actually fetches all entries -> executes the query and caches all entries
    so you can just fetch them in the beginning. You'll gain no performance boost with that filter -->
    {% set entries = craft.entries.relatedTo(tag).order('title').limit(null).find() %}
    {% if entries %}
        {% for entry in entries %}
            <!-- code here you fetched entries -->
        {% endfor %}
    {% else %}
        <!-- you have a tag but no entries related to that tag -->
    {% endif %}
{% else %}
    <!-- you have no tag -> you won't find any entries -->
{% endif %}


Redactor Single Line Mode Is it possible to configure redactor so it will only accept a single line of text and not wrap it's content in a paragraph tag? Essentially, I'm looking to allow an editor to submit some formatted text (bold, italic, links) but place that inside an existing paragraph tag that is coming out of my templates.

In my tests the paragraphize setting did not seem to fully prevent paragraphs from being generated. Instead { linebreaks: true } seems to reliably convert all would-be paragraphs to <br> tags.

If you're really serious about sticking to single lines then you can go even further and block all forms of line breaks:

{
    deniedTags: ['br'],
    enterKey: false,
    pastePlainText: true,
    linebreaks: true
}

The only flaw with this seems to be that linebreaks still show up in the editor if they're pasted in, but they are stripped when the entry is saved.


Should project config be used during development when migrating from Craft 2? I'm looking for general advice on the best approach to handle a reasonable sized Craft 2 site to Craft 3.1, related to DB changes.

Because the Craft 2 project is live and constantly changing, I regularly refresh my development environment with a snapshot of the Craft 2 database to test the migration process and to work with the latest data from the live project on my development environment.

One of the first problems I encountered was needing to make development changes to the Craft 3 database. These changes could include, adding new fields, updating entry types etc (that is specific to Craft 3), but obviously wiping the dev DB each time would kill these changes. I'm aware project config can store a lot of the changes I'm making, but the issue I found early on was things would get "reset" from each new migration and generate new UID values for certain fields etc. So if I was to replace my project.yaml file to the version that is committed to source, it would usually end with pain and MySQL failures. This made me think that project config isn't necessarily suitable for this specific development workflow.

My next approach was content migrations. This provides a way to write any changes as a migration which would get applied each time the DB was refreshed, this solves the problem of losing changes, as the migration would run as part of ./craft migrate/all and apply them again. As content migrations have full access to pretty much all things Craft, content migrations themselves are quite powerful, so seem like an option.

From a Craft 2 to 3 migration point of view, would it be best to not use project config during development and only enable project config once the Craft 3 migration is complete? It looks like the general advice is to enable project config, copy the project.yaml from the production site and a copy of the DB and apply this to any dev/staging environment to synchronise all environments and then proceed with a more linear workflow going forward.

Any thoughts or opinions on this would be appreciated!

Thanks,

I'll answer this for the benefit of anyone else attempting the same thing i.e. sizeable Craft 2 to 3 migration, while you still have the Craft 2 site live.
Ultimately, I chose content migrations and chose to basically ignore the projectConfig functionality for the most part during development. Since I originally asked the question projectConfig changed a bit and got better, rather than it being one big file it is now abstracted out, so it's easier to manage and conflicts are resolved a lot easier now. You previously could disable projectConfig, you actually can't now for the most part, but you can ignore the config/project path at least during development and not check in these files into your source tree, then enable it when you go live and sync the projectConfig files down from production to all environments to then use it going forward.
I chose content migrations because they are repeatable and will continuously test the same logic on any migration run, this verifies for the most part the integrity and conditions that the migration has on each DB migration test and if it fails, it means integrity has failed and it needs to be reviewed.


Template extraction of namespace node values from RSS using Feedme plugin I'm using the Feed Me plugin in a template to extract data from an RSS feed.

So if the RSS contains the following snippet

<category>Physiology</category>
<pubDate>Mon, 02 Nov 2015 00:00:00 +1100</pubDate>
<dc:creator>Joe Bloggs</dc:creator>

I can extract the data for the first two nodes using {{ node.category }} or {{ node.pubDate }}. But for the third {{ node.creator }} doesn't work and {{ node.dc:creator }} results in an error.

What is the correct way to extract node data that has a namespace defined?

As the example actually shows, you'd reference these sort of nodes using the array notation.

{{ node['dc:creator'] }}


How do I handle named route variables passed to a controller? I'm writing a plugin that uses the registerSiteRoutes hook to create some new routes, and passes those routes to some controllers. In these routes, I have a few pieces of the URL that I'm capturing as named subpatterns. I'm curious how I handle these named variables in the controller that receives them.

To quote @Brandon from here:

  Yep you just need to include a $variables argument in your controller
  function, typeset to an array:

public function actionArchive(array $variables = array())
{
    $variables['year'] ...
}


Pro licence error - Craft is unable to purchase an edition upgrade at this time I'm trying to purchase a pro license for Craft 2. The site was on a staging server which is now uploaded to the live server. At first, there were 2 warning messages. First saying running Craft Pro on Solo license. And another saying you are using a license belonging to the staging site.

I removed the license .key from the config folder and cleared the cache and this re-created the license and cleared the staging site message. However, when I go to purchase a pro license it goes through the fields and ends with a message.

Craft is unable to purchase an edition upgrade at this time.

Does anyone have any idea what is going on and how to resolve this? The site needs to go live today.

Cheers

According to their Tweet it seems there was an error on P&T's end:
https://twitter.com/CraftCMS/status/1085975322443448321


How could I have a plugin hook into when I edit or update a post? What I am trying to do is have my plugin know when I edit a post that is part of a particular section - let's call it "parts" - which then checks to see if a field is filled out in the form and then hits up an API and then pulls information from it and inserts it into empty fields in the entry.

So to clarify, here is a flow of what I'm looking to do:

I create an entry in the section "parts".
Upon saving, it checks to see if the part number field is filled in.
If the field is filled in it will access an external json api and I'll pull a certain value (or in some cases multiple values) from the array.
I then want to have it fill in/update/replace the values in fields that I specify that are part of this entry.

So essentially I am trying to figure out how to: Have my plugin trigger once an entry in a specific section is edited or added and then how I can (off of this trigger) have the plugin insert a value (or multiple values) into specific fields in the entry.

Craft has Hooks and Events which get invoked at different points in the core code. In your case the
entries.onBeforeSaveEntry event would be perfect.

Example:

public function init()
{
    parent::init();

    //Event: onBeforeSaveEntry
    craft()->on('entries.onBeforeSaveEntry', function(Event $event)
    {
        //Is the entry in the section 'parts'?
        if ($event->params['entry']->section == 'parts') {

            //Check if field is a number
            if (is_numeric($event->params['entry']->number_field_handle)) {
                //Do your JSON stuff

                //Replace values
                $event->params['entry']->getContent()->number_field_handle = 'something_else';
            }

        }
    });
}

The init() function goes into your Primary Plugin Class.


Posting from controller to controllers with parameter gives an error public function actionMyPluginActionControllerIndex(){
    $this->myPluginActionController($myVariable);
    return something;
}

public function actionMyPluginActionController($myVariable)
{
    return something;
}

This is giving me the error:

{"error": "Missing required parameters": myVariable"}

I did exactly this with a craft 2 plugin, but somehow this doesn's seems to work in craft 3 anymore, what am i missing?

any help will be appreciated :)

You receive this error because actionMyPluginActionController expects a variable in it's parameters. You'll have to declare a default value

public function actionMyPluginActionController($myVariable = null)

or you need to declare something in your actionMyPluginActionControllerIndex

public function actionMyPluginActionControllerIndex(){
    $myVariable = 'foo';
    $this->myPluginActionController($myVariable);
    return something;
}

Unless you deactivated error messages/warnings on global level (via web config, dev mode off or something else), there is no way this would work in Craft 2 by default


How do I configure multiple environments for console commands? I have built a plugin with some console commands for automating some regular tasks that will be run by a cron job for my site.

In order to get the commands working, I had to replicate my database configuration for the console environment in db.php.

All was well until I realized that each of my environments, local, staging and production will have unique database credentials, but there is only one console environment.

Is there a way I can force the yiic command to use a specific environment via a command line switch, either passing the domain name of an existing environment or additional additional arbitrarily named console environments?

Or is there another way to accomplish this so that the console environment has a unique configuration for each copy of the site?

For the time being I've been able to add an --environment switch to craft/app/etc/console/yiic.php which defines the CRAFT_ENVIRONMENT constant ahead of it defaulting to console, but this seems rather hacky and I'd hope there's a better way to do this.

// Existing switch check starting on line 18
if (isset($_SERVER['argv']))
{
    foreach ($argv as $key => $arg)
    {
        if (strpos($arg, '--configPath=') !== false)
        {
            $parts = explode('=', $arg);
            $frontConfigPath = rtrim($parts[1], '/').'/';
            unset($_SERVER['argv'][$key]);
            break;
        }

        // New environment switch added here
        if (strpos($arg, '--environment=') !== false)
        {
            $parts = explode('=', $arg);
            $environment = $parts[1];
            define('CRAFT_ENVIRONMENT', $environment);
            unset($_SERVER['argv'][$key]);
            break;
        }
        // end new environment switch
    }
}

Alternatively, you could write your own yiic shell wrapper for each environment that defined CRAFT_ENVIRONMENT.

Something like yiicstaging:

#!/usr/bin/env php
<?php

define('CRAFT_ENVIRONMENT', 'staging')
require_once('path/to/craft/app/etc/console/yiic.php');


Freeform ReturnURL to same page I'd like my form to return to the same page with a param ?success.

The page slug is dynamic though so will change depending on what form you are on.

/dynamic-url?success

{% set entrySlug = craft.request.lastSegment %}

                                    {{ craft.freeform.form("landingPage", {
                                        id: "form-landing",
                                        useRequiredAttribute: true,
                                        returnUrl: "{{ entrySlug }}?success"
                                    }).render() }}

Obviously if i just use returnUrl: "?success" it takes me back to the homepage.

The idea of this is so I can trigger facebook events upon form completion, so open to any better approaches.

Thanks

Have you tried using the {{ craft.request.url }} variable in your returnUrl setting?

Also you should be able to format it like so:

returnUrl: craft.request.url ~ "?success"

More details about the craft.request model can be found here: https://craftcms.com/docs/templating/craft.request


Count number of consecutive years in category array I need to count the number of consecutive years a user has been a member of our organization. For example, if they've been a member from in 2018, 2019, 2020 and 2021, their loyalty will be 4 years.
If they've been a member in 2018, 2019 and 2021, their loyalty will be 1 year (they missed 2020.)
I'm currently using Categories to assign a year to Users in Craft to do the assignment of a year to a person.
Hope that makes sense. I would very much appreciate some help on how to tackle it!

If you don't want to build a custom plugin, this would be a good time to use Twig's reduce filter, which takes a set of values and iterates over them to output a single value based on supplied logic.
Using Andy's answer as the basis might look like this (untested):
{% set currentYear = now|date('Y') %}

{% set loyaltyScore = currentUser.years.all()|reduce(
    (score, year) =>
        score == 0 and year == currentYear or
        score > 0 and year == currentYear - 1 ?
        score + 1,
        0
) %}

I'm assuming your data is already in the right order if it's a category group.


How do I target the first item in a Twig for loop? I'm looping through some images and want to target just the first image. How do I do that?

{% for image in entry.images %}
<img src="{{ image.url }}" alt="{{ image.title }}">
{% endfor %}

Twig has loop-variables which can be accessed inside for-loops. loop.first will return true on the first iteration.

{% for image in entry.images %}
    <img src="{{ image.url }}" alt="{{ image.title }}">

    {% if loop.first %}
        Do stuff..
    {% endif %}
{% endfor %}


How can I get the same element ids that the DeleteStaleTemplateCaches Task ends up with before the element has saved? I recently made a plugin that tries to keep the existing cache warm. It does this by listening to the elements.onBeforeSaveElement event, grabbing the id of that element and finding all the paths in the craft_templatecaches table then calls them with Guzzle.

The part I'm struggling with is the element id - when the event fires I just get the id of the element that first fired, in most cases the Entry. How do I ensure I get all of the correct cacheIds from the craft_templatecacheelements table? I only have the one element id, is there a way of ensuring I have all of the involved element ids?

I tried getting element ids from craft_relations by sourceId but still don't seem to be able to replicate the same kind of behaviour that the native cache clearing does. When I save an entry I get a bunch of element ids in the DeleteStaleTemplateCaches Task settings but can't find a way to get that same set of ids before the element saves.

I feel like I'm missing something fundamental ...

This is not much of an answer but basically Brad was right - I just needed to replicate the logic that the DeleteStaleTemplateCachesTask does in its getTotalSteps() and runStep() methods.

This allows you to work out exactly what caches will be just about to be deleted. I'm not going to post the code here as it is literally a copy/paste from the DeleteStaleTemplateCachesTask.


Migrations for Deployment Currently each time we make changes to our dev instance of our Craft install (add fields, plugins, change settings in CP), we dump the database and upload it to the production database server. This gets messy now that our production database is accepting guest entries. We obviously do not want to overwrite those changes.

Is there a recommend workflow for this situation.

Joining in at this point. We have some sites powered by Craft which need to get some updates. Its absolutely acceptable if the dev version is outdated regarding the content. Making content changes should not be our job, and we mostly work with placeholder and testing content anyway.

The whole next procedure is optional, so enabling this behavior with a config param (or auto-enable when using dev-mode) might be the best idea.

Best would be to write structural changes along with non-content-related settings like asset transforms, plugin settings etc into a file called "_migrations.sql".

Before pushing an update from "dev" to "production", you simply need to press a "increment database structure version" button which then renames the file to "migrations-($v+1).sql". Also the version number in the database gets incremented so the saved version number is directly up-to-date with latest migration file version number.

If an update then goes live, the production database will be behind latest migration file version and executes them like the craft migrations do, incrementing the structure version in database too. Database will be fully up-to-date at this point without overwriting or changing any entry or asset.

In combination with git we could put these migration files under version control so they get part of the commit without committing all the other trash that changed in the database while working on it.

As long as this is not possible from Craft itself, a dump must be made before and after changes are made and manually processed to create migration by hand, which also must be manually executed on production environment. Depending on the amount of changes this can be very frustrating and time consuming.

Making the web developers spend less time and struggling on daily problems would cause more time for more projects to be made with craft. A win-win situation on both sides.


Execute Plugin init function one time Is it possible for me to execute any "init" like function for my Plugin the first time the user visits the site? You could say when the first userSession is defined.

I tried looking through the docs to see if there was any Event for when the user session is created but I couldn't find any.

I want to add some default values to the userSession the first time the user hits my site.

Sessions are initialized by Craft, and plugins are loaded/called after that, so you'll have to assume the session is already up.

Not sure about your use case, but here is how you could execute code once per session:

if(!craft()->httpSession->get('initialized'))
{
    /*
    Your code executed once per session goes here
    */

    craft()->httpSession->add('initialized', true);
}


Swapping currency when swapping languages Folks:
I have a multilingual and multicurrency site. All works fine when switching currencies or languages independent of one another. But is there a way to have the currency switch when the language is switched? For example, if the user selects German, the currency is switched to Euros.
To complicate matters, I am using GeoMate to detect the IP and redirect to the appropriate language. Can I switch to the correct currency when they are automatically redirected to their language?

You can switch currencies in the following ways:
https://craftcms.com/docs/commerce/3.x/payment-currencies.html#switching-currencies
It looks like GeoMate would need to add support to switch the currency for you using one of the above methods.


Live Preview for Upcoming Entries I have an Events section on my site, and to display upcoming and passed events (entries with a status of pending or expired) I manually set the entry in the template:

Where the URL is /events/my-event-title

{% set entry = craft.entries({
    section: 'Events',
    slug: craft.app.request.segment(2),
    status: ['live','pending','expired']
}).one %}

<h1>{{ entry.title }}</h1>

{{ entry.body }}

This works great except when I go to publish a new Event and use the Live Preview. Since the new entry doesn't have a slug yet, the craft.app.request.segment(2) variable returns null, and so entry returns the last-published Event entry instead. So all of my template variables are pre-populated with a different entry's content.

How do I set this up so my Live Preview displays blank until I enter content?

If your “event” Entry's Section settings define a URI and a template path, Craft will take care of defining entry in the template. No need to look it up by segment!

Generally speaking, this will “just work” for Live Preview, as well.

 I'd recommend setting the Event Section's Template to _events/event, and creating templates/_events/event.twig in your project folder. Then, entry will be automatically available when the template is rendered, either from a front-end request, or via Live Preview.

I can't speak exactly to the internals of Live Preview—but I can say that it side-steps the normal routing by laterally POSTing the updated content to a Craft Controller that independently resolves and renders the template. That said, once it starts rendering the template, it's almost exactly the same context you'll get when the Entry is live, and requested via its normal URL.

   Using an underscore in the template's path will make sure the template is not directly accessible, and is only rendered during a request that Craft has determined matches an Element (in your case, the event Entry), or via the Live Preview controller. Read more about how Craft routes requests, here.


How to find entries with no category I have a field categories in a channel news, and I want to find all the entries in news that don't have a category set. I know I could loop over the entries and find them that way, but I'm hoping to do it with a query. I tried

{% set uncategorized = craft.entries.section('news').categories(':empty:') %}

But it returned none.

You can do this in a single query using the search parameter:

{% set uncategorized = craft.entries.section('news').search('-categories:*') %}

More on searching here.


Element API calling Module that integrates with third-party plugin This is probably a bit niche but anyone especially au fait with the element api here?

On project X I have a custom module within which I am referencing a service from another plugin (bolden/google-maps-api). If I access the module directly (eg via a controller or variable belonging to my module) then all works fine.

However - if I try and access my module service from within an element api endpoint, then the service doesn't work (or rather returns null when trying to access the third-party plugin/service).

For example, in my endpoint I am calling the service ($location is a string):

$data = MyModule::getInstance()->ServiceName->ServiceMethod( $location );

But this returns the following Response: Call to a member function placeFromText() on null (the stack trace highlights the corresponding line within my module/service), eg:

$googleMaps = GoogleMapsApi::getInstance();
$result = $googleMaps->googleMapsApiService->placeFromText( $place, 'geometry' );

The same query, when accessed within my module (eg a controller or variable), works fine and returns a data object from the Google Maps API (as expected).

Bit confused - anyone have any thoughts on why this service isn't accessible from my module when accessed via the element API?

Any thoughts on this issue would be much appreciated!

Cole

You have to use full namespaces in Element API because anything within those functions is out of scope. So you need to use the full path to the Google class.

$googleMaps = new \Vendor\Module\GoogleMapsApi();

Putting a "use" directive at the top of the file will not work.

I had the exact same problem and that resolved my issues immediately.


Conditional check if Matrix block field is empty (no content) I'm having a difficult time with what seems like a fairly straightforward problem:

I'm listing businesses and their related hours of operation (days/times). I'd like to set up a conditional statement that checks if a Matrix field has content—if so, display hours. If not, display message. My code is as follows:

{% if entry.hours.block('days')|length %}

      {% for block in entry.hours %}

        {{ block.days }}
        {{ block.times }}

      {% endfor %}

{% else %}

We're still trying to track down hours.

{% endif %}

I've also attached a screenshot of my Matrix setup. Thanks so much in advance]1

I'm assuming your matrix field is not called hours? Because in your current code you are handeling it like it is.

I think this should work

   {% for block in entry.matrixfieldHandle %}
       {% if block|length %}
           {{block.days}} - {{block.time}}
       {% else %}

Do something else

       {% endif% }
    {% endfor %}

In your code you want to loop over all the different entries (blocks) within the matrix. If you want to add other types you can easely check for hours like so:

{% if block.type == "hours" %}
   do stuff
{% elseif block.type == "anotherblocktype" %}
   ...

However. Since you only use one type of content I'm not sure if a matrix is the best solution. You could easely put this in a table or supertable .

Then you could just do

{% for row in entry.tableHandle %}
   {% if row|length %}
       {{row.text}}
   {% else % }

Fallback

{% endif %}

Another option is to check this little plugin: Store hours


Disable entry versioning Had a quick search online and I can't find a way to disable entry versioning.

Is this possible? There's some plugins that do this but I'm hoping there's some config I can set somewhere?

No need for a plugin, just don't check this option


How to check whether a named Asset Transform exists? I'm using asset transforms in various places to serve appropriately sized images via a Twig macro that I feed an entry and the name of a transform into (the idea is to have the same bit of HTML, but with differently sized images depending on the context). The way I get the image URL is as follows:

entry.mainImage.first().getUrl(transform)

However, at the moment if the named transform is not found (ie. if the value of transform doesn't correspond to the name of an existing transform) I get a Craft error. For my purposes a better failure mode would be to just serve the untransformed, full-size image. I'm wondering if there's a way of checking whether a named transform exists? That way I could just set transform to null if it's not found and it should fail gracefully.

You can check for the existence of a transform within your controller (for example), as follows:

 if (craft()->assetTransforms->getTransformByHandle('jimbob')) {
      // Transform exists.
 } else {
      // Transform does not exist (null is returned).
 }

Unfortunately, there doesn't seem to be an equivalent service (such as craft.assetTransforms) for use within templates.

Stephen


Unavailable plugin during migration to craft 3 During a migration from craft 2 to craft 3, I stumble in 3 issues with plugins.

Plugins are not available in craft 3. For example,"instablog" plugin
Reinstall paid license plugins.
Custom plugins.
What should we handle in different cases?

When updating from Craft 2 to Craft 3, you will need to make a handful of decisions on how to handle plugins that don't have a clear migration path. The answer may be different for each plugin, depending on various circumstances.

Moving forward with dead plugins, you'll generally need to...

Replace it with a completely different plugin, or
Port some version of the necessary code into a custom module, or
Figure out how to replicate that behavior using native Craft features, so you can skip using a plugin or module completely.

If you bought a Craft 2 license for the plugin, see if there is a way to transfer your license to Craft 3. How this is handled will vary greatly between plugin vendors, so you'll need to follow up with the plugin vendor directly.
For custom plugins, you'll want to convert those into a module. It's like a plugin, but different.


How do I display entries from multiple entry types? I have a 'teacher' channel section on my site. That channel has three entry types, 'teacher', 'demoTeacher' and 'guestTeacher' - how do I display entries from teacher and demoTeach combined? At the moment I'm showing one type like this:

{% for teacher in craft.entries.find({section: 'teacher', type: 'demoTeacher'}) %}

Secondly, how can I use a conditional that checks for entry type? I need do something like the following (pseudocode):

{% if entrytype is demoTeacher %}
    display read more button
{% endif %}

You can set the ElementCriteriaModel's type parameter to multiple values by passing it an array of entry type slugs:

{% set teachers = craft.entries.section('teacher').type(['teacher', 'demoTeacher']) %}

Use the type property on the entry model to access its entry type in your conditional (also see this list for other available properties).

{% for teacher in teachers %}

    {{ teacher.title }}

    {% if teacher.type == 'demoTeacher' %}
        ...
    {% endif %}

{% endfor %}


Differences between Craft and WordPress This is a super high level question but it would be good to get a couple of summary answers.  What are the main pros and cons of Craft versus WordPress?

I have a lot of experience with WordPress (8+ years), and I like it. I have less experience with Craft (obviously), though I like it more. Here's my 2 (obviously opinionated) cents regarding WordPress vs. Craft:
Benefits of WordPress (vs. Craft)

Free (although a Craft Pro license is super cheap, and you typically need at least 2 or 3 paid plugins to make WordPress usable as a CMS)
Open source (although Craft is built on Yii, which is open source as well, and the full Craft codebase is on GitHub)
Huge community & amount of resources available – although actually sifting through it all and finding quality content can be a chore/difficult – a lot of it is outdated or just bad practice
High quality 3rd party services available for hosting (WPEngine etc), backups/security (VaultPress) and core management (ManageWP) – although if stuff like that is your thing you can use similar services w/ Craft installs; they're just not tailor-made to Craft
Plugin management. Being able to search for, install and update plugins from the Dashboard is great – although Craft will soon have its own built-in "plugin store" and it will be curated, which is a huge plus. Update: Since writing the original answer, Craft 3 has launched and has a built-in Plugin Store inside the Control Panel, which can be used to browse, install, manage and purchase plugins (all commercial plugins have trial versions, and there are loads of free ones too). If clicking buttons in a virtual Store is not your thing, Craft also has first-party support for Composer)
WooCommerce is good (and free) (although Craft Commerce is out and is looking very nice) Update: Craft Commerce 2 beta is now available, and is looking even nicer
Dashboard is easy to use (though I think Craft's CP is on par and IMO makes a better job with keeping things clean and simple)
The built-in media library/uploader/image editing is pretty good (although it still doesn't have folders. Why on earth doesn't it have folders) ** Update: Craft 3 has a simple image editor for cropping, rotating and focus points**
There's a plugin for everything (...and you'll need them. In my experience, Craft installs typically needs fewer – and more to the point; less CMS-critical – plugins.)
There's a hook or filter for everything (although with their inconsistent naming conventions and priority hell you'll quickly build yourself a maze if you're not careful. Craft primarily uses well-documented events to enable plugin authors to "hook" into and affect the app lifecycle, with fairly self-explanatory names)
WordPress has multi-site (although it's pretty half cooked and loaded with gotchas) **Update: Craft 3 also has multi-site, although it's less geared to the use case of running completely separate sites under the same CMS install, and more to the use case of maintaining separate content for different target groups/languages/etc)
WordPress is stable as hell. Not that there aren't bugs, but breaking changes are very rare (there are "deprecated" APIs still in the codebase that are years old). The WP core team is super focused on backwards compatibility, which means important stuff aren't likely to change in a big way anytime soon – however, it also means that much of the codebase is outdated and/or inconsistent. In comparison, Craft is still fairly young and feels much more in flux. This doesn't mean that Craft breaks all the time – it doesn't, bugs are relatively rare and P&T have generally been super quick w/ bug fixing. Compared to WP, there have been bigger changes between major versions, though (mainly for plugin developers, not so much in terms of frontend code/templating or content modelling). Basically P&T/Craft is dedicated to staying modern and lean whilst WordPress is dedicated to not pissing off a gazillion users. These are very different approaches to building and maintaining a CMS, and one may resonate more for you than the other.
– WordPress has a RESTful API built-in. I haven't tried it, so I couldn't say if it's any good. Craft doesn't have a REST API in core, but for the quick'n'easy stuff there's the first party Element API plugin. Beyond that, since Craft 3 came out it's actually quite easy to go totally headless with Craft.

Weaknesses of WordPress (vs. Craft)

No templating engine (some might deem this a good thing. I'm not among them; personally I recommend Timber for using Twig in WordPress themes)
No advanced custom fields – although ACF exist and is a must-have for any WP install. Full disclosure; I actually prefer parts of ACF to Craft's built-in custom fields – for instance its export/import and conditional functionality is stellar. Update: In place of the WYSIWYG of yore, WordPress has this new-fangled thing called "Gutenberg" now, which is kind of like a core modular content system. I haven't tried it, but personally I think it looks like a total trainwreck. Also, both conditionals and import/export is supposedly coming to Craft core in a 3.x update
WordPress is not really a CMS, but a blogging platform – no matter what they tell you. Unless you're building a traditional blog, you'll constantly be fighting the core (yes WordPress has custom post types and taxonomies, but they feel tacked on and are cumbersome to work with, compared to Craft or ExpressionEngine)
The architecture. Most of WP's core and its theme/plugin APIs aren't even OOP, forget MVC. Again I recommend Timber, which in addition to adding Twig support enables you to build themes using an optional, pseudo-MVC pattern.
There's a lot of redundancy. Even as a fairly basic blog platform, there's a ton of built-in functionality in WP that you'll never need for the average site, and that you will want to remove or deactivate. It's like starting with a Pollock painting and applying paint remover until you have something you can draw on, instead of just starting with a blank sheet of paper in the first place
Obtuse APIs (naming conventions are practically nonexistent and the APIs are super inconsistent, which means you need to look up everything)
Security issues (though its actually very easy to secure a vanilla WP install, its still an issue and always will be, as long as WP is the most popular CMS on the planet)
No built-in multilingual support (WPML is decent, but fairly pricy and also big and slow, in my experience)
WordPress is really strict and opinionated about routing, and creating custom routes is needlessly complex (although Timber will help out here, as well)
Hierarchical content and custom ordering is hell (there are plugins but ew)
Confusing relationship between presentation and content. In WordPress, any custom post types or taxonomies is creating w/ PHP code, usually residing in your theme. This creates a confusing relationship between presentation and content modelling which is totally absent in Craft. The big paradox here is that while Craft isn't really designed to be "theme-able", it still has a much clearer separation between content and presentation than WordPress. (Related WP pro tip: Consider building a custom plugin to add your CPTs and taxonomies, keeping it out of your theme)

Closing notes:
The above is obviously quite opinionated, and I'm clearly partial to Craft.
Obviously, just like with Craft you can basically build anything with WordPress and I find that for the most part, the two systems are fairly interchangeable. There are a few use cases where Craft is obviously the better choice though – e.g. multilingual sites, or sites w/ a lot of hierarchical content. Apart from blogging, I'm having more difficulty coming up with use cases where WordPress is a more obvious choice, which says a lot.
In my opinion, if you're new to both WordPress and Craft, I personally think the experience you'll gain using Craft will be more portable and valuable in the long run, and that you'll experience far fewer gotchas, headaches and WTFs in the process.
Personally, the #1 pro for me w/ Craft vs. WordPress is has been that almost from the get-go (there's a learning cure, sure), I was able to work more effectively w/ Craft than I ever did in WordPress, and I felt more confident about the quality of my work – even with the mentioned 8+ years experience with WordPress. The super consistent codebase/APIs, stellar documentation and Twig templating are important factors here. I also prefer the smaller, super dedicated community around Craft, this SE and the official Slack team being good examples.
PS: I should also note the excellent official support Craft comes with, courtesy of Pixel and Tonic.


Modify an ElementCriteriaModel to compare against numeric field Can anyone tell me why this is returning all entries instead of entries with a creditsUsed field > 0? creditsUsed is a number field that I created for this entry type.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->authorId = craft()->userSession->getUser()->id;
$criteria->section = 'news';
$criteria->creditsUsed > 0;
$criteria->status = null;
$entries = $criteria->total();

Here's what's actually happening with this line of code...

$criteria->creditsUsed > 0;

You are actually generating the boolean value of "is creditsUsed more than zero". Granted, you aren't setting it to an actual variable, but nonetheless you are generating a boolean value. For example:

$moreThanZeroCreditsUsed = ($criteria->creditsUsed > 0);

Even though you're not assigning that new boolean value to a variable, it's still valid PHP (and therefore no error is thrown).

What it looks like you are trying to do instead is to actually set the value of creditsUsed, which you'd need to use an equals sign to do:

$criteria->creditsUsed = "whatever";

If my memory serves me correctly, the way to denote a comparison on an ElementCriteriaModel is to simply pass the comparison as a string:

$criteria->creditsUsed = "> 0";

See the last example in this subsection... Granted, it's being applied via Twig syntax, but it's still modifying the ElementCriteriaModel in the same way:

craft.entries.width('>= 100')


What's the best way to build URLs for dynamic content collections? I'm working on a project where we need to post publication Editions, each containing any number of Stories, of which there can be one of three entry types. The URL structure we're shooting for is foo.com/pub/edition-slug/story-slug, and I'm not sure how to set the "URL Format" field for each Section.

For example, I've set the Editions Section to pub/{slug}, and have tried setting the Stories Section to the following...

pub/*/{slug}: literally includes */ in resulting URL
{parent.last.uri}/{slug}: only results in foo.com/story-slug

My questions, then:

Is it possible to dynamically reference a parent Section's slug when we're not in a Structure?
If no to #1, is there a more appropriate layout (rather than two independent Sections) that'd allow the Edition > Story relationship given that Editions and Stories are distinctly different? (I'm avoiding a Structure because I can't rely on editors not to make a Story top-level with nested Editions, for example—no way I understand to enforce that Edition > Story hierarchy.)

I can get the URLs working with a custom route, but at the loss of a proper Live Preview and the other benefits of clean URLs like sitemap generation, etc.

You need that custom route. With the dynamic URI setting the "entry route" is generated dynamically on entry save, but it stores a single, fixed route only.

But you don't have to miss out on Live Preview when you leave the "entry route" enabled in addition to your custom route. Set up separate Live Preview URIs that you don't link to and if you prefer you can 404 the request for all non Live Preview visits.

{% if not craft.request.isLivePreview %}
    {% exit 404 %}
{% endif %}


Uninstalling a plugin from Craft control panel I'm new to Craft CMS and I'm having trouble figuring out how to uninstall a plugin.  Specifically, it's the "Redactor Custom Styles" plugin.
I gather from searching (please correct me if I'm wrong) that I need to first uninstall it from within the Craft control panel, and then use composer to remove it i.e. composer remove vendor/plugin-handle.  I'm stuck on the first part of that.
Within my control panel, I can't seem to find a list of installed plugins anywhere. The only way I can even see that Redactor Custom Styles plugin is installed is by going to the Plugin Store, searching for it again as if I was going to install it, clicking the result, and then I see a checkmark and "Installed".  However, there's no option to uninstall it.
I must be missing something. Can someone point me in the right direction?

Settings > Plugins
There you will find a pulldown for each plugin with an uninstall option.


Can I use Twig in a FreeForm html field? Is it possible to use the {{ siteUrl }} Variable in a html Field in freeform? I tried it and it threw an error that the variable was not valid. Is it possible to use twig in a html field?

Thanks Kelsey: "Sorry, unfortunately you cannot, as these fields are pre-rendered beforehand. Kelsey Martens"


How do I get a list of craft provided events at runtime? The documentation provides a very comprehensive list of events provided by Craft  but I would like to know if there is a way to get a list of those events at runtime.

Having such list would enable me to display a <select> field whereby a user could choose the event that should trigger an action.

Think of it as dynamic event registration!

Events don’t get pre-registered anywhere in Craft, so there’s no way to easily fetch a definitive list of all events that will ever get called, but with a little PHP we can get a pretty good idea of what they all are.

You’d start by getting a list of all the components on WebApp (what craft() returns) by calling its getComponents() method, loop through each of them, use reflection to get each of their methods, and find the ones that start with on. (By convention, all event methods should start with that, and non-event methods generally shouldn’t start with that, although it’s possible this will yield some false positives, so make sure you double-check the results.)

$events = [];
$components = craft()->getComponents(false);

foreach ($components as $id => $component)
{
    // Skip some non-existent components
    if ($id == 'fieldTypes' || $id == 'file')
    {
        continue;
    }

    // If the component hasn't been loaded yet, $component will just be its config array
    if (is_array($component))
    {
        $component = craft()->getComponent($id);
    }

    // Find the event methods
    $class = new \ReflectionClass($component);
    $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);

    foreach ($methods as $method)
    {
        if (strncasecmp($method->name, 'on', 2) === 0)
        {
            $events[] = $id.'.'.$method->name;
        }
    }
}

// Dump 'em out
Craft::dd($events);


How do you display a file asset (PDF) in the template? I have an asset field (dataCard) which I use to upload a single PDF file tied to an entry. I'm trying, unsuccessfully, to display the asset tied to the entry on a page listing multiple entries. How would I do this? This is what I have so far:

{% set asset = entry.dataCard.first() %}

{% if asset %}
    {{category.title}}
{% endif %}

What do you mean by 'display the asset'? Showing a thumbnail is not an option, because no thumbs are made for PDF files. If you'd want to show the filename, for example, use the filename property of the asset.

If the page contains multiple entries, you'd have to loop through the entries first. Then, for each entry, check if it has an asset in the desired field (by using | length, after which you can display the asset.

{% for entry in craft.entries.section('bla').relatedTo('bla') %}
    {% if entry.dataCard | length %}
        {% set asset = entry.dataCard.first() %}
        {{ asset.filename }}
    {% endif %}
{% endfor %}


Access Image Transforms for S3 images via Element API I'm building a small Craft site to function as a content backend, exposing all of the content via the ElementAPI.

One field I'm retrieving and displaying in the API is the URL on Amazon S3 for an image asset that's contained in a Matrix field.

What I'd ideally like to do is, when the user uploads this image and it's added to the S3 bucket, to be able to access S3 URLs for the small, medium and large cropped Image Transforms that I've defined. Then, I can make all of these available as an Element API endpoint.

My understanding of Image Transforms and S3 is that Craft usually handles this on-the-fly when an image is referenced in a frontend template. But is there a way to do this when there will be no frontend templates, and the only way that information will be accessed is via the Element API?

Yep, you can access transforms the same way you would in a template - via the asset’s getUrl() method.

That $transform argument can either be a string, set to the handle of one of your transforms in Settings → Assets → Transforms, or in can be an array that defines the transform settings at runtime. (Or it can be null if you just want the source image URL.)

Keep in mind that if the transform hasn’t been created yet, the default behavior of getUrl() will be to return a temporary URL that actually triggers the transform generation process, and responds with a redirect pointing to the new image once it has actually been created. But in this case you’d probably prefer for the transform to be created in the actual Element API request, so the actual URL can be returned right off the bat. You can do that by enabling the generateTransformsBeforePageLoad config setting at runtime.

So your transformer function would look something like this:

'transformer' => function(EntryModel $entry) {
    // Generate new image transforms right away
    craft()->config->set('generateTransformsBeforePageLoad', true);

    $blockData = [];

    foreach ($entry->myMatrixField as $block) {
        $image = $block->myAssetsField->first();

        if ($image) {
            $imageUrl = $image->getUrl('myTransform');
        } else {
            $imageUrl = null;
        }

        $blockData[] = [
            'image' => $imageUrl,
            // ...
        ];
    }

    return [
        'blocks' => $blockData,
        // ...
    ];
},


Image alignment and size in Redactor 2 Redactor I had a feature that allowed editing of image alignment (via the image popup) and size (by dragging the square bounding box), is it possible to enable this functionality in Redactor II?

Is this something that can be done with formattingAdd?

No need for a plugin.
Just add:

 "imageResizable": true,
 "imagePosition": true,

to your chosen redactor config file i.e. (/craft/config/redactor/standard.json)


Live Preview and CDN caching We have a problem with using Live Preview on a site that uses CDN caching [CloudFront].

When opening Live Preview a POST is sent to the actual page URL containing the information and the response is rendered

/mypage

However /mypage is in the CDN cache for GET requests and so when Craft sends the POST the headers and cookies are not forwarded to the origin. This causes a 400 error.

We tried using a subdomain just for the CP, but of course the site is still on the cached domain and this is the domain used by the CP.

Is there a way to use live preview with CDN caching?

One potential approach would be to have a cookie set that is only set for logged in CP users, then we can set up a cache rule to bypass the CDN cache for all requests with that cookie.

Unfortunately our hosting partner informs us that we cannot have different caching profiles based upon a cookie. So we really need the Live Preview POST to be to paths that are not the actual cached live site paths.

If it were me, I wouldn't use Cloudfront to offload the entire site. You can certainly use it for static assets but cache invalidation is really expensive. And as you've found it, troublesome. By offloading the static assets, you can keep the web server focused on just serving page requests.

From your previous question, it sounds you get a fair amount of traffic.

Cache invalidation is a tricky subject. I don't know how often you update but a middle-of-the-road approach is using nginx or varnish.

I like nginx myself because of its flexible fastcgi_cache. Even if you set the cache low, like 1 minute, you've just increased your capacity by an order of magnitude without much additional work on your part.

nginx also allows you to cache by location so you could exclude caching any page with a form. POST requests by default bypass the cache.


How to use createFromString() in Craft 3 In Craft 2 I've used createFromString() as following:

DateTime::createFromString($pubDate, craft()->timezone)

But if I use this function in craft cms 3 then I'm getting the following error:

Call to undefined method DateTime::createFromString()

Is there any alternative way to use the createFromString() in Craft 3?

You're looking for the toDateTime() method in the DateTimeHelper class:

DateTimeHelper::toDateTime($pubDate, true);


"Craft isn't installed yet" error after updating to Craft 3.1 I just updated to Craft 3.1 and logged into the admin to make the required updates to the database and this all worked fine. However, when I use the new ./craft update CLI feature, it responds with "Craft isn't installed yet", even though it's on a year old Craft project and just successfully updated to Craft 3.1?

There's not really any other messages to go on for this one. See below.

Have you tried running ./craft setup to double check if your setup is correct?

If ./craft setup completes successfully ./craft should find the existing installation and complete any required setup.

In my experience, this is usually related to a non-default /config/db.php or problematic .env file.

Note: Always do a backup before trying anything related to setup just to be on the safe side.


Cache Order and Priority When {% cache %} in conjunction with {% include ... %} is it better to wrap the Cache outside of the include or put inside of the included file?

{% cache %}
    {% include %}
{% endcache %}

or

{% include "..." %}

with the cache directives inside the include file?

Assume for this question that the entire contents of the include file will be cached (complex nav).

It doesn't really matter where you have the tags. Yes, you do save the overhead of the include by wrapping the tag, but the impact is minimal (not really measurable) and once compiled to PHP it's cached anyways.

I usually have the cache tags within my partials. It's more flexible, you can cache blocks of code separately and leave out certain parts. I also often use the globally flag and include a partial into multiple templates. Defining the cache tag within the partial makes sure I always use the right cache ID.


wp-login.php bloating log files every 20-30 seconds Hi has anyone come across this before. It seems like a hack attempt on the site from a bot trying to access it as a wordpress site. This is obviously causing loads of errors in the log files bloating them and making it hard to find any real logs. Is there anything we can do in craft or on the server to block these attempts?

So what I do is I just redirect anything requesting a WordPress-ish thing to WordPress.com (that's what they are looking for, after all...). You can see how to do that here if you're using Nginx:

https://github.com/nystudio107/nginx-craft/blob/master/sites-available/somedomain.com.conf#L67


How can I make my custom FieldType show up in an element index? I've built a custom FieldType, and I'd like editors to be able to add any fields using this FieldType to element indexes. Unfortunately, fields using my custom FieldType aren't included in the list of fields in the Customizable Element Index configurator.

How can I make it possible to add fields using my custom FieldType to element indexes?

Also, is it possible to define how the value returned from my custom FieldType displays in the element index?

To make it possible to select fields from a custom FieldType in the Customizable Element Indexes interface, your FieldType class needs to implement the IPreviewableFieldType interface, like this:

class ExamplePluginHandleFieldType extends BaseFieldType implements IPreviewableFieldType
{
    ...

If you want to modify how the values from your custom FieldType displays in element indexes, you need to add a getTableAttributeHtml method to your FieldType class:

public function getTableAttributeHtml($value)
{
    return $value ? $value->id : null;
}


What's the function of the Stalled Tasks menu option? Just wondering...

What is the function of the Stalled Tasks menu option?
What is it supposed to do when clicking on it?
Is it normal for it to be there... all the time?
Is it normal for the browser to freeze when I click on it?

What is the function of the Stalled Tasks menu option?

To let you know there is currently a stalled task, to show all of the subsequent tasks that stalled task is blocking and in some scenarios, give you a chance to restart the task.

  What is it supposed to do when clicking on it?

Show a modal with the stalled task and (potentially) other tasks that it is blocking.

  Is it normal for it to be there... all the time?

Nope. The underlying reason that task stalled should be debugged and fixed. https://craftcms.com/support/stuck-tasks

  Is it normal for the browser to freeze when I click on it?

Nope.


Only allowed 100 queries with relatedto? Despite using null and paginate false i can still only return 100 queries with this:

{% set results = craft.entries({
    limit: null,
    paginate: false,
    section: 'directory',
    relatedTo: relationParam
}) %}

How do I get all of them?

* UPDATE *

Well I found the problem and solution which is a bit strange - makes no sense to me.
I am passing relatedTo a merged string 'relationParam' which has the mulitpple categories I want to search for. Once I set the limits on the categories that are related to the entries -see below - it all works.

{% set c = craft.categories.group('locations').slug(countrySlug).limit(null) %}
{% set p = craft.categories.group('locations').slug(portSlug).limit(null) %}

So what doesn't make sense to me is that I am having to set the limit outside of the main entries query. I would have thought the entry limit specification would do this  not on the categories related.

The reason this happens is Craft has a default limit of 100 for all ElementCriteriaModel objects (this includes assets, categories, entries, tags, and users, also relations as you encountered).

This isn't made terribly clear in the documentation, but you can see it under the defineAttributes() method on the ElementCriteriaModel class reference page.

As you discovered, adding a .limit(null) parameter overrides that limit.


Excluding previous entries First time here so excuse me if I get the etiquette and protocols wrong.

I am trying to pull eight featured stories into a page, the first two into a large two column grid and the rest into a three column grid.  Try as I may I can not get this to work... I have searched around here for various solutions but none seem to be exactly what I am trying to achieve, or I have the know how to adapt.

I am trying to exclude the first two entries from the second section but want the whole display to be random. I am guessing the array string of ids() is not being parsed or set up correctly but frankly I am a bit lost so any help would be very much appreciated.

So far I think this is the closest I have come.

    {% set featuredStories = craft.entries.section('work').type('projects') %}
    {% set big = featuredStories.order('RAND()').limit(2) %}

    {% for entry in big %}
        <— stuff —>
    {% endfor %}

{% set bigIds = big.ids() %}
{% set bigIdsString = bigIds | join(', not ') %}

{% set allEntries = featuredStories.id('and, not '~bigIdsString) %}

    {% for entry in allEntries %}
        <— stuff —>
    {% endfor %}

I'd probably try is something like this:

    {# Grab all (8) stories in a random order #}
    {% set allStories = craft.entries.section('work').type('projects').order('RAND()').find() %}

    {# Now loop through only the first two items in the array #}
    {% for entry in allStories|slice(0, 2) %}
        <— stuff —>
    {% endfor %}

    {# Now loop through items 3-8 in the array. #}
    {% for entry in allStories|slice(2, 6) %}
        <— stuff —>
    {% endfor %}

Documentation for the Twig slice() method can be found here: https://twig.sensiolabs.org/doc/2.x/filters/slice.html


Add options to multi-select with Javascript Well, I need to add options to a select field with Javascript. I do that with $(...).append(...), the problem is that I get a "Invalid" message. I think it's because the new option's value is not in the available options.

My question is then: Can I add a wildcard to the options? or bypass the validation for this field?

Any better idea?

Thanks!

Your best option would be to create a custom field type. That's quite a bit of work, though.

Failing that, you could add an extra "Other" option to the select field, and create a separate text field to hold the "free form" option.

Caveats

Craft isn't able to automatically validate the association between two fields. In other words, there's no such thing as "if the user selects the 'other' option, then she must also complete the 'Other' field".

If this is a must-have, you could implement some front-end validation, by injecting custom JavaScript into the Control Panel. Once again, a plugin is the best way to go here, but you may also be able to piggy-back on something like craft-cpjs, by Lindsey Diloreto.


List of reserved field handles Is there somewhere documented on what field handles are reserved? Would be great to have this as a resource here, especially for plugin development.

Edit: A good place to start would be https://github.com/craftcms/cms/tree/master-v2/src/records/FieldRecord.php#L24

For those wondering, here is the link to Craft 3 reserved words:

https://github.com/craftcms/cms/blob/ae64588a4963b06a093636be6686345bd3a9bca8/src/base/Field.php#L190


Using embedded assets plugin to display youtube or vimeo embed urls on a template I'm trying to use the "Embedded Assets" Craft plug-in to embed Youtube and Vimeo videos in a matrix field, but I can't figure it out. I've read through the instructions on the Github page but I can't make sense of it.

I have successfully installed the plug-in, and it seems to be "grabbing" the videos correctly since I can see the video in the assets section and the json files are in the folder on my disk.

I put this twig code from the instructions of the plugin provider in my template:

{% for asset in assets %}
    {% set embed = craft.embeddedAssets.fromAsset(asset) %}
    {% if embed %}
        {{ embed.safeHtml|raw }}
    {% endif %}
{% endfor %}

but it breaks my page.

This is the error message I get, saying the variable "assets" does not exist:

52         <div class="video">
53                 {% for videoEmbed in videoEmbed %}
54                     {% set embed = craft.embeddedAssets.entry.    (videoEmbed) %}
55                     {% if embed %}
56                     {{ embed.safeHtml|raw }}
57                     {% endif %}
58                 {% endfor %}
59                 {% endif %}
60
61         </div>
62
63
64         {% endfor %}

I work locally and have dev mode turned on.

I am trying to use the plugin inside a matrix field with "videoEmbed" as block and field handle.

I created an asset source/ folder called "videos".

And I am on the personal licence.

You need to define your assets, if the asset field is named videoEmbed in your matrix matrixFieldHandle you would loop through the matrix and grab the first asset with:

{% for block in entry.matrixFieldHandle %}

  {% set asset = block.videoEmbed.first() %}

  {% set embed = craft.embeddedAssets.fromAsset(asset) %}

  {% if embed %}
    {{ embed.safeHtml|raw }}
  {% endif %}

{% endfor %}

You can find additional information about matrix-fields and templating here: https://craftcms.com/docs/matrix-fields#templating


Mutliple logouts required on Multiple App Servers We're using Craft CMS (pro) across multiple application servers and using reddis to manage the sessions.

We're needing to click on 'log-out' twice, sometimes several times before it actually logs us out of the control panel.

Any idea what could be causing this?

It sounds like your sessions are not being sticky. How many servers?

Are you having to login multiple times as well to get things done?

Apart from what Brad mentioned, couple things I'd try if you haven't already:

Set an appId in the config settings. You didn't mention AWS but setting an appId seems to have solved it for at least one other poster using multiple servers.
Set overridePhpSessionLocation and feed it your redis server (or auto). (It's possible Craft isn't even using Redis if it's not getting set correctly.)


Plain Text Length Conditional Wondering how to write a conditional that was dependent on the length of a plain text field within a matrix field. I  have something like:

{% for block in entry.pricing %}
    <li>{% if block.destination|length > 25 %}TEST{% endif %}{{ block.smallCost }}</li>
{% endfor %}

Where I’m trying to add TEST if the length of the string of block.destination is more than 25.

Turns out it needs the space in the conditional either side of the vertical bar so the code should’ve been:

{% if block.destination | length > 25 %}
{% endif %} {{ block.smallCost }}


What is the best way to deploy a Craft CMS 3 site? I'm unclear as to the best way to deploy a Craft CMS 3 site. I'm looking for some best practices and guidance.

I'm currently using Rocketeer to deploy the code from my local environment to my staging site. When I do this I get a ServiceUnavailableHttpException. Do I need to install Craft again once it's been deployed to my staging environment? I don't think I need to but I can't figure out why I'm getting this error.

In the past, I've run Craft 2 sites successfully by installing once on each environment and then gitignoring the common files that I want to share. I have a hook in my Rocketeer file that creates symlinks to the common files/directories.

I've thought about taking a similar approach with my Craft 3 site but am unclear as how I would do that now that the the core craft files are required within composer. Move all the core packages to require-dev in my composer file?

Who can help steer me in the right direction?

Thanks in advance!

At the risk of offering a "link answer", the Setting up a New Craft CMS 3 Project has a section on DEPLOYING CRAFT CMS that should be useful to you.

I've never heard of Rocketeer, but popular ways to handle deployments are via buddy.works, Laravel Forge and the like. We talk a lot about this on the Website Deployment without Tears episode of devMode.fm


Re-using includes when the object type changes (entry vs block) - what is the best method? So I am trying to reuse some include files built for a matrix builder that are also in some instances used as stand alone fields (Video, Downloads etc). The way I have coded this is that the object/handle changes from using block.handlename to entry.handlename what would be the most efficient way to code this?

Currently this is what I have done, but not sure it feels ‘right’?

So taking the video as an example. I have an include file _includes/matrix/video.html
I am then calling this from a Matrix Block like so;

{% for block in entry.mainContent.level(1) %}
{% switch block.type %}
{% case block.type %}
{% include '_includes/matrix/' ~ block.type %}
{% endswitch %}
{% endfor %}

And also an entry template like so;

{% if entry.video|length %}

        {% include '_includes/matrix/video' with { object : entry } %}

{% endif %}

In my video include file _includes/matrix/video.html I now have this;

{% set object = object ?? block %}
{% set url = object.video %}

    {{ url|videoEmbed({ byline: 0, autoplay: 0, rel:0 }) }}

But this means i need to this each time I am calling an entry? {% include '_includes/matrix/video with { object : entry } %} Is this the best approach?

Any suggestions/recommendations?

From what I can see here, the only important object you care about in the include file is the video object. So what you could do is simply passing the video field in parameter directly, using, for the entry:

{% include '_includes/matrix/video' with { video : entry.video } only %}

...and for the matrix block:

{% include '_includes/matrix/video' with { video : block.video } only %}

But then you would need to explicitly call each matrix block type with associated parameters.

I would in any case add the "only" keyword after the parameters, as it guarantees that your template will be isolated from other variables already defined in the main template.


Filtering list in CP index page for new ElementType I've created my first new ElementType based on the Events example. The only thing which doesn't seem to be working is the search bar above the listing in the CP. When I type anything into it I just get a blank results returned.

I think it's something to do with me not using Titles, I'm using a property on the Model called name instead. I had to override the __toString method in the model to get it to populate the first column in the listing, so I'm guessing there is some way to also overriding what is used by default for the search as well. Is that the case, and if so how do it do it?

In case anyone else comes up against this, here's what I did to fix it.

In my PluginName_MyElementType class which inherits from BaseElementType, you need to override the defineSearchableAttributes method, returning an array containing all the names of the properties of your Model which need to be searchable. So in my case it's just name. The reason you don't need to worry about adding title is it's already done for you under the hood, it's just that I wasn't using it in this case.

public function defineSearchableAttributes()
{
     return array('name');
}


Task "Resaving all localizable elements" is stuck when adding new new locale I'm trying to add a new locale, but the task "Resaving all localizable elements" is stuck and the new locale is not being added to content.
Even after restarting the task.

There are no errors in the log file.

As from Craft 3.1.15 you could use the resave/entries console command if you want  to offload entry saving to the terminal in order to update your content.

Please note that you should enable propagating entries across all enabled sites (see documentation).


Inline help text for entries As a content strategist, I'm trying to take the memory and guesswork out of my client's experience while updating the site (check out this great article, "Training the CMS"). Field instructions are great for that. But I'm doing some things that aren't intuitive to the user on the back end, and I want to add instructions/explanation on the affected entry types.

I think this could be effective in various places:

Above the Title field
In an Instructions tab
Above or below the right sidebar

Is there a field type that would let me just include text with no user interaction? Or a way to add instructional text to the entry interface? Bonus if I have the option to include images, links, and basic formatting too. I haven't explored plugins yet, because I'm still learning my way around Craft, but I'm open to using them.

I got it! The Sprout Notes Field plugin was what I needed. It allows HTML input with various formatting options.


How to translate de postdate format for a multilanguage site I have a site with 2 languages: Nl and En
Everything translates to Dutch but only the date stays in English...

I use this to get my news items:

{% for entry in craft.entries.section('news').limit(6).find() %}

{{ entry.title}} {{ entry.postDate.format('d M Y') }}

              {{ entry.title }}

{% endfor %}

The month stays in English, how can I format de post date, with the locale I'm viewing the site?

Instead of:

{{ entry.postDate.format('d M Y') }}

Use:

{{ entry.postDate | date('d M Y') }}

That should work.


Selecting descendants of a category when ancestor is clicked I have a question about combining Twig and jQuery in Craft. I have a couple of filters on a page that outputs some entries:
http://www.joycefdn.org/grants

My categories are organized like this:
Education and Economic Mobility
 - Educator Quality
 - Innovation
 - Pathways
Environment
 - Climate Solutions
 - Great Lakes
Culture
 - Arts Access and Participation
 - Arts Leadership and Workforce
 - Creativity and Cultural Production
 - Joyce Awards
Democracy
 - Fair Elections
 - Media
Gun Violence Prevention and Justice Reform
 - Gun Violence Prevention
 - 21st Century Policing
 - Reducing Mass Incarceration
Special Opportunities
 - Communications
 - Cross-Programmatic Innovations
 - Digital Tools

with the top level being Programs and the second level being focus areas.  I would like to have it so that when a Program is selected then the Focus Area select menu gets populated with the categories that are children of that program.  I currently have this jQuery left over from another method I tried which does get the current Programs that are selected:

$(".grants-data form[name='grantSearch'] select[name='program']").change(function(){
    var selectedPrograms = $("form[name='grantSearch'] input[data-name='selectItemprogram'][value!='']:checked").map(function() {
    return this.value;
                }).get().join('|');
});

and I have this which appends all of the descendants of all categories to the focus area menu:

{% set catSlug = craft.categories.title('focusArea').first() %}
            {% set childFAs = craft.categories.descendantOf(catSlug) %}
            $("select#focusArea").html('<option value="">Focus Area</option>');
            {% for fa in childFAs %}
            $("select#focusArea").append('<option value="{{fa.title}}">{{fa.title}}</option>');
            {% endfor %}
            {% if faSlug|length %}
                $("select#focusArea option[value='{{faSlugOrig}}']").attr('selected',true);
            {% endif %}
            </script>

but I can't seem to connect these two so that only the descendants of the program that is clicked get populated.  I think I may be overthinking this or trying to combine two methods that just won't combine.  Any help would be greatly appreciated!

Thanks!!

Okay, please don't be afraid and give it a try. I'm using the angular way, it seems a little bit difficult but it's actually really easy once you get used to it and works perfectly as soon as you understand it a little bit. If you need changes I'll provide whatever you need.
Edit: here you can see a live example for it plunker or course without css but it is your html

Let's get into it.
For testing purposes I created this category structure in my backend and called the group filter.

First you need to include this library you can of course use the {% includeJsRessource %} as well

Then you create 2 javascript arrays one for the Culture, Democracy... I call them parents and one for their children that belong to them

// get all filters of the first level
{% set filters = craft.categories.group('filter').level(1).find() %}

In the end you'll have 2 array that could look like

Now the funny part starts
include this javascript file. You can ask whatever you want I'll explain it. Even if the syntax and everything what's going on seems a little bit strange, but make sure this is loaded after the library from above

var  myApp = angular.module('myApp',[]).config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});

myApp.controller('filterController', ['$scope', function ($scope) {
    // all parents
    $scope.parents = parents;
    // all children
    $scope.children = children;

    // return if the parent is selected or not
    $scope.filterBySelectedParent = function (item) {
        return $scope.selectedParents.indexOf(item.parent) !== -1;
    };

    // an array with all selected parent ids
    $scope.selectedParents = [];

    // include an item to the array or slice it when the input it clicked
    $scope.addFilter = function(id){
        var index = $scope.selectedParents.indexOf(id);
        if(index === -1){
            $scope.selectedParents.push(id);
        }else{
            $scope.selectedParents.splice(index, 1);
        }
    }
}]);

And finally your new html

                <input type="checkbox" ng-click="addFilter(filter.id);" value="{[{filter.id}]}">{[{ filter.title }]}

                <input type="checkbox" data-name="selectItemfocusArea" value="{[{ child.id }]}">{[{ child.title }]}

Explanation: so what actually happens is the following

you create 2 arrays in javascript based on your backend inputs
angular renders your menu based on those two arrays but the second one has a filter. Only clicked items of the first array are shown
as soon as someone clicks on an filter it is included in an array $scope.selectedParents
any change in this array is recognized automatically which results, that the html renders again => your other filters are shown.

Please tell me if I missunderstood you somehow.. based on my current state I can change nearly everything really easily in just a few clicks. For example if you would like to automatically select your children you would include ng-checked="filterBySelectedParent(child)" on your input and remove the | filter: filterBySelectedParent.. that's it


Craft Commerce: Export each order to a specific CSV file and send it throught email Although I don't like this for some reasons, my client wants Craft Commerce to directly send specific formatted CSV file to their CRM system for each order.

Is it possible to write a Craft Commerce plugin to allow such a feature ?

You could write a custom Craft plugin (generate the boilerplate for it at https://pluginfactory.io) that listened to one of Craft Commerce's order events.  Likely onSaveOrder or onOrderComplete depending on your specific requirements.

From there, your plugin could build the CSV the old fashioned way in PHP, or use something like the CSV library to do the heavy lifting for you.

Once you've built the CSV, you can use Craft's EmailService->sendEmail() (accessible through craft()->email->sendEmail() to add the attachment and shoot the email off.


Output field content for a product in Craft Commerce I have added the field "Product Image" to my products. The field is an "asset field" which enables me to upload an image for each product. The field handle is productImage.

How can I output this image in my template?

Welcome to Craft!

A very basic piece of code for displaying your image would look like this (the if statement first checks if the field actually has an asset or not):

{% if product.productImage|length %}

{% endif %}

This quite simply outputs the image as it has been added in Craft, full size. Of course this isn't ideal as the images could be huge. That's why we have Image Transforms, which allow you define the size of the images.

Here is the above code again, but updated to use a new transform we have created in Craft called 'Test Transform', with a handle of 'testTransform':

{% if product.productImage|length %}

{% endif %}

Hopefully that gets you started. I'd recommend reading through the Craft docs for using and templating asset fields.


Get entries related to tags with a score & order by TL:DR; How do I add a custom sorting to Craft?

I am currently building a system which is very tag-centric. I am rebuilding my side project in CraftCMS (https://email.subscribeto.at/) which was custom PHP as a prototype.

Entries are tagged with one or more categories, then on the front-end the user can search for categories and the results are returned.

Currently, the results can be sorted by "relevance" which I would like to replicate on CraftCMS.

I tried to use .search() as it has a score, however this score is not what I want as it is not additive. I want to search with OR but for the score to be additive.

For example, if I have 2 entries, one with tags "a" and on with "a, b" and I search for "a, b", the first one has a score of 50 (as 100% of it's tags match 50% of the search) and the second a score of 17 (not sure how it gets this, would expect 100%)

Also, .search seems a bit fragile when I could us relatedTo().

I have a local module installed for some overrides already, so my question is:

How would I add a custom property to each entry and then order by that?

Thanks in advance for your help

You can add custom properties to elements using behaviors. In this case you want to add your 'getSearchScore()' logic.

Here's a good article on how behaviors work in Craft CMS and a current PR on the documentation to have behaviors information added.


Selecting entries with min value through search param Trying to do something quite basic but can't seem to get it right..

I'm searching through a form, and want to select entries where the value 'pax' is equal or more than the searched value.

{% set params = {
section:    'ships',
limit:      null
} %}

{# pax #}
{% if craft.request.getParam('pax') %}
  {% set pers = craft.request.getParam('pax') %}
  {% set params = params|merge({'pax' : '>= pers'}) %}
{% endif %}

Now, this doesn't seem to work. However, if I'd change the last line to:

  {% set params = params|merge({'pax' : '>= 30'}) %}

It gives me excellent results. So, what am I doing wrong here?

Much appreciated!!

You are currently passing a string '>= pers' to the array. Change this to:

'>= ' ~ pers

This "concatenates" the string '>= ' and the value of your pers variable (converted to a string).


Is there a "sticky post" function built into Craft? How would I make a post(s) sticky so that it appears first in the results and does not repeat later in the results?

You could add a custom lightswitch field or similar and order your entries by that field.

{% set entries = craft.entries.section('news').order('myLightswitch desc') %}

If you need additional sort options, @Brad just shared how to do that with SQL in the order() parameter.


Get last change timestamp in header response I'll be polling an endpoint created with the element-api plugin which will trigger a concourse build. I need to include a timestamp the last time any entry was changed.

So I need something to go in the setHeader function:

HeaderHelper::setHeader([...])

Many thanks in advance!

If you've already got a reference to the entry, this should do it:

HeaderHelper::setHeader('MyHeader', $entry->dateUpdated);


Get entry index - structure not channel I want to display the current entry's index - like in this post Get entry index.

However my entries are in a structure section type not a channel, so they are not ordered by date.

Is is possible to edit the solution (below) from the above post so that it is not sorting the entries by date but rather retaining the custom order of the structure?

{# Get this entry + all entries posted before it #}
{% set postDateParam = '<= ' ~ entry.postDate|date('c') %}
{% set entryIds = craft.entries.section('news')
  .order('postDate asc').postDate(postDateParam).ids() %}

{# Count them #}
{% set position = entryIds|length %}

{{ position }}

I found the clue for how to do this in the getPrevSibling documentation:

  getPrevSibling() will return the previous sibling whether or not it’s enabled. If you want to get the closest enabled sibling, you can do this instead:

  {% set prevSibling = craft.entries.positionedBefore(entry).order('lft desc').first() %}

So this query will get the number of enabled previous siblings:

{% set prevSibsCount = craft.entries.positionedBefore(entry).total() %}

And then your position will be that + 1:

{% set position = prevSibsCount + 1 %}
{{ position }}


How can I order entries by title when each title is numeric? I originally asked this on Stack Overflow, but I'm hoping for more response here.

In Craft, I'm trying to order entries by the title. Each title is a number, but the sort function handles it like a string. Because of that 100 shows up before 2, 31 before 4, and so on.

{% for entry in craft.entries.section('mySection').order('title').find() %}
    <h2>§{{entry.title}}</h2>
{% endfor %}

Is there a way to do this without extending  twig?

You can do that using MySQL’s cast() function:

craft.entries.section('mySection').order('cast(title as unsigned)')

Alternatively, you might get better performance if you create an actual Number field called “numberTitle”, attach it to your Entry Type, and set the Entry Type’s title to be dynamically generated using the template “{numberTitle}”. Then you can just order by that field instead:

craft.entries.section('mySection').order('numberTitle')


Locale URL segment being duplicated, eg https://website.test/en/en/ Problem

I have a problem on a local Valet setup: the locale URL segment is appearing twice in URLs.

Eg from a page at URL of en/about/approach, {{ url('about/approach')}} outputs https://website.test/en/en/about/approach

(And you only get the correct URL if outputting this from /about/approach)

Guessing I've missed something obvious but no idea what... thanks!

Setup

Base URLs are set to @web/en/ and @web/de/.

In the web folder we have two index files, eg de/index.php and en/index.php

Running valet which reports This site is served by [CraftValetDriver].

In general.php I've got:

'test' => [
// Base site URL
'siteUrl' => 'http://website.test'

The Entry URI Format for the Pages section is {parent.slug}/{slug}

Contents of /web/en/index.php:

<?php
/**
 * Craft www bootstrap file
 */

// Set path constants
define('CRAFT_BASE_PATH', dirname(__DIR__, 2));
define('CRAFT_SITE', 'english');
define('CRAFT_VENDOR_PATH', CRAFT_BASE_PATH.'/vendor');

$root = dirname(__DIR__).'/en';

// Load Composer's autoloader
require_once CRAFT_VENDOR_PATH.'/autoload.php';

// Load dotenv?
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
    (new Dotenv\Dotenv(CRAFT_BASE_PATH))->load();
}

// Load and run Craft
define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
$app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php';
$app->run();

Contents of /web/index.php:

<?php
/**
 * Craft web bootstrap file
 */

// Set path constants
define('CRAFT_BASE_PATH', dirname(__DIR__));
define('CRAFT_VENDOR_PATH', CRAFT_BASE_PATH.'/vendor');

// Load Composer's autoloader
require_once CRAFT_VENDOR_PATH.'/autoload.php';

// Load dotenv?
if (file_exists(CRAFT_BASE_PATH.'/.env')) {
    (new Dotenv\Dotenv(CRAFT_BASE_PATH))->load();
}

// Load and run Craft
define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
$app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php';
$app->run();

Your issue is that the @web alias resolves to this:

  The URL to the folder that contains the index.php file that was loaded for the request

Now that you’re serving your English site from web/en/index.php, @web will already resolve to http://website.test/en.

The alias @web/en you are using for your site’s base URL does therefore resolve to http://website.test/en/en

So you can fix it be using @web for your base URLs, or what I would rather recommend is to serve all your sites from a single web/index.php file (which is possible now in Craft 3). With this change @web will always refer to http://website.test and you need to use @web/en again in your site settings.


How can I pre-select a product variant based on user profile? I have a product variant that a user can choose from. It looks like this:

<select name="purchasableId" class="form-control">
    {% for purchasable in product.variants %}
        <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %} value="{{ purchasable.purchasableId }}"
            {% if currentUser is defined and purchasable.myCustomField in currentUser.userField %}selected{% endif %}>{{ purchasable.myCustomField.label }} &ndash; {{ purchasable.price|currency(cart.currency) }}</option>
   {% endfor %}
</select>

Where I'm stuck is this:

purchasable.myCustomField

Should (and does) equal this:

{{ currentUser.userField }}

I know it's a syntax problem... just not sure where I'm off.

EDIT

To test, this is what the data looks like:

purchasable.myCustomField  // this is a drop down value is "blue"
currentUser.userField      // this is a checkbox that has the value "blue" in it

Checkboxes fields (and other multi-select fieldtypes) return a MultiOptionsFieldData instance, not an array.

This should work:

{% if currentUser.userField.contains(purchaseable.myCustomField) %}


"An unknown error occurred." when changing profile avatar image I'm trying to change my profile avatar image, and I'm getting a "An unknown error occurred." No indication of what might have gone wrong. Permissions are correct on /craft/storage/userphotos and all the user directories inside. What am I doing wrong?

Error message in /craft/storage/runtime/logs/craft.log:

2014/09/13 13:39:02 [warning] [application] 404 -
2014/09/13 13:39:02 [error] [exception.Craft\HttpException.404] exception 'Craft\HttpException' in /abs/path/to/craft/app/controllers/TemplatesController.php:59

Check the log files in craft/storage/runtime/logs and search for [error] or [warning] to see the underlying error message.


Send entry as HTML email Looking to build a hybrid news service that publishes to a website but also sends an entry to a mailing list. Has anyone done anything similar?

You would need to attach such functionality to EVENT_AFTER_SAVE event in the custom php module.
The module can be built using plugin factory website. For attaching functionality to the event, you don't need to select any additional components.
https://pluginfactory.io/
You can find useful information about modules here:
https://nystudio107.com/blog/enhancing-a-craft-cms-3-website-with-a-custom-module
Add these statements to use section in main module class:
use yii\base\Event;
use craft\elements\Entry;
use craft\events\ModelEvent;
use craft\helpers\ElementHelper;

Now you need to attach functionality to the event - add this code to modules main class, in init() method:
Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function(ModelEvent $event) {

        // react only to entries from this section:
        $section_id = 1;

        // entry data
        $entry = $event->sender;

        // if it is not a draft
        if (ElementHelper::isDraftOrRevision($entry)) {
            return;
        }

        // if entry has specific section
        if($entry->sectionId != $section_id){
            return;
        }

});

This code will run when you save entry in a specific section. Now, you need to give ourselves some control.
We will make our code run only when we check a specific field in our entry. Create lightswitch field and add it to entry field layout. Thanks to the code below, an email will be sent only when entry is saved and lightswitch is checked. Lightswitch will be automatically de-checked after saving. Just remember that lightswitch field needs to be disabled by default to keep you from accidentally sending email when you save entry first time.
$lightswitchHandle = 'someField';
if($entry->getFieldValue($lightswitchHandle) !== true){
    return;
}

$entry->setFieldValue($lightswitchHandle, false);
Craft::$app->elements->saveElement($entry);

Now we need to compose our email:
// compose email from entry content
$email_template = 'path_to_email_template.twig';
Craft::$app->getView()->setTemplateMode(\craft\web\View::TEMPLATE_MODE_SITE);
$email_html = Craft::$app->view->renderTemplate(
    $email_template,
    [
        'entry' => $entry,
    ]
);
Craft::$app->getView()->setTemplateMode(\craft\web\View::TEMPLATE_MODE_CP);

This code will inject the contents of entry as entry variable into Twig template path_to_email_template.twig placed in templates directory and render email HTML. I suggest giving your email some nice base template - here are good examples:
https://postmarkapp.com/transactional-email-templates
Now what you will do with such email, is up to you. You could potentially send this email manually using Craft mailer class:
$email_recepients = ['bob@email.com', 'mike@email.com'];
$email_subject = 'interesting content inside!';

Craft::$app
->getMailer()
->compose()
->setTo($email_recepients)
->setSubject($email_subject)
->setHtmlBody($email_html)
->send();

Just try to avoid sending emails using server built-in sendmail functionality, this can lead to your ip/domain being marked as spam-sending. It's good to use some middleman services like mailgun.
https://www.mailgun.com/smtp/
You can attach Craft to mailgun SMTP using the application configuration file:
https://docs.craftcms.com/v3/config/app.html#mailer-component
If you want to test how your emails behave, you can use a mock SMTP server like mailtrap:
http://craftsnippets.com/articles/testing-and-debugging-emails-sent-by-craft-cms-using-mailtrap
An alternative to using SMTP might be mailchimp service or something like that - in that case, instead of using Craft mailer, you would use some dedicated PHP library to send email to service API.


Criteria entries by date field I want to get only entries with a specific date. I created a date field customDateField. It has the following code:

{% set entries = craft.entries.section('orders').customDateField('2016-04-14') %}

but this not work. How it will look in php?

In element api plugin i was code:

'endpoints' => [
    'orders.json' => [
        'elementType' => 'Entry',
        'criteria' => [
            'section' => 'orders',
            'date' => '>='.craft()->request->getPost('date')
        ],
        'transformer' => function(EntryModel $entry) {
            return [
                'id' => $entry->id,
            ];
        },
    ],
]

but it only shows a larger date of entries, need to write 'date->format("Y-m-d")'

You don't need any extra php code to do that.

The search function probably does the job for you.

{% set entries = craft.entries.section('orders').search('2016-04-14') %}
{% for entry in entries %}
  <h1>{{entry.title}} - {{entry.customDateField}}</h1>
{% endfor %}