How to use Sprig's "Load More" Recipe After Update This is a continuation of a previous question I had (Here). I am using Sprig's Load More Recipe. In my category page, I want the load more function to only pull up entries that equals the current category page. In a recent update, the category solution that was in my previous question no longer works, since it has been restructured a little. I cannot figure out how get the relatedTo(category) to work again. I currently have it set up like this (the {'relatedTo': category} does not do anything):
_category.twig
{{ sprig('_layouts/_blog/_categories/_loadMore', {'limit': 6},{'relatedTo': category}) }}
{{ sprig.script }}

_loadMore.twig
{% set offset = offset ?? 0 %}

{% set entries = craft.entries.section('caseFiles').offset(offset).limit(limit).relatedTo(category).all() %}

{% for entry in entries %}
   ------Entry Content-----
{% endfor %}

{% if entries %}
  {# Increments `offset` by the value of `limit` and swaps itself out on click #}
  <button class="orange-button" sprig s-vars="offset: {{ offset + limit }}"
    s-target="this" s-swap="outerHTML">

Load More

  </button>
{% endif %}

The problem is that you are doing .relatedTo(category) but the variable you are passing is called relatedTo, not category.
Just like with limit, based on your code, it should be .relatedTo(relatedTo). Also, it should be part of the same hash as your limit.
However, you can't pass a category object to a component and will need to pass its id instead (docs).
Depending on what category is in your case (and I guess it's an object), you could do:
{{ sprig('_components/load-more', {
    'limit': 6,
    'categoryId': category.id
}) }}

Then in your component:
{% set offset = offset ?? 0 %}

{% set query = craft.entries().section('caseFiles').offset(offset).limit(limit) %}

{# Make sure a categoryId is being passed #}
{% if categoryId %}
    {% set query = query.relatedTo(categoryId) %}
{% endif %}

{% set entries = query.all() %}

{% for entry in entries %}
   ------Entry Content-----
{% endfor %}

{% if entries %}
  {# Increments `offset` by the value of `limit` and swaps itself out on click #}
  <button class="orange-button" sprig s-vars="offset: {{ offset + limit }}"
    s-target="this" s-swap="outerHTML">

Load More

  </button>
{% endif %}


Pass URL parameter through General Config file This may sound a little odd so let me explain what's going on.

In my current setup I have allowed new users to sign up. I want these users to follow this flow:

Fill up sign up form and submit
Gets redirected to page that warns them of activation email
User opens email, clicks on link and is forwarded to his/her profile page

So far I've been able to do this without any problems. However, I would like to be able to welcome the user when the account is activated without using a new template.

In this moment 'activateAccountSuccessPath' is set to the profile page, let's call it 'members/profile' I would like to pass a parameter so that I can detect if the account is being activated for the first time and therefore should display a message, e.g.: 'members/profile?activated=true'. As of now, this isn't possible because it looks for the template with that name, not recognizing that it has parameters.

I would like to use this same feature for other variables such as 'setPasswordSuccessPath', which would take you back to the login page, but displaying a message.

If it's impossible to pass arguments this way, how would you recommend going about it?

I think I figured out how to do it but I'd like to get any opinions on this matter.

Right now I've setup a dummy template which contains a redirect to the URL with the parameter I need. So:

'activateAccountSuccessPath' => 'members/activated

And then that template contains:

{% redirect 'members/profile?activated=true' %}

This is working great. And I guess it's a clean way to do it from the point of view that each variable in the config file has a different target. But is it "cool" to do a redirect just for that?


Saving new entry via Ajax then immediately showing it I’ve created a very simple comments system whereby comments are set us a channel, with each (comment )entry related to a main entry from another section. Works fine. I’ve set up editing and deleting the comment via Ajax, but I’m stuck on saving it.
I’ve got the form submitting successfully via ajax, but I want to be able to display it immediately after it is saved/posted.
The successful response I get gives me the author username, entry id, date etc, but not the actual comment field. I also need to display additional user details.

I’m not quite sure on best way to tackle this. Just looking for a pointer in the right direction. Cheers!

Use that as your controller, this is the craft default controller actionSaveEntry that you use right now with a few changes. You can access it in Javascript when you use action: "pluginHandle/entry/saveEntry".

namespace Craft;

class EntryController extends BaseController
{

    /**
     * @var    bool|array Allows anonymous access to this controller's actions.
     * @access protected
     */
    protected $allowAnonymous = array('actionSaveEntry');

    /**
     * Saves an entry.
     *
     * @return null
     */
    public function actionSaveEntry()
    {
        // craft default things.. this is actually the exact same function
        // like you call at the moment, it does the same..
        // just go to the part where I have the !Important! note
        $this->requirePostRequest();

        $entry = $this->_getEntryModel();

        // Permission enforcement
        $this->enforceEditEntryPermissions($entry);
        $userSessionService = craft()->userSession;
        $currentUser = $userSessionService->getUser();

        if ($entry->id) {
            // Is this another user's entry (and it's not a Single)?
            if (
                $entry->authorId != $currentUser->id &&
                $entry->getSection()->type != SectionType::Single
            ) {
                if ($entry->enabled) {
                    // Make sure they have permission to make live changes to those
                    $userSessionService->requirePermission('publishPeerEntries:' . $entry->sectionId);
                }
            }
        }

        // Populate the entry with post data
        $this->_populateEntryModel($entry);

        // Even more permission enforcement
        if ($entry->enabled) {
            if ($entry->id) {
                $userSessionService->requirePermission('publishEntries:' . $entry->sectionId);
            } else if (!$currentUser->can('publishEntries:' . $entry->sectionId)) {
                $entry->enabled = false;
            }
        }

        // Save the entry (finally!)
        // !Important! so this is where your action starts
        if (craft()->entries->saveEntry($entry)) {
            $return['success'] = true;
            $return['id'] = $entry->id;
            $return['title'] = $entry->title;

            // after saving the entry you can render your template
            // the documentation can be found here https://craftcms.com/docs/plugins/templates
            // just read this site and you'll know what to do..
            // this allows you to render your "comments" template like when you
            // visit the page the first initially
            // you'll just do $("#idOfYourCommentsContainer").append(ajaxResponse['html']);
            // and thats it^^
            // in the template you have access to the variables $entry => the new entry
            // and the user currently.. if you need something else, feel free to ask
            $return['html'] = $this->renderTemplate('/path/to/template', array(
                'entry' => $entry,
                'user' => $entry->getAuthor()
            ));

            $return['authorUsername'] = $entry->getAuthor()->username;
            $return['dateCreated'] = DateTimeHelper::toIso8601($entry->dateCreated);
            $return['dateUpdated'] = DateTimeHelper::toIso8601($entry->dateUpdated);
            $return['postDate'] = ($entry->postDate ? DateTimeHelper::toIso8601($entry->postDate) : null);

            $this->returnJson($return);
        } else {
            if (craft()->request->isAjaxRequest()) {
                $this->returnJson(array(
                    'errors' => $entry->getErrors(),
                    'success' => false
                ));
            }
        }
    }
}

If there is an error you get the array with all "mistakes" and error messages. For example if you define the field "headline" as required and the user didn't insert something in the "headline" field your response will be

reponse = [
    "error" => [
        'headline'  => [
            'The Headline field is required //or something like that...'
        ]
    ]
];

You could select the headline field by name or class with javascript and append the error message as well


400 error logging into local Craft 3 project I have just tried to log into an old local Craft 3 project that hasn't been worked on in a few months and I'm getting the following:

HTTP 400 – Bad Request – yii\web\BadRequestHttpException

Unable to verify your data submission.

yii\web\BadRequestHttpException: Unable to verify your data submission. in /Users/user/Development/project/build/vendor/yiisoft/yii2/web/Controller.php:166
Stack trace:
#0 /Users/user/Development/project/build/vendor/craftcms/cms/src/web/Controller.php(82): yii\web\Controller->beforeAction(Object(yii\base\InlineAction))
#1 /Users/user/Development/project/build/vendor/yiisoft/yii2/base/Controller.php(155): craft\web\Controller->beforeAction(Object(yii\base\InlineAction))
#2 /Users/user/Development/project/build/vendor/craftcms/cms/src/web/Controller.php(103): yii\base\Controller->runAction('login', Array)
#3 /Users/user/Development/project/build/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('login', Array)
#4 /Users/user/Development/project/build/vendor/craftcms/cms/src/web/Application.php(282): yii\base\Module->runAction('users/login', Array)
#5 /Users/user/Development/project/build/vendor/craftcms/cms/src/web/Application.php(538): craft\web\Application->runAction('users/login', Array)
#6 /Users/user/Development/project/build/vendor/craftcms/cms/src/web/Application.php(266): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#7 /Users/user/Development/project/build/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#8 /Users/user/Development/project/build/public/index.php(42): yii\base\Application->run()
#9 {main}

The front end of the site fine, the login page at /admin works and I've restarted MAMP multiple times. I have also locally run composer update in case there were any issues with my packages.

But nothing seems to make it want to successfully sign me in.

UPDATE:

After more research, a lot of people have had their issues like this resolved by clearing the cache of their browser. I have tried this in three separate browsers all to no improvement.

I haven't seen this particular issue but generally I've found that from time to time MAMP doesn't like running Craft in CGI mode, i.e. with different PHP versions per host.

Try switching it to module mode (under the PHP tab of MAMP Pro). If that works, then try reverting to CGI mode. You may find it continues to work.


Redirecting certain 404s to a page, handling all others as normal I'm having trouble setting things up to redirect some old news articles a certain way, while still serving existing articles:

  If a page exists at /news/my-article then it should be served as normal.

  If that URL doesn't exist (ie, all non-functioning /news/* URLs), I want the user to be redirected to /news.

  All 404s that aren't within /news should be handled as normal.

My first thought was to use a redirect tag in the 404 template, only if the request URL matches /news/*... but I'm not sure if that's too late in the process. By that time, has a 404 header already been sent, so the user would get 404 -> 301 -> 404 ?

You could also set up a route for news/{slug} to point to your news template, and have it do the check to see if the entry in segment_2 is valid, and do something based on that.

I did something like this for my "members" pages:

 {% set thisProfile = craft.users.id(craft.request.segment(2))[0] %}

 {% if not thisProfile %}
    {% redirect siteUrl %}
 {% endif %}


Get value from dropdown and use in Twig I’m creating an archive of news article entries. For that purpose, I’m trying to get a value from a dropdown (user-selected year and month) and then assign it to a pagination procedure that calls up all articles of that particular year and month.

However, from what I’ve read so far, you cannot pass a Javascript variable to Twig. Is there any other possibility of passing on user selection to Twig?

Thanks! :)

<button class="btn btn-default dropdown-toggle text-sans" type="button" id="selectYear" data-toggle="dropdown">Year </button>

2015

2014

<button class="btn btn-default dropdown-toggle text-sans" type="button" id="selectMonth" data-toggle="dropdown">Month </button>

January

February

    ...

December

{% set firstDayOfMonth = JSYEAR ~ "-" ~ JSMONTH ~ "-01" %}
{% set daysInThisMonth = firstDayOfMonth|date('t') %}
{% set lastDayOfMonth  = JSYEAR ~ "-" ~ JSMONTH ~ "-" ~ daysInThisMonth %}
{% set thisMonthsEntries = craft.entries.section(category).postDate('and', '>= ' ~ firstDayOfMonth, '<= ' ~ lastDayOfMonth) %}
{% paginate thisMonthsEntries as pageEntries %}
   {% for date, articles in pageEntries | group("postDate|date('F Y')") %}
       ...

Twig (and all php) is processed server-side before javascript even gets initiated. And once the page renders in the browser there no way to interact directly with twig. The only two options that you have is to either 1) reload the page or 2) request a page segment via ajax. I would opt for the later in this case.

To do this, you could either listen for an onClick() event on a submit button of some kind, or listen for onChange() events on the drop-down menus themselves; which would trigger an ajax call to the server, and display the results in your placeholder 'div'.

On the craft side you would want to create a separate template that renders just the requested news articles, based on either: variables that you pass to the template via post; or using a custom route that you set up (i.e. '/news/2015/03/').

For an example of creating a page template using custom routes and ajax to load entries based on date, see this example. You will need to adapt it slightly to only use the month and year (vs. month, day, year).

For an ajax example, see this example — which links to additional examples.

If you have a hard time putting the pieces together, leave a comment and I'll try and provide a more specific example.


How do you handle complex navigation in Craft? This seriously can't be this hard. How are you handling complex navigation on your sites? Do you hard-code them? Do you use a dedicated "Menu" Structure Section? I am curious what everyone is doing.

I have a few customers who really need to have control over their menu and its structure, but as I build the templates, I am finding I need complete control over the first level and especially the sub/children of them. I am finding it nearly impossible to come up with a way to be able to loop through children and style them how I need to.

Basically, I am trying to access the Dropdown portion of this menu example and as you can see, I need to be able to add a class and data-toggle to those items.

Link

Link

        Dropdown

Action

Another action

Something else here

Separated link

One more separated link

If the {% nav %} tag doesn't give you enough control over the output, you can always replicate the behavior with custom loops and the getChildren() method. Just nest them as far as your navigation hierarchy possibly gets.

Edit:

Here an example code on how you'd dynamically call getChildren() on each top-level entry of your structure. If you need to go deeper another level in the structure's hierarchy, I marked the line where you would do that:

    {# Get top-level entries in pages structure (exclude home page)  #}
    {% set pages = craft.entries.section('pages').id('not 1').level(1) %}

    {# Loop through top-level entries #}
    {% for page in pages %}

        {# Check if entry has descendants #}
        {% if not page.hasDescendants %}

            {# List navigation item if entry has NO child entries #}

                {{ page.title }}

        {% else %}

            {# List navigation item if entry does have child entries #}

                {{ page.title }}

                    {# Get child entries of current iteration's top-level entry #}
                    {% set subPages = page.getChildren() %}

                    {# Loop through those 2nd-level entries #}
                    {% for subPage in subPages %}

                        {# This is the place where you'd nest the next menu hierarchy !! #}

                        {# List sub-menu navigation item #}

                            {{ subPage.title }}

                    {% endfor %}

        {% endif %}
    {% endfor %}

.

Because most of your question's topics are already covered by other Q/As, I'd also recommend you to read through these too.

How to realize a client editable navigation:

Would you use a Structure as navigation over multiple sections?
How to build a great multi-lingual navigation witch channels, structure, and manageable in the CP
Multi-lingual site navigation made of singles, channels and structure
Add home page to a stucture?

More control over the HTML output of the nav tag:

Custom or complex nav tag


How to recreate symlinks to path-based plugins after moving to live server? I have a couple of custom plugins for a site, which I successfully added by using path repositories in my composer.json file. However, when I upload the site to my staging server (via FTP - no SSH access or Git on this server), the symlinks in craft/vendor/myvendorname (which are automatically created during any composer update) won't upload. Thus, my site breaks, trying to load plugins which it cannot find.

I can manually upload the actual folders to that location (which is my fix for now), but that's not sustainable on an ongoing basis really.

Is there some way I can force Craft (or really Composer I suppose) to recreate those symlinks on the remote server? Or is this a case where I simply need SSH access so I can do it manually?

Symlinks won't transfer over FTP and I'm like 98% sure there isn't a way to get Craft to re-create those symlinks natively.

So you'd need SSH access to the box with Composer installed in the terminal.  Then you could upload your custom plugins, composer.json and run composer update or upload composer.json and composer.lock and run composer install to have the dependencies pulled down and the symlinks re-created.

Alternatively, and this is probably cleaner, you can setup a vcs type of repository in your composer.json file, along side your path repository.  https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository

They'd both point to the same plugin.  When you deploy to production, Composer should see that the path repo doesn't resolve to a valid path on the production file system and move onto the vcs repo for the same plugin and pull the files down that way.

It's compatible with private repositories, too: https://getcomposer.org/doc/05-repositories.md#using-private-repositories and you can setup Github access tokens if you'd rather go that way: https://www.previousnext.com.au/blog/managing-composer-github-access-personal-access-tokens


How to set a URL for the top level of a Structure section? I have entries in a structure section. I'd like the users to view the list of entries without the entries themselves being assigned URLs.

How can I set a URL for the top level of a Structure section without enabling "Entry URL Format"?

If I understand what you're asking—it sounds like you can just disable URLs for that section, and create a template that will get loaded at the URL you want.

For example, if you had a Section called “Plants,” and you wanted to list all plants at mywebsite.com/plants, you could just create craft/templates/plants.twig:

{% set plants = craft.entries({ section: 'plants', limit: null }).find %}

  {% for plant in plants %}

{{ plant.title }}

  {% endear %}

If you need to edit anything on that page, you'll need to create another entry (probably a Single) to manage that content.


Can't import a complete url into an url field with feed-me Description

I have a JSON feed which contains an external URL like "https://example.com" (entries/external_link/url).
There is no error in feed-me logs when I run it, all the text data and assets are imported without any problems. Except for my URL field. I get "[ ]" instead of "https://example.com".

Any help on this ?

JSON exemple

{
    "entries": [
        {
            "id": "140",
            "type": "regular",
            "title": "Banner import title (fr)",
            "subtitle": "Banner import subtitle (fr)",
            "body": "
Banner import body&nbsp;(fr)
",
            "internal_link": [{
                "type": "node",
                "title": "test",
                "id": "6",
                "cta": "Banner import link text (fr)"
            }],
            "external_link": {
                "cta": "Banner import link text (fr)",
                "url": "https://example.com"
            },
            "images": [{
                "url": "",
                "caption": ""
            }],
            "placements": [],
            "postdate": "2019/12/10",
            "status": "1"
        },
    ],
    "nextPage": "",
    "length": 20,
    "totallength": 23
}

Additional info

Plugin version: 4.1.2
Craft version: 3.3.17

Have you tried to make external_link an array?

"external_link": [{
    "cta": "Banner import link text (fr)",
    "url": "https://example.com"
}],


Find an authorId based on first and/or last name Is there a way I can reverse use the User Model to return an authorId based on the first/last name (John Doe)?

Basically, I'm converting the first/last to a readable URI segment (using email addresses as username and I want something more readable than an ID in the URL):

{{ entry.author.firstName|lower ~ '-' ~ entry.author.lastName|lower }}

Returns: john-doe

Then on the listing page, grabbing the URI segment, setting that back to a readable name and spliting to array.

{% set authorName = craft.request.segment(3)|replace({'-':' '})|title|split(' ') %}

Which gives me (the equivalent of):

Array
(
  [0] => John
  [1] => Doe
)

I'd like to get the author id to return all the entries from said author. I thought something along the lines of below would work:

{% set author = craft.users.firstName(authorName.0).lastName(authorName.1) %}

With the above, I get the error:

  Object of class Craft\ElementCriteriaModel could not be converted to string

However, if I return {{ authorName.0 }} it returns a string.

Well, I was 1 minute away from solving this, so I'll post my answer.

{% set author = craft.users.firstName(authorName.0).lastName(authorName.1).first() %}

Once the author object is set, you can access the {{ author.id }}.

Allowing me to neatly return author entries:

{% set entries = craft.entries.section('news').authorId(author.id).limit('10') %}


Register a user to a specific group I'm trying to register a user from the front-end and assign them to a specific group. I know that via control panel I can set a default user group, but there is a registration instance where I need the registrant to be assigned to a different group.

I tried this to no avail...

<input type="hidden" name="groups" value="4">

You can only do this with custom PHP otherwise this is going to be a high security risk. Imagine someone just changes your HTML and inserts a different group id: everyone could just join the group he/she likes.

Instead you can Enhancing a Craft CMS 3 Website with a Custom Module - there is already a default one and insert an event to do this by yourself but you need to be careful. I wouldn't trust user input in that case too much.

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(ElementEvent $event){
        if(\get_class($event->element) === User::class){
            $joinSpecialGroup = (bool)Craft::$app->getRequest()->getBodyParam('joinSpecialGroup');
            if($joinSpecialGroup === true){
                Craft::$app->getUsers()->assignUserToGroups($event->element->id, [4]);
            }
        }
    }
);

Note: I woulnd't call the property joinSpecialGroup - it is just for demonstration


Issue trying to use function from DateTimeHelper class: "timeAgoInWords() is not defined" Not quite sure how to use functions defined in Helper classes in my templates. For example, trying to use "timeAgoInWords" on an entry's dateCreated attribute. I get an internal server error and a "Unknown "timeAgoInWords" function" message when I try to visit the page. It occurs to me that perhaps I have to include or import the DateTimeHelper class? I'm not sure how to go about this.

Here's a link to the Craft docs on the package that I'm trying to include:

https://craftcms.com/classreference/helpers/DateTimeHelper

I'm trying to include the timeAgoInWords function in my index.html template within the templates folder.

Thanks a bunch!

Generally speaking, only Variable classes are exposed to templates in Craft and there isn't a Variable wrapper for DateTimeHelper.

However, that would be a super-simple plugin to write that exposes timeAgoInWords as a Twig filter so you could do something like

entry.postDate|timeAgoInWords


Adding an additional Download PDF to orders Is there a hook or something I can use to add an additional Download PDF option to the Edit Order screen? It looks like a dropdown, but I can't find any docs on how to add to it.

As of Commerce 3.1.12 only the one PDF can be registered in general settings. We will be adding support for additional PDFs to be configured in the next release. Stay tuned.


What is the best way to handle Events that get triggered during a migration? We have a Form plugin and an Email plugin.  Users can setup the Email Plugin to send off notification emails when a particular Event happens.   Some users setup a notification email to be sent when a Form is submitted from the Form plugin.

In a recent upgrade, we needed to migrate all content to the Form plugins entries table.  We did so using the saveFormEntry method in the Form plugin service layer.  This means, that each time that we call saveFormEntry in the migration, if somebody has the Email plugin to send out a notification when a Form Entry is saved, the Event fires and the Email plugin tries to do it's thing.

In our case, this just killed the migration script. Setting the Email plugin to disabled before running the Form migration get's around the issue.

So, what is the best way to handle Events that get triggered during a migration?

One method we've thought of is to just programmatically set the Email plugin to disabled before running our migration.  That might work for us, but what if other plugins need to do the same?  Do we then need to somehow try to communicate this to everyone who might trigger an email event in a migration?

Another idea we've discussed is what if Craft had something like devMode for while migrations were running.  So we could just plan into our Email plugin to only run events when migrationMode = false.

As a general question, are there any benefits to having Events enabled during migrations?  Are there any benefits to having plugins enabled during migrations?  I'm sure this isn't simply a black and white question, but I'm new to thinking about the complexity of having multiple plugins triggering behaviors in other plugins and don't really like the idea that somebody could accidentally trigger several emails to be sent out while trying to run a migration.

Any thoughts on where this is best handled and if we can take any steps to make our code more robust in handling scenarios like these would be appreciated.

In general it’s best to avoid calling service methods from migration files in the first place. The reason for that is, your services should be able to assume that they’re always working with the latest schema design.

Imagine if a month from now you decide you need to add a new column to your formentries table (or whatever it is). The associated record, model, and service all get updated to work with this new column’s data. And you write a migration that adds the column:

$this->addColumn('formentries', 'newColumnName', ColumnType::Varchar);

You test and everything appears to work great, and then release it.

Then someone who was running an old version of your plugin tries to update. Before Craft runs the new migration that adds the new formentries column, it still needs to run your old migration that calls your saveFormEntry() service method. Except that saveFormEntry is now assuming that the new column already exists, and depending on your code, either they run into a validation error (so no form entries get saved) or a MySQL error (because your record is trying to save on a column that doesn’t exist yet).

So, in the long run you’ll be better off if you keep all DB-related changes contained to your migration file.

That said, Craft does cheat a little here - this is exactly why we have the concept of “breakpoint updates” at our disposal. When we mark a release as a breakpoint, it prevents anyone from updating to a version after it, until they have updated to it. So if we do need to call service methods in a migration, then we just need to remember to set a breakpoint at some point before we start making more DB schema changes.

Plugins will also be able to set breakpoints when Craft 3 comes along. Because of that, this is still a relevant question. I’m thinking that the safest thing to do here is to simply disable event dispatching altogether during updates. A plugin should be in full control over what code gets run when it’s updating itself, with no chance of another plugin intervening.

I don’t think we have a way to disable Yii’s event system altogether (and probably shouldn’t even if we could), but we could at the very least prevent craft()->on() from doing its thing during update requests. Maybe even add a new argument to it that can be set to true if the event should get fired even if it’s an update request, in case there are any use cases that I’m overlooking.


Automated Craft 3 installation I am setting up a vagrant development environment and I was wondering if it is possible to somehow pass the installation configuration when running ./craft setup command to avoid any user interaction?

Checking the help output of the setup/index says --interactive: boolean, 0 or 1 (whether to run the command interactively.). When executing ./craft setup --interactive 0 nothing happens. Am I doing something wrong? I tried searching for an explanation and usages of setup parameters but to no avail.

The command line syntax for install without user input should be:

./craft install --interactive=0

There's a great article describing just such an automated approach here.


Is it possible to cache a faceted search form? I have created a search form which allows user to search multiple categories groups and multiple categories within those groups.

So I have

Type

[] Category 1

[x] Category 2

[] Category 3

...

Location

[] Category 1

[x] Category 2

[] Category 3

[] Category 4

I've chosen to use slugs as the search parameter for usability purposes but that means that I have to get the element of each slug and then pass it into the entries query. Long story short,lots of queries to my database before I even get started outputting the categories above.

I'm interested in caching the category queries and I'm doing as follows

{% cache using key "restaurant-filter-type" %}

    {% set typeList = craft.categories.group('restaurantType') %}

    {% for type in typeList %}

            <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}">
            {{ type.title }}

   {% endfor %}

{% endcache %}

The problem I run into is when the user submits the form and the checked form elements arent being persistent because of the caching I've set.

I've tried looking at this SE question to help but the stumbling block for this is that there is the possibility that the parameter holding my restaurant type slugs may hold multiple values, hence the name="type[]". A simple replace filter doesn't look likely to work in that situation.

Would anyone have any ideas how I could get around this?

There're various ways of doing this. The simplest would be to just use the submitted slugs to generate a new cache key for each different search, like Jamie suggests. This is a very straightforward and readable solution, which in most cases would probably yield a "good enough" performance boost. You'd simply create a key based on the params that are used in your cached content, so something like (could be made a bit less verbose if you prefer):

{% set submittedTypesArray = craft.request.getParam('type') %}
{% set submittedTypesString = submittedTypesArray | join('-') %}

{% cache using key "restaurant-filter-type-" ~ submittedTypesString %}
    {% set typeList = craft.categories.group('restaurantType') %}

    {% for type in typeList %}

            <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}"{% if type.slug in submittedTypesArray %} checked{% endif %}>
            {{ type.title }}

    {% endfor %}
{% endcache %}

The backdraw of this solution is that it generates one cache entry for every different combination of the types. If this is "good enough" depends on your project.

If you want to use the approach naboovalley describes in the linked answer, here is a rewrite for your usecase:

{% set typeCategories %}
    {% cache using key "restaurant-filter-type" %}
        {% set typeList = craft.categories.group('restaurantType') %}

        {% for type in typeList %}

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

        {% endfor %}
    {% endcache %}
{% endset %}

{% set types = craft.request.getParam('type') %}
{% for type in types %}
    {% set typeCategories = typeCategories | replace('data-type-' ~ type, 'checked')  %}
{% endfor %}

{{ typeCategories }}

It would be possible to do this with several category groups inside one variable/cache entry, but you'd have to give them different data-names to make sure that you don't run into problems if two categories in different groups have the same slug.

I'm sure there's a wicked elegant way to do the replace without the for loop, I just couldn't wrap my head around it right now. ;)

And, just to add more options, if this was a really high traffic site (or the server that hosts the site is really crappy), I'd actually update the status of the checkboxes with javascript on the client, instead of doing it with Craft. Even though it would maybe annoy a user that has javascript turned off and has to check all the checkboxes for every search, nothing would break. And you can't beat the performance of doing something on the client instead of on the server.


Setting Google maps circles using Smart Map plugin So, I'm trying to set circles around marker locations using Smart Map and some JS.
I've got the following which gives no errors, but outputs no circles.
$(function () {

  $.each( smartMap.marker, function( key, value ) {

    var circle = new google.maps.Circle({
                    map: smartMap.map['smartmap-mapcanvas-1'],
                    radius: 40233,    // 25 miles in metres
                    fillColor: '#000000'
                 });
    circle.bindTo('center', marker, value.getPosition());

    });

  });

});

I'm out of ideas at this point!

This is a shot in the dark, so let me know if this does/doesn't work...

Here's how you're starting your loop:

$.each( smartMap.marker, function( key, value ) {

And near the end, you reference a marker object:

circle.bindTo('center', marker, value.getPosition());

But as far as I can tell, marker is never defined. Did you mean to pass in value instead?


How to set view path for rendering email templates? Trying to send an email

Craft::$app->setViewPath('/Users/stian/dev/site.com/templates/');
Craft::$app->mailer->compose('confirmation.twig', ['orderId' => $orderId, 'customerId' => $customerId])
    ->setFrom('me@me.com')
    ->setTo('me@me.com')
    ->setSubject('hey')
    ->send();

Getting The view file does not exist: /Users/stian/dev/site.com/vendor/craftcms/cms/src/mail/confirmation.twig

Assuming I correctly understand how to render a view for sending as an email, how can I correctly point to its location?

For anyone struggling with this, apparently this is one way of doing it.

I struggled with this for quite some time before posting my original question, but regardless, sorry about that.

Anyway, here it is.

Craft::$app->setViewPath('/path/to/templates/');
$body = Craft::$app->getView()->renderTemplate('confirmation.twig', ['orderId' => $orderId, 'customerId' => $customerId]);
Craft::$app->mailer->compose()
    ->setFrom(['me@me.com')
    ->setTo('me@me.com')
    ->setSubject('hey')
    ->setHtmlBody($body)
    ->send();

Edit:

There's probably a better way of doing this, but if you're working in multiple environments, you can do this in general.php

'dev' => [
    'templatePath' => '/Users/stian/dev/site.com/templates/',
],
'staging' => [
    'templatePath' => '/Users/stian/dev/site.com/templates/',
],
etc

and then Craft::$app->setViewPath(Craft::$app->config->general->templatePath) in your plugin/module.

PS! Will mark as answered once I'm allowed


How to save Entries to an entry? (non-plugin) I've got a 'booking' channel and an 'event' channel setup. Through the frontend, I need the logged in user to be able to submit a saveEntry form on the frontend which saves a new entry in the booking channel. The booking channel has two fields, both Entries fields. The first field is a relation to one user (the logged in user), and the second field is a relation to a single entry in the events channel.

When I submit the form, the entry is being created in the booking channel, both both Entries fields are blank. How do I make it save the related entries? Can't find any documentation on it.

Existing code:

Summary

<form method="post" action="" accept-charset="UTF-8" class="custom">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="events/{{event.slug}}">
    <input type="hidden" name="sectionId" value="18">
    <input type="hidden" name="enabled" value="1">
    <input type="hidden" name="fields[userBooking]" value="{{user.username}}">
    <input type="hidden" name="fields[eventBooking]" value="{{eventID}}">
    <input type="submit" value="Confirm Booking">
</form>

Short version: How do I save a related entry through a frontend form?

All related fields need to be passed as an array even if it is limited to 1.

so for example change your eventBooking and userBooking hidden fields to be the following (also you may need to specify the user id when relating to a user):

<input type="hidden" name="fields[userBooking][]" value="{{user.id}}">
<input type="hidden" name="fields[eventBooking][]" value="{{eventID}}">

This should get you want you need.


Craft 3 setPasswordPath config not working for front end users How do I change the link that's sent in a forgot password email that's sent to front end users in Craft 3? The setPasswordPath config isn't working for me.

The users don't have access to the CP. In my global config settings I have 'setPasswordPath' => '/account/set-password' I have a template based on the doc's Set Password Form example that loads at mysite.test/account/set-password.

The email is sent via a template that is based on the doc's Forgot Password Form example.

The links in the emails look like this: mysite.test/actions/users/set-password?code=r8tyzUikpXko0b2o5A785TC73geK0jvh&id=a91a64a3-8869-4f0d-a11b-2ad54d69303c

I want them to link to my template like this: mysite.test/account/set-password?code=r8tyzUikpXko0b2o5A785TC73geK0jvh&id=a91a64a3-8869-4f0d-a11b-2ad54d69303c

What am I doing wrong?

If you really want to change the password action url (not the password path) you can only do that in your Twig template and use the |replace('actions/users/set-password', 'account/set-password') filter.

The action url is hard coded in PHP and I would suggest you not to change it unless you know what you are doing. It would by default route to an action that does several important things and then redirects to the passwordPath.

So when you replace the route you should include the logic into your custom controller or create a site url rule to the default action


Using the nav tag repeat the parent once in the children I'm using the nav tag to build a menu which works great, but i just want to repeat the parent menu item over to any sub nav. So if there is a sub nav, at the top of the sub navs links, i want the parent url repeated once.

My current code is this

   {% nav page in blah %}

         {% if page.level == 1 %}
            {{ page.title }}
                {% else %}
                    {{ page.getLink() }}
         {% endif %}

         {% ifchildren %}

                {% children %}

         {% endifchildren %}

    {% endnav %}

and i'm looking at doing something like (but i would love it to work obviously)

   {% nav page in blah %}

         {% if page.level == 1 %}
            {{ page.title }}
                {% else %}
                    {{ page.getLink() }}
         {% endif %}

         {% ifchildren %}

{{ page.parent.getLink() }}
 -- this is dodgy
                {% children %}

         {% endifchildren %}

    {% endnav %}

I'm an idiot, i can just do:

   {% nav page in blah %}

         {% if page.level == 1 %}
            {{ page.title }}
                {% else %}
                    {{ page.getLink() }}
         {% endif %}

         {% ifchildren %}

{{ page }}
 -- this is dodgy
                {% children %}

         {% endifchildren %}

    {% endnav %}


How would one go about migrating fields? Is there any "simple" way of migrating fields and layouts from one setup to another?

Example;
Two identical installations/setups have diverged, where some information on certain fields have changed (like descriptive texts and so forth), perhaps there's a SuperTable or Craft Neo field with added blocks, or even a matrix field where there's been blocks added on the one setup, that need to update exactly on the other setup. Perhaps there's been some additions to a structure's field layout. Perhaps something has been removed.

I realize this could possibly be done with some sort of plugin/migration.

The purpose of my question is basically to figure out a) if there's a simple and straight-forward way of doing so programmatically/automated, or b) if there are any plans on, or capability of setting up fields similarly to ACF for WordPress in the theme's function.php—where it can be done programmatically.

A real world usage would be;
You build a set of templates (a theme, essentially), and when you update the templates (theme) and you want to apply those updates to a separate install/setup, what is the most efficient and "simple" way of doing so in Craft?

I've looked into the architect plugin, which is great for clean installs, but alas my limited php, or rather sql, knowledge makes it hard to expand into querying for field names rather than ID's. Of course there's the caveat that if you change a field's name, you probably need the ID, but if we forget that rabbit hole for a bit, is anyone sitting on any smart and simple tips for this type of approach?

Anyone had any success with FeedMe or the CraftImport plugins?

The Migrations

This is an ongoing issue. My best call is currently, to do the changes on production and to sync the DB locally.

I see a lot of folks, using plugins to "lock" the editing for the time, changes are being made. Sync to local, edit, resync to production.

As this is not satisfying, there was discussion with the Craft Team and the result is, for now, migrations coming to Craft 3.

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

This way you basically can create your own migrations from the command line. This should solve your problem, BUT: you should not use Craft 3 in production, yet.

Theming (off topic)

Something like theming is not possible and I think also won't be really in the future.

I solve this by having a Craft CMS dummy on github, which has most setup stuff I usually need (gruntfile, basic partials for matrices I use often). This dummy evolves over time and only includes some dummy files and folders like db.sample.php, general.sample.php and for the app a app.sample folder.

For basic content stuff I also use plugins like architect or the import/export plugin, to set up basic SEO fields and globals I usually use.

But most are missing a way to export groups etc. perfectly, but they do their job.

Hope that helps.


Filtering Matrix through field value and multiple relations I've the following situation:

Accommodations (entry)

title
description (textfield)
...
linkedTo (matrix block)

Sport (category)
targetGroup (category)
minimumAge (number)
maximumAge (number)

What I'm trying to do is fetch all entries (accommodations) related to a sport and targetGroup for a person of a certain age. E.g.: Entries for children with the age of 11 years in the targetGroup 'men/boys' and the sport 'football'.

Finding elements using relatedTo works for me, except I'm not able to filter the age. I'm pretty sure I'm doing something wrong here. I think it's not possible in craft to find textfield values via the relatedTo method, but the question is: How should I do this?

private function get ()
{
    $sport      = $this->findSelectedBySlug('football');
    $targetGroup    = $this->findSelectedBySlug('men-boys');
    $age            = 11;

    $wheres = [
        "and",
        [
            'targetElement' => $sport,
            'field' => "linkedTo.sport"
        ],
        [
            'targetElement' => $targetGroup,
            'field' => "linkedTo.targetGroup"
        ],
        [
            'targetElement' => "<= {$age}",
            'field' => "linkedTo.minimumAge"
        ],
        [
            'targetElement' => "> {$age}",
            'field' => "linkedTo.maximumAge"
        ]
    ];

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

    return $criteria->find();
}
private function findSelectedBySlug ($slug)
{
    $criteria = craft()->elements->getCriteria(ElementType::Category);

    $criteria->slug = $slug;

    return $criteria->first();
}

You're right, this isn't possible with setting relatedTo parameters. But you can pass your ElementCriteriaModel (with all other parameters set) to the buildElementsQuery method, to prepare a DbCommand object. You can now modify the query as you need (→ Craft documentation for Database Queries).

Use join to bring in the "matrixblocks" table and also your Matrix field's content table "matrixcontent_mymatrixfield". Then add the min. and max age conditions with andWhere.

private function addAgeCriteria(ElementCriteriaModel $criteria, $age)
{
    $query = craft()->elements->buildElementsQuery($criteria);

    $params = array(
        ':age' => $age
    );

    $conditions = array('and',
        'matrixcontent_mymatrixfield.field_linkedTo_minimumAge <= :age',
        'matrixcontent_mymatrixfield.field_linkedTo_maximumAge >= :age'
    ),

    $query->andWhere($conditions, $params);

    $query->join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
    $query->join('matrixcontent_mymatrixfield matrixcontent_mymatrixfield', 'matrixcontent_mymatrixfield.elementId = matrixblocks.id');

    $results = $query->queryAll();

    return EntryModel::populateModels($results);
}


Prevent Rich Text editor from removing code tags? In one of the Rich Text Fields I'm entering little snippets like this:

  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility !important;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, .004);

However, each time i edit again it removes the value although when i save it the first time its ok. I think its converting at edit time.

Is there anyway to prevent redactor from doing this?

You've probably got "Purify HTML" checked under your Rich Text field's settings and that's stripping code.

You should really only have that checked if you're accepting input from untrusted sources using the Rich Text field on the front-end of your site. Presumably all users using the control panel are trusted enough not to input malicious code into the site.


Best practice for year based paging Is there a best practice for a paging based on the years of entries (instead of page numbers)?

Example:
I have 3 records with post dates 2019-01-01 2018-01-01 and 2016-01-01. So my paging should look like this:

2019 | 2018 | 2016

It is easy to fetch the needed info with a raw query like:

{% set pagingYears = craft.query()
    .select('DISTINCT YEAR(postDate)')
    .from('entries')
    .where({'sectionId': 1})
    .column()
%}

But does craft provide some components or a better way to solve such a problem?

Welcome to craft

There is a example for a archive on the official page: Creating an “Archive” Page for Entries

Maybe this fit's your use case.


Pull all assets from a specific volume subfolder id Is there a way to pull all assets from a volume subfolder id?

{% set entries = craft.entries.section('pages').type('genealogy').search('pageType:stake') %}
{% for entry in entries.all() %}
    {% if entry.id == x %}
        get all assets from volume subfolder a
    {% elseif entry.id == y %}
        get all assets from volume subfolder b
    {% endif %}
{% endfor %}

Twig

{% set assets = craft.assets.volumeId(y).folderId(x).all() %}

PHP

$assets = Asset::find()->volumeId(y)->folderId(x)->all();


Switching to Craft from ExpressionEngine my client is looking to move away from ExpressionEngine. One of the reasons for this is that we are approaching the maximum number of sites we can run from MSM due to the limit on the number of columns we can create in MySQL for the data table.

Questions:

Managing Multiple Sites

Is it possible to run multiple sites using Craft?
Can you provide a login for users that would give them access to just their site?
Can you share content from the a global site across local sites?

Forms

Is there a plugin like Solspace Freeform for creating and managing forms?

Search

How does site searching work. Would there be a way to tie this in to display local sites only?

Appreciate the help.

You ask multiple questions at once – some of them quite broad. I'd recommend you create separate threads for each of your questions, and to try to be as specific as possible – e.g. elaborate a little on what you mean by "run multiple sites". That being said, in the event this thread isn't closed for being too broad I'll try to answer some of your main questions:

  Is it possible to run multiple sites using Craft?

Craft doesn't have an MSM-type feature, so short answer is no. See this thread for some further details and alternative solutions.

  Is there a plugin like Solspace Freeform for creating and managing
  forms?

Sure is. There's Sprout Forms which is a commercial, full-featured forms plugin, as well as a few free, smaller plugins such as Form Builder.

  How does site searching work. Would there be a way to tie this in to display local sites only?

I'd suggest you look at the official docs on searching in Craft, as well as the example search form.


Can you beta build a Craft site in the www directory while the current site is still running? I'm gungho to get started building in Craft but I don't want the complications of moving the site over from a development directory. Is there a way to easily do this while the current site is up and running?

In general, developing a website on the live server is a risky thing. Should something go wrong while you're developing then you risk the live website. It's unlikely, but an accidental upload to the wrong folder, or a wonky SQL statement, or anything like that can happen.

If you must run the site on the live server though, your best bet is to set up a sub-domain such as beta.mywebsite.com. Host that on your live server and do all the development there. Then, when it's time to retire the old site and make the new one 'live', you can move the files across from the beta directory to the www one.

I wouldn't recommend doing that though. Much less risky to get your local machine set up as a development server, do it all on that, and then put the site live.


Force validation on disabled entries Craft CMS allows you to save entries without any validation if it's not an enabled entry.

Is it possible to disable this? I've had a dig through the core Craft code but can't actually find the conditional that makes this happen. It doesn't seem to be in the Entries service or model or their parents.

Thanks!

Sounds like the Always Validate plugin does what you're looking for.


Looking for an advanced form plugin for Craft CMS I'm currently using amforms from a&m impact on a couple of sites. However, it looks like this plugin won't get a craftcms version 3 update. In addition, my requirements for a form plugin have expanded considerably since my clients want more advanced functionality. Therefore, I am now searching for a good alternative.

My requirements are as follows:

It should be possible to prepopulate fields with existing data
Duplicating forms should be possible
Templating completely customizable
Ability to dynamically add more rows of fields (like in a reservation for a hotel where you can add more rooms or persons)
Validation for at least the basic field types
File uploads should be possible
Custom conditions for custom fields (like a checkbox only checkable after checking another one before)
Custom email template
Translatable
Good documentation
Active development

Right now Solspace's Freeform looks most promising and I already know their calendar plugin. However, Sprout Forms also looks quite capable.

Does anyone of you has experience with one of these plugins or can recommend another plugin that meets all or most of the criteria?

Thank you so much for your help!

To answer your questions in regards to how they will fit with Freeform...

If what you mean by pre-populating fields with existing data is being able to fill fields with data from other elements, Freeform can do this. It allows you to populate fields with data from other Craft Elements or even common Predefined data included with Freeform such as States, Months, Date ranges, number ranges, etc. If what you mean is that you'd like a submitted form to retain its existing data when there's an error upon submitting the form, it can do that as well.
Forms can be duplicated in Freeform.
You have full control over your template formatting in Freeform. You can use one of the default formatting templates included with Freeform (preset for popular frameworks), use one as a starting point and adjust as necessary, or completely customize your own thing.
The best choice here would be to use Freeform's built-in Table field, which allows you to collect and handle repeating data nicely.
Freeform offers a wide variety of field types, and included with them is the necessary validation for each.
File Upload fields are available with Freeform.
Freeform's Conditional Rules feature allows you to show/hide fields based on the contents or selection or check of other field(s). Included in this is also page jumping in multi-page forms.
Freeform offers 5 different ways to send email notifications, and you can have as many different types of email notification templates, and customize them however you please.
It depends what you mean by translatable, but Freeform forms can be translated with static translation files. The CP itself is also translatable.
Freeform has what we believe is fairly comprehensive documentation, and it's always getting better. And when questions or issues arise, you can always contact us for help.
Freeform is the most popular third party form plugin for Craft CMS, and it has a proven history of active development for years. You can preview the meaty changelog filled with countless feature additions, improvements and bug fixes. It's actively developed by Solspace, which has been around and developing software for well over a decade. :)


Smart Map - How to search by a field in address? I have entries using the Smart Map address field. I need to get just the entries that have a combination of city and state (city = "Beverly Hills" AND state = "CA"). I am currently only trying to get simpler search state working and only then will I move to state/city. I can get a "fuzzy" that to my understanding will get everything that has "CA" in any of the fields using:
{% set meetings = craft.entries.section('meetings').search('address:' ~ 'CA') %}

But I want to understand how to create a more specific search that specifically finds 'CA' in address.state.
When I try:
{% set meetings = craft.entries.section('meetings').search('address.state:' ~ 'CA') %}

the search returns nothing. No errors either.
Questions:

How do I search specifically in a field like address.state?
Extending this question, how do I search address.state AND address.city?

It's more "filtering" than "searching", but take a look at this...

Filtering entries by subfield value

Set a filter parameter when creating your element criteria model...
{% set params = {
    filter: {
        city: 'Beverly Hills',
        state: 'CA'
    }
} %}

{% set meetings = craft.entries.address(params) %}


Contact Form Plugin: Validate if a checkbox is checked? What is the cleanest way to validate if a checkbox (i.e. agree to legal terms) is checked?

There's no clean way doing this without making changes to the plugin itself. The  contactForm.beforeSend event makes it possible to prevent the email from being sent from another plugin, but you're only being passed the compiled email message as a string. It's probably possible to post you checkbox data with that string and parse for it in your event listener, but you asked for a clean solution! :)

So fork the plugin and add a new attribute to the ContactFormModel:

'agreedToTerms' => array(AttributeType::Enum, 'required' => true, 'values' => array(true)),

And make the ContactFormController get the attribute value from your form:

$message->agreedToTerms = craft()->request->getPost('agreedToTerms');

You're now all set add a checkbox "agreedToTerms" to your form and add a custom error message in case the model attribute failed validation:

<input type="checkbox" name="agreedToTerms" value="true" {{ message is defined and message.agreedToTerms ? 'checked' }}> Agree the Terms and Conditions

{% if message is defined and message.hasErrors('agreedToTerms') %}

{{ 'You must agree the Terms and Conditions'|t }}

{% endif %}


Get entries with related to selected categories and then group by category Background:

I have a listing overview page that lists teaching staff grouped by their department (A category group holds all departments). E.g.

All Staff Members:

-- Science --
    Mrs Magnesium
    Mr Bunson

 -- P.E --
    Mr Stretch
    Mrs Bend

-- Maths --
    Ms Multiplication
    Mr Trig

To achieve the above I am using this code, which is working perfectly on a single page:

{% set entries = craft.entries.section('staffMembers').with(['staffPhoto']).all() %}
{% for category, catEntries in entries | group('staffGroup.one().title') %}

    {% for entry in catEntries %}

{{ entry.staffTitle }}

{{ entry.staffBio }}

    {% endfor %}

{% endfor %}

Question:

The client now needs to split these staff members across different pages, like the example below. So in order to achieve this I want them to be able use a category field (entry.staffGroups) where they can select multiple categories (departments) to display on each page. Hope I am making sense!

Science Staff Page:

-- Science --
    Mrs Magnesium
    Mr Bunson

Physical Education Staff Page:

 -- P.E --
    Mr Stretch
    Mrs Bend

Mathematics Staff Page

-- Maths --
    Ms Multiplication
    Mr Trig

I am struggling to achieve this, my attempt is below:

{# get the selected categories (departments) from category field #}
{% set departments = entry.allDepartments.all() %}

{# Set the entries, and attempt to relate them to ONLY the selected departments.#}
{% set entries = craft.entries.section('staffMembers').relatedTo(departments|join(',')).with(['staffPhoto']).all() %}
    {% for category, catEntries in entries | group('staffGroup.one().title') %}

        {% for entry in catEntries %}

{{ entry.staffTitle }}

{{ entry.staffBio }}

        {% endfor %}

    {% endfor %}

Example of entry:

Thanks!!

I may not understand fully, but it sounds like you could just loop over the attached Department Categories, then query for Staff related to that category:

{# Load the Departments Categories: #}
{% set departments = entry.allDepartments.all() %}

{% for department in departments %}
  {# Find all the Staff Members associated with the department: #}
  {% set staff = craft.entries({
    section: 'staffMembers',
    relatedTo: department,
    with: ['staffPhoto']
  }).all() %}

{{ department.title }}

    {# Loop over the Staff Members: #}
    {% for person in staff %}

{{ person.title }}

    {% endfor %}

{% endfor %}

  There is a (very slight) performance penalty for performing queries like this in a loop, but it sounds like each of these focused sub-pages won't have too many Departments listed anyway.


Craft News Feed not working after 2.5 Update Not a major thing but I just noticed the Craft News Feed on the dashboard is not showing.  It is still looking for https://craftcms.com/news.rss.  Any ideas what is up with that?

Just checked 2 upgraded sites of me and to me it's working..


Show active parent's listed children when viewing it children When I view a entry that's belong to a small group of children with a parent assigned. When I view the child, I want to display list all children that the child assigned to?

Is there anyway to achieve this method?

I think you're looking for the getSiblings() method. This will return all sibling entries for the current entry. You can also use getParent() to get the parent entry and getChildren() to get the entries child entries.

An example implementation is below:

{% set siblings = entry.getSiblings() %}
{% set parent = entry.getParent() %}
{% set children = entry.getChildren() %}

{% if parent|length %}

Parent

{{ parent.title }}

{% endif %}

{% if siblings|length %}

Siblings

  {% for entry in siblings %}

{{ entry.title }}

  {% endfor %}
{% endif %}

{% if children|length %}

Children

  {% for entry in children %}

{{ entry.title }}

  {% endfor %}
{% endif %}

More info on these methods can be found in the EntryModel documentation.


Twig result/contents into string I'm trying to adjust a google maps so have pins that correspond with my posts. I'm nearly there but I'm trying to load info into the info window. I can set it's content already by hand. And I have turned the info i want in the bubble into a html result. All I need to do is alter this so that the twig commands create a string I can pass on in the function that will add the pin.

So I'm trying to create a string result from the code below, which has all the results in it.

Here's what I got (and this works to produce the HTML I want to put in the info window of the pin:

—

{% set resultsNum = 0 %}

{{ block.location }}

{% set searchString = block.location %}
{% for entry in craft.entries.section('journal').find() %}
{% for block in entry.locations %}
    {% if block.type == "location" %}
        {% if block.location == searchString %}
            {% set resultsNum = resultsNum+1 %}

{{ entry.title }}

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

—

The resulting string would go here (this code works already if i set my own string of html:

    {% set marker = {
    lat: result.geometry.location.lat,
    lng: result.geometry.location.lng,
    content: infoHTML
    } %}

Thanks in advance for any help!

You can wrap your HTML in a {% set myString %} block and use myString however you need too.

{% set myString %}
{% set resultsNum = 0 %}

{{ block.location }}

{% set searchString = block.location %}
{% for entry in craft.entries.section('journal').find() %}
{% for block in entry.locations %}
    {% if block.type == "location" %}
    {% if block.location == searchString %}
        {% set resultsNum = resultsNum+1 %}

{{ entry.title }}

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

{% endset %}


Craft Commerce - Product Types URL I'm working for the first time with Craft Commerce and trying to create product types. So far so good, now I have three product types: "Inspiration", "Gift" and "New". I need the URL of these three product types and don't know how to create it... actually the URL is shop/products with all products.

I need shop/inspiration with the inspiration products, shop/gift with the gift products and shop/new with the new products.

With {{ productType.name }} I can show all my product types, but how can I show the URL of product types?

{% for productType in craft.commerce.productTypes %}
  {{ productType.name }}

    {% for product in craft.commerce.products.type(productType.handle).find() %}
      {{ product.url }}

    {% endfor %}
{% endfor %}

Or do I need to create these product types as categories?

Hope you guys can help me!

Probably the most Craft-y way would be to use categories for classification and set your categories to have URLs.

Alternatively, you could do this with a route that points shop/* (ie. shop/{some token} - at a template, say shop/product_type and in that template use the second segment of the url in retrieving products of the appropriate type (or, of course, create 3 routes and 3 templates if they way you're handling those index pages differs a lot).

In general how Craft deals with routes/urls is documented here:
https://craftcms.com/docs/routing
And some more info on routes is here:
https://straightupcraft.com/events/routes-and-patterns

Then to create your menu/list or whatever, something like:

{% for productType in craft.commerce.productTypes %}
  <a href="/shop/{{ productType.handle }}"{{ productType.name }}

{% endfor %}

(on phone so excuse any syntax errors)


Is it possible to add a Section, Entries in basic/simple HTML page instead of Twig template? In Craft CMS is it possible to add a Secion, Entries in basic/simple HTML page instead of Twig template?

You can't add a Section in Twig either. You have to use PHP in order to create logic. Html is only used to display things on you page but it does not include logic nor is it able to fetch elements (working with databases) Twig is a template engine, you could describe it as a middleman between HTML and PHP it is able to fetch elements and uses a limited amount of PHP to display them

You won't be able to work with Craft properly without using Twig at all unless you modify many things with PHP

Like mentioned in the other thread Craft might not be the correct  CMS for you


Category query very slow on multilingual site I have a directory of sea ports with a google map that loads about 450 records. The map and listings and pagination work fine. On their own, I get a 2.5 sec page load average.

However as soon as I add a search form that populates a chained select for countries and ports the load time goes up to 8 secs.

The search form code looks like this

{% set categories = craft.categories.group('locations').limit(null) %}

Country
<select id="countries" class="countries" name="country">
    <option value="">Select...</option>

    {% cache %}
        {% for country in categories %}
            {% if country.level == 1 %}
                <option value="{{ country.slug }}">{{ country.title }}</option>
            {% endif %}
        {% endfor %}
    {% endcache %}
</select>

Ports
<select id="ports" name="port" class="ports" disabled="disabled">
    <option value="">Select a country first</option>

    {% cache %}
        {% for port in categories %}
            <option value="{{ port.slug }}" class="{{ port.parent | lower }}">{{ port.title }}</option>
       {% endfor %}
    {% endcache %}

</select>

It seems that this code cost about 5 seconds of load time.

I have checked the profile output and seen the query for the categories. It's huge.  I can't see how to get the page to load faster as I can't see eager loading applying to a category group, and caching doesn't really help here.

Any ideas on how to optimise this portion?

It's hard to know for sure without seeing your query profile output, but try eager loading your ports field like so:

{% set categories = craft.categories({
    group: 'locations',
    limit: null,
    with: ['ports']
}) %}


Link to an entry via Entries field type I am attempting to create a "dynamic" button. By that I mean I want the user to be able to update the text and the target (href) of where the button links to when clicked.

So I created fields: buttonText and buttonTarget.

buttonText is just a plain text field - no problem.

For the buttonTarget field type I chose "Entry" and selected the source(s) in the checklist that follows with a limit of one. So far so good.

In my actual entry, I enter the buttonText of "Hello World". Preview the page and "Hello World" shows up as the button text. So far so good.

Lets say I have a page called "Hello". For my buttonTarget field I click on "Add an Entry" and choose "Hello" from the entry list.

When I preview my site now, I get this error:

Object of class Craft\ElementCriteriaModel could not be converted to string

That makes perfect sense since I need everything to evaluate to a string. I'm not sure how I can output (for lack of better words) the object so that I can see/find what properties are.

Here is what I am using to display the button:

html

{{entry.buttonText}}

I assume I need something like {{entry.buttonTarget.uri}} but I haven't been able to find out what the actual parameter is I need. {{entry.uri}} outputs nothing.

EDIT

Doing this gets the result I am after: {{entry.slug}} This uses the current entry's slug instead of the custom field value. Which is ok - I can use the slug as the href target. Ideally I'd like to use the custom field though.

Even if you set the limit to 1, Craft always returns an array of entries. So you need to add first() to access the first (and only) entry.

{{ entry.buttonTargets.first() }}

It you don't add a property, this returns the entry's title by default. So you additionally need to add url to output the URL of that entry.

{{ entry.buttonTargets.first().url }}


Using the custom styled Stripe button with Craft Commerce I know there is the Stripe checkout button that is in the example docs but I would like more control over how things look and work.

I guess this is where it's over to me to look at the Stripe docs:

Styled Custom Button

It's difficult to work out what exactly is required in order to send all the details Stripe requires and then process the response giving Craft Commerce everything it needs. Then send the user to an order complete screen.

I have the custom button sort of working using:

<form method="POST">
  <input type="hidden" name="action" value="commerce/cart/updateCart">

  <button id="paymentButton" class="button is-primary">Purchase</button>

  <script>
    var handler = StripeCheckout.configure({
      key: '{{ cart.paymentMethod.settings.publishableKey ?? '' }}',
      image: '/assets/img/tfa-logo-128.png',
      locale: 'auto',
      token: function(token) {
        // You can access the token ID with `token.id`.
        // Get the token ID to your server-side code for use.
      }
    });

    document.getElementById('paymentButton').addEventListener('click', function(evt) {
      // Open Checkout with further options:
      handler.open({
        name: '{{ siteName }}',
        email: '{{ cart.email }}',
        currency: '{{ cart.paymentCurrency }}',
        description: 'Membership',
        zipCode: true,
        amount: {{ cart.totalPrice|commerceCurrency(cart.paymentCurrency,convert=true,format=false) * 100 }}
      });
      evt.preventDefault();
    });

    // Close Checkout on page navigation:
    window.addEventListener('popstate', function() {
      handler.close();
    });
  </script>
</form>

This looks to work but doesn't send a charge to Stripe or save in the commerce plugin (it just sits as an active cart). I guess this is down to the token not being set but how do you do that?

Here is my working solution, basically all you need to do is grab the token from stripe and then submit it with the form.

<form method="POST" id="payment-form">
  <input type="hidden" name="action" value="commerce/payments/pay">
  <input type="hidden" name="cancelUrl" value="/checkout/payment">
  <input type="hidden" name="redirect" value="/orders/order?number={number}">
  <input type="hidden" name="token" id="stripe-token" value="">
  {{ getCsrfInput() }}

  <button id="paymentButton" class="button is-primary">

        Purchase

  </button>

</form>


Showing the month on an archive page I've set up an archive page as described in the docs... so my archive page url looks something like this http://mysite.dev/news/2014/09.

How do I then make the title display Archive for September 2014?

The {{ month }} variable is set as 09 and doing this -> {{ month|date("F") }} outputs January not September.

Any help would be appreciated.

Figured out a way to do this if anyone who has the same problem.

    {% if year is defined and month is defined %}
    {% set archiveDate = year ~ '-' ~ month ~ '-01' %}

Archive for {{ archiveDate|date('F') }} - {{ year }}

    {% endif %}


Calculating a score based on a drop down field value I am storing a value (number 1-5) in a drop down field and would like to do a calculation based on the numbers filled in.  The only way I could get my calculation to work was to store the number (1-5) in a number field (not a drop down field) so I'm wondering if it's because the drop down content is seen as a string and not an integer. If so, perhaps I need to convert the string to an integer.  Although I have it working with the value (1-5) stored in a number field, I'd like to understand how I could make it work with a drop down.  I saw another post that sounded similar: How can I convert a dropdown field value to an integer within a hash?

Here is my template code that works with my number field:

        {% set imageQualityScoreAorta = craft.entries.section('logsQA').logGeneral_statusWorkflow('reviewed').search('logGeneral_studyType:aorta -logReviewer_imageQualityNumberTest:0').relatedTo(
            { targetElement: currentUser, field: 'logGeneral_sonographerName' }
        ) %}

        {% if imageQualityScoreAorta|length %}

            {% set additionAorta = 0 %}
            {% set countAorta = 0 %}

            {% for entry in imageQualityScoreAorta %}
                {% set additionAorta = additionAorta + entry.logReviewer_imageQualityNumberTest %}
                {% set countAorta = loop.index %}
            {% endfor %}

            {% set averageValueAorta = (additionAorta / countAorta)|round(1, 'floor') %}
        {% endif %}

This is the output:

            Aorta
            {% if imageQualityScoreAorta|length %}
                {{ averageValueAorta }}
            {% else %}
                N/A
            {% endif %}

When working with a dropdown in Twig, it's important to remember that you're dealing with an object (not a simple string).

This is an object:
{{ entry.myDropdown }}

It's easy to forget, however, because Craft works a little magic behind the scenes. There are many objects (including this one) which have an internal __toString behavior. This is called a "magic method", because it will automatically convert the value to a string when you use it as a string.

But in your case, you're not directly outputting it as a string. You're trying to do math with the object, and the object isn't really sure how to respond to that. So nothing gets converted, and your object remains mathematically useless.

Instead, you'll need to append .value to your object. This will give you the selected value of your dropdown, in a format that you can use.

This is the dropdown's selected value:
{{ entry.myDropdown.value }}


Get full url of asset, not just the path I'm trying to output the full asset URL. Using Craft 3.0.0-RC7.1

In .env:

ASSETS_BASE_PATH=/Users/user/code/sitename/web
ASSETS_BASE_URL=http://sitename.test

In config/volumes.php:

'siteAssets' => [
    'path' => getenv('ASSETS_BASE_PATH') . '/assets/images',
    'url' => getenv('ASSETS_BASE_URL') . '/assets/images',
],

In my template:

<meta property="og:image" content="
{{ entry.socialSharingImage.one.getUrl('socialSharing') }}
" />

Output:

<meta property="og:image" content="
/index.php?p=actions/assets/generate-transform&amp;transformId=58">

As you see, no site url at the start. Any ideas?

It seems the getUrl() method returns the path. Prepending it with {{ siteURL }} creates two /'s e.g. http://sitename.test//asseturl.jpg. Same results in dev and production.

Thanks!

You can slice the / from the end of {{ siteUrl }} and combine it with getUrl relative path:

<meta property="og:image" content="{{ siteUrl|slice(0,-1) }}{{ entry.fieldName.one().getUrl('kafel620') }}">

This will produce expected path:

<meta property="og:image" content="http://site.local/assets/images/ramPamPam/headers/_kafel620/tagiatelle.jpg">


Does Craft CMS support 'encryption at rest' / 'data at rest' encryption? Does Craft CMS support 'encryption at rest' / 'data at rest' encryption? I've looked here, here, and here - but can't find any info on this. Explain like I'm 5. Thanks.

As far as I'm aware, it does not. But this is typically something you'd do at the VPS level; examples of doing it on various platforms:

Google Cloud Platform
Linode
Digital Ocean

You could also do it at the database level as described here: MySQL Data at Rest Encryption


Only executing if a matrix checkbox has a specific value I currently have checkboxes in a matrix block that allow a user to select where an image will be placed in the layout (as a featured slider image and/or in an image gallery). I've gotten the slider image to function but if, for some reason, there are no featured images I have a couple of unnecessary
 tags. Because I am selecting only featured images from the matrix block I can not use loop.first and loop.last to move those divs in my for loop.

I had seen an article that seems close to finding the answer to my problem here : Only execute twig block if a Matrix radio has a certain value but I haven't been able to make it work.

Any help would be greatly appreciated.

{# Add Feature Images - Slideshow #}
    {% set photos = entry.photoGallery.type( 'photos' ) %}
    {% if photos|length %}

                {% for block in photos if block.imageLocation.contains('featured')%}
                    {# Get the photo #}
                    {% for photo in block.photo %}

                        {# Get the caption #}
                        {% if block.caption|length %}

{{ block.caption }}

                        {% endif %}

                    {% endfor %}
                {% endfor %}

    {% endif %}

I've attached a screen snapshot of my field setup.

{% if block.checkboxFieldHandle.contains('someChkbxValue') %}

Executed!

{% endif %}

actual for Craft v2.x and v3.x


Where should I make an HTTP REQUEST using AJAX? Where should I put my ajax call if I want to get some data from an external link or website? Should I put it in the controller, or in the service?

You should try to keep your controllers as "thin" as possible. That is, they should call other classes, which do the actual work.

The Craft approach is to keep most of your code in service classes, and if you're just starting out with plugin development, I recommend you follow this pattern.

Bear in mind, though, that your service classes define your plugin's API.

In other words, if you add a public method to one of your plugin service classes, you're essentially telling everyone "hey, you can use this method if you like".

If you're interested, I wrote a blog post about this a while back.

In summary, keeping your code in services is much better than keeping it in controllers, but don't treat your service classes as a dumping ground for everything.


How can I get an entries author custom field? I have a custom field for a user which is an asset, it has the users larger profile photo.

In an entry template I can get their profile photo using:

{{ entry.author.getPhotoUrl }}

But I want to get the custom field.

Something like:

{{ entry.author.authorImage }}

I am sure I am missing something very simple?

Ah it would of been handy if I had of entered the assets loop!

  {% for asset in entry.author.authorImage %}
    <img src="{{ asset.getUrl() }}" alt="{{ entry.author.getFullName }}">
  {% endfor %}


How to correctly output a Table Field? I have set up a Matrix field with three blocks, each contains a Table field.

Each table has one column - a single line text field.

When I call these tables into the template with this code, each row is echoed twice:

{% for block in entry.projectFacts.limit(3) %}

    {% switch block.type %}
        {% case 'code' %}
            {% if block.codePoints | length %}

                    {% for items in block.codePoints %}

                        /* Outputs "Array" */
                        {{ items }}

                        {% for wtf in items %}
                            /* Outputs identical content & wrapper twice */

{{ wtf }}

                        {% endfor %}

                    {% endfor %}

            {% endif %}

{% endfor %}

I'd be delighted if someone were able to point out what I need to do differently.

I suppose in your example codePoints is the actual Table field.

In order to output the table rows, the template should look like this:

{% if block.codePoints | length %}

    {% for row in block.codePoints %}
         {# Assuming 'text' is the column handle of the text field #}

{{ row.text }}

    {% endfor %}

{% endif %}

You get a double output because every row contains an array containing each table field twice, it looks like this:

array(2) { ["col1"]=> string(4) "Some" ["text"]=> string(4) "Some" }

That's why when loop over items you get every text twice.

I hope this helps.


Exclude most recent entry type from a loop Hey everyone I am trying to output entries on the homepage. My goal is that the most recent entry is styled differently.
I achieved this by calling the loop too times:
    {% for entry in craft.entries.section('blogPosts').limit(1) %}
than
   {% for entry in craft.entries.section('blogPosts').all() %}
and it works perfectly.
My only issue is that I want to exclude the most recent post from the second loop, so it only appear in the first loop.

Is there a way in craft for exactly the most recent entry or I should do this with ID?

Thank you for your help!

Best practice is to only query for the data once, then perform any necessary filtering on the result, rather than making multiple expensive calls to craft.entries...

So in your case you could take the first entry using [0], and then use Craft's without filter to filter out the first entry from the list:

{% set posts = craft.entries.section('blogPosts').all() %}
{% set firstPost = posts[0] %}
{% set otherPosts = posts|without(firstPost) %}


Looping out a lot of entries. Ok, so I'm looping through a lot of entries. It's a large request, and I had to up php memory limit to 512M. But I'm sure there is a less memory consuming way to do this. Also, I want to cache the whole thing, apparently 512M isn't enough for that.

Any suggestions? Should I just go ahead and use the ElementAPI?

var geojson = [
          {
            "type": "StationCollection",
            "features": [
            {% for entry in craft.entries.section('map').limit(3000).find() %}
                {
                "type": "Feature",
                "geometry": {
                  "type": "Point",
                  "coordinates": [
                    {{entry.address.lng}},
                    {{entry.address.lat}}
                  ]
                },
                "properties": {
                  "title": "{{entry.title}}",
                  "slug": "{{entry.slug}}",
                  "alwaysOpen": "{{entry.alwaysOpen}}",
                  "phone": "{{entry.phone}}",
                  "saturdays": "{{entry.saturdays}}",
                  "stationType": "{{entry.stationType}}",
                  "sundays": "{{entry.sundays}}",
                  "workingDays": "{{entry.workingDays}}",

                }
              },
            {% endfor %}
        ]
      }
    ];

There isn't really a good way to extract large chunks of Craft entries using the core features in Twig. Every entry you fetch is a EntryModel and those take up some memory due to relations and other stuff in Yii's ActiveRecord class.

What you can do is to create your own custom Plugin that does the same thing but queries the database directly instead, by-passing Crafts EntryModels and just giving you the dataset results directly.

Here's some resources on getting started with Plugin development:

Craft official documentation: https://craftcms.com/docs/plugins/introduction

From StraightUpCraft: https://straightupcraft.com/plugin-development

A wrapper for creating a Plugin default setup: http://pluginfactory.io/


Is there a way to use the includeCssFile tag to include a css file for print media? {% includeCssFile %} can be used to add "regular" css files in the head tag. Is it possible to use this tag for print media?

You can use the {% includeCssFile %}, you just need to make sure and wrap all of the styles in the print stylesheet with @media only print { } or @media print { }

@media only print {
   nav {
       display:none;
   }
   p {
       color:#000000;
   }
   .etc {
   }
}


unserialize(): Error at offset 0 after attempting to download and install plugin within control panel Steps to reproduce:

Log into control panel,
Go to Plugin Store tab and install a plugin (in my case hillholliday/craft-user-manual or dolphiq/sitemap),
Plugin installation error screen,
Navigate to /admin and entire site errors out with this message (control panel and frontend)

unserialize(): Error at offset 0 in ProjectConfig.php

Unsuccessful attempts to correct the issue include:

Restoring latest database backup
Restoring backed up composer.json and composer.lock files from storage/composer-backups and running composer install
Clearing storage/runtime/cache

Any suggestions on how to resolve this issue, and insights to why it's happening in the first place?

I think what ended up working was restoring backed up composer.json and composer.lock files, deleting everything in /vendor directory, and then running composer install


Is it possible for an assigned entry (via field type Entries field) to know what it has been assigned to? I have two entry types 'pipeline' (structure) and 'series' (channel). I know I can add children in a structure, but I want to keep 'pipeline' and 'series' separate to avoid duplication, as a series can belong to multiple pipelines.

I assign a series to a pipeline with a field type Entries field.

As an example I assign 'series1' to 'pipeline1' and 'pipeline2'.

What I'd like to know:

a) Is it possible for 'series1' to know it is assigned to 'pipeline1' and 'pipeline2'?

b) If it's not possible, is there a way to update the series entry when assigning to a pipeline?

Thanks for any help!

You could use the relatedTo param (docs).

{% set relatedPipelines = craft.entries()
    .section('pipeline')
    .relatedTo(yourSeriesEntry)
    .all() %}

Would return pipelines (if any) related to your series1.


Predefined Tags For Editors Is it possible to set up predefined tags in craft which can then be used as either a select list or checkbox selection by editors, so as to only give them the option of adding preset tags as opposed to adding any tag they want?

Not really (or not without a custom solution anyway) — tags are designed to be added by anyone. You might be better off using categories for this, which you can resist access to via userGroup permissions.


Image transforms and modal gallery I'm using a gallery where when an image is clicked it opens a larger version in a modal.

Initially the larger 'galleryLarge' images wouldn't load because the transform hadn't been created. After some digging around on here I found that adding 'generateTransformsBeforePageLoad' => true, to craft/config/general.php would create the transforms (all of them) before the page loads.  This worked a treat and now my modal works as expected!

Problem:  The page now takes forever to load.  I stopped this issue by removing the line from general.php but now of course, any new images added by the client won't get transformed.

Any ideas around this issue would be great.

Many thanks

Martin

When 'generateTransformsBeforePageLoad' => true is set, is it taking a long time to load because of the sheer number of images you have or is it only on the first request when all of the transforms are being generated?

After they are generated, they are quickly served directly by Apache (or whatever your webserver is) and Craft doesn't get involved.

If it's because of the sheer number of images you have, then you'll probably want to look at a front-end method of lazy loading the images as they are needed.


Elegant Way To Pass Configuration To yiic? I am trying to write a console plugin for yiic so that I can import data programmatically from an old site.

I have a multi configuration setup for the craft site. Is there an elegant way to tell yiic which configuration I am targeting (so that it opens the right database etc)?

ok i used the answer brad bell posted above and enhanced it slightly. i wanted to be able to specify the target environment on the command line, and i didn't want to edit a framework file to do it.

so i created the following file, yiic_frontend.php, placed it in $root/utils (a new dir), and call it using php $root/utils/yiic_frontend.php --env=envname plugin cmd:

<?php

/**
 * a front end for yiic.php that looks for env on cmdline and sets CRAFT_ENVIRONMENT
 * accordingly. I put this script in a folder called "utils" in the root of my website
 * install. So instead of doing something like
 *     php $root/craft/app/etc/console/yiic.php plugin cmd
 * you would call
 *     php $root/utils/yiic_frontend.php --env=envname plugin cmd
 * where "envname" is the config environment you wish to use.
 */

for ($i = 1; $i < count($_SERVER['argv']); $i++) {
    $arg = $_SERVER['argv'][$i];
    if (strpos($arg, '--env=') === 0) {
        $env = explode('=', $arg)[1];
        printf("---- setting env \"%s\"\n", $env);
        define('CRAFT_ENVIRONMENT', $env);
        array_splice($_SERVER['argv'], $i, 1);
        break;
    }
}

require(__DIR__ . '/../craft/app/etc/console/yiic.php');


Change asset upload path based on locale We have a localized site with separate public directories. I'm looking for a method to handle image uploads for the different asset paths.

For example when uploading an asset within a particular locale, the image will be deposited in that public_*/uploads folder.

I thought perhaps concatenating the {craft.locale} in the asset path might work but it threw an error. I'm thinking that the locale doesn't change when selecting the language from the sidebar or asset dropdown.

I'm pretty stuck on this one and there doesn't seem to be any answers online. Any other ideas or solutions would be appreciated.

{craft.locale} won't work because the single curly brace syntax is short for {{object.craft.locale}} where object is the element that is currently being edited (in your case, the entry).  You can read more about that here: https://craftcms.com/docs/assets-fields#dynamic-subfolder-paths

Your screenshot shows the double curly syntax, though (which should work fine).

Alternatively you could use {locale}, which would translate into {{object.locale}}, which would be the currently locale of the entry.


Getting all entries posted on any given weekday Super simple request, not sure if it's possible...

Can we pull all entries that were posted on a Monday, for example? Or pull all entries but group them by the day name they were posted on?

Can't think of a way how to query posts from a certain day, but you can certainly group entries by day they were posted on:

{% set allEntries = craft.entries.section('blog').limit(null) %}
{% for day, entries in allEntries | group("postDate|date('l')") %}

{{ day }}

        {% for entry in entries %}

{{ entry.getLink() }}

        {% endfor %}

{% endfor %}


Credit card fee to the final order in CP I need to add the credit card fee to the order in the CP. I get a response from the gateway with a custom txnfee variable and would like to view it in the CP. Just like an custom adjuster. Does anyone have any experience with that?

Example:

Order = $100
Tax = $5
Credit card fee = $1
Total = $106

I would save the response to an incognito field (or fields) on your order (probably both the entire response and also just the fee separate out).

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

The readonly incognito field is particularly good for this sort of thing - I use a bunch of these fields in a debug tab on my order layout to save useful things.

Just create the fields, add the fields to your order, and you update the values with the usual <input name="fields[fieldName]"> syntax with any cart operation, or use setContentFromPost if you're in a plugin:

    $order->setContentFromPost(array(
        'fieldName' => $creditCardFee,
    ));
    craft()->commerce_orders->saveOrder($order);


Sort entries in a category via entry field I have a section for Businesses. I also have categories that these businesses can belong to. On each category page I want to list all the businesses that belong to that category. So far so good, but here's the rub: Each business also has an entry field that relates the business to a Town entry.

Businesses belong both to a category and a town entry.

On the category page I want to list the businesses by towns. So instead of having a laundry list of businesses, the businesses would be broken up by the different towns they belong to:

Town A
    - Business 1
    - Business 2
Town B
    - Business 3
Town C
    - Business 4
    - Business 5
    - Business 6

I am grabbing my businesses like this:

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

I have seen other answers to different questions suggest GROUP, but I'm not sure how to correctly go about using the group method on an array when I am trying to group via another array (entry field).

I tried this, but it results in "Object of class Craft\ElementCriteriaModel could not be converted to string":

{% set businessesByTown = businesses|group('bizTown') %}

I know that's fishy and incorrect, but I don't know how to accomplish it the right way. bizTown is the entry field I want to sort by.

If anyone could help, that'd be wonderful! Thank you!

You are getting this error because the "entries" fields are always considered to be a query (ElementCriteriaModel) that can return more than one element. Therefore, if you know for sure that you will always have one and only one town linked to a business, you could do something like that:

{% set businessesByTown = businesses|group('bizTown[0].title') %}

If the title field is the name of the town you should get an associative array with the town names as keys and the businesses entries as values.

Additional info about sorting, following swthate's comment below:

If you want to sort the businesses, I think it can be done in the original query, so it would become:

{% set businesses = craft.entries.relatedTo(category).order('title') %}

However, the towns cannot be sorted directly since Twig's sort filter uses asort which sorts the array based on values. What you can do then is extract the businessesByTown array's keys in another array:

{% set towns = businessesByTown|keys|sort %}

You now have a sorted list of towns. Using this list, you can loop on all towns and businesses like that:

{% for town in towns %}
    {{ town }}
    {% set townBusinesses = businessesByTown[town] %}
    {% for business in townBusinesses %}
        {{ business.title }}
    {% endfor %}
{% endfor %}


Disabled Plugin Now Cannot Access Admin As per the title, I have disabled a plugin in admin and now the admin is not accessible.  It returns an Internal Server Error.

Any help would be appreciated

Fixed.  Had to delete the plugin entry from the database plugins table.


Alternatives to Mamp Pro – which works with Craft CMS I've been a long time user of Mamp Pro, but I'm getting an error using v3 with Craft3, due to needing to update to Mamp Pro 4, however after some hrs trying to update to Mamp 4, I can't get mySQL to start and therefore wondered what alternatives to Mamp other devs use – which isn't overly complex?

I'd highly recommend you check out Laravel Valet.

Here's an article on it that may be useful to you as well: Running Craft CMS 3 on Laravel Valet