How to use url segments like with Freebie in EE I'm trying to make the jump from EE to Craft but struggling in this area (and thinking I may be approaching this all wrong).

In EE, I often use url segments (in combination with Freebie to ignore them) for certain logic in templates (ie. adding a last segment of 'thanks' to show a thank you message).

I cannot figure out how to do this well in Craft - or even if it is the right approach.

I have a channel entry with a slug of 'contact' and want to add 'thanks' to the url to conditionally display a thank you message on that page. I know I could add a route so that 'contact/thanks' will still load the correct template for that channel but I then run into the issue of that URL not matching the entry slug and no entry data is available for {{entry.whateverFields}}.

So then I did this to try to get around the issue by putting all my entry data in a for loop:

{% for entry in craft.entries.section('standard').slug(craft.request.firstSegment) %}
    {{entry.title}}
    ...other template code in here
    {% if craft.request.lastSegment == 'thanks' %}
        ...thank you message
    {% endif %}
{% endfor %}

This lets me now get the correct entry data loaded for this entry (or others in this section) and my thank you message still appears however it just feels like an awkward way to do it and I suspect in other scenarios it could become really messy.

Is there a better way to approach this in Craft?

Or can you actually have Craft ignore certain url segments?

One easy way to work around this is to use a query string instead of a segment. You'd redirect the user to for instance /contact?receipt=thanks instead of /contact/thanks, and you change the conditional in your template to something like this:

{% if craft.request. getParam('receipt') == 'thanks' %}
    ...thank you message
{% endif %}

I've always felt that this kind of information doesn't belong as a segment-part of an url, and the only reason we did that in EE was the lack of easy access to the query string.

Another way would be to set up a route like you did. Maybe set it to (slug)/thanks, where (slug) is the slug token. Then, at the beginning of your template, before trying to access entry, you check if it exists, and if it doesn't you pull it manually. Like this:

{% if entry is not defined %}
    {% set entry = craft.entries({ slug: craft.request.segment(1) }).first() %}
{% endif %}

Hope one of those solutions helps.


How can I sort entries by a custom field in the CP, Craft 3? I have an events section with a custom field of eventDate and it would be very helpful to editors to have them listed in event date order.
In Craft 2 I used the plugin CP Sortable Custom Columns by Mikkel Rummelhoff but he hasn't ported it to Craft 3 and may not, he says.

I would have thought this option would be useful to many people, so has anyone got any suggestions as to how to achieve it, I'm not a plugin developer myself.

Craft 3.2 beta adds support sortable custom fields.


redirect on a Structure Client has created /exhibitors but wishes it to point to /exhibitors/partners

Can that be done using routes or should we be looking at htaccess rules?

If it's just a simple redirect, it'll be quicker to do it in .htaccess and not invoke PHP/Craft at all.


Can locales be used to switch layouts? In my particular case I need to be able to switch the layout that the template extends. Is this possible to do using locales?

Untested, but should be fairly straightforward.

{% if craft.locale == 'de' %}
    {% set template = '_layout_de.html' %}
{% else %}
    {% set template = '_layout.html' %}
{% endif %}
{% extends template %}

or

{% extends craft.locale == 'de' ? '_layout_de.html' : '_layout.html' %}

or using a locale folder (thank josh baker)

{% extends craft.locale ~ '/_layout' %}


Specify FolderId When Uploading a File on the Frontend In a front-end form where I am uploading a file, I need to specify a specific subfolder. I can't do it in the cp dynamic field for reasons so I was hoping to use a hidden field to set the folderId. The folderId exists and each entry has a different folder. I have this code that works but I can't figure out the code, for example something like: folderId: 44
<form method="post">
 {{ csrfInput() }}
 {{ actionInput('entries/save-entry') }}
 {{ hiddenInput('sectionId', '3') }}
 {{ hiddenInput('enabled', '1') }}
 {{ hiddenInput('entryId', entry.id) }}
 {{ hiddenInput('redirect', craft.app.request.absoluteUrl|hash) }}

    {% for relatedAssetId in entry.patientFiles.ids() %}
      {{ input(
          'hidden',
          'fields[patientFiles][]',
          relatedAssetId,
        ) }}
    {% endfor %}
          {{ input('file', 'fields[patientFiles][]', options={
             multiple: true,
          }) }}
    <button class="btn btn-primary" type="submit">Upload</button>

You can find a specific folder using the Assets service:
https://docs.craftcms.com/api/v3/craft-services-assets.html#public-methods
If you know all the necessary information when that template is parsed, the findFolder method might be useful but ensureFolderByFullPathAndVolume is probably more precise.
For example:
{{ hiddenInput( 'secret_folder_id',
    craft.app.assets.ensureFolderByFullPathAndVolume($volumePath, $assetVolume) ) }}


How can I follow relations in ElementCriteriaModels from plugin code? In Twig code you can use craft->entries->relatedTo to do all sorts of neat things.

From plugin code I am not sure how this works?

$c = craft()->elements->getCriteria(ElementType::Entry);
$c->section = 'concepts';
$c->relatedTo(array('targetElement'=>$e, 'field'=>'entry'));
$concepts = $c->find();

This doesn't throw an error - but it doesn't work either.

How can I use the criteria model to retrieve entries that have some relationship?

Cheers!

You're very close! Try this:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'concepts';
$criteria->limit   = null;
$criteria->relatedTo = array(
    'targetElement' => $e,
    'field'         => $field
);
$elements = craft()->elements->findElements($criteria);

Keep in mind, in this instance, $field is the field object which can be retrieved with something like the following:

$singleFieldModel = craft()->fields->getFieldById($singleField);

See the documentation (https://craftcms.com/classreference/services/FieldsService) for other ways to get a field object.


Why is Craft rendering a blank page instead of an error template? I'm currently seeing this in the PHP error logs:

Fatal error: Uncaught exception 'Craft\\HttpException' with message '' in
/home/vagrant/htdocs/site/craft/app/controllers/TemplatesController.php:59\nStack
trace:\n#0 (): Craft\\TemplatesController->actionRender()\n#1
/home/vagrant/htdocs/site/craft/app/framework/web/actions/CAction.php(109):
ReflectionMethod->invokeArgs()\n#2
/home/vagrant/htdocs/site/craft/app/framework/web/actions/CInlineAction.php(47):
CAction->runWithParamsInternal()\n#3
/home/vagrant/htdocs/site/craft/app/framework/web/CController.php(308):
CInlineAction->runWithParams()\n#4
/home/vagrant/htdocs/site/craft/app/framework/web/CController.php(286):
CController->runAction()\n#5
/home/vagrant/htdocs/site/craft/app/framework/web/CController.php(265):
CController->runActionWithFilters()\n#6
/home/vagrant/htdocs/site/craft/app/framework/web/CWebApplication.php(284):
CController->run()\n#7
/home/vagrant/htdocs/site/craft/app/framework/web/CWebApplication.php(141):
CWebApplication->runController()\n#8
/home/vagrant/htdocs/site/craft/app/etc/web/WebApp.php(288):
CWebApplication->processRequest()\n#9
/home/vagrant/htdocs/site/craft/app/framework/base/CApplication.php(185):
Craft\\WebApp->processRequest()\n#10
/home/vagrant/htdocs/site/craft/app/index.php(62):
CApplication->run()\n#11
/home/vagrant/htdocs/site/public/index.php(19): include()\n#12 {main}

I have a _404.html template under templates/ and the errorTemplatePrefix set to _.

Turns out it was HHVM causing the issue. Switching back to 'normal' PHP made the problem disappear.


.getUrl() outputting {{ siteUrl }} in address I haven't used Craft in a while now and I have just revisited it, I'm trying to output an image URL from a global matrix field like so:

{% for block in globalName.matrixField %}

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

        {% set image = block.blockType1.first() %}

        link

    {% endif %}

{% endfor %}

But it keeps outputting as: {{ siteUrl }}/resources/images/my-image.jpg (instead of actually outputting the website URL).

Am I missing something?

If your putting the variable in the craft settings input, try wrapping it in single brackets like {siteUrl} instead of {{ siteUrl }}

That should do the trick


Set Search to query multiple attributes (e.g. title, body) Craft Pro 2.5.2761 (no plugins)

I've got a basic search form, and on my results template, the following:

{% set query = craft.request.getParam('q') %}

{% set articles = craft.entries({
section: 'article',
order: 'score',
search: {
  attribute: 'keywords',
  query: query,
  subLeft: true,
  subRight: true
}
}) %}

Which works as expected (I get results when the query term matches the keyword of an entry).

However, I want my search to encompass not just keywords, but also the  title and the body field.

[edit - deleted part of my post because it was misleading as to the real problem]

It doesn't look like it's possible to pass an array of attributes to the attribute parameter, the Craft docs explicitly state that it expects a string.

https://craftcms.com/docs/config-settings#defaultSearchTermOptions


How do I reference the settings of my plugin? In the main Plugin.php file of my plugin, I can retrieve the plugin's settings like this:

$this->getSettings()

How do I retrieve those same settings from elsewhere in the plugin?

I want to reference those setting from my Service.php file.


Selling tickets to repeating events with Commerce (and Solspace Calendar?) We need to build a ticketing system for venue tours, that happen every week within certain date ranges, and with an option to exclude specific dates from the availability list.

Looking at Solspace Calendar, it offers almost exactly the fields we need for this out of the box: (screenshot below)

But I can't figure out how to either:

(1) Recreate this setup as fields on a Commerce product .

(2) Create a relationship between a Solspace Calendar event and a Commerce product (that only allows for a certain number of products to be sold for each date in the calendar).

I think you will have to get your hands a bit dirty with this one.

The Calendar Events fieldtype will get you part of the way, but you still need some module code to pull this off.

A suggested approach is:

Create a product type with the Events fieldtype
Create some module code that creates/updates a product + variants for each date, where the inventory is set to n.
List the events as you would normally do, and pull in the products and its variants with the reverse relationship.

If the available number of tickets is always the same, you could have one field on the event where you enter the number.

If the amount of tickets vary by day, there is probably multiple approaches. Maybe a Matrix field that assumes position of block with quantity field === date in same position/with a date picker, maybe something else.

You can create a example module over at pluginfactory.io


Craft 3 multisite - are entries accessible between sites? In multi-site is it possible to access entries between sites in the templates.  Like a feed?   ie. entry "a" on site "A" shows up in an index on site "B", and links back to the entry on site A, not a duplicate of the entry on site "B"?

Yes it is. Just include the site id of the the site in your query

set siteId = 2
set entries = craft.entries.section('foo').site(siteId).all()

if you want to get the current entry for another site

set currentEntrySiteB = craft.entries.id(entry.id).site(2).one()

If you want to search for disabled entries (for example in CP templates) for other sites you can do

craft.entries.id(entry.id).site(2).enabledForSite(false).one()


Possible to change view of related entries field? Is it possible to change the display of the related entries field, to include extra info (hoping to add thumbnail, because otherwise these entries are damn hard to identify!)

I don't think they are quite the same as a standard table view and therefore hookable by defineAdditionalEntryTableAttributes
Or can you override the normal view of the field type?

Easy task: you can create your own relations field and use that instead.
Take a look at the default Entries field here is the php code for it click

All you have to do is changing the template that should be rendered so you'll end up with something like

class MyCustomRelationField extends BaseRelationField
{
    // Static
    // =========================================================================
    /**
     * @inheritdoc
     */
    public static function displayName(): string
    {
        return Craft::t('app', 'My awesome field');
    }
    /**
     * @inheritdoc
     */
    protected static function elementType(): string
    {
        return Entry::class;
    }
    /**
     * @inheritdoc
     */
    public static function defaultSelectionLabel(): string
    {
        return Craft::t('app', 'Add an entry');
    }

    /**
     * @var string Template to use for field rendering
     */
    protected $inputTemplate = 'path/to/your/custom/template';
}

the $inputTemplate is the template that gets rendered in the cp so you'll take the default one here as your base and change the parts you need

<div class="elements">
    {% for element in elements %}
        {% include "_elements/element" with {
            context: 'field',
            size: (viewMode == 'large' ? 'large' : 'small')
        } %}
    {% endfor %}
</div>

to something you like. Because the default content in this include is generated here. Take that as a reference what you have to change/include in your own template (or hook) together with your icon/thumbnail


How to check if a DateTime attribute is set? I have a optional dateFinished attribute in my Record:

protected function defineAttributes()
{
    return array(
        ...
        'dateFinished'  => AttributeType::DateTime,
        ...
    );
}

Some Records have it set to a DateTime other have it set to null (default).

To prevent Twig errors I tried using the is defined test:

{{ log.dateFinished is defined ? log.dateFinished|date('m.d.y - H:m'|t) : '-'}}

But this doesn't work, I'm getting the typical "Scope error". After taking a look at the dump() it looks that even a null value is getting defined:

  ["dateFinished"]=>
  object(Craft\DateTime)#2670 (3) {
    ["date"]=>
    string(19) "2014-07-15 17:48:25"
    ["timezone_type"]=>
    int(1)
    ["timezone"]=>
    string(6) "+00:00"
  }

  ....

  ["dateFinished"]=>
  array(2) {
    ["column"]=>
    string(8) "datetime"
    ["type"]=>
    string(8) "datetime"
  }

I tried to solve this by "Check(ing) if a variable is a date with Twig":

{{ log.dateFinished is defined and log.dateFinished.timestamp is defined ? log.dateFinished|date('m.d.y - H:m'|t) : '-'}}

But this doesn't make a difference, I'm still getting the "Scope error". Any ideas?

You shouldn't be returning a record instance to your templates directly. That can lead to all sorts of badness like templates being able to update the database themselves.

Have your plugin's service populate a Mailer_LogModel with just the attributes you want to expose to your template and return that.  Pretty sure after you do that, a simple:

{% if log.dateFinished %}

will work.


Disable Stripe email notifications from Commerce When a customer completes an order using Stripe they get an email notification from Stripe. I have configured notifications to be sent from Craft and would like them to only get those emails. After looking into this for a bit, it seems like I need to stop Commerce from passing the receipt_email to Stripe to stop this from happening?

https://craftcommerce.com/changelog#build1323

Commerce now provides Stripe with the customer’s email address to support Stripe’s receipt email feature.

https://support.stripe.com/questions/email-receipts

If you charge a customer that already has an email address attached to it, passing in a receipt_email with a charge will override the customer’s stored email address, and we’ll send the receipt to the email address specified in your charge request’s receipt_email regardless of your email settings.

You shouldn't need to adjust Craft Commerce at all. You can disable email receipts on the Stripe side in your account settings.

Account Settings > Emails

Uncheck "Email Customers for: Successful Payments"

As far as Stripe using the previous email address saved with the Customer, as far as I know OmniPay (which powers Commerce) doesn't create a Customer in Stripe, it only creates a Charge.


Multisort flag doesn't seem to work The multisort flag for arrays doesn't work the way I'm trying it. This is how I'm using it.

{% for conv in conversations|multisort(['postDate'],['SORT_DESC']) %}

This is the error I keep getting.

array_multisort(): Argument #2 is expected to be an array or a sort flag

Any ideas?

I think you should change ['SORT_DESC'] to [SORT_DESC]. See this tweet for an example. SORT_DESC is a PHP constant, not a string.


Not require password on user signup I have a form to sign up for a trial (offline product) and I feel like the most logical place to store that data is Users, but requiring a password on sign up will likely put people off.
How could I get a frontend form to create a user without requiring a password? One thought it a hidden field and then programmatically changing the password to something random immediately after the save-user action, but I'm not sure how to do that.
Very open to other ideas too.

What you want is the deferPublicRegistrationPassword config setting.

By default, Craft will require a 'password' field to be submitted on front-end, public user registrations. Setting this to true will no longer require it on the initial registration form.
If you have email verification enabled, new users will set their password once they've clicked on the verification link in the email. If you don't, the only way they can set their password is to go through your "forgot password" workflow.


Is it possible to create a Craft boilerplate out of a project.yaml file? I have setup a boilerplate for Craft sites with a homepage Single setup, plugins installed, common field types setup and a few other jobs I have to do every single time I start a new project.

I was wondering if this is something I can safely turn into a CraftCMS boilerplate?

In an ideal world it's something I'd keep in Git and when I start a new project in 3 months time or whatever it may be, I can copy this project.yaml into my new project and I'm an hour or so ahead of where I would be.

I know technically I probably could, but I'd like some advice on whether this is something I should or should not be doing.

Cheers

I have just setup a Craft 3 boilerplate and got it working great. So yeah... this does work.


Rich text editor Redactor adding additional paragraph p tags The rich text editor redactor is adding in additional p tags to rich text content. Is there a way to modify this so it accepts the unmodified HTML but still has the advantage of WYSIWYG editing?

Perhaps it is fixed in version 10.0.1 as I see Craft uses v9.2.6 of this editor. Will it be upgraded perhaps to test?

Update: This seems to be part of the config: http://imperavi.com/redactor/docs/settings/clean/#setting-replaceDivs

I believe we should be able to turn on/off some things. e.g. http://imperavi.com/redactor/docs/settings/clean/#setting-removeEmpty http://imperavi.com/redactor/docs/settings/clean/#setting-paragraphize

http://imperavi.com/redactor/docs/settings/clean/#setting-replaceDivs
http://imperavi.com/redactor/docs/settings/clean/#setting-removeEmpty http://imperavi.com/redactor/docs/settings/clean/#setting-paragraphize

Standard.json

{
    buttons: ['html','formatting','bold','italic','unorderedlist','orderedlist','link','image','video', 'table'],
    plugins: ['fullscreen'],
    toolbarFixedBox: true,
    paragraphize: false,
    replaceDivs: false
}

Edit: This bug also happens in the most recent version of Redactor as seen on their example page.


Contact form plugin only sending the content of the textarea? I'm working in a form with five fields, but I'm only receiving the content in the comments field; I'm not getting anything from the other four, please check my code
below.

{{ block.contactFormHeadline }}

    {% macro errorList(errors) %}
    {% if message is defined %}
        {% if errors %}
            {% for error in errors %}
                {{ error }}
            {% endfor %}
        {% endif %}
        {% endif %}
    {% endmacro %}
    {% from _self import errorList %}
    <form method="POST" action="">
        {{ getCsrfInput() }}
        <input type="hidden" name="action" value="contactForm/sendMessage">

            <input id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}" placeholder="Full Name">
            {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

            <input type="email" name="fromEmail" id="from-email" class="form-control" placeholder="Email" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
            {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

            <input type="text" name="message[Company]" id="company" class="form-control" placeholder="Company Name" value="">

            <input id="phone" type="text" name="message[Phone]" value="" Placeholder="Phone Number">

            <textarea rows="3" cols="30" id="message" name="message" placeholder="Comments">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
            {{ message is defined and message ? errorList(message.getErrors('message')) }}

        <input type="submit" class="Btn mini-form" value="Submit">

        <input type="text" name="sales" id="sales" class="hidden">
    </form>

When using multiple fields, you'll need to use message[body] for the main message field's name attribute. Passing just message as the name for your main text field will clobber your other custom fields that precede it, as will custom fields, if they appear after it.

I think the only fix you'll need in this case is to the “Comments” textarea:

<textarea name="message[body]">Your initial text</textarea>


Craft 3 multisite - best practice to minimize confusion and database size? Usage Scenario
One organization with branches in several cities. Most of the events in one city are only advertised to that one city, but some of the larger events in any given city will be advertised for the other cities. While the different branches are similar, some have many offerings (categories), and some just a few.

What we used to do
In Craft 2, we had one single URL shared by all the cities, one large set of categories which mapped to the drop-down menus, and entries as events that fall into the categories.

What we want to do
Individual URLs for the different cities, focusing on the offerings in that city, but a few from other cities.

Dilemma / Question
Since we don't need multiple versions of the events entries, it seems that we need very little of the multi-site functionality. Just needing to call different templates with different navigation and css, depending on the request URL.
In
Settings > Sections > Events --> Site Settings
is it necessary to

switch on all the light switches, and
check Propagate entries across all enabled sites?

It seems this might triple the size of the database.

Thank you very much, Robin and Clive.

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

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

Folder Structure

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

Main Page Template

Now starts with:

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

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

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

Config File

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

<?php

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

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

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


Havin trouble with registerCpRoutes I'm having trouble registering a CP route. What I have is a "working" SiteAdministrator_UserController.php (other form save actions already work through this controller, so its functional). Inside the controller I have a function :

public function actionCurrent()
{
    die ('Works!');
}

In my Plugin I have the following:

public function registerCpRoutes()
{
    return array(
        'siteadministator/currentusers' => array('action' => 'siteAdministrator/user/current')
    );
}

trying the uri http://cms.craft.dev/admin/siteadministrator/currentusers

Craft says its a  404.

What am I doing wrong and/or is there a way to debug this?

Thanks in advance

Based on your code excerpts, things look good.  I've encountered issues with spelling and caps  when referencing controllers and templates within my controllers...so pay close attention to them.

I would suggest referencing the 'Cocktail Recipes' sample plugin: https://github.com/seandelaney/cocktailrecipes (Craft 2.x) as it contains an example of what you're trying to do.

EDIT: Updated link to Craft 2.x version as per comment below.


Search question: dot (period) and partials We have a job inventory where the jobs are being saved as entries.
When searching against jobs by keyword we search against two fields: the title and a job description field.

However we are experiencing some unusual results when using the search parameter to search against the term ".net". For example:

{% set results = craft.entries()
.search('title:".net" OR description:".net"')
.all() %}

Is there a way to use search() to specifically only return entries where the title or description contains .net as at present it is returning partial matches (eg jobs where the title or description features 'networking').

The description field is a redactor/rich text field. Would this affect it?

I don't think it will be possible using the native Craft search engine as part of the search keyword normalization process involves removing all punctuation from the keywords: https://github.com/craftcms/cms/blob/develop/src/helpers/Search.php#L62

It might be possible on front-end searching using something like Algolia, though:
 https://plugins.craftcms.com/algolia


Image entry in a category template I'm running into an issue here, hopefully someone can shed some light.
I'm in a news category template,

{% for entry in craft.entries.section('news').relatedTo(category) %}
  {% for image in news.newsimage %}

  {% endfor %}
  {{ entry.title }}
{% endfor %}

My entry.title, date, etc. all output correctly, I can't figure out how to output the image asset associated with newsimage.

It looks like you are trying to access a news variable that probably doesn't exist.

{% for entry in craft.entries.section('news').relatedTo(category) %}

    {# Your image field will be found on your `entry` variable (not a `news` variable) #}
    {% for image in entry.newsimage %}

        {# One you are looping through your image field,
           you can access the image properties via the `image`
           variable you defined in your loop #}

    {% endfor %}

{% endfor %}

If you only have a single news image, you can grab that image directly using the first() method, instead of looping through your image field:

{% for entry in craft.entries.section('news').relatedTo(category) %}

    {% set image = entry.newsimage.first() %}

    {% if image %}

    {% endif %}

{% endfor %}


Add variable to twig context I have created an event to transform the entry data before rendering the page so that it's ready to render components in the template.

Event::on(View::class, View::EVENT_BEGIN_PAGE, [$this, 'transformSingleEntry']);

Here's an example of what the function looks like. I've cut out most of the code, but essentially at the end of the function I have a $transformed_entry variable that I want to add to the twig context.

public function transformSingleEntry() {
  $entry = Craft::$app->urlManager->getMatchedElement();
  // ... do stuff
  $transformed_entry = [
    'title' => 'test',
    'url' => 'test',
  ];
  // Add $transformed_entry to the page context
}

I cannot find anything in the Craft documentation to help here. Any ideas?

So the way Twig works is that it populates a Twig Environment with a context of global variables.

Then any time a template includes another template, the context is passed down to it.

So if you want something to be globally available you have to insert it into the Twig environment before Twig is used, for it to be truly globally available.

You can do that via a Twig extension that implements GlobalsInterface like this:

https://github.com/nystudio107/craft-seomatic/blob/v3/src/twigextensions/SeomaticTwigExtension.php#L36

So you might need to revise how you're doing it actually, and instead of using View::EVENT_BEGIN_PAGE you can just do whatever you need to do inside your Twig extension.


Get UI elements of entry in front end Is is possible to get UI-elements of Craft 3.5 in the front end? Specifically wanting to get hold of the headers I use to separate fields of products.
This is my current code:
{% set layout = product.getFieldLayout() %}
{% for tab in layout.tabs %}
    {% if tab.name == "Detaljer" %}
        {% for field in tab.getFields %}
            {% if not product.getFieldValue(field.handle) is empty %}
                {% switch field.className() %}

                    {# Can I get UI header out of the tab.getFields method? #}
                    {% case "craft\\fields\\UI-header-element" %}
                        {# Do stuff #}
                    {% case "craft\\fields\\PlainText" %}

                            {{ field.name|t }}
                            {{ product.getFieldValue(field.handle )}}

                    {% case "craft\\fields\\Categories" %}

                            {{ field.name|t }}

                                {% include 'commerce/_blocks/categoryList' with { categories: product.getFieldValue(field.handle) } %}

                    {% case "craft\\fields\\Dropdown" %}

                            {{ field.name|t }}
                            {{ product.getFieldValue(field.handle).label}}

                    {% case "craft\\fields\\Lightswitch" %}

                            {{ field.name|t }}
                            {% include 'commerce/_blocks/fieldLightswitch' with { data: product.getFieldValue(field.handle) } %}

                    {% case "craft\\fields\\Number" %}

                            {{ field.name|t }}
                            {{ product.getFieldValue(field.handle) }} {{ field.suffix }}

                    {% default %}

                            {{ field.name|t }}
                            {{ field.className() }}

                        {# todo: other non implemented fields #}
                {% endswitch %}
            {% endif %}
        {% endfor %}
    {% endif %}
{% endfor %}

Use the Kint plugin to spit out the current tab to the JS debug console:

{% for tab in layout.tabs %}
    {% if tab.name == "Detaljer" %}

        {{ j(tab) }}

        {% for field in tab.getFields %}

You will see that the structure of the tab-object actually contains the UI-elements as well:

Instead of looping tab.getFields, loop tab.elements:

{% set layout = product.getFieldLayout() %}
{% for tab in layout.tabs %}
    {% if tab.name == "Detaljer" %}

        {% for element in tab.elements %}
            {% switch element.className() %}

            {% case "craft\\fieldlayoutelements\\Heading" %}

{{ element.heading }}

            {% case "craft\\fieldlayoutelements\\CustomField" %}

                {% set field = element.getField() %}
                {% if not product.getFieldValue(field.handle) is empty %}

                    {% switch field.className() %}
                        {% case "craft\\fields\\PlainText" %}

                                {{ field.name|t }}
                                {{ product.getFieldValue(field.handle )}}

                        {% case "craft\\fields\\Categories" %}

                                {{ field.name|t }}

                                    {% include 'commerce/_blocks/categoryList' with { categories: product.getFieldValue(field.handle) } %}

                        {% case "craft\\fields\\Dropdown" %}

                                {{ field.name|t }}
                                {{ product.getFieldValue(field.handle).label}}

                        {% case "craft\\fields\\Lightswitch" %}

                                {{ field.name|t }}
                                {% include 'commerce/_blocks/fieldLightswitch' with { data: product.getFieldValue(field.handle) } %}

                        {% case "craft\\fields\\Number" %}

                                {{ field.name|t }}
                                {{ product.getFieldValue(field.handle) }} {{ field.suffix }}

                        {% default %}

                                {{ field.name|t }}
                                {{ field.className() }}

                            {# todo: other non implemented fields #}
                    {% endswitch %}
                {% endif %}

            {% endswitch %}
        {% endfor %}

    {% endif %}
{% endfor %}


Missing CSS/JS in the Control Panel The issue I am experiencing is very similar to the one described here: link.  The fix described there does not work.

Here is what happens when I request a resource from that page directly using curl:

$ curl -v 'http://localhost/admin/resources/js/craft.js?d=1474612391'
*   Trying ::1...
* Connected to localhost (::1) port 80 (#0)
> GET /admin/resources/js/craft.js?d=1474612391 HTTP/1.1
> Host: localhost
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Fri, 23 Sep 2016 07:07:59 GMT
< Content-Type: application/javascript; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
< X-Powered-By: PHP/7.0.8-0ubuntu0.16.04.2
< Content-Disposition: attachment; filename="craft.js"
< X-Sendfile: [CENSORED]/craft/app/resources/js/compressed/craft.js
<
* Connection #0 to host localhost left intact

Here is some version info:

Linux: 16.04 LTS (Xenial Xerus)
PHP: 7.0.8-0ubuntu0.16.04.2
nginx: 1.10.0

Here is a link to my nginx config (approximately).

Here is a screenshot of what the page looks like:

The setting useXSendFile was set to true.  I changed this setting to false and everything works now.  Looks like this guide could help to get things working when this setting is set to true.


How to filter entries by month and year? I'm taking the month and year from parameters in the url like this...

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

The url would look like this: ?month=September&Year=2014

... and want to return entries from a specific section where the postDate month and year match those parameters.

Be very grateful for any pointers.

Thanks
Lee

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) %}


Adding Navigation Menu I am new to Craft..
I created the Entries but didn't understood how to setup them to display as a menu. Seen the documentation, templating references.. But not get any idea about how to add navigation menu for the entries type. I am using the default template.

Thanks

I'm assuming that you are trying to create an 'index' page for your channel entries. There are a few ways to do this depending on the requirements of your site, but a very simple way is to create a 'single'. In the template for the single you can request the channel entries, and loop through the response to generate your index navigation.

{% set entries = craft.entries.section('myChannelSectionHandle').limit(null) %}

    {% for entry in entries %}

{{entry.title}}

    {% endfor %}

If you want the uri's to match up nicely then you can set the 'uri' of the single to be mySectionName and the 'uri' of the channel entries to be mySectionName/{slug} in the section settings — such that to the end user, it will simply feel like they are all part of the same section.

For some slightly more complex options, see these answers, here and here.


Craft internal error exposing sensitive data I have a craft installation and recently my server had issues and on the page rendering mysql and other errors were shown.
Of course this creates security implications. Is there a way to restrict these errors? My guess it that i just need to change the devMode to false in general.php. Is there anything else i need to do? I am asking because I cannot really reproduce the error anymore.

Your guess is correct... as the docs say, you should never have devMode enabled in production environments specifically for reasons like this (as well as many others).

If you find errors that are leaking sensitive server info with devMode disabled, then that is a bug and should be reported to support@buildwithcraft.com.


Get a twig | replace to output html rather than the text I've got a craft field where I have an such as:

Learn more about this great %Job Title% job.

I'm then using Twig Replace to insert the actual entry.jobTitle into the %Job Title% space.

This works great.

But visually, I'd like to highlight the job entry. So I'm wrapping it in a span tag.

Here is an example of the output I want:

Fantastic opportunity for a Head Chef

So at the moment I've got it looking like this, pulling in the jobStatement (The line with %Job Title% somewhere in it):

{{ jobs.jobStatement|replace({'%Job Title%': "" ~ jobs.jobTitle ~ "" }) }}

Alas, when the template is rendered, it is rendering the entries as text. How can I insert the HTML span tags around the Job Title area?

Any help much appreciated,

Stephen

Try using twig's raw filter.

{{ jobs.jobStatement|replace({'%Job Title%': "" ~ jobs.jobTitle ~ "" })|raw }}


Animated GIFs not animating - sometimes I've had trouble getting animated GIFs to transform properly on my Craft site.

I've installed Imagick on my server, and set $imageDriver to imagick explicitly. This seems to have allowed some GIFs to transform but not others. I've tried GIFs I've made myself in Photoshop, and GIFs found online, with completely mixed results. No rhyme or reason to it at all as far as I can tell.

Examples:

A GIF that resized correctly: http://craft.kingzog.com/img/_thumbnail/OH-TEE.gif

And one that didn't: http://craft.kingzog.com/img/_thumbnail/tennis_gif.gif

(I'm not allowed to post too many links, but of course you can remove /_thumbnail from the URLs to view the original, still-animated GIFs).

I'm stumped. Anyone have any knowledge about file formatting, config or anything else that might help?

I'd make sure you're running the latest stable version of both the Imagick library as well as the Imagick PHP module.

It's possible that older version had bugs in them which might explain what you're seeing.


How do I validate an array model attribute against a set of possible values? I have a need to set a property on a plugin Model that is an array of one or more valid values.

I can see that I can use AttributeType::Enum and record and define a set of values but if I'm not mistaken, that enables me to validate a single value against that set of values:

class MyModel extends BaseModel
{
    protected function defineAttributes()
    {
        return [
            'mySetting' => [ AttributeType::Enum, 'values' => 'validOption1,validOption2,validOption3' ]
        ];
     }
}

What I want to do is enable mySetting to be an array that would be valid when set as an array containing any combination of the defined options:

MyModel::populateModel(['mySetting' => [
    'validOption1'
]]); // is valid

MyModel::populateModel(['mySetting' => [
    'validOption1',
    'validOption3'
]]); // is valid

MyModel::populateModel(['mySetting' => [
    'invalidOption',
    'validOption3'
]]); // is *not* valid

MyModel::populateModel(['mySetting' => []); // is *not* valid

Etc.

Found an answer in the form of a customer validator class on the model:

https://experiencehq.net/blog/the-definitive-guide-to-validation-in-craft-part-5-custom-validators#newsletter

So something like this:

    public function validateMySetting($attribute)
    {
        $values = (is_array($this->$attribute)) ? $this->$attribute : [ $this->$attribute ];

        $validValues = ['validOption1', 'validOption2', 'validOption3'];

        foreach($values as $value)
        {
            if ( ! in_array($value, $validValues))
            {
                $this->addError($attribute, "{$value} is not a valid setting");
            }
        }
    }

And then to call it, override the parent class' rules method:

public function rules ()
{
    return array_merge(parent::rules(), [
        'someAttributeName', 'validateMySetting'
    ];
}


How do I show a Garnish hud in the CP I've written a custom plugin and added a custom button to the right panel of an entry page

Now I'm trying to show a Garnish Hud if I click the red button (like the one when you re-index assets)

The content of the hud would be two radio buttons and a button which triggers a controller function. It should also show the progress bar and the success icon after the button was clicked (so basically the same behaviour as the assets indexing thing)

I put this code in my plugin specific js file

var hud = new Garnish.HUD($('#generate-pdf'), 'test', {
        orientations: ['top', 'bottom', 'right', 'left'],
        hudClass: 'hud toolhud',
    });

But this shows the hud after page load and the trigger (that's the button with the id #generate-pdf) doesn't work at all.

Can anyone point me in the right direction?

I finally figured this out. I was actually close.

Here's the HTML that I use

        <form>

            {% import "_includes/forms" as forms %}

            {{ forms.lightswitchField({
                 class: 'docraptorize-prod-lightswitch',
                 name: 'prod-pdf',
                 on: true
            }) }}

            <input type="submit" class="btn submit" value="{{ "Go!"|t }}">
        </form>

and this is the corresponding JS

var $btn = $('#generate-pdf-hud'),
$form = $('#generate-pdf-form');

$btn.on('click',function(){
    var hud = new Garnish.HUD($btn, $form, {
        orientations: ['top', 'bottom', 'right', 'left']
    });
   return false;
});


Craft 3 validate new password in change password I'm trying to validate user's new password and confirm password in my custom plugin init().

Event::on(User::class, User::EVENT_BEFORE_SAVE, function(Event $event) {
    $formData = $_POST;
    $newPassword =  $formData['newPassword'];
    $confirmPassword =  $formData['confirmPassword'];

    if ($newPassword != $confirmPassword){
        Craft::$app->session->setError('Confirm password does not match new password');
    }
});

On the template:

{% set error = craft.app.session.getFlash('error') %}
{% if error|length > 0 %}
    {{error}}
{% endif %}

The problem with this is, it displays the message "Confirm password does not match new password" on frontend but the password gets changed into newPassword value. Is there a way to stop processing any further after returning error?

I believe what you're looking for is this:

if ($newPassword != $confirmPassword){
    Craft::$app->session->setError('Confirm password does not match new password');
    $event->isValid = false;
}

Setting isValid to false will stop further processing of that element (the user in this case).


Password protect a single page Is it possible to password protect a single page in Craft? Wordpress has this functionality built in. I would love to do it in Craft as well.

Yes. Use the RequireLogin tag at the top of a page:

{% requireLogin %}

  This tag will ensure that the user is logged in. If they aren’t, they will be redirected to the Login page, and returned to the original page after successfully logging in.

(make sure you are logged out before you test this!)


Craft hanging when updating an Entry When saving an entry, Craft will sit endlessly waiting for the page to load. I've seen this behaviour intermittently in the past - but not for months. It's doing it again now though.

Seems to me to be related to PHP or Apache in some way. I can restart Apache and Craft will then work fine on the first save, but edit and save again and it'll sit spinning forever. The 'hung' save does actually work, you can see changes reflected by checking the front-end in a different browser. However, while the save 'redirect' is hung, you can't browse any of the website, back-end or front, from the browser you were using to edit the entry.

This is only happening on our staging server, not our local machines, though both run the same website and same database.

Staging is Debian Jessie, on PHP 5.6.17-0+deb8u1 and Apache/2.4.10 (Debian). Our local machines are Macs running PHP 5.5.31 and Apache/2.4.16 (Unix).

I haven't found a cause or solution, and there doesn't seem to be anything of use in the craft.log either (though I'm not sure what to look for).

(This post is a follow-on from Craft hangs when updating entry, which never seemed to be answered definitively).

If you have gzip compression enabled (either at the PHP or Apache level), try disabling that and see if helps.  Obviously that's not a proper long-term solution, but if you leave it on and set the runTasksAutomatically config setting to false and setup a cron job as described in the docs, you can see if that helps as well.


How does template caching work? The {% cache %} tag is quite powerful, and can be used to greatly increase the performance of templates.

But ultimately the whole thing is still pretty mysterious. I can see three tables in the database which seem to relate to caching:

craft_templatecachecriteria
craft_templatecacheelements
craft_templatecaches

I'm still trying to grasp how it all ties together... If I can get a better understanding of how it all works in the "big picture", it will help me to make better decisions as to when & where to use caching.

I know the answer is probably complex, but I'd still love to know... How does caching work?

Cache Creation

The primary files to look at are Cache_Node.php in app/etc/templating/twigextensions and TemplateCacheService.php in app/services.

The Cache Node does some basic checking before deciding what content to output, and what to do with that content. It builds a cache key (either automatically, or uses the one defined), and then looks for an existing cached template. If a cache is found for that key, it is outputted and the template process moves on. If no cache is found for that key, the caching process begins.

If the cache node is not in a situation where caching is being ignored (either Live Preview or a config setting), then it starts caching with the Template Cache Service. That service has a method called startTemplateCache. This method creates an array of element queries and element IDs that are stored under the cache key.

The template within the cache node is then compiled with Twig's subcompile method. While this is happening, the element queries and resulting element IDs are stored in the previously created arrays. The compiled result is then placed in a variable and then given (along with the other cache parameters) to the endTemplateCache method.

The endTemplateCache method stores the cache in the templatecaches table. It also loops over the element criteria and element id arrays to tag the caches using the templatecachecriteria and templatecacheelements respectively.

Finally, the cache tag outputs the body (cached or otherwise).

Cache Clearing

When you make changes to elements in the control panel, the Template Cache Service does one or two things to clear caches:

If the element was modified or deleted, it will check the templatecacheelements table to immediately clear any caches that it knows the element was involved in.
If the element was added or modified, it queues up a new “Delete Stale Template Caches” task, which cycles through the templatecachecriteria table to see if there are any cached element queries which (if not cached) would have started showing the just-saved element. If the query returns the element, its corresponding cache will be deleted.


Use Entries fieldtype functionality in plugin populated by REST api data Is it possible to use the Entries FieldType widget in my plugin and populate the modal with data from a third party REST API?

You are speaking of the Element Selector Modal. It is javascript and available to use by third-party devs, but the code is specific to Craft Elements (Entries, Assets, Users, etc.). I don't think you'll get it to work with information polled from a third-party API.

There's a post about it in the Craft Dev Google+ group (invite only), but I'm not sure if the info exists anywhere else.


$allowAnonymous = true - not working I want to be able to access a plugin page without having to login (for a cron job).

I have added this to the plugin's controller:

protected $allowAnonymous = true;

However, this url still requires login:

/admin/[plugin]

(If I login to admin, the above url works.)

If I try the url without /admin:

/[plugin]

The page doesn't work at all (logged in or not):

  Page Not Found
  The requested URL was not found on this server.

How do I make it so I can access my plugin page without login?

BTW, I also have this in the [plugin]Plugin.php file:

public function registerCpRoutes()
{
  return array(
    '[plugin]' => array('action' => '[Plugin]/[Action]'),
  );
}

It sounds like you just want a cron job to trigger an action on your plugin.

You don't need to register any Control Panel routes for that, so you can remove your registerCpRoutes method.

If your plugin only has one controller, the URL your cron job would want to target would be:

yoursite.com/actions/pluginHandle/pluginAction

You can read more about it in the plugin controller docs.


Lookup row in matrix field by "Name" column? If I have a matrix field with 2 fields "Name" and "Entry" is it possible to lookup the first row in that matrix field which has a specific "Name"?

Context: Twig template.

According to this answer the only ways to filter matrix blocks are by type, or by position. So you need to use the if condition on the twig for tag.

{% for m in entry.myMatrix if m.theName == nameImLookingFor %}
  {% if loop.index == 1 %}
    got the first one, it is {{m.theName}}
  {% endif %}
{% endfor %}

If you don't want to loop over all of the blocks, you can also install the mnbreakandcontinue plugin and break out of the loop after the first match:

{% for m in entry.myMatrix if m.theName == nameImLookingFor %}
  got the first one, it is {{m.theName}}
  {% break %}
{% endfor %}


How do I save a front-end form as a specific Entry Type? I have a few different forms on my site for different kinds of enquiries, each represented by an Entry Type with different fields in a single Enquiries channel. How can I get the entries/saveEntry form to save as a specific entry type?

My existing form:

<input type="hidden" name="action" value="guestEntries/saveEntry">
<input type="hidden" name="redirect" value="/hire-us/get-a-quote/success">
<input type="hidden" name="sectionId" value="61">

I have two entry types in that channel, ID 111 and 112. When I add the line:

<input type="hidden" name="typeId" value="111">

then submit the form, I get an error message saying "Unable to find the template 'hire-us/enquiryPlanningEvent'". It appears that Craft is looking for a template named after the entry type I'm trying to save, but obviously there isn't one.
What's the solution to this?

This has been solved via a support ticket, which I'm posting here for others etc.

  The first time you load the template, the URI is mapping to your "Get
  A Quote" entry, which gets assigned to the entry variable when your
  template is loaded.

  When you submit the form, the same URL is requested again, once again
  matching your "Get A Quote" entry, but this time the
  guestEntries/saveEntry controller action is summoned. When there's a
  validation error, Guest Entries will pass the new entry back to the
  template as an entry variable, overriding the "Get A Quote" entry that
  the URL matched. So, then the template gets routed to
  hire-us/index.html like it normally did, but this time entry.type is
  enquiryWeddingDance instead of getAQuote, since it's a different entry
  altogether. The template tries to include
  hire-us/enquiryWeddingDance.html, but that doesn't exist, so you get
  the error.

  To fix this, I've just released an update to the Guest Entries plugin,
  which adds a new entryVariable config setting. You can use that to
  customize the variable name that Guest Entries will set the invalid
  entry to (i.e. 'guestEntry' or 'invalidEntry'), so it doesn't conflict
  with the entry variable that the request is getting routed to.

After setting the Guest Entries variable as suggested in the documentation, it's now working as expected without conflicts. Thanks Brandon!

Usage:

{% if guestEntry is defined %}{{ errorList(guestEntry.getErrors('variableName')) }}{% endif %}


Automatically link to entries in rich text field Has anyone implemented auto linking of words within a redactor field? For example, a rich text field would contain this:

  A small boat surrounds a large island

In a channel there are entries titled boat and island. I would like to automatically link to these without the editor having to manually link them.

Not sure how approach this so any hints to get me on my way are most appreciated.

How about just using the replace filter?

{% set text = "A small boat surrounds a large island" %}

{% set linkedText = text|replace({'boat':'boat'}) %}

{{ linkedText|raw }}

That works.

In theory there should be a way to do it with parseRefs too, but my initial test isn't working yet:

{% set refText = text|replace({'boat':'boat'}) %}

{% set parsedText = refText|parseRefs %}

{{ parsedText|raw }}

...which leaves an unparsed ref tag so far.  I'm just heading out of the office but maybe a simple replace as above is enough to get you started?


Getting properties out from the Craft text object I got this kind of object.

Craft\RichTextData Object
(
    [_pages:Craft\RichTextData:private] =>
    [_rawContent:Craft\RichTextData:private] =>
    Standard Rate:  Cancellation policy is 24 hours prior to 11.00am
        on day of arrival.

    [content:protected] =>
    Standard Rate:  Cancellation policy is 24 hours prior to 11.00am
        on day of arrival.

    [charset:protected] => UTF-8
 )

Can someone help me to get the text out from this ?

This Object has a __toString function that executes return $this->content;.
If you are in a template just do

{{ object }}

You can call the function getParsedContent as well

{{ object.getParsedContent() }}

In PHP

$text = $object->getParsedContent();


How to return data to an ajax succes callback I want to call an action via an ajax call with the following code:

$.ajax({
    url: Craft.getActionUrl(_this.options.updateRestockAction),
    method: 'POST',
    headers: headers,
    data: data,
    success: function(data) {
        console.log(data);
    },
    error: function(jqXHR, textStatus) {
        console.log('error');
    },
    complete: function(jqXHR, textStatus) {
        console.log('complete');
    }
});

My action is being called successfully. However, I can't find out how to return data to the success callback. Any idea how to do this? I'm using Craft 3.

Thanks

As Robin mentions, your controller needs to return an object of type Response, and in your case you probably want to return it with the format set to json. There's a helper method in Craft's Controller class, asJson, which is handy for this. Example:

public function actionMyControllerAction()
{
    $result = ['my' => 'data'];
    return $this->asJson($result);
}

This should give you back an object for data with a key of my with value data.


Filtering category objects in a template? So I have a Commerce product template page that grabs products something like this (segment 3 is the category slug):

{% set category = craft.categories.slug(craft.request.getSegment(3)).first() %}

{% set product = craft.commerce.products({
    relatedTo: category,
    status: 'live',
}).first() %}

However, I need this page to 404 if the category slug isn't in a collection of categories that are chosen in a global field:

{% for category in myGlobal.liveCategories %}
    These categories, like this one {{ category.title }}, are the only categories that are allowed right now
{% endfor %}

So I want to filter

{% set category = craft.categories.slug(craft.request.getSegment(3)).first() %}

against my global category field:

myGlobal.liveCategories

so that only the category that gets passed to my product loop is a valid category in the global set. Here is what I'm trying to accomplish, but this code block doesn't work:

{% set category = craft.categories.slug(craft.request.getSegment(3)).first() %}

{% if category not in myGlobal.liveCategories %}
    {% redirect 404 %}
{% endif %}

I assume I have to do some twig filtering, or create arrays and combine, ...or something.

You can do

{% set ids = myGlobal.liveCategories.ids() %}
{% set category = craft.categories.slug(craft.request.getSegment(3)).id(ids).first() %}
{% if category %}
    The category is valid
{% else %}
    No slug found, or the category is not in the list
{% endif %}

Explanation: you grab all the ids from your allowed categories and search for them in your query. If a category is found it is one of the allowed categories. If not the category is another one or the there is no element with a matching slug.


What's the best way to increment a number of a class or id? I have the following code which works fine. I'm just wondering if there is a more simple way of incrementing the id number?

{% set counter = '1' %}
{% for block in entry.news %}
  {% if block.type == "bodyBlock" %}
    {{ block.body }}
  {% elseif block.type == "codeBlock" %}
  {% set counter = counter + 1%}
    <div id="accordion{{ counter }}">
    ...
    </div>
  {% endif %}
{% endfor %}

By using the default filter you can get away with a single line of Twig to set and increment the counter:

{% for block in entry.news %}
    {% if block.type == "bodyBlock" %}
        {{ block.body }}
    {% elseif block.type == "codeBlock" %}
        {% set counter = ( counter | default(0) ) + 1 %}

            ...

    {% endif %}
{% endfor %}

Also, I'm guessing you need the accordion elements to be chronologically numbered, but if you don't, you can use the index property of the loop variable, which is available inside the for loop:

{% for block in entry.news %}
    {% if block.type == "bodyBlock" %}
        {{ block.body }}
    {% elseif block.type == "codeBlock" %}

            ...

    {% endif %}
{% endfor %}


Is it possible to have secure (private) assets? For a member only area I would like to secure (private) assets:

The files should not be accessible when not logged in
The file download URL should be randomly generated and should expire after some time OR the files can be placed above the web root

There is for example Link Vault for ExpressionEngine which is able to achieve that.

I ran into this requirement today and initially assumed a plugin would be required, but then I spotted that the native Assets action menu already included a Download File option and it was working just fine with files that weren’t publicly accessible. Maybe we could use that rather than reinventing the wheel?

If you check DownloadFileElementAction.php you can see the markup and JS that’s used for this button in the control panel. It generates a simple <form> tag that POSTs to assets/downloadAsset. With a tiny bit of tweaking that can be converted to a code suitable for use in a frontend template:

<form method="post" target="_blank" action="">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="assets/downloadAsset" />
    <input type="hidden" name="assetId" value="123" />
    <input type="submit" value="Submit" />
</form>

This works a treat and includes all native permissions checks as you’d expect. So long as the requesting user has the viewAssetSource permission for the Asset Source the download will work. If the requesting user is logged out then they are automatically redirected to your loginPath.

The only snag I’ve noticed is that Craft does return a JSON formatted error string if your user doesn’t have permission to view the asset. In my case this doesn’t matter, as all authenticated users will have permission to view the files - we’re just trying to prevent guests from seeing them.

Since this approach requires POSTs it’s a bit limiting (secured img tags are a non-starter), but for typical download button use cases it looks fine to me and avoids the need for third party plugins.

(This is a Craft 2 build, I haven’t tested this with Craft 3)


Set Password on Test User Account in Localhost I'm trying to set the password for a 'test' user account on my localhost test site.  I don't have an email server to send the reset emails, so I've been using the copy URL method.
When I do go to the URL and change the password, I get a 'Page Not Found' page.  I went ahead and checked to see if the password was in fact changed, but upon successive login tests, they failed.
I was wondering what might be causing the 'Page Not Found' error?  Is there a way to set the password through a plugin, etc?

Thanks

If you have access to the database you can change the user's password to: $2y$13$FfVKvo1W1N5Gsba3c19r8uz.x9R5NRQgRu8jmXvOjVCStg1sKGcoW which is 'secret' when un-hashed.

Source: https://twitter.com/nystudio107/status/1063135843441954816


Showing related entries field I have a section called Services. I have another section called Case Studies.

For each Case Study I want to show which service is being used so I add an entry field and choose the right service. On my case study I can see that the service is showing as it should.

On the Service page I want to see which case studies are being associated with the Service.

So your Case Study has a field called services which is an entry relation. You show the services on that Case Study page using

// entry is the current Case Study
{% set related_services = craft.entries.section( 'services' ).relatedTo( entry ) %}

To show all Case Studies that are related to a Service you can use the same entries query.

// entry is the current Service
{% set related_case_studies = craft.entries.section( 'caseStudies' ).relatedTo( entry ) %}


Programmatically create new entry with saveElement I am currently trying to save a new entry with craft()->elements->saveElement(), as I want to avoid triggering the onBeforeSave and onAfterSave events.

When I run my script, it returns a successful entry id, but there is no entry in the admin.

Here is my code:

$entry = new EntryModel();
$entry->sectionId = $sectionId;
$entry->typeId = $entryTypeId;
$entry->enabled = true;
$entry->authorId = 1;

$success = craft()->elements->saveElement($entry, false);

if ($success) {
    echo $entry->id;
}

In Craft's v3 API documentation they give an example:

https://docs.craftcms.com/api/v3/craft-services-elements.html#method-saveelement

$entry = new Entry();
$entry->sectionId = 10;
$entry->typeId = 1;
$entry->authorId = 5;
$entry->enabled = true;
$entry->title = "Hello World!";
$entry->setFieldValues([
    'body' => "
I can’t believe I literally just called this “Hello World!”.
",
]);
$success = Craft::$app->elements->saveElement($entry);
if (!$success) {
    Craft::error('Couldn’t save the entry "'.$entry->title.'"', __METHOD__);
}


Sending an e-mail to current user in FeedMe hook I have made a custom module that allows a user to upload a CSV and import it using a FeedMe feed. This all works fine, however I want to send an e-mail to the user when the import has completed.

I have this so far, but realised it doesn't work because the event doesn't have access to the user session:

Event::on(Process::class, Process::EVENT_AFTER_PROCESS_FEED, function(FeedProcessEvent $event) {
    $email = Craft::$app->getUser()->getIdentity()->email;
    if ($event->feed->id === getenv('USER_FEED_ID')) {
        $message = new Message();
        $message->setTo($email);
        $message->setSubject("Import complete");
        $message->setHtmlBody('Data has been imported successfully');
        $message->send();
    }
});

I've been scratching my furry head but can't think of a solution, is there any way to do this?

As long as you have control of the CSV on upload, you could change its name to filename_test@test.test.csv (or some other properly escaped filename with the current user's email address in it). Then get the filename from the feed (must be in there somewhere) and extract the email address.

Bit of a workaround, but if it works, it works.


How to add assets field to control panel plugin template So, a date field can be added to a plugin template within the control panel using:

{% from "_includes/forms" import date %}
{{ date({
        id: 'fields-invoiceDate',
        name: 'fields[invoiceDate]'
}) }}

But how do you go about adding an assets field a similar way?

Something like this...

{{ forms.elementSelect({
    id: 'invoicePdf',
    name: 'fields[invoicePdf]',
    elementType: craft.elements.getElementType("Asset"),
    elements: invoice.invoicePdf | default,
    criteria: {"kind":[],"localeEnabled":null,"locale":"en_gb"},
    jsClass: 'Craft.AssetSelectInput',
    addButtonLabel: 'Upload invoice',
    limit: 1,
    sources: ['folder:1']
}) }}


composer.json file not updating when plugins are updated My composer.json file doesn't update to the latest plugin versions when I update my plugins via the Craft CP or command line.

If you have a caret icon infront of your version number, for example

"craftcms/cms": "^3.0.0",

These version numbers in composer.json will not change when you update.

The caret icon tells Composer it has free reign to update this package, but not to the next major version number. ^3.0.0 can update to 3.1.0, 3.2.0, 3.2.1 etc, but won't update to 4.0.0. As such, it does not need to write to composer.json because the caret icon is already giving it the instructions it needs.

You can read more about it in the Composer documentation.

Running composer update will (if there are updates to perform) write to composer.lock instead. If you are using version control, you can run a git diff to see what changes have been made to your lock file immediately after running an update.


Change order within grouped archive I have an archive of exhibitions with entries grouped by year. The order of the groups should be descending, the order of the entries within the group should be ascending.

For example: The order of the years should be 2018, 2017, 2016, …
The entries within the group 2018 should start with the first exhibition of the year and end with the last one.

Here is my code:

{% set archive = craft.entries.section("exhibitions").order('dateStart desc').dateEnd('<' ~ now).limit(null)  %}
{% set archiveGrouped = archive|group('dateStart.year') %}
{% for year, entriesInYear in archiveGrouped %}

{{ year }}

    {% for entry in entriesInYear %}

And the link to the Website: https://kunsthausbaselland.ch/en/ausstellungen

I guess there is an easy solution for this. But I couldn’t figure it out and found nothing in the docs.

Assuming the years are currently rendered in the correct (descending) order, an easy way to make sure the entries are rendered in ascending order would be to simply reverse the entriesInYear array, i.e.:

...

{% for entry in entriesInYear|reverse %}
    ...
{% endfor %}


Craft on digital ocean Ubuntu: Craft can’t connect to the database with the credentials in craft/config/db.php I have been working locally on MAMP and now have deployed the site to Digital Ocean using this guide.
However I can't access the site. for page links I get the service unavailable error, and for the admin I get the 'Craft can’t connect to the database with the credentials in craft/config/db.php.' error.
i have checked my database credentials many times and they match.

return array(
    '*' => array(
        'tablePrefix' => 'craft'
    ),
    '000.00.000.00' => array(
        'server' => 'localhost',
        'user' => 'craftcms',
        'password' => '************',
        'database' => 'craft'
    ),
    'localhost' => array(
        'server' => 'localhost',
        'user' => 'root',
        'password' => '************',
        'database' => 'craftdev'
    ),
);

my general config settings are as follows:

return array(
    '*' => array(
        //'siteUrl' => "//projectname:8888/html/",
        'environmentVariables' => array(
            'basePath' => '/users/toddpadwick/Sites/projectname/html/',
            'siteUrl'  => '//projectname:8888/html/',
        ),
        'testToEmailAddress' => 'email@email.com',
        // Default Week Start Day (0 = Sunday, 1 = Monday...)
        'defaultWeekStartDay' => 0,
        // Enable CSRF Protection (recommended, will be enabled by default in Craft 3)
        'enableCsrfProtection' => true,
        // Whether "index.php" should be visible in URLs (true, false, "auto")
        'omitScriptNameInUrls' => 'auto',
        // Control Panel trigger word
        'cpTrigger' => 'admin',
        // Dev Mode (see https://craftcms.com/support/dev-mode)
        'devMode' => true,
    ),
    // Use IP address of your droplet below
    '000.00.000.00' => array(

        //'siteUrl' => 'http://000.00.000.00/',

        'environmentVariables' => array(
            'basePath' => '/var/www/html/',
            'siteUrl'  => 'http://000.00.000.00/',
        ),
        // Default Week Start Day (0 = Sunday, 1 = Monday...)
        'defaultWeekStartDay' => 0,
        // Enable CSRF Protection (recommended, will be enabled by default in Craft 3)
        'enableCsrfProtection' => true,
        // Whether "index.php" should be visible in URLs (true, false, "auto")
        'omitScriptNameInUrls' => 'auto',
        // Control Panel trigger word
        'cpTrigger' => 'admin',
        // Dev Mode (see https://craftcms.com/support/dev-mode)
        'devMode' => false,
    )
);

Any help would be greatly appreciated!

Could you post your nginx/apache configuration?

In short the configuration array key is matched based on the server name (server_name in nginx, ServerName in Apache httpd iirc).

If you're using some sort of default configuration it might not have a server_name, or a bogus one.

Thus, if your configuration array is like this:

<?php

return array(

  '1.2.3.4' => array(
    'someSetting' => 'foo'
  );
);

You should have a corresponding configuration in (nginx in this example):

server {
  listen 80;
  server_name 1.2.3.4;
  ....
}

If you have more than one host in server_name, Craft will match on the first.


Loop through remaining craft.entries I have a layout in Craft with twig that gets the first 3 entries and applies them to the first three containers in the grid.

I can't figure out how to loop through the remaining entries to add to the grid-remaining div.  With the current code it will repeat entries 1-3 in the grid-remaining div.

Here's what I have at the moment:

{% set firstEntry = craft.entries.section('shows').first() %}
{% set secondEntry = craft.entries.section('shows').nth(2) %}
{% set thirdEntry = craft.entries.section('shows').nth(3) %}

{% extends "_layout" %}

{% block content %}

            {% include "_partials/card" with { entry: firstEntry } %}

AD

            {% include "_partials/card" with { entry: secondEntry } %}

            {% include "_partials/card" with { entry: thirdEntry } %}

        {% for entry in craft.entries.section('shows') %}

            {% include "_partials/card" %}

        {% endfor %}

{% endblock %}

EDIT

The following works, but I feel like there must be a cleaner way to achieve the same result.

    {% for entry in craft.entries.section('shows') %}
    {% if loop.index != 1 and loop.index != 2 and loop.index != 3 %}

        {% include "_partials/card" %}

    {% endif %}
    {% endfor %}

I think you can just add .offset(3) to the "remaining" craft.entries query to get the result that you want. Or you could exclude the id's of the first three.

But, this is quite ineffective (performance wise), since you're doing four separate queries to get the entries. An alternative would be to loop over all, and use the loop object together with conditionals to build the output. Something like this:

{% for entry in craft.entries.section('shows') %}
    {% if loop.index==1 %}

                {% include "_partials/card" %}

AD

    {% elseif loop.index==2 %}

                {% include "_partials/card" %}

    {% elseif loop.index==3 %}

                {% include "_partials/card" %}

    {% elseif loop.index>3 %}
        {% if loop.index==4 %}

        {% endif %}

                {% include "_partials/card" %}

        {% if loop.index==loop.last %}

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


How can I prevent CMYK image colours being shifted when importing into Assets? When importing CMYK images into Assets the colour of the image can be shifted dramatically. Often giving a washed out look.

How can I prevent this and ensure the image colours are as accurate as possible?

It is necessary to add the following lines to your config

'preserveImageColorProfiles' => true,
'preserveCmykColorspace' => true

This will ensure that the image colours are retained when imported to Assets. You should also ensure that the images are converted to RGB for output. I do this with the Imager plugin and specify the image should be converted to RGB in my transform options.

Also, ensure that you are using ImageMagick for any transformations by installing it on your server and adding the following to your config.

'imageDriver' => 'imagick',


Caching tables not clearing out We are running Craft on a site that gets a decent level of traffic, thousands of hits per day. We are running craft caching to try and keep things quick. The caching tables have been growing significantly over the past few days and don't appear to be clearing out. These are the three tables and the row counts. 1+ million rows in two of them.

| craft_templatecaches                |      34685 |
| craft_templatecachecriteria         |    1197874 |
| craft_templatecacheelements         |    1364424 |

Any ideas on why these tables would be growing so large and why they don't appear to be removing any old rows?

Sounds like you probably have a stuck or error'd "Delete Stale Template Cache" task.

You can tell if a task is stuck because there will be a circular progress bar in the upper-right hand corner of the CP that isn't progressing.

If it error'd, it will be red and you'll have the option to re-try it.

Regardless, here's the general troubleshooting steps necessary for both cases: http://buildwithcraft.com/help/stuck-tasks


Is caching the layout wrapper template a viable option? I've been thinking about creating the simplest possible cache solution and would like to know if this is a worthwhile option.

Using the outstanding cacheflag plugin, I place the entire layout wrapper template inside these tags:

{% cacheflag flagged "content" globally using key craft.request.path %}
 ... lots o code....
{% endcacheflag %}

In the back end, I flag each of the section with a "content" flag.

I think by doing this, each url should have it's own cache file. And all caches are cleared whenever a new entry is posted.

Granted it may a bit of a sledgehammer style solution, but if traffic is average it could perhaps be effective?

Is my understanding correct or is this a bad idea?

In my opinion it's a good, easy and fast way to caching content. We use similar solutions on different Websites and it works perfect for us. Maybe you should do a more specific flagging to avoid deleting all cached entries at once. And you should take care about possible dynamic code parts like forms.


Add or extend attributes (table column) to fields table I'm trying to find a way to extend the meta fields inside a custom field definition. To illustrate:

I need a min_vis def_vis and max_vis column for each field (or anytime a new one is added). Preferably these would be right under the name, handle, instructions text fields. So in this illustration below, there would be a select box added for each of these 3 new meta (or columns) after the instructions meta field.

I know it probably isn't a good idea to modify the core stuff, including the fields table, so should I use a plugin to define some a new model and record? Should I extend the form for fields registration to add these additional attributes as select boxes? Should I give the new attributes their own table (via record class) and set BELONGS_TO where they are related to each field?

If there is a better way to approach this, or if I'm pushing to hard for something custom no worries just give me a heads up that I shouldn't be extending the core fields attributes.

I did look at this issue but wasn't sure if it actually pertained to my question?

I'd probably re-think my approach.  Creating/extending a field type will give plugins access to the settings area below the horizontal rule in your screenshot, but that's on a per-field type basis and Craft doesn't provide a way to hook into where you're looking.

What are min_vis, def_vis, and max_vis actually being used for?


Does Craft support gated content and form fills? I'm a content marketer looking to get contact information for customers visiting my site. Does Craft support workflows with form fills?

For example:

User sees an ad for an ebook, white paper, or other marketing content. Goes to landing page > form fill with contact information > thank you page with content
User sees an ad for a webinar or other event. User goest to event page > form fill > thank you page with confirmation time.

Wondering if Craft supports this type of multi-step content workflow.

Craft is definitely a good fit to manage content around these workflows, but the workflows themselves will require a bit of planning as to how they get implemented.

While there are several potential solutions, I'll share one workflow that can be used for this type of content using the Sprout Forms plugin (which my team is behind).

Create a Landing Pages or Events Channel in Craft. Add whatever fields you want to customize your Landing Page or Events however you need to. These fields can be related to the content, layout, design; event information; or promotional content like the items you mentioned (ebook, white paper, etc)
Create a Form in Sprout Forms for each type of lead capture form you want. You could have one that just requests an email; another that requests name, email, and a few other details; and another that let's a user select which event Date/Time they want to participate in.
On the Landing Page Channel add the Forms Relations field. This will allow you to build flexible Landing pages with variations on your layout and design, as well as relate the form that you want to the Landing Pages or Event pages you are going to be sharing with your users.

After a user submits a form they will be redirected to a thank you page that you can set in the form settings. Depending on how you'd like to protect any content there are several different ways you could grant access to the page, but you have complete flexibility (some of these methods may require more setup than others):

Just redirect and share the confirmation info or marketing content
Redirect with a token that enables the content on the thank you page to only be seen by someone submitting the form
Trigger an email to the user who submits the form with a unique link to the content you want them to have access to


Best practices in debugging an 'Unknown error' How can I debug an 'Unknown error' message that I get with every request in Craft?
Logging says:

******************************************************************************************************
2015/01/16 14:03:36 [error] [exception.Craft\HttpException.503] exception 'Craft\HttpException' in /storage/www/imagecenter/acceptance/craft/app/etc/web/WebApp.php:873
Stack trace:
#0 /storage/www/imagecenter/acceptance/craft/app/etc/web/WebApp.php(218): Craft\WebApp->_processUpdateLogic()
#1 /storage/www/imagecenter/acceptance/craft/app/framework/base/CApplication.php(180): Craft\WebApp->processRequest()
#2 /storage/www/imagecenter/acceptance/craft/app/index.php(62): CApplication->run()
#3 /storage/www/imagecenter/acceptance/htdocs/index.php(16): require_once('/storage/www/im...')
#4 {main}
REQUEST_URI=/index.php?p=admin/actions/users/getAuthTimeout&dontExtendSession=1
HTTP_REFERER=http://acceptance.imagecenter.blinkdev.nl/index.php?p=admin/entries
---
2015/01/16 14:03:36 [error] [application]

******************************************************************************************************

Unknown error messages in the control panel almost always happen over an AJAX request and are usually 500 response code Internal Server Errors, so there isn't an convenient way to display a meaningful error message with a full stack trace to help debug.

But you've found the next best thing... the error logs in craft/storage/runtime/logs.

Usually if you see it on every page in the CP, it's from something like Craft trying to write a license file to the craft/config folder, but it can't. The error you shared is a 503 response, which means "Service Unavailable".  You'd typically only see that if a request comes into the front-end of the site while Craft is in the middle of an update, or the front-end of the site is offline.

So I'm not 100% sure the error you posted is the one that's causing the "unknown error".  I'd enable devMode, clear out all your log files, reproduce the problem and scour the logs again to see if anything else pops out.


How to save multiple related entries on the frontend with 1 checkbox? I have a frontend form and would like to save multiple related entries by checking 1 checkbox.
I have this working to save 1 related entry:

<input type="checkbox" id="user-type-select-{{ userType|kebab }}" name="fields[hasUserTypes][]" value="{{ userType.id }}" />

But how do I pass multiple userType.id values in there? I tried various syntaxes such as comma seperated, enclosed in brackets like an array or a comma seperated string with the |hash filter as seen here but nothing worked.

What is the correct sytax?

You can't solve that with one input alone but you can make use of hidden fields (like craft does)
Your solution would be 1 visible dummy checkbox and multiple hidden "real" inputs.. So your visible dummy checkbox triggers a javascript event, that sets the values of your hidden.
Here is the syntax

<input type="checkbox" id="user-type-select-{{ userType|kebab }}" />

You have to add a javascript/jquery onchange event that sets the values of your hidden fields

<input type="hidden" id="someId1" name="fields[hasUserTypes][]" value="someIntegerValue1" />
<input type="hidden" id="someId2" name="fields[hasUserTypes][]" value="someIntegerValue2" />
<input type="hidden" id="someId3" name="fields[hasUserTypes][]" value="someIntegerValue3" />

in your php part your $_POST variable would be looking like

array(
    ....
    'fields' => array(
        'hasUserTypes' => array(
            someIntegerValue1, someIntegerValue2, someIntegerValue3
        ),
    ),
    ....
);

If you have (let us say) 3 visible checkboxes and each of it contains 2-3 relation presets you would like to store you have to change the values of your 2-3 hidden fields depending on what the user has selected. If you right click on craft cp pages and inspect the code you'll see craft does exactly the same, for every relation you select one <input type="hidden"> is created with the value of the id from the related entry


How to only show entries older than 12 months I want to build an archive template where only entries older than 12 months show up.
Is there an clean and easy way to do so? I only have strange calculations in mind.
Something like this would be nice :)

{% for entry in craft.entries.section('news') if entry.postDate > 12monthsago %}
{% endfor %}

You were close, you can set a postDate param on your craft.entries criteria model. And the Twig filter date_modify helps you to get the DateTime from 12 months ago.

{% set timeAgo = now|date_modify('5:00 -12 months') %}
{% set postDateParam = '< ' ~ timeAgo|date('U') %}

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


Is there a way to retrieve the type of an entry? To be more specific, I would like to know if an entry is a Single or part of a Structure or Channel.

entry.type seems to return the name of the single or section.

Is there a way to retrieve this information for every entry?

The structure type is stored in the section, not in the entry type. entry.type doesn't return the name, it returns the entry type as an object

{% set structureType = entry.getSection().type %}

It will return a string that can have the following values.

const TYPE_SINGLE = 'single';
const TYPE_CHANNEL = 'channel';
const TYPE_STRUCTURE = 'structure';


How to add a custom tab in the user editing page I try to add a custom tab to user account editing page, but there is only one default tab called 'profile' to use and we are not allowed to add another tab there. I am just wondering if this is the case and if Craft CMS will allow us to add a custom tab there in future versions.

Thanks.
Spencer

That's currently not natively possible in Craft, but this feature request sounds like what you're looking for if you want to vote for it.


Can't add anymore fields / blocks to Matrix Field I have a really big / flexible Matrix field for one of my websites. It works great and is easy to handle.

The problem is that I need to add another block containing some fields.
I already extenended the php_value max_input_vars to 9000. This worked for a while but I guess I need even more now.

The Matrix field contains 25 blocks with an average of 5 fields per block as of now but, I need to build another one. If I add another block right now the block will stay but If I add a field to the block and save it, it won't appear when reloading the matrix field.

I know it's alot of blocks inside a matrix field but, it actually is really easy to work with.

Now the question is. Is there another way to extend the limit or maybe a better solution?

There's nothing in Craft limiting the amount of Matrix Blocks and fields you can add, it's purely environmental.

The most common values to increase are max_input_vars, post_max_size and memory_limit, so you'd need to bump one or more of those to higher values to be able to add more.

If you're running things like Suhosin or mod_security, they provide their own additional settings that sit on top of php.ini settings that you might need to adjust as well.


Copy a Craft 3 site to my local machine (MAMP) I have a client who started a Craft CMS site with another developer. I guess the other developer quit, and now the client wants me to make some changes to the site.

The site was created with Composer (which I haven't used before), and I'm stumped on how to get it installed on my local machine using MAMP. I ran Composer to install the dependencies, but there isn't a "Craft" folder and a "Public" folder like I'm used to seeing.

Here's a screenshot of the file structure.

Anyone have any advice on how to get this site installed locally so I can make the changes requested?

Thank you in advance!!

From what I see in your screenshot, it looks like you stumbled upon a Craft 3 installation, in which case neither a Craft nor Public folder exist.

Craft 3 specific

The public folder is now called web, so that's where you should point your MAMP documentroot (or whatever that's called in MAMP). The Craft code is now located in composer's vendor folder, that should magically appear after running composer install. Craft's source would then be in vendor/craftcms/cms.

You can read more about the overall structure of a Craft CMS 3 project in the Setting up a New Craft CMS 3 Project article.

Frontend build tools and JS dependencies (package.json, webpack.mix.js)

Further more, I see that Laravel Mix is used for frontend (js, css) automization, meaning that you have to install JS dependencies by running npm install or yarn install, after which you can use the command defined in package.json to run Mix. I guess this is something like npm run watch (when developing) or npm run prod before you push anything to production.

Modules

And: I see a modules folder, that would most likely mean that a custom module was used for this specific site. Modules are a (poorly documented ;)) Craft 3 way of extending your site without building a plugin and trying to get that to work through composer. They are essentially a wrapper for Yii2's modules.

It's very possible that the Module is just vestigial, however, since that folder is created by default if you do composer create-project -s RC craftcms/craft PATH. You can read more about Modules in the Enhancing a Craft CMS 3 Website with a Custom Module article.

Environment settings

Last but not least: copy .env.example to .env and use that to set credentials for your environment (db settings and stuff).


Field removed from entry layout is still displaying So I'm setting my meta author tag this way:

<meta name="author" content="{% if seoAuthor is defined %}{{seoAuthor}}{% else %}{{globalSeo.seoAuthor}}{% endif %}">

seoAuthor is a field that only appears in some entrie's layout (blog posts). At first the field was on every entry, but I changed it later.

The problem is that the data on the entries that no longer have that field in their layout is still displaying.

So is it possible to only show fields that are currently in the layout of the entry ?

I figured it out. The problem was that the code that set seoAuthor on every template was still there. So even tho the field was removed from the layout, the db still contains that field, so is able to retrieve it.

The fix was to remove the code that set the variable in the templates, and now works as intended.

One thing that still confuses me is why craft still pulls the data if is not in the layout anymore.