Pulling blog entries related to a structure entry field type

You can run a related to query, passing in all of the descendants of the 'parent' structure entry like so (assuming you are on the 'parent' entry page, else you'll need to query that entry first)

// Get the index pages children
{% set descendants = entry.descendants.all() %}

{% set recentBlogPosts = craft.entries({
  section: blog,
  relatedTo: descendants,
  limit: 3,
  orderBy: 'postDate desc'
}).all() %}

Or, if you don't mind getting blog posts related to the parent page also, you can use the fact that in order to be related to a child page, a blog post must also be related to the parent:

{% set recentBlogPosts = craft.entries({
  section: blog,
  relatedTo: entry,
  limit: 3,
  orderBy: 'postDate desc'
}).all() %}


Sure, have a look at the Craft site for details about downloading a specifc build of Craft:

http://buildwithcraft.com/help/download-previous-versions

So if you want to download 2.2.2579, the URL will be:

http://download.buildwithcraft.com/craft/2.2/2.2.2579/Craft-2.2.2579.zip


Assets problem (/cpresources/transforms/) after update to Craft Client 2.5.2750

I had similar issue but I was tinkering with Elements API. The JSON payload gave me that cpresources/transforms/ but once I clicked on the link it shows the proper image with the transforms applied.

Upon returning to the JSON printout, the URL for the assets looks correct. In my case it is pointing to the S3 bucket I had setup previously.


How to filter entries by month and year?

You could try this (not tested):

{% set month = craft.request.getParam('month') %}
{% set year = craft.request.getParam('year')  %}

{% set firstDayOfMonth = now | date_modify('first day of ' ~ month ~ ' ' ~ year ~ ' 00:00:00') %}
{% set lastDayOfMonth = now | date_modify('last day of ' ~ month ~ ' ' ~ year ~ ' 23:59:59') %}

{% set entries = craft.entries.section('yourSection').postDate('and', '>= ' ~ firstDayOfMonth, '<= ' ~ lastDayOfMonth) %}


I tend to try hard to avoid making changes directly to the DB if at all possible. It's a good feature idea that isn't built into Craft, so I think a custom plugin might be a good option. It'd be easy enough to build and then you'd have it readily available for other projects in the future.


Export from Craft 3.4 to Craft 3.0 using Feedback

I would highly advise against trying to import anything directly into tables. I don't know when it was added, but everything now has a global identifier (UID) which you cannot add manually. FeedMe sounded like the right approach; I'd look at running that import on the production site and letting FeedMe import the content for you through the control panel rather than trying to directly add it to the database.


I can't get Tags and Archive pages to appear

Sounds like you are missing a few tags, which we can fix when you post your code. Meanwhile, if you can spare the time, checkout Mijingo.com Craft Essentials, it's like being in the matrix as within one day you'll know lots about Craft!

It will safe you lots of time figuring out the basics....


Changing the name of the Craft folder when placed above the webroot?

Yes, you can change the name of the craft folder. In the index.php file in the public folder update the path for the craft folder in the $craftPath variable. I use the following naming scheme for my sites:

// Path to your craft/ folder
$craftPath = '../craft-domainname';

So my server directory looks something like this:

/(server-root)
  --craft-domain1
  --craft-domain2
  --craft-domain3
  --public_html
    --domain1
    --domain2
    --domain3

I keep the name craft in my folder structure but you don’t need to. I just do so it groups all the Craft installations together.


HTTP 503 – Service Unavailable – craft\web\ServiceUnavailableHttpException [installation]

Very likely it cannot connect to the database; that's typically what the 503 error is about:

https://httpstatuses.com/503

...so check the credentials in your .env file, and make sure that the version of MySQL that your website is using is the internal MAMP MySQL, and not the system-wide MySQL (if any).

This video may help you: Installing Craft CMS v3 with MAMP Pro

...and also a discussion of local development environments we had here might be of interest as well: Shootout at the Local Dev Corral


Is is possible to allow auto-updates for a plugin?

You could go through all of that effort, or you could just wait until the plugin store gets finished and any plugin that is listed in the store will get automatic updating for free nicely integrated into Craft's auto-updating functionality. :)


Map one asset attribute field to another using MySQL

You want to look at the craft_content table. There you should find the title column and the field_altTag column. You could set the title to the field_altTag value where that value is not empty.

Back up the database first...


How sell products with Craft and secure the product viewing pages?

I can only really comment on securing content as I haven't used any ecommerce solutions with craft. But as far as that is concerned — one approach would be to add a related entries field-type on the users' field layout (called 'purchasedProducts'). When a user purchases a product you can add that entry to their purchased products via a plugin. You can then check the current entry against the related entries to determine if the user is authorized to view the content.

{% set authorized = false %}
{% if currentUser %}
    {% if entry.id in currentUser.purchasedProducts.ids() %}
        {% set authorized = true %}
    {% endfor %}
{% endif %}

{% if not authorized %}

    {% redirect 403 %}

    // or display product teaser and purchase button

{{ product.title }}

{{ product.description }}

    Purchase

{% else %}

     {# output entry #}

{% endif %}

To create an index page of all purchased entries, you can loop through the currentUsers purchased entries.

{% if currentUser %}

        {% for entry in currentUser.purchasedProducts %}

{{ entry.title }}

        {% else %}

You have not purchased any products.

        {% endfor %}

{% endif %}

To show all products and add a 'purchase' or 'view' button depending on whether they've purchased the product or not, you can check if the entry is in a 'purchasedProductsIds' array.

{% set purchasedProductsIds = [] %}
{% if currentUser %}
    {% set purchasedProductsIds = currentUser.purchasedProducts.ids() %}
{% endif %}

    {% for product in craft.entries.section('products') %}

{{ product.title }}

{{ product.description }}

            {% if product.id in purchasedProductsIds %}
                View
            {% else %}
                Purchase
            {% endif %}
    {% endfor %}

Obviously you will also need to add a small plugin to respond to the purchase process (via a hook or event) and update the user's purchasedProducts. Check out usersService saveUser method for more info or search this site for many examples.

As far as ecommerce solutions, I haven't used any with craft so I can't really comment. However, I did find a tutorial on managing your craft inventory with snip cart, which should describe everything you need to create the webhook.


Feed Me Plugin: Can Match fields but feed not importing

This info may be outdated now, but just for anyone else who Googles "File path cannot be found " and ends up here (this page is the only result), it seems Feed Me is incompatible with the AsyncQueue plugin. I uninstalled Async Queue, and the import from Feed Me ran without issue.


Hmm... hard to tell because I can’t know what your expected result would be. But if I had to guess then you might be looking for just this:

{% if aPrice %}
    {% set thisMonthEarning = thisMonthEarning + aPrice %}
{% endif %}


I'm running the latest IIS 10 on Windows 10 and "pretty URLs" (i.e. craft.dev/admin/dashboard worked out-of-the-box using Craft's stock web.config file in the public HTML folder with no modifications.

I'd double check you've got that file in place and haven't made any modifications to it.


Richtext Redactor Field - Standard Layout does not show image button

Tested and it works fine for me locally with the stock Standard.json config of

{
    buttons: ['html','formatting','bold','italic','unorderedlist','orderedlist','link','image','video'],
    plugins: ['fullscreen','video'],
    toolbarFixed: true
}

I'd make sure you don't have any other plugins installed that might be interfering and that you've actually got the 'image' value listed under your buttons: key.


Search without leaving or refreshing page

Here is some example code that should probably help you get things set up. The relevant part is the line {% if query|length and query.search %}, where you’d test if there’s a query string at all and additionally if the search param is set (you can leave out that part if you want).

{% set query = craft.request.getQuery() %}

<form action="">
    {% set value = query.search is defined ? query.search : '' %}
    <input type="search" id="search" name="search" value="{{ value }}" autocomplete="off">
    Search

    <input type="submit" value="Search">
</form>

{% if query|length and query.search %}
    {% set entries = craft.entries.search(query.search) %}

Search Results

        {% if entries|length %}

                {% for entry in entries %}

{{ entry.title }}

                {% endfor %}

        {% else %}

No results.

        {% endif %}

{% endif %}


JPG upload not completing in Craft 2.6.2789

My guess is you had an auto-update or a git deployment go bad and some files didn't get updated properly.

To be safe, I'd download a fresh copy of Craft from https://craftcms.com and replace your existing craft/app folder with the new one to make sure you've got all of the latest files.


Can anyone tell me what's wrong with the 'andWhere' part of this query?

The syntax for comparing a date should be:

->andWhere('dateCreated > "2017-02-11"')


Not everything in the Control Panel gets published to the cpresources folder, especially things like dynamically generated images (thumbnails are basically just image transforms).

  Is there a way to make Craft use direct links to the thumbnails instead of using PHP to deliver the images?

Not currently.


This is definitely a bug in Craft.  Doesn't just affect Matrix, but any relational field as well (Assets, Users, etc.)

It's not an super-easy fix, but as a workaround, you can re-save the entry in the original locale (before making any edits in the new) and the content will get duplicated over.


Unfortunately there currently isn't a built-in way for this to work. It is on the feature requests list for Calendar for future consideration, however.


Displaying entries with pagination on a category page where the entry's last category in the array is the current category

Found the solution, thanks to Aaron Berkowitz on How to get entries related to current category only (not children)

You need to exclude the entries related to the subcategories.

 {% if category is defined %}
 {% set dontInclude = [] %}
     {% for child in craft.categories.descendantOf(category) %}
        {% set dontInclude = dontInclude|merge(craft.entries.relatedTo(child).ids) %}
      {% endfor %}

      {% set str = dontInclude|join(', not ') %}

  {% if dontInclude|length > 0 %}
    {% set params = params | merge({
      relatedTo: category,
      order: 'order ASC',
      id: 'and, not '~str
    }) %}
  {% else %}
    {% set params = params | merge({
      relatedTo: category,
      order: 'order ASC'
    }) %}
  {% endif %}
    {% endif %}

    {% set blogEntries = craft.entries(params) %}

    {% paginate blogEntries.limit(2) as pageInfo, pageEntries %}

      {% for entry in pageEntries %}

{{ entry.title }} ({{ entry.productCategory|join(', ') }})

      {% endfor %}


Is the 'find and replace' feature (found in the control panel settings screen) documented?

There's a short description of what it does in the 2.0 release notes.

  Added a new Find and Replace tool in Settings, for finding/replacing text within all Rich/Plain Text fields (including ones in a Matrix field).


Filter Sprout Form entries throwing error

Seems to be working after upgrading to 3.0.0-beta.21. Thanks @Ben!


A similar question was asked in the Craft Slack today, so I thought I'd transcribe the consensus:

Internally, CSRF tokens come from a call to Craft::$app->getRequest()->getCsrfToken(). This means that any controller (or template, for that matter—more often handled by the {{ csrfInput() }} shortcut method) can grab a CSRF token at will.

In the original post, I'd noted that the users/get-remaining-session-time action returns a token—that token comes from the above call, so it certainly sounds like a valid built-in method for grabbing tokens.

That said, it does have some potential side effects related to the session (aside from refreshing the CSRF token).

Ultimately—provided the time—it seems like the recommended method is to create a custom controller and call the method explicitly.

As far as the client-side handling… if your application has a means to consolidate AJAX calls, it'd be worth automating the refresh and inclusion of CSRF tokens as HTTP headers. For example, before a regular POST request is initiated, the client might first ensure it has a fresh CSRF token, then issue the request with the new token.

Hope this helps anyone else getting started with client-rendered applications!

  Edit: As of Craft 3.1.13, you get a CSRF token in the JSON response when a user logs in (assuming the login occurs over Ajax)!


How do I access an asset field in the 'onSaveEntry' event?

This gives you an EntryModel:

$entryModel = $event->params['entry'];

This will give you an array of AssetFileModels:

$assetFileModels = $entryModel->myAssetFieldHandle

You can loop through them like so:

foreach ($assetFileModels as $assetFileModel)
{
    $url = $assetFileModel->getUrl();
}


Craft 2 doesn't really have the concept of sessions or logging in for it's console app.

If I had to guess that error is more about file system permissions, but you'd want to check your log files for a full stack trace to see where it's originating from.


Guest Entries - Saving entries as drafts

Edited based on comment below

No sorry I see what you mean now. But I think with entry drafts you need to have first published an entry, then you create a draft from that entry, essentially creating two versions of the same one.

I think for approving entries as comments this is going to lead to a lot of complexity and you might struggle to get the results you want, and to do this the way you want would probably require writing your own plugin...

This plugin would listen to when an entry is saved, get that new entry id, create a new EntryDraftModel and then save it via craft()->entryRevisions->saveDraft() method. You would then need to set your new entry to disabled anyway (to stop it from showing) as creating a draft won't affect the newly created entry.

Then to approve an entry you would go into the newly created entry, switch to the draft (which would most likely be the same) and then apply it and enable the entry.

This is a complex process when your entire workflow could be condensed to:

Create a new entry as disabled
Enable an entry to approve it

Setting all new entries to disabled and then setting ones to active you want to approve will make your life easier and keep your build streamlined.

I don't think there is extensive info about drafts in particular but it might be worth checking the docs but essentially they are intended for entry revisions, not so much approving whole entries.

So...you can set entries to be disabled when they are submitted from within the guest entries plugin itself:

Just make sure the light switch is off for the correct section and entries wont be published. Then you will be able to set them to enabled as part of your approval process.

Doing this with a standard entry form

If you wanted to do this using crafts native entry form (with a logged in user), you would need to set the status at a template level

// entry form ...
<input type="hidden" name="enabled" value="0">

But a quick test revealed this didn't have any effect when using the guest entries plugin.


To test if a field exists, you'll have to use brackets notation, i.e.

{% if entry['eventLevel'] is defined %}
   ...
{% endif %}

When the field exists, but there isn't a selected option, the Radio FieldType returns an empty string, so you also need to test for entry.eventLevel != ''.

Putting it together, I believe a ternary conditional would perhaps be the most succinct solution in your particular case:

{{ entry['eventLevel'] is defined and entry.eventLevel != '' ? entry.eventLevel : 'Activity' }}

What the above does is to first check if the entry has a property 'eventLevel' – the brackets notation is needed here, to avoid Twig throwing an exception if the entry variable doesn't have the property – before checking if the attribute's value is not an empty string. If both of those statements evaluate to true, then the attribute's value is printed; if not, the string Activity outputs.

This is a bit beside the point, but if you're wondering about the syntax here, the so called ternary operator (e.g. {{ variable ? 'yes' : 'no' }}) is just a kind of a short-hand way to write conditionals. Ternary operators are supported in many programming languages (including JavaScript and PHP).

If you wanted to, you could write out the full conditional and it would work exactly the same:

    {% if entry['eventLevel'] is defined and entry.eventLevel != '' %}
       {{ entry.eventLevel }}
    {% else %}
       Activity
    {% endif %}

I'd argue that a ternary operator is more readable, shorter and also makes it easier to deal with potential whitespace issues etc. when inlined in markup like this, though.


Get all fields within Matrix for position?

If I'm understanding what you've asked correctly (and there's every chance I'm not – it's been a long day), I've got something similar on one of my sites and I'm using the following code:

{% for faq in entry.faq if faq.column == 'Left' %}

{{ faq.question }}

{{ faq.answer }}

{% endfor %}

then:

{% for faq in entry.faq if faq.column == 'Right' %}

{{ faq.question }}

{{ faq.answer }}

{% endfor %}

In this case 'faq' is the Matrix field and 'faq.column' is the Position Select field.

There are neater ways to do this to avoid the repeated code, but you get the idea.


How do I setup the Login Page to work with requireLogin?

You didn't specify Craft 2 or 3, but I'm pretty sure this answer applies to both.

The template should live at templates/login/index.twig or templates/login.twig. Craft will resolve to both of them.

I tested this on a fresh Craft Pro install and created a Single with a template path of login.  There is a templates/login.twig with the login example here: https://docs.craftcms.com/v3/dev/examples/login-form.html and a templates/test.twig that only has {% requireLogin %} in it.

I logged out of Craft, then went to mysite.com/test in a browser and was successfully redirected to mysite.com/login that rendered the example login template.


Yes, you do it with the setRouteVariables mathod on UrlManager, like this:

craft()->urlManager->setRouteVariables(array(
    'variable' => array(
      'name' => 'silvanus',
      'office' => 'OOTS
    )
));

$this->renderTemplate('confirm');

Now you can access your variables like this in your template:

{{ variable.name }}
{{ variable.office }}

Check out the documentation on Controllers, there's an example.

EDIT:
The above method is how I've done it in the past, but I see now that the renderTemplate method also can be used. I think the problem is just how you access it in your templates, I think you should just do:

{{ confirm.name }}
{{ confirm.office }}


Impossible to invoke a method ("limit") on an array... but it's not an array?

I'm not calling .all(), so this is still an object, right?

Nope.  When you execute the for loop, it will explicitly run the database query and return the array of results.  You're probably getting a deprecation error logged using that syntax as well since Craft wants you to use {% for album in albums.all() %}

See here in the docs:  https://docs.craftcms.com/v3/changes-in-craft-3.html#treating-queries-as-arrays

If you want the first results for the album cover, you can use:

{% set albumCover = album.townPhotoAlbum[0] %}


No, unfortunately there's no way to re-use a Field Layout in Craft.

You might want to consider adding a feature request at http://feedback.buildwithcraft.com.


Best way to programmatically create categories?

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

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

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

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


It should probably be more accurately renamed to Default instead of Auto, but if that is selected, then it will use the defaultImageQuality config setting value.


'Unable to find component class 'FocusPoint_FocusPoint' - Craft CMS 3 Migrating from Focus Point Fields

The migration script only converts your existing focal points as good as it can (see the repo description) but doesn't convert the fields. Since the settings that were stored in your field are now in the assets you can savely convert those fields to asset fields


What's the best way to setup a conditional to see if a matrix block is used?

I would use a loop to set a conditional, and then check it afterwards. You need to initialize the conditional outside of the loop, otherwise it won't be set outside the loop later.

{% set haveAVideo = false %}
{% for block in matrixBlocks %}
  {% if block.type == 'video' %}
    {% set haveAVideo = true %}
  {% endif %}
{% endfor %}

{% if haveAVideo %}
  {# video block js #}
  {% includeJsFile ... %}
{% endif %}


Error on updating Craft install with Sprout vendor files

I was also getting the same error and tried so many times install/uninstall but couldn't succeed. In my case, it was basically php 7 version compatibility issue.

You should change your php version to php 7.1.16 or higher, if using lower like php 7.0

Fixed by Dev: https://github.com/barrelstrength/craft-sprout-forms/issues/195

Code to be modified: https://github.com/barrelstrength/craft-sprout-base/commit/5e8ce5eb9b1815d1d2a66ed69664a890271d6620

Regards

Ankit Chauhan


Redactor I source button no longer working?

Updated the files, still didn't work, clicked uninstall, then installed again and its back, not sure what happened.


Limit ElementAPI results with custom date/time field

After some exploration and trial and error, I was able to find a solution. Ultimately there are two problems:

startDateTime, endDateTime and php’s date() function were not returning the same timezone date & time.
The correct formatting for matching multiple values needs to be in an array.

The fix:

At the top of my elementapi.php file I added this line to make sure php’s date() function returns the same timezone craft has been set to in the admin config.

date_default_timezone_set(craft()->timezone);

Then I reformatted my criteria settings as such:

'criteria' => [
    'section' => 'mySection',
    'type' => 'mySectionType',
    'startDateTime' => ['<=' . date("Y-m-d H:i:s.u"), ':empty:'],
    'endDateTime' => ['>=' . date("Y-m-d H:i:s.u"), ':empty:']
],


Why is news/_entry not extending _layout?

News/_entry should definitely be extending _layout (or any layout you want to use). That's how it's setup when you download a fresh copy of Craft as well.

{% extends "_layout" %}

The CSS file should not be in the templates folder (that's only for twig templates), but in your web root which is the same folder as index.php. In your case that would probably be something like public/css/material.css and public/css/main.css Also make sure that any assets used in these CSS files are located in that folder instead of the templates folder.

Unless these CSS files are specific to the news entry template I'd also include them in the layout file.


Why is it when I update an entry within a structure in the admin, it reorders it to the bottom of the list?

It's not intended behaviour when you're editing an existing entry, and it can't be changed - because it's not meant to be doing it. I noticed this on a site last week, but I can't replicate it right now.
I think it'd be worth filing a bug report on https://github.com/craftcms/cms/issues


Combine variables with text to make variable

You can concatenate variables like this:

{% set foo = 'foo' %}
{% set bar = 'bar' %}
{% set foobar = 'Hello' ~ foo ~ bar %}
{{ foobar }} #Outputs Hello foobar

It's explained by Brandon here.


I believe what you asking about are Hooks and Events.  Craft has several of them listed in the Hooks Reference and Events Reference.  And Craft also allows us to add Hooks and Events in our plugins, which other plugins can leverage.

In the case of Sprout Forms, as of this post, we don't have any documented events yet, but there are a couple in there and we'll be formalizing them more in the next release.

You'll probably want to take a look at sproutForms.beforeSaveEntry Event.  Right now, plugins like Sprout Invisible Captcha, SpamGuard, and Snaptcha use that Event to add spam protection to Forms.  You could use that event as well to check for a confirmation field, and add a user to a list in Campaign Monitor.

Here's an example of how SpamGuard uses the event, which you can see here in the init() method of primary plugin class file (I've added the comments myself in relation to your question):

# Check for an Event in your plugins init method
public function init()
{
    # If you add a setting that allows a user to turn your integration on or off
    # you can check for that setting here, before you run your code
    if ($this->getSettings()->getAttribute('enableSproutFormsSupport'))
    {
        # Listen for the event where you want to add behavior
        craft()->on('sproutForms.beforeSaveEntry', function(Event $event)
        {
            # Do your thing!
            $spam = spamGuard()->detectDynamicFormSpam($event->params['entry']);
            if ($spam)
            {
                $event->fakeIt  = true;
                $event->isValid = false;
            }
        });
    }
}


Checking for an object, based on a string, using Twig

After a Slack conversation with @carlcs, we discovered another slick solution...

{{ 'myVariable' in _context|keys }}

The in operator works much like PHP's in_array function.
The keys filter works just like PHP's array_keys function.


All redirect parameters needs to be hashed in Craft 3. If not, they're completely ignored.

Try using:

<input type="hidden" name="redirect" value="{{ '/profile' | hash }}">

Or

{{ redirectInput('profile') }}


Are there any intentions to release multisite support for Craft?

Currently multi-site support isn't planned.

If you want simple multi-site-support you could use the localization feature with a custom locale. But with Craft's auto-update's and easy deployment, why would you want to use MSM anyway?

.

  ...we're pretty against adding it to Craft... at least in the way EE did
  it, where everything is stored on a per-site basis.

  However you should take a look at Craft's localization features. With
  that, all content can be stored on a per-locale basis, all users can
  have per-locale permissions, each locale can have its own base URL,
  templates, routes, etc.. Really is pretty powerful. The only thing
  missing is the ability to define custom locales, in the event that
  your localized sites aren't defined by territory/language, but some
  other factor. That's the main thing that's going to be changing ;)

https://plus.google.com/105300374023226628031/posts/CS2uUefs6Ah

.

  Correct. Initially it did have an MSM-type feature, but we ended up
  taking it out, due to it overcomplicating the system.

  If you want to run multiple domains/sites off of Craft, you’ll just
  need multiple Craft installs.

https://plus.google.com/102316327373347344486/posts/71qEZ4SANhP

EDIT:

You can however use one craft/app/ folder for multiple sites. But since you'd still need multiple databases, configs, plugins, templates... it's probably not worth it, except that you would save a few bytes on files.


Set site locale to display correct date format in date/time field

Dates and times are both formatted for the user’s preferred locale.

You have to select your "preferred locale" when installing Craft. If you chose the wrong one  you (currently) can't undo it from the CP, but have to change it directly in the database (--> "craft_locales" table).

Another way would be to install a second locale (even if you don't need it at all). Because if your Craft site is multilingual you can switch between installed locales from the user settings in the CP though.


Remote assets space issue storage/runtime/assets/sources

You can instruct Craft not to keep a local copy of remote assets by setting the maxCachedCloudImage config variable to 0 (zero).

It may be worth experimenting with that setting, to find a balance between caching some smaller images locally (thereby speeding up transformations), and preserving disk space.


What are the best practices for using the {% cache %} tag?

Generally you’ll just want to cache areas of your templates that are going to trigger a lot of database queries, or fetch a lot of data, since those are going to have the biggest hit on your site’s performance. Matrix field loops that have relationship fields inside them (Entries/Assets/etc.) are a good example, since each Matrix block is going to come with one or more DB queries.

There’s not much advantage to caching less intensive areas of your templates, and might lead to unexpected consequences, if you have anything dynamic being output that’s not pure-content, such as the logged in user’s username.

  ..to combine the cache-tag with other supported caches?

Worth mentioning that template caching does not respect the cacheMethod setting – that’s just for data caches. Template caches always go to the database, which in this case is the most performant option.


Search results with partial match to query

Is there a way for search to return a result that is only a partial match to the query to take into account slight differences between the query and a page title?

Not natively.

When you put a title of "ABC-123" into a title in Craft, it will normalize it down to " abc 123 " when putting it into the craft_searchindex table (lowercasing all letter and removing punctuation).  And Craft does a similar thing for searches (lowercases them and removes punctuation).

With subLeft and subRight enabled, searching for ABC turns it into a MySQL fulltext search with wildcards on the left and right... i.e. LIKE '%abc%' so it will match what's in the search_index table.

Likewise ABC-123 gets converted to %abc 123%, which will match, ABC 123 also gets converted to %abc 123%, which will match and 123 into %123% which will match.

ABC123 would get converted to %abc123% which wouldn't match (nor would ABB-123.

MySQL does have a SOUNDEX() method, which might do what you're looking for, but it does have enough drawbacks that Craft wouldn't use it natively.

i.e. it won't work against full text indexes, inconsistent results in non-English languages and inconsistent results with multi-byte characters (even if they are UTF-8).

Some other search services might offer more robust solutions (Algolia, Apache Lucere, etc.) that you could wrap with a plugin for searches on the front-end of a Craft site, but you should add a thumbs-up comment to this Github issue if you'd like the ability for plugins to swap out the core search provider that Craft uses wholesale (including for the Control Panel).


How give parent in navigation-structure the active tag

How a look at the isAncestorOf() method in the Docs. The given example code probably covers all you need:

{% set expanded = entry is defined and page.isAncestorOf(entry) %}
<li{% if expanded %} class="expanded"{% endif %}>

To only address the direct parent, use isParentOf() instead.


Eager load elements from Solspace Plugin

Currently Calendar does not support eager loading, but it's much more likely the Craft 3 version will in the future, as we refactored a lot of code and tried to somewhat "normalize" the code to work more natively with Craft than we did in Craft 2.


Is there a better way to localise channel url?

In my experience, the easiest and best to maintain way to do this is to use entries only. If you make that news index page an entry (e.g. structure or single section) it is as easy as entering your translated slug in that entry's CP.

Another advantage is that you can add fields to that entry (e.g. to edit the meta description or some copy), so this can make sense in many cases, not just for multilingual routing.


How can I show next/previous paging that's limited by specific criteria?

You can only pass an object or an ElementCriteriaModel (what you get when you type 'craft.entries') into getNext() and getPrev().

Calling find() on an ElementCriteriaModel, as I'm doing in my code, turns it into an actual array of entries, which is not something getNext() and getPrev() can work with.

So changing the first line to this will work:

{% set params = craft.entries.section('leadership').leadershipType(entry.leadershipType) %}

Or this using the object syntax for setting parameters:

{% set params = craft.entries({
    section: 'leadership',
    leadershipType: entry.leadershipType
}) %}


Choose custom email template for Contact Form plugin

The first part of the answer in the post you linked to is wrong in the context of the Contact Form plugin.

Craft only takes the custom "HTML Template Path" email setting into account when EmailService's sendEmailByKey is called, which is used for pre-defined Craft emails.

The Contact Form uses EmailService's sendEmail, which won't take it into account.

It hasn't been released as part of an official Contact Form plugin release yet so there's no documentation, but thanks to this pull request, you've got an onBeforeMessageCompile event that will give a plugin a chance to modify the contents of the email.


Using Label instead of Value from Dropdown

The value of dropdown fields are set in the dashboard. How to set the value is dependent on the form plugin or craft field type you are using.


Is there a fallback when a Twig extension is not enabled?

I can't think of a native way to do this, but Twig does have a hasExtension method, which you could make use of in a Craft plugin.  But if you wrote a plugin to utilize it (similar to this) obviously that wouldn't help if the plugin was disabled or uninstalled.

Alternatively, you can add this as a feature request to add to Craft natively. If you go that route, be sure and go into details on your specific use-case as I'm not sure I'm following it 100% here.


Try changing it to this:
    "nystudio107/craft-seomatic": "^3.3.0",


Can I disable template caching for local development?

As of Craft 2.4, it is now possible to use the enableTemplateCaching config value.

'enableTemplateCaching' => false,

Simply add that to your local environment in config/general.php, and it'll disable the cache tags entirely.


Guest Entries - How I can send message to user after saving form information

You could do this with a small plugin that listened to the Guest Entries afterSaveEntry event.

The logic would look something like this:

use craft\guestentries\controllers\SaveController;
use craft\guestentries\events\SaveEvent;
use yii\base\Event;

// ...

Event::on(SaveController::class, SaveController::EVENT_AFTER_SAVE_ENTRY, function(SaveEvent $e) {
    // Grab the entry
    $entry = $e->entry;

    // Assuming `toEmail` is a custom field on the entry.
    Craft::$app->getMailer()->compose()
        ->setSubject('Thanks for your submission!')
        ->setTextBody('You are amazing.')
        ->setTo($entry->toEmail)
        ->send();
});

You can generate Craft 3 boilerplate plugin code using https://pluginfactory.io/ and the official Craft 3 Plugin docs are here: https://docs.craftcms.com/v3/extend/plugin-guide.html


Although I agree to close this, I think Anubarak deserves an answer as to why this is not Craft related.

The Garnish Modal doesn't care what you use it for, it's just a modal. So, what Daryl and Mats is hinting at, is that you just need to style the content of the modal properly, and you'll have scroll. Which is what you've tried to do with overflow: auto on the div. But this doesn't work since the wrapping element doesn't have a height. Also, the div itself needs a height to know when to introduce the scroll.

Taking the header into account (assuming you want it fixed in the top of the modal), something like this should get you started (inline styles cause I'm lazy, these should of course go into classes):

Modal header

        (insert long content here)

Again, this isn't specific to craft, it's a pure CSS question.


When redirecting to HTTPS from www, index.php appears in URL

There are docs for removing index.php from your URLs here: https://craftcms.com/support/remove-index.php

There are also docs for enforcing SSL for all CP requests here: https://craftcms.com/support/force-ssl

Note that they mention the the SSL rewrite should happen before the index.php rewrite in your .htaccess file.


Using multiple sections VS a single section with entry types

It's hard to answer without examples of your content types.

I would suggest that if you would ever need deliberately relate one Entry to another using the Entries field type, then making use of separate Sections for each type of content would be the way to go.

e.g. If an "office location" entry is the parent to multiple "services"

A more obvious factor is when an entry type needs to be a Channel vs a Structure. This can only be set at the Section-level

Hope that helps


P/T ContactForm Retrieving Custom fields Value after submitting form

In Craft 2.5 with Contact Form 1.4 I'm receiving the same error when using:

{% if message is defined %}{{ message.contactTel }}{% endif %}

I've gotten around this by using the Craft Request method getPost which can return a post value from an array. In the case of the original question, the following should work:

<label for="fromCompany">Company:</label>
<input id="fromCompany" type="text" name="message[fromCompany]" value="{% if message is defined %}{{ craft.request.getPost('message.fromCompany') }}{% endif %}">


How do I maintain the on value with a lightswitch-field as a plugin setting?

I believe you need to set the on value of your lightswitch field.

on: (settings.mailerShowInfo is defined) ? settings.mailerShowInfo : ""

So, the full settings of your twig code would be:

{{  forms.lightswitchField({
        label: "Show info in sidebar?"|t,
        id: 'mailerShowInfo',
        name: 'mailerShowInfo',
        value: settings.mailerShowInfo,
        required: true
        on: (settings.mailerShowInfo is defined) ? settings.mailerShowInfo : ""
    })
}}


Need somebody to help us with our existing Craft web page

Sorry to hear about your disappearing developer.

Stack Exchange as a Q&A site usually isn't the best place to find a developer, unless you'd like to post to Stack Overflow Jobs (https://stackoverflow.com/jobs).

For Craft specific developers, there are a couple of places you could look:

https://craftcms.com/partners
https://www.workwithcraft.com/
https://straightupcraft.com/jobs
The Craft Slack #jobs channel: https://craftcms.com/community#slack


I'm not really sure what this has to do with Craft because it's the same process with every single PHP file... You download xampp/wampp/lampp or whatever you want, install it, open it, activate your apache and MySQL, copy your project into your htdocs folder, create your database at localhost/phpmyadmin and start to create your plugin.

Anyway when you use a good IDE it makes absolutely no difference whether you create it locally or not since a good IDE will upload/download/compare your files on the server automatically. You don't have to upload all your files with programs like Filezilla or something like that


I was able to fix the issue - it had to do with the URL structure I had set in the Section's URL format area. For nested entries, I had put {parent-uri}/{slug} when in fact it needed to be {parent.uri}/{slug}.

I can now assign parents to entries and this is reflected in the URLs on the front end.


Javascript issue when setting an expiry date for entry

The issue here was an error in a translations file:

array(
    'some key' => 'some value',
    'key missing value',   <== no value assigned to this key
    'other key' => 'other value value'
);


How can I set an entires status via ajax from a front-end form?

My best guess, based on what you want to do, is that you don't have the correct permissions to change the entry's status. The requirePermission method kicks in and will send a 403 if you don't have permission to enable an entry.

I think the only way to change this, is to make sure that the logged in user has the correct permission(s).


Craft 3 How to get custom user field values

You should be able to access the custom fields on element\user object.

Craft::$app->getUser()->getIdentity()->getFieldValue('customfieldname');


In this line here (reformatted for legibilty):

  {{ category.title}}

You are generating the url by from craft.request.url and appending the category. But the original query is not part of the url at this point. I think this will work and be clearer:

  {{ category.title}}

This uses the url function, passing it the query string parameters.


content and fields won't show up on new single

I fixed it... I hadn't assigned a field to the section.


How do I access a specific element of a supersorted array?

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

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


I was adding a slash in from after grabbing image urls in my template code,

/{{ image }}

Did not think about how it might break redactor.


Looping through element queries directly has been deprecated

For your first issue, if you are not paginating then your {% else %} should be:

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

So that the query gets executed. In full:

{% if pagination is defined and pagination == true %}
        {% paginate entries as pageInfo, pageEntries %}
    {% else %}
        {% set pageEntries = entries.all() %}
    {% endif %}

Regarding the update to your question, it's the same thing.

Until you add .all() to your featuredEvents query (or any query), it's like the query hasn't run yet. Adding .all() executes the query.

Craft is smart enough to still run it without .all() but it will warn you hence the deprecation warning.

You should read more about element queries and how to execute them.


You shouldn't really need to do that, you're just adding custom fields to the user when those can be fetched easilly.
A customer will always be a user, but a user might not be a customer.

If you intend to get the customer details from a plugin (with PHP) you can just get the customer details (if exist) from the user, by using the Commerce_CustomersService

code example would be

$customer = craft()->commerce_customers->getCustomerByUserId($user->id);

this will either return the customer model or null (if a customer is not created against the user).


How do you output the Image Caption on an asset?

You should give a try:

{{ craft.assets.filename('refresh1.png').one().imageCaption }}

Where imageCaption is the handle of your Image Caption field (imageCaption is an example, you should check this value).

More informations about how to fetch assets: https://docs.craftcms.com/v3/dev/element-queries/asset-queries.html


Mandatory order fields in Craft Commerce 2

There is a setting for this specific instance allowEmptyCartOnCheckout.

Creating a commerce.php file in the config directory with the following code will prevent customers from checkout out with an empty cart.

<?php

return [
  'allowEmptyCartOnCheckout' => false
];


Twas my own fault - I have addTrailingSlashesToUrls set to true and falsely thought it added one after .com/ but was wrong.  As soon as I added / to the link back in order.


How to reference the current entry element in custom Control Panel templates?

As you discovered, you can get the current element that a field type is getting applied to via $this->element. However you must keep in mind that that property will not always be set. So make sure that your PHP/template code is defensive about the possibility that there is no known element yet.

Another assumption to avoid is that the current element is going to be an entry. Craft lets you associate fields with any type of element - entries, users, assets, categories, tags, globals, and Matrix blocks, and even any custom element types that plugins may add. So $this->element->section should be avoided unless you know that $this->element is actually an EntryModel; otherwise that will give you a PHP error.


Programmatically add entries to an Entry field (craft\fields\Entries)

If you are running on Craft 3, as of 3.4.0 (and really since the release of craft 3), setting custom field values directly like

$entry->customField = [id1, id2, id3];

is broken. You should instead use the setFieldValue or setFieldValues methods.

in your case, a relationship field can be set like so:

$reglages->setFieldValue(curatedHomepageArticles, [<ARRAY OF ENTRY IDs]);


You are mixing Craft 2 methods with Craft 3 methods.
This will get the the assets extension with $asset->getFilename(true) and add test_ in the beginning of the filename:

Event::on(
    \craft\services\Elements::class,
    \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event)   {
        $asset = $event->element;
        $folderId = $asset->getFolder();

        if ($event->isNew && $asset instanceof craft\elements\Asset && $folderId == '22') {
            $newName =  'test_' . $asset->getFilename(true);
            Craft::$app->assets->moveAsset($asset, $folderId, $newName);
        }
    }
);


Console command runing from Cron job failing after Craft update

This ended up being a case of looking at the wrong database.  The version/build/schema numbers for the correct database were all in sync.


Return previous or next enabled sibling of same parent

After trying a few more things, I realised I needed the descendantOf parameter to get this working.

This is what my code looks like:

{% set prevEntry = craft.entries.descendantOf(entry.parent).positionedBefore(entry).order('lft desc').first() %}
{% if prevEntry is null %}
  {% set prevEntry = entry.siblings.last() %}
{% endif %}

{% set nextEntry = craft.entries.descendantOf(entry.parent).positionedAfter(entry).first() %}
{% if nextEntry is null %}
  {% set nextEntry = entry.siblings.first() %}
{% endif %}

This restricts the positionedBefore and positionedAfter parameters to only work with entries that have the same parent as the current entry.

If there is no previous or next entry, I link to the first or last sibling entry instead, creating a loop.


Brandon has answered this here.

tl;dr: technically possible, legally questionable, in practice not a good idea.


How to link to an anchor on an entry page from within Rich Text editor

As of Craft 2.5.2759 this is now possible.

  It is now possible to include custom URL fragments in links to entries within Rich Text fields, alongside the entry's reference fragment (e.g. href="my-entry#custom-fragment#entry:123").


Processing Business Logic on user.saveUser

The user has already been saved at this point and is available as $event->params['user']. If you modify data and save again, however, you will need to be careful of creating an endless loop — not sure what you are trying to do. In this case you should be ok because of the "IsNewUser" conditional.

public function init()
{
    parent::init();
    craft()->on('users.saveUser', function(Event $event) {

        if ($event->params['isNewUser']) {

            $user = $event->params['user'];
            // update default fields
            $user->firstName = "Bob";
            // update custom fields
            $user->getContent()->setAttributes(array(
                'phone' => "222-222-5555"
            ));
            // save user
            $success = craft()->users->saveUser($user);

            if (!$success) {
                MyPlugin::log('Couldn’t update user "'.$user->username.'"', LogLevel::Error);
            } else {
                MyPlugin::log('Successfully updated user "'.$user->username.'"', LogLevel::Info);
            }
        }

    });
}


Feed Me - importing Commerce variants from Google Sheets?

The solution at https://github.com/craftcms/feed-me/issues/368#issuecomment-555710613 works just fine.

(Mentioning this in the docs would be good :)

I didn't bother with step 7 as it seems the first line automatically becomes the default variant if one isn't set.

1. Create a new custom field e.g. "Import ID" and add it to the product type that has variants
2. Create new line for each product variant.
3. Make sure "Import ID" is the same for variants of the same product (But unique for each product).
4. Under "Import Strategy" of Feed Me check both: "Create new elements" and "Update existing elements".
5. Under "Set a unique identifier to match against existing elements" check the field you created in step 1: eg. "Import ID".
6. Map all other fields as you would normally do with a non-variant import.
7. Make sure you have an extra column for the "Is Default" field and that only one of the variants has that value to set to 1


Database: Syncing "craft_fields" table through SQL dumps not possible?

You might want to develop a workflow where you have one database (usually live production or staging) where all changes are made, and then sync down the database/assets from there.

Adding this concept of which server is the "source of truth" will greatly simplify keeping things in sync.

Craft-Scripts are a collection of shell scripts that help you do just that. All of this is discussed in detail in the article Database & Asset Syncing Between Environments in Craft CMS


You're likely getting a validation error that you're not checking for.  Do something like this:

if ($entry->validate())
{
    $service->saveEntry($entry);
}
else
{
    $errors = $entry->getErrors();
}

Update:

Do you get anything if you do:

if (!$service->saveEntry($entry))
{
    $errors = $entry->getErrors();
}


How to use promotable Boolean in Craft Commerce?

In Craft Commerce?

  promotable (true or false)
  Is this product and its variants able to be on sale or at a discount.

https://craftcommerce.com/docs/product-model#promotable


Global override specific field templates in Sprout Forms Plugin

The HTML of the input fields are managed by the Custom Field, not within Sprout Forms, so Sprout Forms does not have easy access to that code to give you control over it. There are a few input types where we have to make assumptions about the HTML and the checkboxes field is one of them.

We're looking into ways to give better control here. Right now, the best option if you want an upgrade-safe way to modify that HTML would be to create a [Custom Front-end Field integration](https://sprout.barrelstrengthdesign.com/craft-plugins/forms/docs/customization/custom-front-end-fields
) for the fields you wish to update the input.

Using this approach, you would create a separate plugin and add front-end support for whatever fields you need to modify the input HTML for and your new field would display in the field dropdown when creating a form. As a starting point, you could copy just about everything from the Sprout Forms checkboxes integration which is located in sproutforms/integrations/sproutforms/fields/SproutFormsCheckboxesField.php. Aside from wrapping the Custom Front-end Field in a new plugin, the main things you will need to change is the name of the field so you can identify it in your dropdown and the input HTML in the front-end field template file.


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

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

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


Sprout Email: object variables will not resolve in text and redactor field since upgrade

This is expected behavior. This feature was changed due to a security vulnerability and is mentioned in the upgrade notes.
To create similar behavior you will need to confine your dynamic variables in the Control Panel to the Subject or Default Body fields. Any other custom variables will need to be added and managed in a custom email template.
We will consider adding back improved functionality in the CP workflow if we can find a way to do it safely.


Route token that includes forward slashes

The CP route settings don’t have a token for matching multiple URI segments. However you can pull it off from craft/config/routes.php instead:

return array(
    'blog/(.+)' => 'path/to/template',
);

You’ll be able to access whatever was captured by (.*) from your templates via matches[1].


Upgraded to Craft 3 and lost my Commerce Gateways

Commerce 2 moved all payment gateways to plugins.  You can see the relevant bit in the docs here: https://docs.craftcms.com/commerce/v2/payment-gateways.html

There are currently seven 1st party plugins that add payment gateways and the two most popular, Stripe and PayPal are free.  You can see the table for the remaining in the above link.  All of these are currently in the Plugin Store. 3rd parties can additionally write plugins that work with other payment gateways.


User activation success path not working (Craft v2.3.2621)

The issue was solved by updating Craft to the latest version (2.3.2625), which brought back support for the activateAccountSuccessPath config setting. Thanks to Brandon Kelly for the heads up.


Incomplete localization of `{{ entry.postDate.diff(now)|duration }}`

Because neither Craft (nor Yii) provides a default Dutch translation for the word "and".

https://github.com/craftcms/cms/tree/develop/src/translations

https://github.com/yiisoft/yii2/tree/master/framework/messages

You can provide your own translations using Craft's static translations feature, though: https://docs.craftcms.com/v3/static-translations.html


Any chance you've got xDebug installed on the server?  If so, sounds like you're running into this: Why are some entry detail views empty in the control panel?

If that's the case, your data isn't missing from the database, so there's no need to revert.  You just need to fix the underlying problem so the edit entry page can display properly.


firstName, lastName, and email are actual user fields (not custom), so their name= attributes shouldn’t have the fields[] namespace.

<input type="email" class="form-control" id="email" name="email" value="{{ user.email }}">

<input type="text" class="form-control" id="firstName" name="firstName" value="{{ user.firstName }}">

<input type="text" class="form-control" id="lastName" name="lastName" value="{{ user.lastName }}">

I’m guessing that once you fix those, your phoneNumber custom field will also start saving.


Homepage showing up as "index of \" page

I found the problem, I guess it wasn't craft cms related.

I had to update my apache2 site-enabled config file!


Sprout Forms -- How to link to individual entries on the front-end

A note on Elements

Craft allows plugins to create custom Element Types. Elements have the option to support URIs, but it is not required. Out of the box, Craft currently has 7 Element Types and only two of them (Entries, Categories) support URIs.  Here's a good overview of the default Elements.

Sprout Form Element Types and URIs

Sprout Forms adds two new Elements to Craft. The SproutForms_Form Element and the SproutForms_Entry Element both which do not support URIs simply because we didn't feel there was a strong use case for them to be implemented for most form submission scenarios.

While it may not make sense to support URIs for all SproutForm_Entry Elements out of the box, you can still create a way for those Elements to be linked to in your templates, you will just have to do it manually.

How to manually create URIs for Sprout Form Entry Elements

To customize Craft to handle custom URLs for an Element that doesn't support URLs (of even for an Element that supports that that you need to do something fancy with), here is a rough example of the steps needed.

Loop through your Elements and output the URL you wish them to have to link to your Entries:

/submissions/{{ formEntry.id }}

You will then need to setup a route to tell Craft which template it should load when it encounters a URL like that. You can create a route in the CP or in the craft/config/routes.php file. This route tells Craft to load the submission/_entry.html template each time a URL matches submission/ANYTHING:

return array(
    'submissions/(?P<formEntryId>.*)' => 'submissions/_entry'
);

In your submissions/_entry template, you will need to use the ID information in the URL to query for the Form Entry that you wish to display:

{% set entry = craft.sproutForms.getEntryById(formEntryId) %}

In the above example, we're able to use the formEntryId variable because we setup our route to assign the second segment of the URL to the value formEntryId. If you setup your route in the control panel, you may need to grab the ID using getSegment:

{% set formEntryId = craft.request.getSegment(2) %}
{% set entry = craft.sproutForms.getEntryById(formEntryId) %}


How to validate a unique field in Craft 3 element?

Here's my findings after some experimentation:

Elements and Records are two entirely separate entities. The Element is basically the core Craft database entry, while the Record is the additional database entry in a new table with your custom fields.
Validation should always be done on the element if you use the pattern used in the question, because saveElement() will call validate on the element itself, not the record. If you validate on the record and it fails ($record->save() returning false), the phantom element will still be created, but no record will refer to it. Yikes.
When validating on the element, some rules such as unique require access to the database, which is not bound to the element per se. In that case, you should map the targetClass parameter of the rule to the record class.
However that does mess up same-model detection with UniqueValidator: the validation will fail even if you're editing the current model, saying its unique field is already in use (by itself!).
Thankfully, you can use the filter parameter of the rule to manually ignore the current ID. However, you must make sure not to use that is the ID is null (i.e. when creating a new element), because != does not work with NULL values in SQL (you should be using IS NOT instead).

Summary: here's how to implement unique validation on the Element class:

    $rules[] =
    [
        'myField',
        'unique',
        'targetClass' => MyRecord::class,
        'filter' => function($query) {
            if ($this->id !== null) {
                $query->andWhere('`id` != :id', [ 'id' => $this->id ] );
            }
        }
    ];

That's it!


craft_searchindex is MyISAM all others InnoDB

The searchindex table has to be MyISAM because up until MySQL 5.6.4, MyISAM was the only engine that supported full text search indexing.

Craft currently supports back to MySQL 5.1.

It is normal for that table to be large because it's keeping a record of every searchable thing on your web site.


How do I hide a login form if user is logged in?

The Twig variable currentUser contains information about the currently logged in user, and will be null if no user is currently logged in.

{% if not currentUser %}

    <!-- Your login form -->

{% endif %}


Get the related entry from an Entries field in a Matrix block within a plugin craft 3

figured this one out on my own, so to get all of the related objects, I just needed to change the above query to $buildings = $location->buildings->all();


Which is the best place to learn Craft CMS with tutorials?

CraftQuest.io has some great Craft CMS videos; many are free, but some of the more in-depth ones are not.


What is the different between url() and getUrl()

They do the same thing. url() is an alias of getUrl(). This is the link from the Craft 2 docs: https://docs.craftcms.com/v2/templating/entrymodel.html#url.
It works the same way in Craft 3, but I can never find anything in the Craft 3 docs.


I can't think of an existing way to do this (other than something ugly like have a separate plugin whose sole job is to clean up the data from the first).

I think this would make the case for things like onBeforePluginUninstall, onPluginUninstall, onBeforePluginInstall, onPluginInstall, onBeforePluginDeactivate, etc. events to be added so that you could listen for these events and have time to do all of the cleanup necessary before uninstallation continues.

Probably worth adding as a feature request and linking to this thread!


I see a few issues with your code. (1) Unless you set heroImage as a variable somewhere, then you need to change heroImage to entry.heroImage. (2) But, an asset field returns an assetModel, not the actual image. To access the image, you need to use .first() to select the first asset in the assetModel. (3) Then you need to access the URL on that image, by using url.

This code should work:

{% set heroImage = entry.heroImage.first() %}

 {{ entry.description }}

                        {{ entry.buttonText }}


How do I set the user password when using saveUser service method?

Use newPassword instead:

$user->newPassword = '123456';


How to use a note from the Line Item Model

The example template show how to display the note, but here is the jist of it:

{% for item in cart.lineItems %}
 {{item.qty }} x {{ item.description }} - {{ item.note }}
{% endfor %}


Is it Possible to Use Live Preview with Global Settings

Anything's possible, but not without hacking core files, which isn't recommended.

By default, global settings don't even have the concept of a "template", which is a fundamental part of getting a Live Preview request to work.


Sprout Forms - Custom Form Notification Recipients With sproutForms.onBeforeSaveEntry

Based on the event you are referencing, I believe this is a question about Sprout Forms for Craft 2. In Sprout Forms for Craft 3, notifications are handled a differently.

In Sprout Forms for Craft 2, the event you'll want to use for this is the SproutForms_OnBeforePopulateEntryEvent.

You're not able to modify which value gets set directly, so you'll have to swap in the value you want using Craft Object syntax.

In your notificationRecipients field, add a value using Craft Object Syntax: {myRecipientsEmail}. Once you have called sproutForms.onBeforePopulateEntryEvent you can modify the $_POST data that gets processed when assigning the recipient value and it sure it has the value you want: $_POST['myRecipientsEmail'] = 'so-and-so@website.com'


Please read the docs (or this) about how to render plugin templates. It's all well explained there . You don't need to define src/templates but your plugin handle

`plugin-handle/settings.html`


You could use the category handle.

If that doesn't suit your requirements, you can associate custom fields with categories, same as you can with entries.


Amazon S3 plugin uploading to different directory

Ah, it looked like it was thanks to the blank folder name - moving it all to a new folder which actually has a name seems to have done the trick!


Radio buttons in matrix field not saving

Steps to fix:

Change the radio button default to an alternative option.
Go to entry and remove the matrix block.
Save entry
Readd the matrix block.

You should be able to correctly save the block, a long process but I couldn’t figure out what was going on.


Change the size of a users profile photo?

I found the answer on the Craft website under the UserModel section:

getPhotoUrl( size )
Returns a URL to the user’s photo at a given size in pixels (defaults to 100). You can also pass in "original" if you want to get a non-resized photo back.

Although this does answer my question, I feel the behavior between handling this "asset" compared to an actual native asset is a little cumbersome, especially considering if I wanted to apply an image transformation on the original file.


I'm inferring from that last line that you're trying to install the Happy Lager demo.

However, that demo is currently only compatible with Craft 2.

The app folder was removed in Craft 3. And the demo has not yet been updated for Craft 3.

So if you really want to play with the Happy Lager demo, you'll need to download Craft 2. Or visit demo.craftcms.com, which will spin up a full copy of the demo for you.


How can I display category title inside another category

If I get you right you have a category select field inside a category. If you want to grab any field values from a category you can do it the same way as with entries. Code works almost the same.

{% for category in craft.categories.group('handle') %}
    <p> {{category.title}} </p>
    <p> {{category.title}} </p>

    {# You can access any field like you normally do inside your category #}
    {{ category.categoryField }}

    {#
       If you want to access another loop-able
       field inside your category you can just make another loop.
       Like you're looping over entries
    #}
    {% for block in category.categoryFieldName %}
        {{ block.fieldName }}
    {% endfor %}
{% endfor %}


How can I create a visually weighted tag cloud?

Brandon commented on getting tag usage count (and how it can be expensive) in this Google+ post and again in this SE question where I was trying to think through a plugin.

So to completely steal from that, you could loop through your tags and get a count for each...

{% set tags = craft.tags.find() %}

{% for tag in tags %}
    {% set count = craft.entries.section('blog').relatedTo(tag).total() %}
    {{ tag.name }}
{% endfor %}

Then manipulate the listing with JavaScript or find the max count and loop again to apply inline CSS percentages or font-sizes that are scaled accordingly. As Brandon noted in that post, be sure to wrap everything in {% cache %} tags since this will be an intense template to render.

Update:

Since this answer, Phil Birnie released a plugin for this he's linked to below, and I came up with my own that we trashed in a Straight Up Craft Hangout thanks to Marion's stellar idea of using a Preparse field to tally counts, which I've added here as an alternative answer.


Cart completed at gateway redirect issue

Just to update this with an answer, thanks very much to P&T's excellent dev team.

The model implementing RequestResponseInterface returned from the gateway's authorize() method isSuccessful() method should only return true when completing a payment.

I also had to return false on the isProcessing() method during my tests. Not sure what that method does but setting both those methods to return false fixed the issue.

It was a recent change in the commerce code that identified this bug in my gateway's code.


Craft CMS and LiteSpeed (403 error on login)

It turns out mod_security was the culprit, so disabling it got Craft working.


Ok, so this is the relevant code in the service processing the feed, where the stepBeforeElementMatch is being called:

        // Fire an 'onStepBeforeElementMatch' event
        if ($this->hasEventHandlers(self::EVENT_STEP_BEFORE_ELEMENT_MATCH)) {
            $event = new FeedProcessEvent([
                'feed' => $feed,
                'feedData' => $feedData,
                'contentData' => $matchExistingElementData,
            ]);

            $this->trigger(self::EVENT_STEP_BEFORE_ELEMENT_MATCH, $event);

            if (!$event->isValid) {
                return;
            }

            // Allow event to modify variables
            $feed = $event->feed;
            $feedData = $event->feedData;
            $matchExistingElementData = $event->contentData;
        }

I have not tested this, but by the looks of it, it should be enough to set the $event->isValid to false in your code after doing the necessary checks that you want.

Be aware that the $event->feedData you are working on is an array representation of your feed data (converted from, XML, JSON or whatever). So you need to do your checks accordingly. At this point, Feed Me has not tried to match against potentially existing elements in Craft. Your example code basically assumes there's a field in the feed element with the name status with the value false. If that's not the case, you could do your checks on whatever you want, before a certain date, etc.

But if it is, something like this would be likely to work (again untested):

if($event->feedData['status'] == "false") {

    $event->isValid = false;
}

If you're looking to skip based on some Craft element, you'd either need to query for it (basically doing some custom matching), or use an event later in the process (I can help you out there too, but maybe it's easier in your case to skip it already here).


Ok figured it out. I was going about it completely the wrong way. As the field in question is an Entry type, I needed to use the Relations Service

$globalSet = craft()->globals->getSetByHandle('[globalSetHAndle]');
$selectedField = craft()->fields->getFieldByHandle('[fieldHandle]');
craft()->relations->saveRelations($selectedField, $globalSet, array($entryId));

Passing null instead of array($entryId) will clear the relation values


What purpose does the site-selector under assets fulfill?

Assets aren't technically multi-site, in that it's currently not possible to limit Volumes to specific Sites, and all uploaded Assets will be available across all Sites, regardless of which Site it was uploaded from.

Assets titles and custom fields can be translated, though. So the purpose of the Site selector in the Assets index is to have the titles and any custom field values render with a specific Site's translations.


Yes, it's possible.

It essentially works just like it does in twig...you just call getURL with the valid name of a transform

$criteria = craft()->elements->getCriteria(ElementType::Asset);
$criteria->id = 1;
$asset = $criteria->first();

if ($asset)
{
    $url = $asset->getUrl('myTransform');
}

$imgUrl = $image->getUrl('tranformHandle);

...as I understand it that triggers the  image to be transformed on-demand if the transform does not already exist.


Script tags should be put in plain text field types (if they need to be editable by the client at all, otherwise put them in the templates).


Filtering Matrix through field value and multiple relations

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

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

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

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

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

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

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

    $results = $query->queryAll();

    return EntryModel::populateModels($results);
}


Show Live Preview even if whole page is disabled

You can combine .status( null ) with the isLivePreview property on craft.request. More info can be found in the docs.


Does Redactor have a button that adds a horizontal rule ( tag)?

Yes. Edit config/redactor/standard.json file (or the relevant file in your Craft project) and add "line" in the buttons items list.

You should see the "Line" button in the toolbar which will add a hr tag to your contents.


How can I use the Courier plugin to notify a user when an entry is enabled?

In your Courier Blueprint listen to entry.beforeSaveEntry events and use this code for the Trigger Condition:

{% set oldEntry = craft.entries({
    id: entry.id,
    status: null,
}).first() %}

{%- set wasDisabled = oldEntry.status == 'disabled' %}
{%- set isEnabled = entry.status == 'live' %}

{{- wasDisabled and isEnabled ? 'true' : 'false' }}


How to output a resized Assets image in a template

You can dynamically create and specify transform parameters from your templates to achieve what you're looking for.  See here for an example.


Figured it out, posting here in case someone runs into something similar. I opened up the composer.json file in the root and removed the line "solspace/craft-freeform": "2.5.27" from the "required" list.

From there, I was able to update Craft, and then I was able to update Freeform. All is well, and all up-to-date!


Is Craft a good fit for a project w/ social network features?

It really depends on whether you consider Craft a platform, that you're willing to do some custom development on, or an off-the-shelf, finished product.

Even though I love Craft, I have to be honest. As an off-the-shelf product, and if the main goal of the project is building a social network, I think you're be better off choosing some other, more specialised, platform.

You can probably solve all the things you mention with Craft; user handling, posting content to different channels from the front-end, updating content with likes, updating users with followers, etc. But, you don't get any specific social network functionality "for free", you'll have to use the building blocks that exists in Craft to create this functionality.

But, if you're willing to do some custom plugin development, you could definitely use Craft as the platform. The plugin API is extremely powerful, and let's you build and integrate pretty much whatever you want into Craft.


Efficient way of looping through a large amount of users?

You could just setup a criteria model in your “categories” for-loop, prepared to query for the users related to that category. And then use the total() method to get the count.

foreach($category as $interest) {
    $user_criteria = craft()->elements->getCriteria(ElementType::User);
    $user_criteria->relatedTo = $interest->id;
    $count = $user_criteria->total();

    $interestArray[$interest->title] = $count;
}

Using the total() method is a lot faster than find(), the underlaying SQL which is necessary to get the amount of rows performs better and Craft also doesn’t have to populate the Entry models with all the data.

(Not sure why @LukePearce deleted his answer, where he basically suggested to do the same thing.)


Parse error: syntax error, unexpected '['

The Charge plugin requires a minimum of PHP 5.4.

The brackets notation for arrays (which is what Charge uses) was added in 5.4.

  http://php.net/manual/en/language.types.array.php

Contact your hosting provider to find out how to upgrade.


Performing Image Transformations Locally

It is very likely that your "File System Path" on the asset source is unsuitable for a local environment.

You can set the fileSystemPath in your config like this:

'environmentVariables' => array(
    'fileSystemPath' => '../../public'
)

Then you can change your asset source settings to something like the following:


Craft Commerce: where to modify data sent to gateway (need to send customer data)?

Ok so it works pretty much how the documentation would lead you to think.

This is for Commerce V1 but apart from hooking up to the event, it should be much the same for V2.

public function commerce_modifyGatewayRequestData($data,$type,$transaction)
{

        // Dump the data to see what is there...you can do what you like to $data and then you return it at the end...
        BusinessLogicPlugin::log("commerce_modifyGatewayRequestData - UNMODIFIED DATA");
        BusinessLogicPlugin::log("data");
        BusinessLogicPlugin::log($data);
        BusinessLogicPlugin::log("type");
        BusinessLogicPlugin::log($type);
        BusinessLogicPlugin::log("transaction");
        BusinessLogicPlugin::log($transaction);
    }

    # Example...
    # TRUNCATE any over-sized data eWay might not like....
    # Data limits come from here: https://eway.io/api-v3/#direct-connection

    if(isset($data['Customer']['FirstName']))
        $data['Customer']['FirstName'] = substr($data['Customer']['FirstName'], 0, 49);

    ...etc

        // Dump the modified data for checking if you need to...

        BusinessLogicPlugin::log("commerce_modifyGatewayRequestData - MODIFIED DATA");
        BusinessLogicPlugin::log("data");

    // Now actually return the modified data...
    return $data
}


You would just pass the other value (i.e. the section handle) in to that template as GET or POST parameter and in the search results template grab the paramater and use it, as in your code.

If using GET, the url you'd construct would be something like:

http://whatever.com/search?query=blah&sectionHandle=blah2

or with POST you might use e.g. a radio for the section option with the name being sectionHandle and the value being the actual handle of the chosen section.

Either way, in your template you then just:

{% set sectionHandle = craft.request.getParam(sectionHandle) %}
{% paginate craft.entries.search(query).section(sectionHandle).limit(5) as entries %}


Thanks to the P&T team and the latests update to Craft (2.3.2640), this is now possible through a plugin! https://github.com/engram-design/CPNav


Get additional category field when outputing entries grouped by categories

Just focusing on the assets part I would try to eager-load the image and insert it into your template that way.

{% set entriesByCat = {} %}
{% set entries = craft.entries.section('words').find() %}
{% set cats = craft.categories.group(themes).find({
    with: ['categoryImage']
}) %}

{% for cat in cats %}
  {% set entries = entries.relatedTo(cat) %}
  {% set catImage = cat.categoryImage[0] ?? null %}
  {% if entries|length %}
    {% set entriesByCat = entriesByCat|merge({ (cat.title): { entries: entries, image: catImage}) %}
  {% endif %}
{% endfor %}

{% if cats|length %}
    {% for catTitle, catInfo in entriesByCat %}

{{ catTitle }}

        {% for entry in catInfo.entries %}
          {# Entry content goes here... #}
          ...
        {% endfor %}
    {% endfor %}
{% endif %}

You may want to change the naming convention a little bit, but I just wanted to try and stick to yours as is.


Using a custom Commerce 2 Adjuster in a Craft Plugin

the adjuster had the wrong namespace, changing it to:

namespace hendrikeng\friendsdiscount\adjusters

fixed the issue


You can restore your database from your pre-update attempt database backup that you (hopefully) made.  Assuming you've got the the backupDbOnUpdate config setting set to true, Craft made one for you in craft/storage/runtime/backups as well.

You can also download any previous version of Craft's files via: Where can I download previous versions of Craft?

Just replace the existing craft/app folder with the fresh one you downloaded and delete app.bak.  I wouldn't recommend restoring directly from app.bak because depending on where your update failed, it could be in an inconsistent state.

I'd recommend doing a manual update when you're ready to update again as you probably ran into your server's max execution time or memory limit (which tends to happen on these larger updates).


Error: File to import not found or unreadable: ../../../../../lib/craftcms-sass/mixins

Okay, so it turns out my file watcher (WebStorm) was the cause.
It compiled the dashboard.scss, so I simply changed the Scope to make sure it only compiled my own files.


Guest Entries - Two ajax forms for different section entries. Receiving 404 only on second form?

I shall answer my own question.

The issue was because I was logged in as admin in another browser tab. I was not receiving the "Unauthorized" response from craft. Just the 404. By testing in an incognito window I was able to see I was receiving an unauthorized response from craft which led me to the problem. Which was the sectionId for that particular form was incorrect. SectionId on second form should have been 2 not 4.

Hope this helps anyone else having a similar problem.


{% switch entry.postDate|date('M') %}

    {% case 'Dec' or 'Jan' or 'Feb' %}
        {% set season = 'Winter' %}

    {% case 'Mar' or 'Apr' or 'May' %}
        {% set season = 'Spring' %}

    {% case 'Jun' or 'Jul' or 'Aug' %}
        {% set season = 'Summer' %}

    {% case 'Sep' or 'Oct' or 'Nov' %}
        {% set season = 'Fall' %}

{% endswitch %}

<p>{{ season }} {{ entry.postDate|date('Y') }}</p>


Live Preview across different root domains is currently not possible in Craft. See here for more info: https://craftcms.stackexchange.com/a/14966/57

You can use it across different subdomains that share the same root domain, though: https://craftcms.com/support/cross-domain-live-preview


Can you change the URL for Assets uploaded to a Rackspace CDN?

Not really Craft related, but: for this to work in Craft, you should first make sure Rackspace recognizes the url you want to use. They explain how to do this here.

In short: create a CNAME record for your domain, pointing to your Rackspace domain. After doing that, change the display url for your asset source.


You're just entering the command slightly wrong is all. Where you go:

composer create-project craftcms/Users/lestone2

It should be:

composer create-project craftcms/craft /path/to/project

The craftcms/craft bit isn't a directory, it's vendor/package. The path to where you want your project to be (including the name) comes after. Good luck!


This is an obvious one, but have you checked the plugin is installed correctly? If you're working from multiple development locations, or servers then perhaps you have a discrepancy between them?


Activate correct locale upon front-end entry

Using <input type="hidden" name="locale" value="en_us”> works as expected, as long as the section settings for that entry has all the locales set to be disabled by default.

Upon creating a new entry via front-end form, only the specific locale was activated. However, creating the entry in the admin panel, they are all left off by default. (Seems correct, just remind any clients that might be using the admin panel to enable whichever locale).


Make fields required when using Guest Entries

If the fields are marked as required in your field layout, then they should fail validation even on the front-end, so it sounds like a bug to me.  Can you send a database backup as well as the template code you're using for the form over to support@buildwithcraft.com?

Update

The issue was that if your entries were set to be disabled by default, then Craft won't run any validation on them.  Just made a change so that if you use the latest Guest Entries, you'll have an additional plugin setting to enable/disable validation on a per section basis, regardless of the default status of the entry.


Skipping the shipping part for custom virtual product

There is nothing stopping you selling products that are not physical. Just mark the product as free shipping, and skip the address and shipping method selection screens entirely (the front-end is totally up to you).

p.s Product Type settings even have a 'has dimensions' checkbox you can turn off.

p.p.s check out https://github.com/craftcms/digital-products


How to add Facebook pixel code to my website

Craft makes no assumptions on how your site should be built so it's impossible for us to say exactly where to put the pixel code.

You would add the code to whichever template you needed it in. This depends entirely on how your site is put together.

Oftentimes the <head> portion will be within your main _layout file but that is not necessarily always the case. This file can also be anywhere within your templates directory.

For Craft 2, look in your /craft/templates directory
For Craft 3, look in your /templates directory


Returning a "is currently unable to handle this request. 500 Error" when client posts

As Lindsey pointed out, I'd also highly recommend taking some time to update to the latest Craft release. Craft 1.3 is over 3 years old now.

If you're getting a 500 Internal Server Error, then it's either being generated by Craft or by your web server.

If it's generated by Craft, it will be Craft styled and the underlying error message will be in your craft/storage/runtime/logs folder.

If it's generated by your web server, the underlying error message should be in your web server's error logs.


How to manage multiple categories and entry url formats

I can think of a couple possible solutions here:

1. Rethink your url structure
You could always remove the category segment from the url. Maybe create a field for the main category and then another field for all the categories, and use the main category field for your URL. Or you could fetch the first productCategory instead of the last one, so there's less chance of it changing. In my opinion you're going to have a lot of SEO issues if your url changes whenever you add a new productCategory, not to mention broken links and all sorts of other headaches.

2. Do some fancy stuff with routes and entry queries
I think technically you could set up a route like flowers/{productCategory}/{slug} and then in your template do an entry query for an entry with that slug. But probably better to think over #1 and find a cleaner solution.


Use variable passed via include to set value of paramenter

You'll need to concatenate the string you pass to the level parameter, using the ~ operator:

{% set pages = craft.entries.section('navigation').level('<='~navLevel) %}


Override the output of class S3AssetSourceType->getBucketList from a plugin

OK, this doesn't completely answer my question, but I think this is the more elegant solution to the problem I was trying to solve. If you don't have the all s3:ListAllMyBuckets permission available in AWS then the following plugin code will allow you to pass in a static bucket list. This meant I didn't have to start hacking the core code.

<?php
namespace Craft;

class MyPlugin extends BasePlugin
{
    public function init()
    {
        parent::init();

        if(isset($_GET['p']) && $_GET['p'] == "admin/actions/assetSources/getS3Buckets")
        {
            // Requires an admin
            craft()->userSession->requireAdmin();

            // Making the money
            craft()->requireEdition(Craft::Pro);

            $bucketList = array();

            $bucketList[] = array(
                'bucket' => 'my-bucket-name',
                'location' => 'EU',
                'urlPrefix' => 'http://s3-eu-west-1.amazonaws.com/my-bucket-name/'
            );

            $this->returnJson($bucketList);
        }
    }

    private function returnJson($var = array(), $options = array())
    {
        // Set the 'application/json' Content-Type header
        JsonHelper::setJsonContentTypeHeader();

        $options = array_merge(array(
            'expires' => false,
        ), $options);

        // Set the Expires header
        if ($options['expires'] === false)
        {
            HeaderHelper::setNoCache();
        }
        else if ($options['expires'])
        {
            HeaderHelper::setExpires($options['expires']);
        }

        // Output it into a buffer, in case TasksService wants to close the connection prematurely
        ob_start();
        echo JsonHelper::encode($var);

        craft()->end();
    }
}


How to create new variable from For Loop results

If I understood your question correctly then you should be able to do it as follows:

{% set sizes = [] %}

{% for productAttribute in entry.productAttributes %}
    {% set sizes = sizes|merge([productAttribute.size]) %}
{% endfor %}

{% set sizes = sizes|join('|') %}

The sizes variable will then be a string containing the pipeline separated sizes, for example:

small|medium|large


How to Render a State Abbreviation in Craft CMS?

I don't think there's anything native (and haven't seen a plugin) that does this, but one way to do it is to create a macro where you add all the states and their abbreviations to a map. Something like this should work:

In a file called templates/_macros/helpers.html or the like (abbreviations map shortened in example; you can find a full list here, just need to convert it to Twig object syntax):

{% macro abbreviateState(stateName) %}{% spaceless %}

    {% set abbreviations = {
        'Alabama': 'AL',
        'Alaska': 'AK',
        'Arizona': 'AZ',
        'Arkansas': 'AR',
        'California': 'CA',
        'Colorado': 'CO',
        'Connecticut': 'CT',
        ...
    } %}

    {{ abbreviations[stateName|trim] ?? stateName }}

{% endspaceless %}{% endmacro %}

In your template (i.e. /templates/entry.html):

{# Import macro at the top of the template #}
{% import '_macros/helpers' as helpers %}

{% if eventType.eventState | length %}

    {{ helpers.abbreviateState(eventType.eventState) }}

{% endif %}

Of course, this solution hinges on the state names being typed properly (exactly the same way as they appear in the macro); if somebody were to write "New york" and you've got "New York" in the macro, a proper abbreviation would not be found and the state name "New york" would simply render as-is.

To mitigate this, you might consider opting for a different input field type other than Plain Text, e.g. a Dropdown where you set up all the states as options.

If you're sticking with a Plain Text field, you could also circumvent the specific issue of capitalisation being off by making the state names in the macro map all lowercase, and applying the |lower filter to the state name when you try to pull the abbreviation:

{% set abbreviations = {
    'alabama': 'AL',
    'alaska': 'AK',
    'arizona': 'AZ',
    'arkansas': 'AR',
    'california': 'CA',
    'colorado': 'CO',
    'connecticut': 'CT',
    ...
} %}

{{ abbreviations[stateName|trim|lower] ?? stateName }}


I kind of found a work around, but doesn't seem like it's the correct way to be doing this.

{parent.uri ? parent.uri : 'static'}/{slug}


Editing error messages and allowing a phone number input in a P&T Contact Form

I found it! It took quite a bit of digging about, but eventually I found the files I needed to edit. In case anyone else is struggling with this same issue, here's what you need to do:

Look in the folder 'craft/app/framework/validators/' for a file called 'CRequiredValidator.php'. Open the file in a text editor and look for the text: 'cannot be blank'.

Part of this line reads: '{attribute} cannot be blank.'

You can change the text 'cannot be blank' to whatever you like and can move '{attribute}' to after the alternative text that you've put in without breaking anything. Save and upload your altered file to the correct location.

Now, look in the folder 'contactform/models/' for a file called 'ContactFormModel.php' (probably the only one there).

By default, it has the following written into it:

    return array(
        'fromName'          => array(AttributeType::String, 'label' => 'Your Name'),
        'fromEmail'         => array(AttributeType::Email,  'required' => true, 'label' => 'Your Email'),
        'message'           => array(AttributeType::String, 'required' => true, 'label' => 'Message'),
        'messageFields'     => array(AttributeType::Mixed),
        'subject'           => array(AttributeType::String, 'label' => 'Subject'),
        'attachment'        => AttributeType::Mixed,
    );

The bits you need to alter to complete the customised error messages are found after 'label' =>

Save and upload your second altered file to the correct location, and check out the new error messages for your form!


You might do something like this, concerned that you want to set current on active category.

{% set categorySlug = craft.request.getLastSegment() %}

{% nav category in craft.categories.group('blogCategories') %}
    {% set current = (category.slug == categorySlug) %}
    <a class="button button--outline-blue
       {% if current %} current{% endif %}
       href="{{ category.url }}">
       {{ category.title }}
    </a>
{% endnav %}


Adding a RESTful, OAuth API on top of Craft

Short answer: yes I have, I used OAuth 2 and I would absolutely do it again.

I wrote up my experience in general terms here but essentially it boiled down to two plugins, one on each site: one acting as the server and another as the client.

I used league/oauth2-server for the server and then tied in directly to the Dukt OAuth plugin for the client, but in retrospect it would’ve been simpler just using league/oauth2-client for that.

For transforming data like the Element API does I used league/fractal and then to get proper request behaviour I used zendframework/zend-diactoros.

Essentially I think this sort of thing is perfectly feasible in Craft, due to plugins being so flexible you can load whatever libraries you need and go nuts. Craft 3 could simplified things somewhat with Yii Modules as I’m guessing you could package up the whole API code as a module, but it shouldn’t be necessary.

Hope that helps!


What's the difference between setting cache with {% header %} tag and {% cache %} tag?

The header tag sets an HTTP response header, which may be used to (among other things) tell the browser that the response content is "cacheable".

The cache tag tells Craft to cache the generated HTML on the server side (as a file).


Including CSS and JS files on multilanguage sites

Use the alias instead {{ alias('@web') }}

It will always point to your web directory


Assuming you are using the Rich Text field, you'll want to look at the Redactor setting, convertDivs.

  convertDivs (Default setting is true)

  With this option turned on, Redactor will automatically replace divs to paragraphs.

Go in to your field settings:
Craft Admin › Settings › Fields › Rich Text field name

Look at the config settings to determine which config file you are using. Then, go in to your craft/config/redactor/ConfigFile.json file and edit your redactor settings to exclude the convertDivs setting (assuming nothing else in your config file):

{
    convertDivs: false
}


If you're running Craft CMS 2.6.2783, you can pass in an 'expires' key to the optional $options 2nd parameter of returnJson with the value set to the time in seconds that will be passed to the cache control expiration headers.  If you ignore it, it will have the current behavior of not caching at all.


Craft 3 Upgrade having issues with rich text editor

Solved it by installing the Redactor plugin, going through admin/settings/fields on the admin page and changing the field types dropdown from Plain Text to Redactor.


Best practice for collecting a response from a third party

After the payment has been made, you can have the response callback go to an anonymous action method on your plugin's controller.

The URL for that would look something like this:

http://mydomain.com/index.php/actions/myPluginHanlde/myPluginController/myPluginAction

From there you can perform any additional business logic (validation, record saving, etc.), and $this->redirect(''); to a success template.


Problems Displaying Label and Instructions in Forms

You should be using forms.radioGroupField instead of forms.radioGroup, just like you're using forms.lightswitchField.


Craft Installation Next Button Not doing anything

Well, things should be going very smoothly from here, so there is pretty surely something not right with your installation.

1) did you make sure to rename the installed file public/htaccess to public/.htaccess? I'm not sure if this is critical to the installer, but it might be.

2) You can look in craft/storage/runtime/logs. There you find craft.log and phperrors.log. Either may hold information to help.

3) It sounds that your database login config is ok, as otherwise the Craft installer would notify about that, but you may not have all the other server requirements in place yet. See: https://craftcms.com/docs/requirements.

For requirements testing, see: Is there a quick way to check a server for Craft's minimum requirements?

4) Getting no response would be quite unusual. It's possible that your Craft installation is faulty -- FTP in general is often not entirely reliable. You could remove, then re-upload and replace the installation. If you do this and can, I'd suggest uploading the zip, then unzipping it on the server. Again, then, don't forget to rename the htaccess to .htaccess.

5) all this presumes you are running on Apache. If Nginx instead, here are two references that should help. I'd go with the first as that's from the Craft team based on what works for others. I use Nginx all the time, as do many others, and it's fine once configured:

What is the recommended Nginx configuration for Craft?

https://gist.github.com/kenzie/5811327

Good fortune then. Again, Craft installs are nearly as effortless as Craft updates, unless there is something wrong in the configuration or preparations.


How should a multi-stage editorial process be implemented in Craft?

Have you already seen the workflow plugin? Maybe it could give you some inputs for your further development: https://github.com/engram-design/Workflow.