Action route not available from URL. What do I have wrong?

Turns out the controller action was running, but since I was just using return, Craft was looking for a template to show once the functions were complete, and failing when it didn't find one. Using die(); after the function runs is working fine.


Can we set properties to establish a valid asset per field?

Currently, no. The only file-based validation Assets fields have right now is the type. If you want to enforce a certain size, you can do that on the template end using image transforms. I would suggest adding some instruction text to your Assets field that provides a minimum suggested size, and note that smaller images will be scaled up and look gross.

That said, if you really want to enforce a minimum width/height, or other properties, you can do so by writing a plugin that provides its own field type, which extends AssetsFieldType and overrides its validate() method with your custom validation:

public function validate($value)
{
    // Let AssetsFieldType do its validation first
    $errors = parent::validate($value);

    if (!is_array($errors))
    {
        $errors = array();
    }

    if (is_array($value) && !empty($value))
    {
        foreach ($value as $fileId)
        {
            $file = craft()->assets->getFileById($fileId);

            if ($file)
            {
                if ($file->width < 600 || $file->height < 400)
                {
                    $errors[] = Craft::t(
                        '{filename} must be at least 600x400px.',
                        array('filename' => $file->filename)
                    );
                }
            }
        }
    }

    if ($errors)
    {
        return $errors;
    }
    else
    {
        return true;
    }
}


Is Craft Suitable for Large Public Body website

One of the biggest Craft projects I've worked on has around 25 sections, 10+ global sets,  250+ fields, and 12,000+ elements across 16 locales (although only 1 locale has launched atm). Craft itself (the CP) has not had any problems I can remember handling it so far, especially with the element index updates that have been introduced over the last few months. I know there must be people running sites much bigger than that too.

On the front-end, we definitely had some slow templates where we are looping over a lot of related elements and outputting assets that were generating hundreds of queries per page, but careful planning, template caching, and in some cases using plugin code to pre-fetch data outside of the craft.entries etc calls in templates helped a lot. You can suffer from N+1 problems with relations and images - as you can with any CMS/website.

I wrote a small plugin for storing template caches in Craft's data cache (in our case Redis), which I'll see if I can release; we stuck Varnish in front of everything except CP requests; use S3 & CloudFront for serving assets; and while there's still room for improvement, we're now getting straight A's on webpagetest.org, so Craft certainly isn't just for small hobby-projects.


You don't necessarily need to use the nav tag, you can just spin through the entries in a normal {% for entry in entries %} loop, making use of the level property and the getDescendants method.

There are some good suggestions for more complicated nav code in this answer:

How do you handle complex navigation in Craft?

and there's some good pointers in the answers to this question:

Custom or complex nav tag


Best Method of Handling Repeated Content Within Existing Fields?

Forgive me but after re-reading everyone's input, I lean towards Moto_Nomad relationships suggestion, mostly because it will make life as easy as possible for the content-administrator.

In your latest comment you write:

  ...but the issue is not about relating entries, but smaller bits of information, for which there is not a prescribed location.

Q: Could you give us an example of a 'smaller bit of information', please?

  That is, there are bits of information which could be used nearly anywhere within the CMS (things like the event booking link, booking deadline, event start date etc etc)

I'd suggest that the 'smaller bits of information' as well as the info you mention above, which are relevant to a Festival/Event should be stored within those (Event) Entries.

Especially if these 'bits of info' are updated over time i.e. from from one event to the next.

(I'll avoid going into an explanation of the Entries field type)

;)

  The ideal solution would be that these bits of information are housed in one place in the CMS (probably will be a global), and can cleanly be pulled through to other areas of the CMS with a super user-friendly bit of syntax.

Check out this thread: Is it possible to use Twig in a Rich Text Field?

I realise the above is about the Front-End but thought it might be useful.

Let us know how you get on, Mike :)


You can grab the first word with the split filter according to this thread

{% set array = entry.title|split(' ', 2) %}

   {{ attribute(array, 0) }}
   {{ attribute(array, 1) }}

I didn't test this tough.

Edit: there is a Twig Fiddle demonstrating it.


Output raw html from if statement and combining strings?

{# set test variable, to make your code work #}
{% set block = {imageWidth: 300} %}

{# the real output #}
<img{{ block.imageWidth|length ? (' width="' ~ block.imageWidth~ 'px"')|raw }} />

Works for me


CSS uploaded to S3 is not rendering in the browser

Have you added the css content-type on S3? You can check this in the console > network tab

s3cmd put -m "text/css" $YOUR_PATH s3://$BUCKET/$YOUR PATH


You're likely running into Craft's userSessionDuration config setting.  It defaults to one hour and will automatically log you out (thereby destroying your session) after reaching that period of inactivity.


Apply custom filter on the entries in admin control panel using custom plugin in craft cms 3.5

Found it!!! Used ElementQuery::EVENT_AFTER_PREPARE


How to filter entries by multiple checkbox field types

Apologies if I’ve misunderstood your question and over-simplified things, but wouldn’t the search() method give you precisely what you need?
As in:
{% set valsToFind = "field_photoColor:red OR field_photoColor:green OR field_photoSubject:animal OR field_photoSize:small" %}
{% set galleries = craft.entries.section("gallery").search(valsToFind).all() %}


Redirecting "if entry is not defined" returns 404 instead

The reason you're getting a 404 is because Craft isn't even hitting your help/_entry.html template. Because there's no entry matching the URI /help/asdf, the template will never render and the request will go straight to 404.

The solution is to create a dynamic route matching your section's URL format (i.e. help/<slug>), and point it to the same template.

This works, because whenever Craft can't match a URI to an entry or category, it'll then try to render any dynamic route matching the URI's format (for a deeper understanding of how Craft manages routes and requests, I'd recommend looking at the the official docs' page on routing).


I just tested this and it works as you'd expect it to work for me locally:

<?php

$craft = require '/path/to/craft/app/bootstrap.php';

if ($craft->userSession->isAdmin())
{
    echo 'I am an admin.';
}
else
{
    echo 'I am not an admin.';
}

if ($craft->userSession->isLoggedIn())
{
    echo 'I am logged in.';
}
else
{
    echo 'I am not logged in.';
}


One large plugin vs multiple smaller plugins

I don't believe there's any significant impact in having multiple small plugins vs. one big plugin. It's probably safe to say that there is a small amount of overhead in loading each plugin separately, but that effect is probably negligible.

Personally, I'd keep all of that functionality combined into a single plugin. You say they are for "different, likely unrelated, things", but I'm guessing that they all serve a larger purpose of handling the business logic. If you haven't already, you may want to check out the Business Logic template, which is designed as a starter plugin for exactly this type of scenario.


Craft 3 multisite - best practice to minimize confusion and database size?

Thank you very much, Robin and Clive.

Note: I think there are better answers than what I have written here, such as this but they didn't appear to me after writing this.

In case it might benefit anyone, it's clear there are many ways to do this. My setup does not use Craft's "multi-site" capabilities, but has three urls pointing to the same index.php. It functions more or less as follows:

Folder Structure

craft/config/sitedata.php
craft/templates/_genericPageTemplate.html
               /mifc/_navigation.html
                    /local.css
               /migr/_navigation.html
                    /local.css
               /miwy/_navigation.html
                    /local.css
public_html/index.php

Main Page Template

Now starts with:

{% set domain = craft.app.request.ServerName %}
{% set siteUrl = '//' ~ domain ~ '/' %}
{% set env = getenv('ENVIRONMENT') %}
{% set sitesData = craft.app.config.getConfigFromFile('sitedata')[env] %}
{% set siteData = sitesData[domain] %}
{% set categoriesToDisplay = siteData.nativeCategoryIds|merge(siteData.sharedCategoryIds) %}

and later brings in the css and navigation depending on site:

<link rel='stylesheet' id='localCss'  href='/{{siteData.handle}}/local.css' type='text/css' media='all' />
...
{% include siteData.handle~'/_navigation.html' %}

Config File

In {% set sitesData = craft.app.config.getConfigFromFile('sitedata')[env] %}
the page template references craft/config/sitedata.php which contains stuff specific to each site, both for production and development:

<?php

/**
 * Return an array indexed by locale code
 */

return [
   'production' => [
        'site1.org' => [
            'live'                  => true,
            'handle'                => 'mifc',
            'nameInMenus'           => 'Fort Collins',
            'siteTitleSuffix'       => 'Fort Collins Meditation & Modern Buddhism',
            'url'                   => 'site1.org',
            'titleMainBig'          => 'Meditation & Buddhism',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Fort Collins and the Surrounding Areas',
            'topNativeCategoryIds'  => [194,195,220],
            'nativeCategoryIds'     => [194,198,10,11,14,196,7,1775,2476,5,4,9,6,8,267,2073,195,63,66,67,20,70,71,220,12,221,222,1688,223],
            'topSharedCategoryIds'  => [13,60],
            'sharedCategoryIds'     => [13,60],
        ],
        'site2.org' => [
            'live'                  => true,
            'handle'                => 'migr',
            'nameInMenus'           => 'Greeley',
            'url'                   => 'site2.org',
            'siteTitleSuffix'       => 'Greeley Meditation & Modern Buddhism',
            'titleMainBig'          => 'Meditation & Buddhism in Greeley',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Greeley',
            'topNativeCategoryIds'  => [197],
            'nativeCategoryIds'     => [197,3112,58,61,2940,59,62,60],
            'topSharedCategoryIds'  => [198,67,13],
            'sharedCategoryIds'     => [198,10,11,14,67,13],
            'eventsCategoryIds'     => [60,198,10,11,14,67,13],
        ],
        'site3.org' => [
            'live'                  => true,
            'handle'                => 'miwy',
            'nameInMenus'           => 'Wyoming',
            'url'                   => 'site3.org',
            'siteTitleSuffix'       => 'Wyoming Meditation & Modern Buddhism',
            'titleMainBig'          => 'Meditation & Buddhism in Wyoming',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Wyoming',
            'topNativeCategoryIds'  => [3151],
            'nativeCategoryIds'     => [3151,2969,65,64,68,69,72],
            'topSharedCategoryIds'  => [198,60,13],
            'sharedCategoryIds'     => [198,10,11,14,60,13],
            'eventsCategoryIds'     => [60,198,10,11,14,67,13],
        ],
    ],
    'dev' => [
        'f.dev' => [
            'live'                  => true,
            'handle'                => 'mifc',
            'nameInMenus'           => 'Fort Collins',
            'siteTitleSuffix'       => 'Fort Collins Meditation & Modern Buddhism',
            'url'                   => 'f.dev',
            'titleMainBig'          => 'Meditation & Buddhism',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Fort Collins and the Surrounding Areas',
            'topNativeCategoryIds'  => [194,195,220],
            'nativeCategoryIds'     => [194,198,10,11,14,196,7,1775,2476,5,4,9,6,8,267,2073,195,63,66,67,20,70,71,220,12,221,222,1688,223],
            'topSharedCategoryIds'  => [13,60],
            'sharedCategoryIds'     => [13,60],
        ],
        'g.dev' => [
            'live'                  => true,
            'handle'                => 'migr',
            'nameInMenus'           => 'Greeley',
            'url'                   => 'g.dev',
            'siteTitleSuffix'       => 'Greeley Meditation & Modern Buddhism',
            'titleMainBig'          => 'Meditation & Buddhism in Greeley',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Greeley',
            'topNativeCategoryIds'  => [197],
            'nativeCategoryIds'     => [197,3112,58,61,2940,59,62,60],
            'topSharedCategoryIds'  => [198,67,13],
            'sharedCategoryIds'     => [198,10,11,14,67,13],
            'eventsCategoryIds'     => [60,198,10,11,14,67,13],
        ],
        'w.dev' => [
            'live'                  => true,
            'handle'                => 'miwy',
            'nameInMenus'           => 'Wyoming',
            'url'                   => 'w.dev',
            'siteTitleSuffix'       => 'Wyoming Meditation & Modern Buddhism',
            'titleMainBig'          => 'Meditation & Buddhism in Wyoming',
            'titleSmallerSecondLine'=> 'Heruka Buddhist Center in Wyoming',
            'topNativeCategoryIds'  => [3151],
            'nativeCategoryIds'     => [3151,2969,65,64,68,69,72],
            'topSharedCategoryIds'  => [198,60,13],
            'sharedCategoryIds'     => [198,10,11,14,60,13],
            'eventsCategoryIds'     => [60,198,10,11,14,67,13],
        ],
    ]
];

Feel free to point out any mistakes, etc, in this way of doing things.


Why is my custom console command throwing Calling unknown method: ...getAcceptsJson?

I had a hunch that a web controller with a similar name was getting called, and indeed that is what was happening. In my module's init method I was setting the controller namespace like this:

$this->controllerNamespace = 'modules\vetscripts\controllers';`

By default, then, the console was going to the web controller, I'm assuming. @Selvin pointed me in the right direction with this:

use craft\console\Application as Console

...

public function init()
{
    ...
    if (Craft::$app instanceof Console) {
        $this->controllerNamespace = 'modules\vetscripts\console\controllers';
    }
    ...
}

Now I can see my module's custom console actions when running ./craft from the console.


How do I add an HTML tag to the formatting drop-down in the rich text editor?

Might formattingAdd be something you can use for this? Not tested, just a quick look at Redactor's options page.

formattingAdd: [
    {
        tag: 'code',
        title: 'Code'
    }
]


I just tested it for you and this

$craftPath = './craft';

or this

$craftPath = 'craft';

does both work for me!

This probably doesn't help you much; I only wanted to confirm, that your $craftPath = './craft'; config should be working for your file structure.


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

Manipulating the map in JavaScript

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


Override a wildcard dynamic route template

Sort order matters, move the more specific route up and you should be good. Alternativly set it up in routes.php using some regular expressions.


"Craft isn't installed yet" error after updating to Craft 3.1

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

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

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

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


How to prevent Craft from injecting scripts in the page?

You can set the runQueueAutomatically config setting to false to prevent this.

You'll just want to set up an alternative way to process the queue as noted in the docs.


How do I implement Google+ comments on a Craft site?

This is a bit tricky, and there may be some tradeoffs that I'm unaware of, but the following code works for me:

Two things to note about the code above.

You want to pass the url that will be associated with the comments to the data-href attribute. The example above assumes you are on a page where {{ entry.url }} is the value you want.
The line that references BLOGGER is required: data-first_party_property="BLOGGER"

I can't explain why that is, but the odd specificity of it may also be a reason why this isn't an easy thing to figure out how to do, as it may suggest this is an unsupported method of adding Google Comments to your site or that the method to add Google Comments to your site will change at some point.

In my searches however, this was the only method I found to do it at all and it seems to be used by several people and work just fine at the time of this post.


Issue Excluding Entries with Multiple Categories in Query

Start by getting the category ID(s) you want to exclude:

{% set categoryIds = craft.categories()
    .group('categories')
    .slug('category-one')
    .ids() %}

Then get all the entry IDs that are related to them, which should be excluded:

{% set excludeIds = craft.entries()
    .relatedTo({
        targetElement: categoryIds
    })
    .ids() %}

Then run your main news query, excluding those entry IDs.

{% set latestNews = craft.entries()
    .section('news')
    .id(['not']|merge(excludeIds))
    .with([
        ['image', {
            withTransforms: ['medium']
        }]
    ])
    .orderBy('postDate desc')
    .limit(4)
    .all() %}


Render styled output using Printmaker plugin

I've had this same problem getting Printmaker use an external stylesheet.

Simply putting the styles in the head of the template sorted it out.

You could also try setting the path to your css with a . like so;

<link href="./path/to/styles.css" rel="stylesheet" type="text/css">


How to merge/combine/transfer-entries-between two categories in the CP?

This could easily be accomplished with a MySQL query on your DB. Of course, BACK UP YOUR DATABASE FIRST!

Example, assuming the old category ID is 1 and the new one is 2...

UPDATE `craft_relations`
SET `target_id` = 2
WHERE `field_id` = [your field id] AND `target_id` = 1;


How to route to a controller action in Craft3?

The problem ended up being something underlying in craft or yii2 that will not route the word "echo".

I changed out "echo" to "test" and it works fine. Even with both routes in, one does not and one does:

    // Register our site routes
    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_SITE_URL_RULES,
        function (RegisterUrlRulesEvent $event) {
            $event->rules['echo'] = 'site-dom-injector/default/index';
            $event->rules['test'] = 'site-dom-injector/default/index';
        }
    );


FormBuilder 2 - Notification email to the form submitter

You could use the also wonderful amforms, which has this standard built in. The only thing is that it will send an exact copy of the admin mail. If you need a custom submitter mail, my guess is that sproutforms + sprout email is the best solution (you'll need them both).


Controller action redirection when called via route

You're mistaken about how redirectToPostedUrl works... That's designed to redirect from a form submission, when the redirect field was supplied:

<input type="hidden" name="redirect" value="page/to/redirect/to">

What you really want is this:

$this->redirect(craft()->request->getUrlReferrer());

The request->getUrlReferrer method will actually retrieve the originating page URL.


This should work:

{% if block['blockTitle'] is defined %}
    // Do your thing
{% endif %}


Is it possible to detach event listeners?

Not possible currently, but there's a feature request.


Cache not invalidating when using pagination with cache

One issue I'm seeing, is that you're currently using craft.request.path as your cache key – however, that property doesn't actually include the pagination segment (i.e. the pageTrigger; p2, p3 or the like), which means that you're currently going to see the same, cached content across all of your pages, because you're caching globally using an identical key (i.e. the root URI of your paginated template).

For Craft 2, AFAIK there's no single property or method on the HttpRequestService that will give you the full URL including the pagination segment – so you'll need to append the pagination number using craft.request.getPageNum():

{% cache globally using key craft.request.path ~ craft.request.getPageNum() until cacheUntil %}

For Craft 3, there's craft.app.request.getFullPath(), which does include the pagination segment – so the following should do the trick:

{% cache globally using key craft.app.request.getFullPath() until cacheUntil %}

As far as your solution for breaking the cache whenever "pending" entries are published, I'm not sure, but I'm not seeing any problems with it, at a glance.

The reason why you're not seeing the cache cleared when you create new entries, is probably because your second craft.entries query (the one that actually fetches the entries) is outside your {% cache %} tag (this would be a performance issue as well; your current code isn't really caching anything, except a bit of not too demanding Twig code). You should probably move the second craft.entries query, the {% paginate %} tag and the {% include '_includes/partials/pagination' %} statement inside the {% cache %} tag pair.

Also, you might want to re-think having a default cache duration of 1 year – that's a long time, and if your site builds up a lot of pages, it could balloon your database and possibly cause issues with stalled Deleting state template caches tasks. My advice would be to keep the duration to something sane like 1 month, max – there's little point in keeping year-old caches around, normally :)


Craft CMS contact form plugin works locally but not in production?

There's a support article here you can help use to debug email deliver issues: https://craftcms.com/support/troubleshooting-email-errors#dealing-with-email-delivery-issues

The TL/DR is, use a transaction email provider like Postmark, Mailgun, etc. and make sure you've got DKIM/SPF and DMARC all setup properly as well.


Accessing admin panel after deploying local MAMP

Apparently what I did was correct, because now it works. I had some EE files right next to the index.php files and these messed things up for some reason. Probably the admin.php file.

At least now I know it's easy to deploy Craft with the three steps I mentioned above


Managing sections and field updates between environments

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


Having problems with dynamic Asset folders and {owner.slug}

According to Andris this is the expected behavior in this situation. The bug fix does make Craft work as intended but creates a slightly confusing workflow if you don't know what to expect. The good news is my expected behavior, which is to have assets available if {owner.slug} has been created in my assets folder already, is on the official list of features to implement. Well, assuming Andris doesn't go into a drunken stupor and forget to tell Brad or Brandon.


which Sources of asset field are checked

You can get all available sources with

field.getSourceOptions()

Which returns you an array of all sources, no matter if they are selected or not (just to get the ids and such)

and with

field.sources

you'll receive an array if you selected several sources or a string (*) if all are selected.


getting the current user entries from elementapi

If you really want the entries for the currently logged in user, having a parameter for userId in your endpoint URL doesn't really make sense.

Not tested, but something like this should work:

'api/v1/user.json' => function () {

    $author = craft()->userSession->getUser();

    if (!$author) {
        HeaderHelper::setHeader(array('status' => 404));
        craft()->end();
    }

    return [
        'elementType' => ElementType::Entry,
        'criteria' => [
            'section' => 'jobs',
            'authorId' => $author->id,
        ],
    ];
}

Notice that the above example endpoint would be available at http://example.com/api/v1/user.json, where your example code would create an endpoint with a required userId parameter, i.e. http://example.com/api/v1/user/12345.json.

Also notice that the currently logged in user is pulled via the UserSessionService (craft()->userSession).

Finally, note that you should use 'authorId' => $author->id in your criteria – not 'author' => $author.


Displaying entries from a specific custom date year

I ended up using this code.

{% set upcoming = craft.entries.section('section').order('customDate')%}

{% for entry in upcoming %}
    {% if entry.customDate =='2018-10-12' %}
        {{entry.title}}
    {% endif %}
{% endfor %}

Works for now anyway.


Multisite system messages: change domain in {{ link }}, other than primary domain

This is currently expected behavior due to this bit of code, which explicitly passes in the primary site ID when generating those link URLs for a user:

https://github.com/craftcms/cms/blob/develop/src/services/Users.php#L1079-L1081

The reasoning is that even on a multi-site setup, users are all "global" (i.e. not defined per site).

If you feel this is a bug or produces undesired behavior, feel free to create an issue where it can be further discussed.


How to Redirect After Successful Registration Confirmation

The config settings you're looking for are probably 'activateAccountSuccessPath' and 'autoLoginAfterAccountActivation'.


Use GET parameters to query for array of entry IDs

I found a response for Craft 2 that looks like it's similar to what I want: (Passing multiple parameters to the Element API) which uses the getQuery() or getRequiredQuery() functions, but I'm not sure those still exist in Craft 3?

In Craft 3, you'd use:

Craft::$app->getRequest()->getRequiredQueryParam('myArr')

https://docs.craftcms.com/api/v3/craft-web-request.html#method-getrequiredqueryparam


When is Craft 3 ready for commercial use

The full release is only 23 days so I would suggest that it's time to start looking: https://craftcms.com/news/craft-3-launch-faq


If I'm understanding you correctly, you've got a Rich Text field you're using in one of your Single's field layouts.

That Rich Text field will have settings (under Settings->Fields->(click on the Rich Text field you're using for that single)).  From there, you can select the specific craft/config/redactor/config.json config file you'd like that specific Rich Text field to use.


I think your checkboxes need to be as follows:

<input type="checkbox" name="fields[Classification][]" value="Hub Zone">Hub Zone
<input type="checkbox" name="fields[Classification][]" value="Not Applicable">Not


Relating entries to assets within an ElementAction

So it seems what I was doing wrong was passing in a single $artistId rather than an array. With the change shown below it works as expected:

foreach ($assets as $asset)
{
    $artistFieldModel = craft()->fields->getFieldByHandle('artist');
    craft()->relations->saveRelations($artistFieldModel, $asset, [$artistId]);
}


Getting unknown property: craft\web\Application::GeneralConfig

Please use a proper IDE or take a look into the source code to get to know the functions of the class. As you can see in the class reference the function is called

Craft::$app->getConfig()

However - in order to create urls you should use the UrlHelper


Clicking New field on /admin/settings/field/new hangs site

We discovered that the verbb/icon-picker plugin makes a call out to retrieve a file from it's cpresources cache and this was done with a fully qualified URL. Our AWS machines in CI/CD can be auto-provisioned and as such won't have their own name in the /etc/hosts file. So a call to https://fully.qualified.url/cpresources/577762fa/json/font-awesome.json?v=1556336828 was failing and hanging the site because it tried to get it five times in a row.

I've registered an issue with the Verbb folks, and put a PR together, so crossing my fingers!


How can I retrieve channel data in json format?

I just threw together a add-on that will provide a Twig filter called prune to allow you to more easily do what you're asking here.

https://github.com/mattstauffer/craftcms-prune

With prune you can now just do the following:

{{ craft.entries.section('news').find() | prune(['title', 'body']) | json_encode() | raw }}

Just pass in an array of the fields you want to pluck out. It's pretty new and could use some love, but it'll get the basics done for sure.


In Craft 3 plugins, should CRUD operations go in Controllers or Services?

Putting aside the term "CRUD" for a moment, it essentially breaks down like this...

If something wants to ping your site, it is (almost) inevitably going to be pinging a Controller.
If you want to do something in the database (create, update, delete), you should probably be doing that in a Service.

Which raises the question, "how/where to bridge that gap?"

The answer is, "it depends."

You could keep most of your logic in the Controller, and just move the DB interactions to the Service. Or you could immediately ping a Service method as soon as your Controller is hit. Either way is fine, and it depends heavily on what the site requires, and what you (as the developer) are more comfortable with.

As you noted, sometimes people bend the rules and put DB interactions directly into the Controller method. While that's frowned upon, there may not be any negative repercussions. So don't worry too much about how other people are handling it... just do what makes sense to you.


How to include JS and CSS resources for a plugin variable

You can use these and Craft automatically adds the files in the appropriate spots.

$output = craft()->templates->includeJsFile(UrlHelper::getResourceUrl('plugin/script.js'));

$output .= craft()->templates->includeCssResource(UrlHelper::getResourceUrl('plugin/styles.css'));


DevMode not showing detailed Internal 500 Errors

I confirmed this was a regression with the Yii 1.1.16/Craft 2.4 update and it's been fixed for the next post 2.4.2670 update.


orderBy title, but remove the word "The" from titles

{% set entries = craft.entries().section('media').orderBy("(CASE WHEN `title` LIKE 'The %' THEN SUBSTRING(`title`, 5) WHEN `title` LIKE 'A %' THEN SUBSTRING(`title`, 3) ELSE `title` END) asc").limit(24).all() %}
worked.


Internal Server Error when adding new Fields

Solution

Login to the server and access mysql and find your database.

Select the fields table to locate the ID of the problem field.

SELECT * FROM fields;
Remove the field using the ID.

DELETE from fields where id = '355';


How do I create an advanced route with multiple slugs?

Brad nails the problem in his comment:

  The error is because you've got two named subpatterns with the same name (<slug>)

And the solution is simple... Change the name(s) of your subpattern(s).

The term slug is just a convention of Craft. It doesn't matter what the names are, they can be anything useful to you:

(?P<domain>[^/]+)/(?P<category>[^/]+)/feed

Whatever values match those named patterns are automatically passed into the Twig template as "magic" variables. So your Twig template can now make use of the domain and category values.


You need to use /actions (or whatever your Trigger word is) to access Controller actions.

Documentation: http://buildwithcraft.com/docs/config-settings#actionTrigger

EDIT: I realize I wasn't clear enough; this variable defaults to /actions. Unless you've set it to something else in your Config, add the /actions to your URL to access the Controller action.

So, your URL would be this: http://domain.craft.dev/actions/PluginHandle/Duh/foo

Note that capitalization matters.

It's also important to make sure that if you plan on making calls to this URL from outside Craft, you'll need to make sure that you're allowing anonymous access by setting that variable at the top of your controller:

protected $allowAnonymous = true;


Incorrect canonical URLs and redirect chains

Update to the latest SEOmatic; the issue you're describing is a case where SEOmatic operates the same as Craft CMS does in terms of returning a root URL without a trailing slash, but we added a fix to SEOmatic 3.3.18 anyway.


Stop Redactor automatically creating hyperlinks

Use the autoparse option to deactivate that behaviour in the redactor configs

Go to: config/redactor/ and add this I believe (untested):

{
  "whatever": true,
  "autoparseStart": false
}


Element API Endpoint returns data but has 404 header

Removing this from my site's nginx conf fixed it:

location ~* \.(?:manifest|appcache|html?|xml|json)$ {
 expires -1;
}

However, what I really want to do is cache stuff, without breaking this endpoint


Image Transforms - Image not processed until second page refresh

In your config file, set generateTransformsBeforePageLoad to true:

general.php:

return array(
    //other configs
    'generateTransformsBeforePageLoad' => true
);

This will trigger craft to generate and save transforms ahead of loading the page, as explained in the documentation here, this is will also work if you're using a plugin to provide the images.


Craft 3 - Programatically get all the values contained in a field of type category

Your field contains an object of type ElementQuery in order to get all Categories you'll need to execute it.

$categories = $element->getfieldValue('productTheme')->all();
$categoryTitles = [];
for($categories as $category){
    $categoryTitles[] = $category->title;
}

Please read the documentation


Is it possible to repopulate radio button inputs with values from submission.fieldMetaData using the standard form.render() method?

A little messy but here's how I got it to work in case anyone else has this question. It even seems to respect the conditional display rules on my form.

{% if form|length %}
    {{ form.renderTag }}

    {% if form.hasErrors %}

        {{ "Error! Please review the form and try submitting again."|t('freeform') }}

        {% if form.errors|length %}

            {% for error in form.errors %}

{{ error }}

            {% endfor %}

        {% endif %}

    {% endif %}

    {% for row in form %}

        {% for field in row %}
          {% set columnClass = "freeform-column " ~ form.customAttributes.columnClass %}
          {% if field.type == "submit" %}
            {% set columnClass = columnClass ~ " freeform-column-content-align-" ~ field.position %}
          {% endif %}
          {% if field.type == "radio_group" %}

                {{ field.renderLabel() }}

                 {{ field.renderInstructions() }}

                {% if field.errors %}

                    {% for error in field.errors %}

{{ error }}

                    {% endfor %}

                {% endif %}
                {% for option in field.options %}

                        <input type="radio" class="freeform-input"
                          name="{{ field.handle }}" type="radio"
                          id="form-input-{{ field.handle }}-{{ loop.index }}"
                          value="{{ option.value }}"
                          {{ option.value == submittedValues[field.handle] ? 'checked' : '' }}>
                        {{ option.label }}

                {% endfor %}

          {% else %}

            {{ field.render({
              class: field.type != "submit" ? "freeform-input" : "",
              labelClass: "freeform-label" ~ (field.inputOnly ? " freeform-input-only-label" : "") ~ (field.required ? " freeform-required" : ""),
              errorClass: "freeform-errors",
              instructionsClass: "freeform-instructions",
              overrideValue: field.handle ? submittedValues[field.handle] : ''
            }) }}

          {% endif %}
        {% endfor %}

    {% endfor %}
    <input type="hidden" name="statusId" value="2">
    <input type="hidden" name="submissionId" value="{{ application.id }}">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">
    <input type="hidden" name="userEmail" value="{{ currentUser.email }}">
    {{ form.renderClosingTag }}
    {% endif %}

{% js %}
    var act = document.getElementsByName('action');
    act[0].value = 'freeform/submissions/save'
{% endjs %}


In entry.getPrev/Next navigation, show entries from a specific category only

Try this

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

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

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

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


Getting previous order history in a Commerce 2 adjuster

The method to check the previous orders would look something like this:

public function checkIfDonated($order)
{

    $email = $order->getEmail();

    if (!$email) {
        return false;
    }

    $orders = Plugin::getInstance()->getOrders()->getOrdersByEmail($email);

    $didDonate = false;
    foreach ($orders as $previousOrder) {
        foreach ($previousOrder->getLineItems() as $lineItem) {
            $purchable = $lineItem->getPurchasable();
            if ($purchable && $purchable instanceof \craft\commerce\elements\Variant && $purchasable->getProduct()->getType()->handle == 'typeA') {
                $didDonate = true;
            }
        }
    }

    return $didDonate;
}

That above assumes you want to look at all orders made by anyone with that email address. You could add additional guards after the email check to see if they are logged in as a user etc. Hope that helps.

Also, don't forget to pass the order to the method: if ($this->checkIfDonated($order) == true)

And to add the Plugin import: use craft\commerce\Plugin; to the top of the adjuster class.


Tricky is a mild way of putting it.

EE and Craft both hash (not encrypt) their passwords differently. Hashing differs from encryption in a few ways, but the most important one here is that hashing is not reversible, which means that the passwords cannot be recovered. Which, in turn, means that if you import the user information into Craft, the members still would all have to reset their passwords.

If that's okay, then you would be looking at a custom plugin that uses the Users Service.


Two Plugins not showing in CP after pushing to staging server

Check if the plugin folders in craft/plugins are named correctly. Most local environments aren't case-sensitive, but most servers are.

Valid:

craft/plugins/trunchtml/
craft/plugins/import/

Invalid:

craft/plugins/truncHTML/
craft/plugins/Import/


You can't just upload files via serialized form data by default with jQuery. I suggest you to create a new FormData instead and append the files from your input, so you need to grab them first

You can see a good guide simple file uploads


Instructions for Using Craft "Embedded Assets" Plug-in?

Author of EA here. Adding in that extraAllowedFileExtensions config setting is about all you need to do. Any other configuration is just for "power" users (for lack of a better term) and you shouldn't need to worry about them.

There's many reasons why you might not be seeing anything show up in your templates. You also said it sometimes breaks the page altogether? Can you please elaborate on this? Are you running in dev mode? If there are any errors, what are they?

It might be better for you to post this as an issue on the Github page, so it can be more of a discussion. I don't really have an answer for you as I don't yet know what the cause of the problem is.


Filtering a Matrix block for future dates

Thanks Marten, yes, that's correct.

After plugging away I have gotten it to work, but it's likely not as efficient as it could be...

{% set today = now|date('Y-m-d') %}
{% set todayday = now|date('l') %}
{% for block in entry.closedDates.date('>=' ~ today).limit(1) %}
    {% set closedDate = block.date.format('Y-m-d') %}
    {% if closedDate == today %}

It's a holiday, sorry, we're closed

    {% elseif todayday == 'Sunday' %}

It's {{ todayday }}, sorry, we're closed

    {% else %}

We're Open!

    {% endif %}
{% endfor %}

I added a check for whether today is Sunday, which is a normally closed day that would not be in the entry.

Doug


How do I redirect traffic from a legacy category URL to a new category URL?

There are a few plugins which can handle this, but Retour is the newest and shiniest!

  https://github.com/nystudio107/retour

It's from the same developer as SEOmatic... he puts a lot of love & attention into his plugins, so you know it's safe to rely on.


How do I select a default in the Position Select field?

As there's no settings option to define a default, there's two things you can do:

Copy / fork the field type and add the option or simply hack it to your needs.
Contact P&T and make a feature request for setting field type defaults for Position select (and others).


To test if the current block is the last in the loop and of a certain type, you could do something like:

{% if loop.last and block.type == "yourBlockType" %}yes{% endif %}

or shorthand

{{ loop.last and block.type == "yourBlockType" ? 'yes' : 'no' }}

In the above example replace 'no' with '' to output nothing. It's  just there if you want to output something in case of false

or even shorter

{{ loop.last and block.type == "yourBlockType" ? 'yes' }}


Copy of subsite is still serving index.php in the links?

You should have the setting 'omitScriptNameInUrls' => true on either both sites, or in the wildcard config.

<?php

return [
    '*' => [
        // ...
        'omitScriptNameInUrls' => true,
        // ...
    ]
];

You can read more about it here:
https://craftcms.com/support/remove-index.php


You need to get all possible translations of your entry slug to do a thorough comparison.

This is only possible with additional DB queries (ElementCriteriaModels) for each of your navigation items and each of your installed locales, if you don't want to hardcode the values into your template.

Because your navigation probably doesn't change that often, I'd do it anyways and simply wrap the whole navigation in {% cache %} tags with a really long invalidation time (it does get updated if anything is changed within the tags though!).

{% cache for 3 years %}
{% for naviItem in navi %}

    {# Get the relevant URL segment #}
    {% set segment = craft.request.segment(1) %}

    {# Get all possible translations of the entry slug #}
    {% set enSlug = craft.entries.id(naviItem.id).locale('en').first().uri %}
    {% set frSlug = craft.entries.id(naviItem.id).locale('fr').first().uri %}
    {% set deSlug = craft.entries.id(naviItem.id).locale('de').first().uri %}

    {# Define a variable `activeClass` if the URL segment matches one of the slug translations #}
    {% if segment == enSlug or segment == frSlug or segment == deSlug %}
        {% set activeClass = ' active' %}
    {% endif %}

        {# If the `activeClass` var is set, add its value to the link's classes #}

            {{ naviItem.naviTitel }}

{% endfor %}
{% endcache %}


Display entries based on 'entries fields'

You are correct in your assumption! Using relatedTo with the associated field:

{% set entries_fields = craft.entries.section('blog').relatedTo({
    sourceElement: entry,
    field: 'fieldHandle'
}) %}

Note that field can be the field handle of your Entries Field but it can also be a field ID.


Commerce - add new tab to order page in control panel

This certainly used to be possible and was quite handy, but I believe since the commerce orders admin area moved to using Vue, there's no easy way to hook in and do this any more.
Would love to be proven wrong, though!


February always comes out as March - expect /yyyy/mm to be 2018/02 but it's 2018/03

I think the problem is that you are not being specific enough with the date that you are passing to the date function. You are in effect calling date("February") and the PHP date function has to make an assumption and uses the current day of the month, i.e. February 30 which equates to March. If this is correct you will have even more issues tomorrow being the 31st!

If you make the date being passed more specific i.e. February 1 it should work fine.

A related PHP bug post, that wasn't a bug, explains it https://bugs.php.net/bug.php?id=49115


loop.index and loop.index0 will both return integers.

So when you do {% set previous = loop.index - 1 %}, on the first iteratin of that loop, loop.index returns 1, then you subtract 1 from it and previous is now equal to 0.

Later you call previous.url(), which is equal to 0.url() and the error message you get says there is no method named url() for the integer 0.

If you want to access the previous row, then you can probably do something like {% set previousRow = module.contents[previous] %}.


Redirect user to the page they wanted after login

If you are using {% requireLogin %} tags, then the Craft UserSession service has a getReturnUrl() method which should give you what you want. It is accessible in your templates via craft.session.returnUrl. Here is a link to the docs. Hope this helps!


It's not a simple question, but a fundamental one.

Whenever you query one of Craft's Element API services (such as craft.entries, craft.assets and craft.categories) or a relational field (such as an Entries or Assets field, i.e. entry.myAssetsField) you'll get back an ElementCriteriaModel instance.

The ElementCriteriaModel is basically a fancy wrapper for your query, which you can call methods on (such as .find(), .ids(), .first() and .last()), in order to actually pull elements based on your criteria (e.g. .section('sectionHandle')). Some methods – such as .find() – will return an array of elements (Craft actually calls .find() implicitly unless you use one of the other methods), while others will return a single element (.first(), .last()). There are also methods that can do different things entirely, such as returning an array of matching element IDs (.ids()).

In your example, you're using .find() – which means Craft will return an array of elements (even if there's only one). In such cases, it usually makes more sense to use .first(), to make Craft return a single element and avoid the for loop:

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

However, since the query may not always return any matching elements, it's usually a good idea to wrap the result in a conditional:

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

The above will of course also be true for any relational fields – consider an Assets field for a "featured image"; even if you limit the field to a single image, simply accessing the field in a template will always return an ElementCriteriaModel, unless you use .first():

{# Returns an ElementCriteriaModel #}
{% set featuredImage = entry.someAssetsField %}

{# Returns an array of elements #}
{% set featuredImage = entry.someAssetsField.find() %}

{# Returns a single Asset #}
{% set featuredImage = entry.someAssetsField.first() %}

  Also I am curious if 'entry' in the for loop actually means anything or is just a good symantic name to use

It's just a semantic name – the result variable for your query can be named whatever you want:

{% set myAwesomeSingleEntry = craft.entries.section('sectionHandle').first() %}

However, a good thing to know about is that whenever Craft matches the current URL request to an element – e.g. your Single entry – it'll automatically populate your template with an entry variable. In other words, if the current page is the actual URL for your Single entry, you won't need to do any craft.entries query at all (this is true for all Entries and Categories that have URLs enabled).


This could be because you are setting your Settings → Assets → your volume File System Path to an absolute location outside the VM.
Create an alias (or hard-set webroot) using:
'aliases' => [
    'webroot' => dirname(__DIR__) . '/web'
],

In your config/general.php (changing web if you have a different public root).
With this in place, change the File System Path of your volume to @webroot/your/path which should solve you issue.


Using Image Transform as another custom field

The imageTransform value is actually an object, representing the entire dropdown field.

Update the first line to this...

{% set imageTransform = storyEntry.storyThumbnailTransform.value %}

This will ensure that the selected value is passed on, instead of the full object.

(The reason that you see the proper value when you output it directly is because the object's __toString method is automatically being called internally.)


This warning appears when the content column type of the current selected field is different than the new one -> you'll lose all the information that is currently stored.

For example: changing from number to text won't be a huge problem but changing from text to date will result in a data loss


Looking to use a tag slug/URI and loop through entries of that tag

Here's a really DRY way to do it.

Setup a route, something like "news/tags/(tag)" to load the "news/index" template (the same one used for listing all entries).

In the "news/index" template:

{# If there is a tag token in the URL, set a filtered variable. #}
{% if tag is defined %}

Tag: {{ tag }}

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

    {% set entriesToShow = craft.entries.section('news').relatedTo(tag) %}

{% else %} {# No tag token in URL, assume unfiltered overview page. #}

    {% set entriesToShow = craft.entries.section('news') %}

{% endif %}

{# the entry loop for both filtered and unfiltered entries #}
{% for entry in entriesToShow %}
    {# display entry #}
{% endfor %}

When templating tag links to this system use:

{{ siteUrl }}news/tag/{{ tag.name|url_encode }}

This method allows you to reuse your entry loop and you don't even need a "tags" template. I can also be expanded to filter by categories as well without needing another template.


Load a page via HTTP and make an AJAX request via HTTPS afterwards using CSRF-Token

Completely untested, but try setting the recently added useSecureCookies setting to false and see if that works.


The best way to accomplish what you're trying to accomplish would be to utilize the after.sh shell script that Homestead provides. Check out Extending Homestead and Local Development with Vagrant / Homestead


ServiceUnavailableHttpException on front end, and 404 on admin

It turns out it was because I had Apache running and on port 80. I saw something about this somewhere in the guides I followed, but forgot to come back and stop Apache. Oops.


How to check for an HTML element in a rich text field?

You can get this to work if you first escape your string using Twig escape filter. Not exactly sure what's going on, but it'll only work for me if I make Twig double escape the string like so:

{% set strategy = 'html' %}
{% set doubleEscapedString = entry.richTextFieldHandle|escape(strategy) %}
{% set hasTable = '&lt;/table&gt;' in doubleEscapedString %}

<div class="{{ hasTable ? 'hasTable' : 'hasNoTable' }}">
    {{ entry.richTextFieldHandle }}
</div>


How to lock down entries to specific levels of Craft CMS Structure

Honestly, the answer to your question is to not use structures to solve this problem. Here's a rule of thumb on structures: don't mix content types in the same structure ("content type" being a generic term for specific pieces of your content; e.g. blog posts, projects, testimonials, slides, pages, etc). So, for example, in your case a structure shouldn't contain projects and slides. However, if you had maybe projects and sub-projects, that could work well as a structure.

There are at least two options that I think are a better way to solve this. I personally would prefer #2 but figured I'd give you both of the ones I thought of off the top of my head.

Create a channel of slides, and then from your project entries in your structure use an entries field to select the slides that should belong to that project entry. However, this could and probably would become an editing nightmare because all the slides of all the projects will be all in the same channel and depending on your editing workflow it could be a pain to try to edit one particular slide.
Utilize a Table, SuperTable, Matrix, or Neo field to create the slides inline in the project entries. All of these field types have the concept of repeating rows or blocks that you could use to create something like a collection of slides. A pro tip: if you want to keep the slides "separate" from your project content, you could always create a new tab in the field layout for your "slider builder".

Hopefully that helps... If you need me to clarify anything I said feel free to comment below and I can update this answer accordingly!

Update:

Here are some screenshots explaining what I was referring to in #2:

First create your matrix field:

Then when you're editing your projects you can "create" slides inline:

You can learn more about querying your new slides matrix field here: https://docs.craftcms.com/v3/matrix-fields.html


You can't echo out of the controller function. Though, you can send back the rendered template via a convenient controller function.

$this->renderTemplate('notifications/_test');

To add variables for your template to access (because it's not automatic for security reasons). You can do this.

$this->renderTemplate('notifications/_test', array(
    'message' => $message
));


Freeform - get option label & value on submissions page

The code above is correct, but it turns out there was an actual bug in the code if you had a number as the option value.

This affects Freeform 1.5.1 and earlier. The next version (1.5.2) of Freeform will include a fix for this. If anyone needs a patched copy of Freeform before 1.5.2 is available, just contact us via our support form. :)


loop through responsive images in matrix with imager plugin

You’re currently passing in the image model you queried for using first() into the craft.imager.transformImage function, but you actually need to pass in the models that you get when looping through all images added to your block’s field.

There’s no reason to do the first() at all, and it would add additional queries.

{% if block.image|lenght %}
    {% for image in block.image %}
        {% set transformedImages = craft.imager.transformImage(image, transforms, options) %}

        <img src="{{ transformedImages[1].url }}"
            sizes="33vw"
            srcset="{{ craft.imager.srcset(transformedImages) }}">
    {% endfor %}
{% endif %}


So I took another approach to my problem and ended up creating a plugin variable allowing me to set data inside a macro and have it accessible in the template. It's not complicated and does the trick.

class MyPluginVariable
{
  /**
   * Store data for use within both
   * templates and macros. Easy way around
   * macros having their own context
   * @var [Array]
   */
  private static $store = [];

  /**
   * Set data in storage array
   * @param [String] $key
   * @param $value
   */
  public function set($key, $value) {
    self::$store[$key] = $value;
  }

  /**
   * Retrieve data from storage array
   * @param  [String] $key
   */
  public function get($key) {
    return self::$store[$key];
  }
}

To set data you simply call {% do craft.MyPlugin.set('myVar', true) %} and to retrieve it {% set myVar = craft.MyPlugin.get('myVar') %}


The UserModel has a getGroups() function which:

  Returns an array of
  UserGroupModel
  objects that the user belongs to.

Since a user can belong to multiple usergroups, you have to loop through the array containing them:

{% set thePartner = craft.users.username( craft.request.getSegment(2) ) %}

# Loop through array of UserGroupModels #
{% for group in thePartner.getGroups() %}
    # Print name of current UserGroupModel #
    {{ group.name }}
{% endfor %}

If you are sure the user only belongs to one group, you can fetch the first UserGroupModel from like this:

{% set thePartner = craft.users.username( craft.request.getSegment(2) ) %}

# Get first UserGroupModel #
{% set group = thePartner.getGroups().first %}

# Print name #
{{ group.name }}


Craft Cookies Plugin: Font Loading Detection

So I'm not sure what you're accomplishing with this line:

    {% do setCookie('fonts-loaded', fontLoad, now | date_modify("+1 hour").timestamp) %}

I guess trying to give the cookie a longer duration if it was already set? Probably it's best to set the fonts-loaded cookie via JavaScript once FontFaceObserver tells us that the font as been loaded; there's probably no reason to do it here.

FWIW, we can start using the font-display property as a progressive enhancement now to want to eliminate FOUT on modern browsers. Older browsers will still work, but they'll get FOUT: https://caniuse.com/#search=font-display


Use different template for paginated entries

I don't know if there's a route way to handle this, but you could do a conditional on the craft.request method getPageNum() like so:

{% if craft.request.getPageNum == 1 %}
    <!-- Header for the home page -->
{% else %}
    <!-- Header for pagination pages -->
{% endif %}


Posting remotely - to fields in a channel or a plugin's fields?

I'm not sure if this is the 'best' approach, but you can definitely accomplish this without creating your own tables, unless you have some other specific need. In your plugin defineSettings method you could either define individual fields (if the entry fields are predetermined) or a table field (if both the post data and entry fields should be configurable) to store field mappings. In your public controller method you can then map the post data to your entry's fields via the settings that you defined, perform other security/data checks, etc. and save the entry.

In the plugin's controller:

public function actionSaveJob()
{
    // get 'post to field' mappings from plugin settings
    $pluginSettings = craft()->plugins->getPlugin('JobPostPlugin')->getSettings();
    $titlePostVar   = $pluginSettings->titlePostVar;
    $bodyPostVar    = $pluginSettings->bodyPostVar;
    $summaryPostVar = $pluginSettings->summaryPostVar;

    // retrieve post data
    $title   = craft()->request->getPost($titlePostVar);
    $body     = craft()->request->getPost($bodyPostVar);
    $summary = craft()->request->getPost($summaryPostVar);

    // create a new entry
    $entry = new EntryModel();
    $entry->sectionId  = 2;
    $entry->typeId     = 2;
    $entry->authorId   = 1;
    $entry->enabled    = true;

    // set entry content
    $entry->getContent()->setAttributes(array(
        'title'     => $title,
        'body'      => $body,
        'summary'   => $summary,
    ));

    // save the entry
    $success = craft()->entries->saveEntry($entry);
}

Completely untested, but should be more or less correct. If anyone sees an error please comment or feel free to edit.

You would also want to add conditions to ensure that the post data exists and that it is formatted correctly, and that whatever security conditions you've established are met, and perhaps record/return success and or errors.

For simplicity I have shown this all happening in a controller action, however, I think the recommended approach would be to separate this between a controller and a corresponding service, so that the controller is never actually modifying the DB.


Export database table as .sql before deleting/removing a plugin

If your plugin overrides onBeforeUninstall(), then you could call craft()->db->backup();

But that will backup the whole database via PHP code, which might not be what you want.

Since you're in a plugin, I'd probably make sure mysqldump is available to PHP via the command line and use that to execute it and that way you can also specify the exact tables you'd like to dump.


phpmailer Exception while using Pixel & Tonic contact-form plugin

Looks like you've got some nested escape tags in Twig, which is a no-no.

value="{{ '{{category.contactEmail}}'|hash }}"

You just need to use:

value="{{ category.contactEmail|hash }}"


Combine Eager-Loading and relatedTo(category)

I usually like to use the .find() method and then you can pass in an object in your twig with criteria for the query. This is an example of eager-loading and relatedTo.

{% set entries = craft.entries.find({
    section: 'articles',
    with: ['featuredImage'],
    limit: 4,
    relatedTo: category
}) %}

Let me know if this helps at all otherwise I'd be happy to dig into your use case more.


You can build an array of the filtered results, then paginate that.

{% set entries = craft.entries().section('produkte').relatedTo(category) %}
{% set filteredEntries = [] %}
{% set existingtitle = [] %}
{% for entry in entries %}
    {% if entry.title not in existingtitle %}
        {% set filteredEntries = filteredEntries|merge([entry]) %}
    {% endif %}
    {% set existingtitle = existingtitle|merge([entry.title]) %}
{% endfor %}

Then modify this code to paginate array: https://gist.github.com/juban/a55781d49f2f68ec3ca47979bcaaa49a


How do you pull entries with a specific category value?

Is this the best way to do it?

`{% set results = craft.entries.section(posts).search('countryName:"United Kingdom"') %}

It appears to work.


I think this is an excellent use case for twig's attribute function.

  The attribute function can be used to access a "dynamic" attribute of a variable:

{% for i in 1..6 %}
  {% if attribute(block, 'bioName'~i) %}

        {% for asset in attribute(block, 'bioImage'~i) %}

          ...etc...
        {% endfor %}

  {% endif %}
{% endfor %}


You should be able to do this with Craft's handy group filter.

{% set players = entry.myPlayersMatrix %}
{% set playersGrouped = players|group('myPositionDropdown.label') %}

{% for position, playersInPosition in playersGrouped %}

{{ position }}

    {% for player in playersInPosition %}
        {% set playerData = craft.entries.section('myPlayersChannel').relatedTo(player).first() %}

            {{ playerData.fullName }}
            {{ playerData.age }}
            ...

    {% endfor %}

{% endfor %}


Image Transform Problems, Timeouts, Stuck Transforms

Craft release 2.6.2911 has made a significant improvement, and with it, our troublesome animated GIFs are transforming correctly.


How can I select channel index/root pages from an Entries Field Type?

Having thought about it a bit more, this doesn't really make much sense. Obviously the entries will only link to... entries. I got a little confused as to why it also allowed me to select "single" pages.

I still think it's worth including the option to add channel index/root pages. In the meantime, because I'm using this as a crude navigation maker, I've just created an additional single section. I then directed the Entry Template to the same directory as the index.html page. This then gives me the option to add it in my entry field, without messing any links up.


Changing some letters in entry's uri before save it

I solved like this, maybe any of you will use with different types of it.

craft()->on('entries.onBeforeSaveEntry', function(Event $event) {
  $entry = $event->params['entry'];
  $turkishCharacters = ['ı', 'ü', 'ö', 'ş', 'ç', 'ğ'];
  $englishCharacters = ['i', 'u', 'o', 's', 'c', 'g'];

  $entrySlug = $entry->slug;
  $entrySlug = str_replace($turkishCharacters, $englishCharacters, $entrySlug);
  $entry->slug = $entrySlug;
});


Ok, this is what I get for trying to be clever (lazy)...

I've always begrudged typing in 'craft.myPlugin...' every time I wanted refer to my plugin, so I set a Route Variable in my plugin like so:

  craft()->urlManager->setRouteVariables(
    array(
      'myPlugin' => craft()->myPlugin,
    )
  );

It would appear none of my route variables work in the 404 template. That in itself is a bit odd, so to accomodate my laziness I've added this to the top of my 404 code:

{% set myPlugin = craft.myPlugin %}

It would be interesting to know if this choice has any detrimental effects? (besides being looked down upon by my peers)


Trying to capture categories field type data in user profile save/update

Usually, its very easy to pull data from a relational fieldtype (Categories, Entries, Assets etc). E.g. if your Categories field handle is memberGroups, you can simply do this:

$categories = $user->memberGroups;

However, your Categories field handle is groups, which conflicts with the built-in UserModel attribute groups, used to pull any user groups the user is a member of – this means that calling $user->groups will give you an array of UserGroupModel instances, ignoring your Categories field.

Also, the $user->getContent()->getAttribute('groups'); method doesn't appear to work for relational fields.

The easy answer: I'd suggest you simply change the field handle for your Categories field to something else – for example memberGroups. Don't worry, you won't lose any data if you do. Then you can just do $categories = $user->memberGroups;.

If you can't or wont change the field handle, here's a workaround:

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->relatedTo = array(
    'sourceElement' => $user,
    'field' => 'groups'
);
$categories = $criteria->find();


Trouble with twig syntax for discount conditions

For anyone interested in why this didn't work...It appears that you can't include a filter in the twig statement for discount formula conditions, at least not |date() as I was using. The error message in the CP isn't so great since it is valid twig syntax, but I totally get not using filters in this situation.


Currently it’s not possible to delete tags (or otherwise manage them).


Enabling CSRF Protection for Mailchimp Subscribe plugin and other forms

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


You shouldn't need to create a custom plugin to do that.

You can easily create a Matrix content field for your carousel. Create a new block called slide. From there you can create an asset field to upload the slide image.

You can render this into whatever markup you'd like (even bootstrap).

As for cropping an image and converting it into a jpg, check out Aviary Image Editor. It's a wysiwyg editor in the admin panel for doing exactly what you are looking for.


Issue with htaccess redirect adding parameters

I was having a similar issue. Combining your use of:

RewriteRule (.+) index.php [QSA,L]

but with the following for the non-www redirect

RewriteCond %{HTTP_HOST} =www.domain.com
RewriteRule (.*) http://domain.com/$1 [R=302,L]

worked for me.


Craft 3: how can I auto-redirect to a site version using the user IP?

Country Redirect will let you do that without any latency from external services, with the soon-to-be-released Craft 3 version (I'll update the answer once its out).


Ordering Structure Sections with Structure Handles

Use SuperSort or write your own Twig filter for it. Craft/Twig don't come with a sort filter to sort by key and replicating the functionality  (storing array keys, nested loops) is possible but kind of messy and also not performing as well.

I can understand the desire to not be reliant on too many plugin, but the functionality you need from SuperSort is simply a wrapper for a PHP function, so you can easily swap it out for another plugin if ever necessary.

It is also a great opportunity to start looking into plugin dev, write your first Twig extension or a simple Template Variable might just do it.


Received from the developer on Twitter:

  There’s no way to handle pagination or offsets automatically yet I’m
  afraid. You’d have to roll your own solution to handle this at the
  moment

I've been thinking about creating a plugin that polls the API and triggers a FeedMe task with a custom offset parameter. It would also need to record the status of the task once it's complete and the offset for the next 100 records as well.


Flushing logs halfway through a request?

You should be able to do that with something like this:

Craft::getLogger()->flush();


You can do this without hacking core files using Craft's static translation support.


Use Matrix to let client add Bootstrap Accordian Items

Yes, you can make use of the matrix loop index to create unique ID's.

          Senior Construction Planner

    ..variable content..


For alt tag content you can just click the image in the richtext field, hit the 'edit' button and add a title.

As far as I know there is no way to integrate an alt text field (or any other fields) from assets without writing a custom redactor plugin. I posted a similar question here and the only solution was to use a matrix field instead. But I too would love to hear about any other options.


Can an integer be formatted as a telephone number using Twig?

Assuming that you always want to add a space after every two digits, something like this using Twig's split and join filters should work:

{% set splitArray = "20304050"|split('', 2) %}
{% set formattedString = splitArray|join(' ') %}

If you want a different format, like 203 04 050, then you could use slice:

{% set firstSeg = "20404050"|slice(0, 3) %}
{% set secondSeg = "20404050"|slice(3, 2) %}
{% set thirdSeg = "20404050"|slice(5, 3) %}

{% set formattedString = firstSeg ~ ' ' ~ secondSeg ~ ' ' ~ thirdSeg %}


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

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

To be used like this:

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

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


How do I search craft.entries with multiple parameters?

100% untested, but try something like this.

You're basically creating an array of all of your search criteria, then joining them into one .search() call at the end as a string separated with a space.  That's because Craft does "and" searching with multiple terms by default.

{% set req = craft.request %}

{% set results = craft.entries.section("properties") %}

{% set params = ['location', 'min-price', 'max-price', 'status'] %}
{% set query = {} %}
{% set search = [] %}

{% for param in params %}
    {% set key = param | camel %}
    {% set value = req.getParam(param) %}
    {% set query = query | merge({ (key):(value) }) %}
{% endfor %}

{% if query.location %}
    {% set search = search|merge([query.location]) %}
{% endif %}

{% if query.minPrice or query.maxPrice %}
    {% set min = query.minPrice ? query.minPrice : '' %}
    {% set max = query.maxPrice ? query.maxPrice : '' %}
    {% set search = search|merge(["price:" ~ '500000']) %}
{% endif %}

{% if query.status %}
    {% set search = search|merge(['statusCategory:' ~ query.status]) %}
{% endif %}

{% if search|length %}
    {% set results = results.search(search|join(' ') %}
{% endif %}

{% for entry in results %}
    ...


NOT TESTED

I think you can just add an array to gistDistribution, it will get
json_encoded before saving.
I think you'd have to set the variable like this:

$arr[0] = array(...);

That way, you provide a multidimensional array, which is what a table needs.


Internal Server Error: missing method or closure

Thanks everyone for taking a look. I forgot that I had implemented something on the receiving templates that allowed you to navigate between articles from the newsletter, if the referral url was the newsletter. After I implemented the text only block, I forgot to change this to ignore those blocks.


Add them to the environmentVariables section of your config file, and retrieve them using the craft.config template tag.

For example:

// Config
"environmentVariables" => [
    "color" => "blue",
]

// Template
{{ craft.config.environmentVariables.color }}


Using the Matrix field to output content in a slideshow

I reduced your code a little: You can use elseif to cycle trough each block so you don't have to write each if statement. Now where do you want your div?

If you want each block with one separate div you write them inside the if statement (As I did in this example).

 {% for block in entry.homepageSlider %}

       {% if block.type == "sliderText" %}

{# content of first block #}

       {% elseif block.type == "sliderImage" %}

{# content of second block #}

        {% endif %}

 {% endfor %}

If you want to add the content of both blocks into one single div it would look like this:

 {% for block in entry.homepageSlider %}

       {% if block.type == "sliderText" %}
         {# content of first block #}
       {% elseif block.type == "sliderImage" %}
         {# content of second block #}
        {% endif %}

 {% endfor %}

But this is basically what you already did. So I'm not sure If I understand what you are trying to accomplish.


I wouldn’t recommend it until Yii is 100% compatible. And I’m guessing there’s not a lot of motivation to do that, since Yii 2 is almost out and is pretty much a complete rewrite.


Does a up to date boilerplate for Bootstrap 4 with live reload, sass and js build exist?

Craft doesn't use themes, in the way WordPress does, so you won't find a direct equivalent to Roots / Sage.

That said, none of what you listed is CMS-specific, so there's nothing stopping you setting up a generic development / build workflow which matches your stated requirements.

Stack Overflow is a better place to ask about general tooling, though.


Possibility to use Craft's search function to search in PDF files

As far as I know, there is no ready-built solutions available for Craft that makes text in PDFs searchable.

You probably have to look into building this plugin yourself, or hire someone to do it.

Posting in the #jobs channel on Craft's Slack is a good place to start.


How can I display dateUpdated for the most recent updated entry in a category?

You can order entries by dateUpdated in descending order and then get the first entry. You would use that entries dateUpdated field to show when the site was last updated.

{% set entry = craft.entries.order( 'dateUpdated desc' ).first() %}
{{ entry.dateUpdated }}


EDIT:
I'm so sorry - I messed it up... I rechecked the craft code and I was all the way wrong with the first answer. I hope you had no trouble because of me.
The correct answer is this one....
Event::on(UrlManager::class, UrlManager::EVENT_REGISTER_SITE_URL_RULES, function(RegisterUrlRulesEvent $event) {
    $event->rules['redirect/<action:\w+>'] = 'customer-portal/portal/';
    $event->rules['checkout']              = 'customer-portal/portal/checkout';
});

and in your controller
public function actionIndex(){
    $request = Craft::$app->getRequest();
    $method = $request->getParam('action');
    return $this->redirect($method);
}

In order to have access to the backend function you need to make it "public" so you have to include a protected $allowAnonymous = true; or an array with all functions protected $allowAnonymous = ['functionOne', 'functionTwo'];
Your Controller could look like this
class UserController extends Controller {
    protected $allowAnonymous = true;

    // pretend the request is /redirect/foo and we have created the rule
    // $event->rules['foo']                    = 'customer-portal/user/foo'; and
    // $event->rules['redirect/<action:\w+>']  = 'customer-portal/user/redirect';
    public function actionRedirect(){
        $request = Craft::$app->getRequest();
        $method = $request->getParam('action');
        return $this->redirect($method);
    }

    public function actionFoo(){
        die("foo");
    }

}

Old Post... ignore this
It's not a bug, that's the way how craft handles it. Unlike in other cms plugins in craft are not supposed to handle entire frontend page requests in order to render the entire page.
You can access actions from controllers only via the /action url. Everything else is handled by entries/elements
So you'll not be able to achieve what you want since craft tries to access an entry when you don't include an action url. All frontend request without an action url need to be related to an entry/element or a category. So when you try to access /redirect craft will search for an entry with the slug redirect
What you want is the following:

creating an entry with the slug "redirect"
$entry = Craft::$app-> //your logic to fetch this specific entry
$this->redirect($entry->url)

When you want to create a plugin for other people to use it, you have to create a settings page, include a relation field to that and let other people link an entry to the redirect -> you can fetch this entry from your settings and redirect to it.
The other thing... $event->rules['portal/<action>'] = 'customer-portal/portal/<action>'; is wrong.. Take a look at this documentation
$event->rules['portal/<action:\w+>'] = 'customer-portal/portal/handle-redirect';
and in your portalController
public function actionHandleRedirect(){
    $request = Craft::$app->getRequest();
    $function = "action" . $request->getParam('action');
    $this->$function();
}

But I would suggest you not to do that and use the craft way to handle these things


Conditionally apply a tax zone in commerce

OK So I figured this one out eventually. It's a very hacky fix. I added an adjuster that is basically an exact copy of the built-in Tax Adjuster (found at plugins/commerce/Commerce/Adjusters/Commerce_TaxAdjuster.php). The only difference is that I added a condition to check for my Tax Exempt field (and that we're in the OH tax zone), and then removed the tax amount instead of added it.

ie, I changed things like

$allRemovedTax += $amount;
$item->tax += $amount;

to

$allRemovedTax -= $amount;
$item->tax -= $amount;

And then added the whole thing to a new custom plugin.

What this results in is tax being applied normally, and then the same tax being removed.

If anybody comes across this and has a better solution, I'd love to hear it. But this works for now.


How to include external JavaScript in place?

In your template you can use the <script src=""> tag as it's a combination of the html and twig. So it will load your external javascript files.
Also you can use the inline javascript or javascript file using this tag {% js %} like below.
{# Use for JS file #}
{% js "/assets/js/script.js" %}

{# Use as a JS code block #}
{% js %}

console.log("hello World");

{% endjs %}


You can add a param to your returnUrl in the form composer then check the template for the param.

For example:

You redirect to /contact?success

{% set successParam = craft.request.getParam('success') %}
{% if successParam is not null %}

Hooray! Success!!

{% endif %}

Another option is to Ajax submit your form and just have a modal or something on a succes submit. An example of an Ajax submit can be found in the official freeform docs here.


Search return wrong result with special character like @#! in Craft 3

Without knowing more specifics, Craft will "normalize" search keywords before putting them into the search index table in the database, and one of the steps in the normalization process is to remove punctuation, which is why searching for punctuation doesn't work.

You can see the whole normalization process here: https://github.com/craftcms/cms/blob/develop/src/helpers/Search.php#L41-L81


Convert string to date format that can be used in a craft.entries tag

You could do this:
{# Your date 2020-11 in atom format e.g 2020-11-01T00:00:00+01:00 #}
{% set departureDate = craft.app.request.getParam('departure') | date("Y-m") | atom %}

{# Your date + 1 month in atom format e.g 2020-12-01T00:00:00+01:00 #}
{% set untilDate = departureDate | date_modify('+1 month') | atom %}

{# Query between those 2 dates #}
{% set query = query.startsOn(['and','>=' ~ departureDate, '<' ~  untilDate ]) %}

Note that on the November the 25th for example, you'd only be querying 5 days of the month


How can I get the type of a field using Twig?

You can use the className function

{% switch className(field) %}
    {% case 'craft\\fields\\PlainText' %}
    {% case 'craft\\fields\\Dropdown' %}


Custom Fieldtype in a plugin at user profile save

The best approach is probably to use the onAfterElementSave hook available to custom fieldtypes. Here's what that could look like (the following method should go into your custom fieldtype class, e.g. myawesomeplugin/fieldtypes/MyAwesomePluginFieldType.php):

public function onAfterElementSave()
{
    $field = $this;
    $fieldId = $this->model->id;
    $fieldHandle = $this->model->handle;
    $element = $this->element; // This is the UserModel, in your case
    $fieldContent = $element->getContent()->getAttribute($fieldHandle); // This is the content for the field

    // Do something awesome with the data above
    ...

}


Figured it out. Config was set to force https, but the new server didn't have an ssl certificate set up. Fixing that cleared up the issue.


Thanks to Robin Schambach. The answer was as simple as serialize the form data with the CSRF in there already by using the default {{ getCsrfInput() }}

  serializeArray won't produce data in a way Craft CMS will proceed it.
  It's not a good idea to do that. Besides that why don't you include
  the token in your form from the beginning? Because this is never the
  default code you can find in every ajax request – Robin Schambach 14
  hours ago


Developer of Charge here.

Yes - Charge supports all the native Craft criteria search parameters for fields.

Like you mentioned, there are a few special fields that aren't supported currently within that. Those are fields like description, notes etc.. The supported direct attributes on the Charge model that can be searched (in addition to all the basic ElementType attributes) are :

userId
sourceUrl
timestamp
hash
customerId
mode
meta

This is in addition to all Craft fields you might have attached to the charges.

For example - if I wanted to find all the charges based on a specific customerId (the stripe identifier), it'd look something like this :

{% set charges = craft.charge.charges({ customerId : 'cus_00000000' }) %}

They can be of course be combined, so all charges for that customer only in live mode :

{% set charges = craft.charge.charges({ mode: 'live', customerId : 'cus_00000000' }) %}

If we had a field on the charge model with a name of ourCustomField, we could search for that like :

{% set charges = craft.charge.charges({ search : { query : 'ourCustomField:' ~ someSearchValue }}) %}

And also, we could combine all those into a single thing too:

{% set charges = craft.charge.charges(
   { mode: 'live',
     customerId : 'cus_00000000',
     search : {
        query : 'ourCustomField:' ~ someSearchValue
   }}) %}

Or in the alternative syntax, that could be:

{% set q = 'ourCustomField:' ~ someSearchValue %}
{% set charges = craft.charge.charges()
      .customerId('cus_00000000')
      .mode('live')
      .search(q) %}


Great question! Let's define some terminology to make this easier to discuss...

Static images: Uploaded via FTP (or similar). Not tied into the CMS in any meaningful way.
Dynamic images: Uploaded via the Control Panel (or synced after FTP upload). Can easily be related to entries and other elements, or even have fields assigned directly to your assets.

Static images are the more "traditional" way of storing images, just as you would with a non-CMS website. There are absolutely some good reasons to use static images... for example, anything on your website which will basically never change (like the company logo).

Dynamic images (aka "Assets") are ideal for dynamic content. If you're writing articles with images, this is a perfect use-case. There are far more complex examples as well, but this is a great starting point.

If an image makes more sense being static, then let it be static. Conversely, if you believe it needs to be dynamic, then make it dynamic. Don't try to force an image to be something that it's not. With just a little bit more experience, it will quickly become obvious which kinds of images should be static vs dynamic.

Here's how I've got my folder structure setup...

/craft
/public
    /assets
        /(ASSET SOURCE FOLDER 1)
        /(ASSET SOURCE FOLDER 2)
        /(ASSET SOURCE FOLDER 3)
    /resources
        /css
        /js
        /images

My static images go into /public/resources/images. They are then referenced just as if the site were not using a CMS at all.

My dynamic images go into various subfolders within /public/assets. Each subfolder maps directly to an Asset Source, defined in the CMS control panel.

  NOTE:

  Make sure your assets subfolders have proper read/write permissions! Craft will need to interact with those files when uploading, and also when creating image transforms.

  Permissions for your static folder can be much stricter... Those will only need to be read, never written to.

Of course, this all assumes that you're storing your dynamic images in a local folder... Things are slightly different when you want to keep your assets in the cloud (S3, Rackspace, Google), but that's a different conversation altogether.

Hope that helps!


Matrix block fields returning NULL when using MatrixBlock query

The right Field ID to add is the Matrix field id as defined in the Fields section.  Do not use the ids of the matrix block fields.


P&T Contact Form plugin : how can I dynamically add multiple email recipients inside the form config file?

This is how to achieve this :

<?php

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


Error: Variable 'entry' does not exist - When adding homepage or other entry with URL

After trying many different things I noticed that the background tasks que was backed up:

The queue was not moving. After a little research I came across the support ticket on craft on how to Resolve "Stuck" Background Tasks. After completing the couple steps of updating the stuck task status and restarting the queue, they all cleared out.

After this, my homepage was pulling in the entry properly and parsing the 'entry' variable without issue.

My guess is that if you create an entry while the background tasks queue is stuck you will run into this issue.


Git Workflow and Multi Environment - how to approach

Matt has a point, this is similar to What's the best practice for handling data migration and organization across development environments?, but that question focuses mainly on how to handle the database (definitely see those answers).

More generally speaking...

Multi-Environment Config

Set yourself up with Multi-Environment Configs in both craft/config/general.php and craft/config/db.php so that you don't have to be updating path settings every time you migrate data between environments.

Be sure to set some Environment-Specific Variables for the site URL and server path for each environment. That way you can use those variables in the control panel settings (the Site URL setting in the Setting → System → General and Assets paths in Settings → Assets → Your asset settings).

Here is a sample general.php file

return array(

    '*' => array(
        'omitScriptNameInUrls' => true,
        'usePathInfo'=> true,
        'cpTrigger' => 'example-admin',
        'allowAutoUpdates' => false,
    ),

    'example.dev' => array(
        'devMode' => true,
        'useCompressedJs' => false,
        'allowAutoUpdates' => true,
        'environmentVariables' => array(
            'siteUrl' => 'http://example.dev/',
            'sitePath' => '/Applications/MAMP/htdocs/example/html/',
        ),
    ),

    'staging.example.com' => array(
        'environmentVariables' => array(
            'siteUrl' => 'http://staging.example.com/',
            'sitePath' => '/var/www/vhosts/staging.example.com/html/',
        ),
    ),

);

And an example db.php file

return array(

    '*' => array(
        'tablePrefix'   => 'craft',
    ),

    'example.dev' => array(
        'server'        => 'localhost',
        'user'          => 'root',
        'password'      => 'root',
        'database'      => 'example_dev',
    ),

    'staging.example.com' => array(
        'server'        => 'localhost',
        'user'          => 'example_staging',
        'password'      => '********************',
        'database'      => 'example_staging',
    ),

);

For more on Multi-Environment Configs see Multi-Environment Workflows on Straight Up Craft

Version control with Git

You can definitely use Git. I version everything except for user file uploads and /craft/storage and it works great.

My master .gitignore file in the root of my project looks like (specific to my setup, YMMV)

.DS_Store

# Node/Sass
node_modules
html/css/public/main.css.map

# Config
dandelion.yml
sftp-config.json
craft/config/db.php

Then in each directory I want to ignore the contents of (craft storage and user uploads) I put a .gitignore file with...

# Ignore everything
*

# But not this file
!.gitignore

And as Matt pointed out in his other comment on your question, do see the answers on the related question What's the best practice for upgrading a versioned Craft site?


Can't backup DB locally with MAMP PRO 5.5.1

I have run the following on my computer in order to allow Mac OS's terminal to speak to MAMP's MySQL. I have not done the steps outlined in your linked article. Craft's built-in backup tool works fine for me so perhaps this will help you too.

sudo ln -s /Applications/MAMP/Library/bin/mysqldump /usr/local/bin/mysqldump

Here's a github issue on the matter that runs through a few possible solutions (including the one above).


How can I reference images separately within a rich text field?

There is currently no native way to achieve this with Feed Me, short of writing your own PHP middle-man script which would parse the HTML, extract just the images, and append it to you XML/JSON.

We do plan on adding hooks later (potentially with examples) for this sort of scenario, as its quite common, but will not be until at least Feed Me 3.1.


How to output the matrix block type name in Craft? Possible feature request

The guys at Supercool have developed a Craft plugin that does exactly what I was after, and as a bonus it allows you to group matrix block types which is very handy.

UPDATE

As of Craft 2.3, matrix block titles are now shown as part of the core functionality, thanks P&T!


How can I loop through a field and print each value individually?

Variable "entry" does not exist

This error is being caused by the first line of your code:

... in entry.isotope %}

You are either using this template code on an element that isn't an entry or haven't defined a variable called entry anywhere.

So we can help you more, what type of element is this field being used on?


Matt and I managed to work this out together. Seems like setting the pending and unverifiedEmail attributes on the userModel before saving the user does the trick.

$user = new UserModel();
$user->pending = true;
$user->unverifiedEmail = "username@domain.com";
craft()->users->saveUser($user);

Edit: Might also want to look into another syntax that I noticed in this question.

$user = new UserModel();
$user->status = UserStatus::Pending;
$user->email = "username@domain.com";
craft()->users->saveUser($user);


How do multiple date queries differ between Craft 2 and 3

My Craft 3 version is:

{% set result = craft.entries()
    .section('events')
    .eventDate( ['and', '<' ~ now|atom, '>' ~ now|date_modify('-6 days')|atom ] )
    .results(':notempty:')
    .orderBy('eventDate desc')
    .limit(3)
    .with(['imageGallery'])
    .all()
%}

Note the extra |atom after the date_modify('-6 days')


This is a side-effect of Craft's amazing automagical cache system. :) Check out my answer on this question for an explanation of what happens.

Regarding your question of how to fix this, part of the solution is probably what I wrote in the answer, to make sure that you don't create more caches than you need, by caching globally and using the request path as key.

Other ways to counter this problem is to use the ColdCache and CacheFlag plugins. They serve different purposes, and isn't right for all caches, but they have one thing in common, they doesn't save anything to the templatecachecriteria table, which determines the length of the delete stale template caches task. I usually end up with a combination of all three on projects that have a lot of content.

ColdCache is good to use in the cases where you primarily are caching a single entry, and you can get away with breaking the cache when the entry is saved. By using the modified date of the entry as part of your cache key, Craft will create a new cache every time you save the entry (don't worry, the old caches will be deleted when they expire, and doesn't affect performance in any way).

CacheFlag is good to use when you know what sections, globals, categories or... whatever, you're caching. For instance, if you have a news section, and are caching a list of news entries, you could add a flag to the section in CacheFlags settings, wrap the list in the CacheFlag tags and add the flag. Whenever an entry in that section gets saved, all caches with that flag gets deleted and refreshed the next time the list is shown.

Both of these approaches sacrifices something in terms of cache breaking - and it takes some thinking through to get right - but performance wise you gain a lot.


I had the same issue. Tried setting a bunch of mysql and php configs for timeouts, packet sizes, etc, and nothing would help. Finally found that turning off dev mode fixed it for me. Don't know why. Just thought I'd throw that out there in case someone else was having the same problem.


Accessing named parameter in custom route from within a controller

Hat tip to Andrew Welch for the answer.

With the route my-account/orders/<order>/pause it's possible to simply add the parameter to my controller method definition and it gets populated from the named parameter in the route.

  public function actionPauseOrder($order = null)
    {

       // do stuff
    }

The value of the named parameter order can then be accessed in the function as one would expect.

Super simple!


Removing x-powered-by and changing cookies names for security?

Will it be against the terms and agreements of craft to remove those headers?
Will writing a plugin for it be the best way

No to both questions – just add the following config values to your /config/general.php file:
'sendPoweredByHeader' => false,
'phpSessionName' => 'WhateverYouWant',

Also, check out this excellent post by Brad Bell on the topic of Craft and security.


Got this working with help from Udo's answer.
For anyone using TeamCity who would find this useful I'll share my setup for it.

First I deploy the site from a Git VCS root and use the 'SSH Upload' runner type

Then I was trying to set up the sync command through an 'SSH Exec' runner but that didn't seem to work, not sure what the issue was with it so might be able to set it up that way still.
The working method is the 'Command Line' runner, set it to run a custom script with the code provided by Udo, ssh {user}@{host} {file_path}/craft project-config/sync the command line is run from the TeamCity agent server not the production server like the SSH Exec runner is meant to.

Additional note to make sure the craft file is executable, if not you will need to do chmod a+x craft


Please take a look at the docs there are so many examples how to search here at stack exchange and it's well explained in the docs. I posted the same answer multiple times within the last days

entry.matrixField.search("mykeyword").all()

As I already said a few times too "looping through queries is still deprecated". Please fetch your results with .all() or .one(). There is no reason to fill your logs with deprecated warnings - you won't have any benefits


Webhooks are like callback events. Basically when something happens on Stripe's side (eg a new customer created, a trial subscription cancelled, etc.) your application can get notified as well and take the appropriate action.
They're less useful when your application controls that entire process but in the case of subscriptions, let's say the customer's card declines after month 2. You definitely want to get notified when that happens and take the appropriate action since Stripe is taking care of those payments.
A webhook signing secret is optional but it's basically a signature for verifying that whatever webhook Stripe is sending is legit. Stripe uses a secret key that Commerce can use to verify that Stripe was the really author of that webhook call which can help prevent things like replay attacks.
It's less useful in the case of smaller applications but if you're building something with Stripe Connect where multiple users can authenticate, get payouts, etc. it becomes essential.
In the case of security, nothing is ever binary. Much like CSRF protection, you want layers of an onion and signing secrets provide another layer of protection.


This could be achieved through a recursive macro:

{% macro recursive_nav(entries, depth) %}
{% import _self as self %}

    {% for e in entries %}

            {{ e.title }}
            {% if e.hasDescendants() %}
                {{ self.recursive_nav(e.children, depth+1) }}
            {% endif %}

    {% endfor %}

{% endmacro %}

And then to use it in your template:

{% import '_macros/recursive-nav.twig' as rn %}
{% set entry = craft.entries.section('people').level(1) %}

People

    {{ rn.recursive_nav(entry, 1) }}

This was borrowed and slightly modified from Marion's answer here. That question is also a great resource for other ways to achieve this result.