Best way to handle large amount of records

In sake of performance it would be better to create a custom field type and one or two record(s).

You can store your information/records in a separate table and link them with their ID to a category. Craft CMS will create a record in at least 4 tables for every elements and it has to join those tables to populate it. So an additional amount of 20k will decrease your performance for sure.

It's better to create a separate table rather than using categories for this task. You can combine your records with other elements with an normal Query like Craft does it with it's  ElementCriteriaModel.

It's going to be much more work if you are not used to Craft but it will help you in the future as a good practice


Stripping this back, your basic problem is saving data to the database from an unreliable source. This is a fundamentally insecure operation—we've got no idea if this user is genuine or attempting something malicious. That's why the underlying Yii framework is trying to protect your install of Craft, and which is the reason you're seeing this ‘buggy’ behaviour with setAttributes().

The Yii framework implements a ‘safe’ validator. A key point made in this helpful article is this:

  Massive Assignment will only be made for fields which have passed
  some explicit validation rule.

This means that any attributes you define without an explicit validation rule will be considered unsafe. This will be the reason that only your email field was saving—it has an explicit validation rule (i.e. an email pattern).

How can you resolve this, then?

Set attributes explicitly

Firstly, you could explicitly set each attribute like you have been doing. Since this is not a massive assignment, the data is treated as safe and will save OK. Both $record->setAttribute() and $record->attribute() will work for this.

Define attributes with explicit validation

Another solution is to define explicit validation rules, and will allow massive assignment on these attributes, but explicit rules only really apply for some data types. What if you want a simple string?

Make existing attributes safe

A solution could be to add the safe rule to your attribute definition. If you follow the definition of attributes down the rabbit hole, you'll find that attribute configs are normalised by ModelHelper::normalizeAttributeConfig() (and subsequently ModelHelper::getRules()) which does not cater for this. Now where does that leave us?

It's possible to override (and extend) the inherited rules() method. Assuming you wanted to make all attributes safe and valid for massive assignment, I reckon something like this would work.

public function rules()
{
    // Are there any existing rules?
    $rules = parent::rules();

    // Make all attributes safe
    $rules[] = array(implode(',', array_keys($this->getAttributes())), 'safe');

    // Send it on outta here
    return $rules;
}

You should then be able to massively set attributes with $record->setAttributes().


If you're getting all the descendants in the for loop, you can use loop to get the index of the current iteration:

{% for chapter in entry.descendants %}

Part {{ loop.index | numbersToWords }}

{% endfor %}

See the documentation for loop in the Twig docs for more details.

This gives you the index of the current iteration in the for loop though, not the actual position of the child in the structure. So if you query only a subset of the descendants, or reorder and manipulate the descendants, this won't work.


Commerce 2 Stripe gateway seems to be working correctly, but order remains unpaid

The processing transaction status is used when a gateway returns from offsite correctly (the user has done everything they can to make payment on the order) but since we didn't get a definitive answer from the gateway that the card has been charged, we put the transaction into a 'processing' status.

This status means we complete the order as there is nothing more for the customer to do.

We later get a response from the gateway (outside of the user checkout flow) to the webhook URL to let us know the payment charge on the card has been made. We then update the order with a successful payment transaction.

It sounds like the webhook isn't being hit with that update information.

After looking at your logs and config, I see that after the webhook request from stripe comes in, the system raises an error.

The error is caused by the fact that you have set the isSystemOn config to false in production. This means the webhook request from stripe is failing, since only logged-in admins can access the system with that config setting set to false.

My guess is you made the payment with the example templates while admin :)


Crafts ActiveRecord has a function beforeSave

/**
 * @inheritdoc
 */
public function beforeSave($insert)
{
    foreach ($this->fields() as $attribute) {
        $this->$attribute = Db::prepareValueForDb($this->$attribute);
    }

    // Prepare the values
    $now = Db::prepareDateForDb(new \DateTime());

    if ($this->getIsNewRecord()) {
        if ($this->hasAttribute('dateCreated')) {
            $this->dateCreated = $now;
        }

        if ($this->hasAttribute('uid')) {
            $this->uid = StringHelper::UUID();
        }
    }

    if ($this->hasAttribute('dateUpdated')) {
        $this->dateUpdated = $now;
    }

    return parent::beforeSave($insert);
}

You can overwrite this method and include your StringHelper::encodeMb4() into it so every time $record->save() is executed your string will be converted


Can I find log activity of who deleted a user and who edited an entry?

Craft only stores minimum audit information in the database... mainly just when a row was created and last updated.

If you're on Craft 2, there is a deprecated Audit Log plugin which might do what you're looking for.

I don't think the author has intentions of porting it to Craft 3, but there is a commercial plugin called Audit that is in the Craft Plugin Store.


No live preview & SEO plugin cannot find content on page

Pretty simple answer - the .env file was not showing the correct primary site i.e.
PRIMARY_SITE_URL=https://www.XXXXXXX.com

http:// XXXXXX

should have been
https:// XXXXXX

very embarrassingly for me, this error was clearly displayed in the console log of the live preview site i.e.

navigate to the live preview page
enter dev tools
view console for the log errors

There is also another post of this issue as well:
Live Preview not loading - https / http conflict
(I'd like to suggest this post be left open as I had previously seen that post but did not attribute it to this issue - possibly due the double digits spent infront of the screen...)


Where are all the references to the URL stored?

Craft makes it easy to handle multiple environments, but you need to make it aware about the differences. Usually it's smart enough to enough to know the base folder path that you have it hosted in.

It's also smart enough to usually which url's you want. Sometimes it doesn't properly remove index.php from the URL, and that you can manually override with the setting omitScriptNameInUrls.

Since your public folder is named public_html, it's not clear from your question if you are running with the standard folder structure (index.php located in public folder, $craftPath inside index.php pointing to craft/ folder one level above public folder).

In general, you should have a look at the documentation regarding multi-environment configuration.

The one other area where it's usually necessary to set environment specific settings is Asset sources: Check out the chapter on that in the docs as well.


At the moment there is no better solution for this. You could write a plugin that defines a new fieldtype.


Craft 3 multi-site route to template (no entry)

I don’t think it has something to do with URI to template routing. It should just work once you have your sites setup correctly in Craft and in server configurations.

What you can do to test correct site setup in Craft is to request the page using the query string:

https://example.com/site1/?p=foo


I think you are looking for a plugin called Table Maker. I've never tried it but it looks like it lets your users create tables in the cp.

Table Maker


Category slug variable is not available when category url's are disabled

That's by design, slugs are used for building the url to link to a specific element, in this case, a category.

Edit: seems I was wrong on the above, see comment. Leaving the rest of the answer as using the ID offers a solution.

You'll have to use the id to refer to the category as value, like so:

<select name="field-styles" id="field-styles" class="select">
    <option value="">Style</option>
    {% for style in craft.categories.group('productStyles').order('title') %}
    <option value="{{ style.id }}">{{ style.title }}</option>
    {% endfor %}
</select>


If you look at how Craft handles routing you will see this:

  If the URI matches an entry’s or category’s URI, the section’s/category group’s template will get loaded, and the matched element will be made available to the template via a pre-populated entry or category variable.

So Craft is assigning that entry variable that you are referencing on line 1 of your code. Then on line 3, you do {% set entry = block.sideLink.first() %} which overwrites that initial entry variable with this new value, which is why the second matrix disappears.

What you probably want to do is this:

{% for block in entry.sideMenu %}
  {% if block.type == "sideMenuItem" %}
    {% set sideLinkEntry = block.sideLink.first() %}
    {% if sideLinkEntry %}
       {{ block.sideTitle }}
    {% endif %}
  {% endif %}
{% endfor %}

And your original entry will be unmodified.


Front End Dropdown Field from Super Table

You should be able to do this in the same way as for a dropdown field in Craft as described in the docs.

Something like this should work if entry is populated:

    Visibility:
    <select name="fields[{{ fieldHandle }}][{{ block.id }}][fields][visibility]">
      {% for option in entry.static.visibility.options %}
         <option value="{{ option.value }}"{% if option.selected %} selected{% endif %}>{{ option.label }}</option>
      {% endfor %}
    </select>


I'm going to guess that there is some sort of CSS or JS conflict which is causing this peculiar behavior. Smart Map must be bumping up against some other styling on the page.

Check through your existing CSS/JS to see if you can find the source of the conflict.


Caching is hard.

https://twitter.com/codinghorror/status/506010907021828096

Something like this should work.

{% if newsExpiration is defined %}
    {% cache until newsExpiration.expiryDate  %}
        ...
    {% endcache %}
{% else %}
    {% cache %}
        ...
    {% endcache %}
{% endif %}

You'd probably want to use an include for the body of the two cache tags to keep things DRY.


How do I display tags comma separated with "and" between the last two tags?

Not very elegant, but... :)

{% for tag in tags %}
    {{ tag.type }}{{ loop.index < loop.length-1 ? ', ' : loop.index < loop.length ? ' and' }}
{% endfor %}


Why is Live Preview scrolling to the top of page after every change?

Figured it out. The issue was related to Font Awesome 5's SVG replacement with JS method but specifically Asynchronous Loading Indicators. Once I stopped using this async stuff all is peachy again.


Steps to publish a craft website from local to server

It probably depends most on your hosting but following these instructions are probably your best bet: http://buildwithcraft.com/docs/installing The only exception being instead of "installing" you'd move your files up and import your database.

If you are using github, it's as easy as "pulling" your code to your production server and importing the database into production database as well (local mysql, cloud db etc.)

You'll probably be best off looking at http://buildwithcraft.com/docs/multi-environment-configs so you can create settings for both your local environment and production.

Here's an example of a sample craft database file: https://gist.github.com/mccombs/5e17c84743a25dafddb9

Here's an example of a sample craft general config file:
https://gist.github.com/mccombs/b6a161cabc064d1f51b3

Hope this helps!


Does Craft have a timeout setting for template requests?

Nothing directly in Craft, but you're probably looking for PHP's max_execution_time, which governs how long a PHP script is allowed to execute.  It defaults to 30 seconds.

You can edit that value from you php.ini file.


Restrict viewing front end to specific group permissions

If you setup a User Group with the same handle as the Site you want them to have access to, this could be fairly easy.
Let's say you have a site called "Acme" setup in the Sites settings. You also created a corresponding User Group called "Acme." The handles for the Acme Site and Acme User Group are both "acme."
When you're on the Acme site's front-end, possibly example.com/acme depending on how you set up your site URLs, the {{ currentSite.handle }} tag will return acme.
To test if a user has access to content in your template you can use something like {% if currentUser.isInGroup(currentSite.handle) %}.
Adding this to any template will prevent unauthorized access if a user is not in a group:
{% if not currentUser.isInGroup(currentSite.handle) %}
  {% exit 403 %}
{% endif %}

You would also probably want to allow admins or users groups who can access the control panel:
allow admins:

{% if not currentUser.isInGroup(currentSite.handle) or not currentUser.admin %}
  {% exit 403 %}
{% endif %}

... or allow any user that can access the control panel:

{% if not currentUser.isInGroup(currentSite.handle) or not currentUser.can('accessCp') %}
  {% exit 403 %}
{% endif %}

Redirecting to the correct site after a login page is a little trickier because users can belong to more than one group.
But assuming that users only belong to one group you could redirect users to a sort of "routing" template that's only job is to send you to the right place.
{% set firstGroup = currentUser.getGroups()[0] ?? null %}

{% if firstGroup %}
  {% redirect firstGroup.handle %}
{% else %}
  ... default redirect or error
{% endif %}

Also, here's a list of permission you can use with the currentUser.can() method:
https://docs.craftcms.com/v3/users.html#permissions


How to process Matrix field in controller

You have to loop the Matrix field first, something like this:

foreach($entry->matrixHandle->all() as $block) {
   echo $block->fieldHandle;
}


Disabling the target="_blank" on admin site title link

You can use the handy Control Panel JS plugin and add some JS that targets the site-name class on the anchor and removes it.  jQuery's removeAttr should do the trick.


Here are some basics:

First, tags and categories are two different things. As a first step, think long and hard about how you want to organize your content. Keep in mind that Categories can be hierarchical, whereas Tags are not.

To start using Categories, you must first create a Category set, say, "Blog", then specify categories within that set, e.g. Beauty, Health, etc. Note that you can assign fields to a category set, so you can associate things like icons or brief description for each one!

To use your Categories in entries, first create a Category field(s) and then add it to one or more of your channel entry types. then, when you create a new entry, you can assign a category to it.

To access entries by category in your templates, refer to this section of Craft Docs


Applying an image transform returns a 404 cpresources URL

For what it's worth, I also had his issue, turned to imager, which gave me some more useful error messages as to my root cause of the issue:

You may need to make sure that the path to the asset file is complete, not just relative to the site base. So for instance, a base path of ./assets works fine for standard purposes, but appears no use for transforming images, you would need http://site/assets.

If your setting a base path in config, you can use something like

'environmentVariables' => array(
    'assetsBaseUrl' => '/assets',
    'assetsBasePath' => "{$_SERVER['DOCUMENT_ROOT']}/assets",
),


How to get latest entries by particular field?

Looks like you're trying to echo out the results using {{ instead of actually setting it using %} tags.

{% set entries = craft.entries.section('works').order('fieldname desc').limit(5) %}

{% for entry in entries %}
   {{ entry.title }}
{% endfor %}

This should fix your problem.


You can see what Craft does when uninstalling a plugin by looking at craft/app/services/PluginsService's uninstallPlugin method.

Craft will delete any custom elements the plugin has defined from craft_elements and the cascading deletes across foreign keys to that table will trigger.  It will drop any tables defined by any plugin records. It will remove the plugin row from the craft_plugins table and any migrations from the craft_migrations table.

craft_field and craft_fieldgroups won't get picked up because they don't have any indirect FK connection to craft_elements, but you can add an onBeforeUninstall method in your base plugin class and do any custom cleanup you want there.


Change the name of 'CraftSessionId' from HTTP header requests?

I'm not sure I'm understanding 100% what you're trying to do, but by preventing the Set-Cookie header, aren't you essentially blocking any cookies from being set in your browser?

All of Craft's authentication is cookie based, so it's not surprising that trying to login to the control panel doesn't work.


If you want to get the values of your global table field, you need to loop through it.

somewhere in a template:

{% js %}
    var table = '
    {% for row in global.tableFieldName %}
      ({{ row.column1 }} - {{ row.column2 }}){% if not loop.last %},{% endif %}
    {% endfor %}'
{% endjs %}

Output:

<script>var table = '(Value 1-1 - Value 1-2),(Value 2-1 - Value 2-2)';</script>

You should check out the documentation about Craft 3 Table Fields, {% js %} Tag and for removing the trailing comma Remove trailing comma from an output loop?


When using .limit on matrix blocks they don't show in live preview

I noticed the same issue with live preview, but using the type property on the Matrix field: Issue with Matrix type property and Live Preview? According to Brandon's answer this is a current bug / limitation of the Matrix field that you have to find a workaround for.

In this case this is rather easy, get all the blocks and use the slice filter to loop over a subset:

{% for serviceBlock in entry.serviceBlocks|slice(0, 2) %}


Updating Craft 3 from RC3 to RC4 through Composer

So, not all hosts allow just using composer and impose to use php composer.phar.

Knowing that, I can now answer my two questions:

When installing Craft using php composer.phar create-project -s RC craftcms/craft $HOME/craft, the -s switch is just telling which branch of the source project to use. Here, RC stands for Release Candidate. Before that, we had to use -s BETA in order to install the betas. Something I didn't knew since I waited for the RC to jump in Craft 3 and start over from Craft 2.
When you want to update using php composer.Phar, you need to go inside your project folder (where you installed Craft; craft for me which means once logged I had to cd craft) and then type php ../composer.phar update, where ../composer.phar tells to go looking for Composer from the parent folder.

I am ashamed not having thought of that; I really need to stop overthinking things.


Uploading animated GIF outputs only first frame

Your ImageMagick library version is 3.5 years old.  I'd start by updating that to something newer.

You didn't list the PHP Imagick extension version, but I'd bet it's out of date as well.  3.1.2 is the latest stable release.

Also, Craft will automatically try and detect if Imagick is installed and available via PHP, but it won't hurt to explicitly set the imageDriver config setting to imagick to be sure.

  Is there a way to disable image transforms for animated GIFs or GIFs in general?

Not currently, sorry.


Math with numeric values derived from a dropdown field


I found a way to get around this problem by creating a controller which extends the console controller.
Then I can call the functions in this child controller.

But if anyone knows how to call console controllers directly, please tell me.Thx


You can configure the columns to display using the little cogwheel icon at the bottom (below the list of sections):

This will open a modal window allowing you to select the fields you want to display in the table for each section. You can also rearrange the fields using drag-and-drop with the little handle icon to the left of the field name.
As a sidenote, this modal also allows you to reorder the sections in the sidebar, and use your own headings instead of the default headings for channels and structures.


Solspace select options not being stored

Unfortunately this is currently a limitation of Freeform. It expects that the option values are predefined for the field, and not dynamically loaded at template level.

It's on our feature requests list to come up with a way to let users override this functionality. :)


Rendering pages from Craft CMS as static HTML

There are a few different solutions for this. Personally my favourite is to switch on static caching in nginx, as it's a relatively quick and easy solution. Andrew has you covered on how to do that here: https://nystudio107.com/blog/static-caching-with-craft-cms
If you're not using nginx, then a popular choice is the Blitz plugin: https://plugins.craftcms.com/blitz (I've not used it myself so can't really comment, but it sounds good if you're not into rolling your own solution in nginx). Blitz offers a static export of your site too, so it's literally just html files, which would be more portable than nginx's static cache (i.e., you could host the site directly on a CDN).
With any kind of static system, you'll need to ensure:

That any form submissions such as keyword search and contact forms still work by dynamically refreshing any CSRF tokens via AJAX.

That the relevant actions in Craft cause the cache to be deleted. Again, Andrew has you covered here if you're using nginx static caching with the FastCGI Cache Bust plugin: https://github.com/nystudio107/craft-fastcgicachebust

Overall I prefer nginx static caching because I still have the dynamic benefits of a CMS and don't have to worry about complicated workflows for updating an entire load of files and redeploying them somewhere whenever someone corrects a spelling mistake... but I guess if you can fully automate that it's a fine solution.


How can I make an entry (in this case a page from structure) only visible to users with cp access?

Craft has a handy {% requireLogin %} tag; this seems like the quickest and easiest solution for you.

If this particular entry has its own Twig template you can just put this tag at the top of the file.

Alternatively, as you say you could create a lightswitch field, add that to your entry type and simply tick the entries you would like to be password protected.

A simple piece of Twig code that checks the lightswitch and does what you need could look like this:

{% if entry.requireLogin %}
    {% requireLogin %}
{% endif %}


Turns out the issue was my config set incorrectly. I was doing this:

'siteUrl' => array(
    'en' => 'http://website.dev/en',
    'en-gb' => 'http://website.dev/en-gb',
    'en-us' => 'http://website.dev/en-us',
    'en-au' => 'http://website.dev/en-au',
    'en-nz' => 'http://website.dev/en-nz'
),

When the array keys need to match the way they are set in craft with underscores (and your public/locale/index.php file)

'siteUrl' => array(
    'en' => 'http://website.dev/en',
    'en_gb' => 'http://website.dev/en-gb',
    'en_us' => 'http://website.dev/en-us',
    'en_au' => 'http://website.dev/en-au',
    'en_nz' => 'http://website.dev/en-nz'
),


It all depends on what your template is doing with the global.

If it's doing something to cause multiple database calls, then yes, you'll probably see some improvement (maybe minuscule, maybe more significant).

Anywhere you use a cache tags brings an overhead of one additional database call, so you just need to make sure it's worth it.


Top level entry url not rendering category in url

I imagine it's because you're trying to access productCategory on category instead of the entry. When you're setting entry urls you don't need to use the entry prefix as it automatically expects this to be the case. So try products{productCategory.first().slug}/{slug}


Craft - suitability for membership/user registration and document upload/management

Should be no problem, Craft has extensive user management capabilities, check https://craftcms.com/features/users & https://craftcms.com/docs/users as well as solid asset management https://craftcms.com/features/assets

Log in to the demo https://demo.craftcms.com/ or do a local install, as long as your test domain has .dev in the url you can fully test Craft with purchasing a license.


Craft 2.6.2999 install error: Base table or view already exists: 1050 Table 'craft_entryversions' already exists'

This is an indirect answer, but if you don't have time to debug the install process to set up a Vagrant box, grab this:

https://github.com/niceandserious/crafty-vagrant

Something about it doesn't trigger the duplicate table trouble. Someday I'll have time to figure out why.


How to allow browsers to cache Craft's admin static files?

I don't think it's a great idea to disable this cache busting; they put it in there for a reason.  However, if you really need/want to do it, instead of modifying Craft, I'd just configure Apache/Nginx to discard the query string for paths that match /admin/resources/

https://wiki.apache.org/httpd/RewriteQueryString


Using search to display entries based on a value in a number field

You can do a certain amount of logic in the ElementCriteriaModel syntax. I think this will work:

{% set entries = craft.entries.section('equipment').modelYear('and, > 2006, < 2009') %}
{% for entry in entries %}
  ...
{% endfor %}


Post to Sprout Forms plugin from an app or another website

Assuming you're using a hidden action input, then sproutForms/entries/saveEntry should be correct.  You can see that in the Craft docs here: https://docs.craftcms.com/v2/plugins/controllers.html#posting-to-controller-actions

If you're not using that input, or you're constructing the URL to post to manually, then it will likely be actions/sproutForms/entries/saveEntry instead, assuming you have set a custom actionTrigger in your general config.


Is it possible to install Craft on a cPanel temp user URL?

http://buildwithcraft.com/docs/multi-environment-configs

'example.com' => array(...

'should' work with an address like:

'123.45.67.89/%7eusername' => array(...

You might also try:

'123.45.67.89/~username' => array(...

Although using a proper domain name as in my comment above would be better.

Good luck. :)


How does "hash" work in the context of the Contact Form?

In the context of the Contact Form plugin, the |hash filter is only necessary if you want to dynamically add recipients to the submission.

It is there to ensure that data isn't tampered with between the time it is submitted and the time that it hits Craft.  Contact Form cares about this so malicious people/scripts don't turn your Craft install into an email SPAM relay machine.

Looks like you're using it on the hidden redirect parameter... it's completely unnecessary there, so you can remove it.


Replace substring in string with variable named as substring?

It sounds like you'd be better off using Yii's Message Translations for this, if that's possible in your situation. They are what powers Craft's |t / |translate filter:

{{ "String with {something} and {somethingElse}"|t('site', entry) }}

With this, {something} and {somethingElse} would be replaced with the string values of entry.something and entry.somethingElse.

You can also pass an array for more complex substitutions:

{{ "String with {something} and {somethingElse}"|t('site', {
    something: entry.something,
    somethingElse: entry.somethingElse,
}) }}


Handling non-image uploads when updating user photo from front-end form

Update:

As of the next (post 2.4.2702) Craft release, Craft will now return a validation error on the UserModel if a non-image is uploaded for the user's profile photo.

I consider this a bug in Craft and we've already got a ticket open to address it.

Until then, I can think of two options work work around it, either of them particularly pretty. 1. Hack core Craft files to do the detection. 2. Have some JavaScript on your upload form that detects the extension of the file they're trying to upload.


Set custom sort order for index pages in the CP?

You weren’t overlooking anything, we were :)

We just released Craft 2.3.2616 with four new hooks:

modifyEntrySortableAttributes
modifyCategorySortableAttributes
modifyAssetSortableAttributes
modifyUserSortableAttributes

That should do the trick for you.


I am new to craftcms and webdev. Therefore I am unable to tell you an exact route, but this can definitely be solved, I already read about it. This guy has excellent tutorials about craftcms and development and these two topics could solve your question. Just give it a spin and read through:

https://nystudio107.com/blog/database-asset-syncing-between-environments-in-craft-cms

https://nystudio107.com/blog/multi-environment-config-for-craft-cms


Order of {% set %} tags changing output unexpectedly

This is a change in behaviour from Craft 2 to Craft 3 and here is the explanation.
In short, you need to clone your query (docs), something like the below should work:
{# Initiate your query #}
{% set content = entry.pageBuilder %}

{# Clone the original query to get your blurb #}
{% set blurb = clone(content).type('copy,faq').limit(1).all() %}

{# Get everything #}
{% for block in content.all() %}
    {% include "blocks/_" ~ block.type ignore missing %}
{% endfor %}


Swapping currency when swapping languages

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


Do field values get serialized before validation?

First of all: this validator requires an active record as target in order to know what table it should check to search for uniqueness. Since Craft has not such a thing you would need to create a record for the content table in order to make it work.

Furthermore you'll need to check the context of the field, if it's inside a matrix or inside a super table field or whatever so you need to set the target Attribute dynamically based on the table.

Finally it won't serialize your value automatically and search for the string, instead it will just fail because of these lines

foreach ($rawConditions as $key => $value) {
    if (is_array($value)) {
        $this->addError($model, $attribute, Yii::t('yii', '{attribute} is invalid.'));
         return;
    }
    $conditions[] = [$key => $value];
}

Your value is an array so it will add an error no matter what

However: you can rebuild the functionality by actually validating the model by yourself with this validator instead of defining a validator and letting Craft handling it.

You can see an example in the matrix field it inserts just a function that is being called in the class instead of a validator. Then you can create a dynamic model  and validate that one. You can read more about  ad hock validations

$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
if ($validator->validate($email, $error)) {
    echo 'Email is valid.';
} else {
    echo $error;
}


Title Format - Object Label instead of Value

Here's the documentation you're looking for: Working with Dropdown Field Data
You can get the label by adding .label, so you'll end up with {{object.exampleOne.label}}
The dropdown field contains a few properties:

label
selected
value (default)
valid


Yep so can just create a route in the control panel.

See: https://docs.craftcms.com/v3/routing.html

You'll see you can use a slug (using the token slug) so that Craft will validate the url actually has a valid slug on the end, or you can just use * and craft will route to this template no matter what is on the end.

(I personally prefer to create routes in source control managed & commented code using the routes.php config file - https://docs.craftcms.com/v3/routing.html#advanced-routing-with-url-rules  ... so this would be something like:

'samples/sample/<slug>'          => ['template' => '/your/samples/template']

Then, on the main product page, build your url to the samples page as, basically:

/samples/sample/{{ thisProduct.slug }}

Then, in your samples template you just grab the last segment, as you are, and use that in your code to pre-select the particular sample from you list...as you are.

So basically, you're almost there apart from creating the route.


By default, Matrix blocks will display in the order you have entered them in your entry form.
If you need to change the display order, you can drag/drop your blocks straight from your entry form using the small handle on the right of the blocks and the order will be reflected on your page.


The docs explain how to generate links to controller actions. Assuming your action trigger is "actions" (as it is by default) then your URL will look as follows:

http://www.domain.com/actions/pluginName/controllerName/actionName

Following the first example in the docs, the URL will look as follows:

http://www.domain.com/actions/cocktailRecipes/ingredients/deleteIngredient

Be sure to allow anonymous access to your controller action so it can be reached by the cron job.


Don't allow multiple users with same the password

This is not a common practice out of the box, and not even desirable as you may also imply that other users have the same password creating the possibility for this new user to just try different emails with that password.

What you could do is run via a plugin the user password against a list of weak passwords, and return a message if the password entered is easy to break.

If 2 or more users have the same password and their password is good, there's no reason for letting one of them know about the existence of the others. The same thought does not apply to emails or usernames though, since they are the unique ids within the system.


onBeforeRender event? Is there an event or hook I can use with my plugin?

The full list of events that Craft provides is documented here.

There currently isn't onBeforeRender or onRender events, but it is on our list with no particular ETA.  It gets tricky because it's difficult to distinguish between the main template and any other template that might happen to call TemplateService->render() (includes, etc.).


Array to string conversion Template Error

According to the docs for the Icons plugin, icon is actually an object. Try this instead...

In both scenarios, I'd take another look at your rendered HTML... your first example may actually be rendering the word Array instead of the class name that you are looking for. You can also leave off the leading fa-, since that will be automatically included in the class name.

Where you have called icon in both examples, you're simply referring to the field itself. You actually want to be referring to the values of the field.

To output the HTML you're looking for, either of these two options will work:

{{ block.icon.icon }}

And for your non-matrix example, just replace block with point.


Live Preview only works with published entries

My understanding is you have to save an entry first before you can use live preview.

Brandon says as much in his answer here as well:
https://craftcms.stackexchange.com/a/12091/103


How to add/link an entry to an object using PHP?

Ah got it :

$lNewUser->getContent()->setAttributes(array(
    'companiesDropdown' => array($aUser->companyId),
));


It’s important to understand that using relations fields in the template works similar to using craft.entries. They return a element query object, for example entry.plantEntity in your entries loop. And you need to call the all() method on them to query for the elements. The same applies to querying for the asset elements in your inner entries loop.

{% set plantCares = craft.entries
    .section('plantCare')
    .all() %}

{% for plantCare in plantCares %}
    {% for plantEntity in plantCare.plantEntity.all() %}
        {% for plantPhoto in plantEntity.plantPhoto.all() %}

        {% endfor %}

        {{ plantEntity.title }}
    {% endfor %}
{% endfor %}

You should generally avoid querying in a loop though, and use eager-loading instead.

{% set plantCares = craft.entries
    .section('plantCare')
    .with([
        'plantEntity',
        'plantEntity.plantPhoto'
    ])
    .all() %}

{% for plantCare in plantCares %}
    {% for plantEntity in plantCare.plantEntity %}
        {% for plantPhoto in plantEntity.plantPhoto %}

        {% endfor %}

        {{ plantEntity.title }}
    {% endfor %}
{% endfor %}

If you’ve got many plantCare entries consider paginating through them.


Setting valueless boolean attributes with the tag function

If an attribute is set to true, it will get added without a value.
{{ tag('input', {
    id: idVar,
    name: nameVar,
    required: true
}) }}

Also, if it is set to null or false, it will be omitted, as if it was never listed in the first place.


You already pass the array keys into the loop as a variable pageInfo. There's a couple of properties you can access from it, see the Craft docs:

Templating Reference → {% paginate %}

Of interest for you is probably these:

  pageInfo.total – The total number of elements across all pages
  pageInfo.currentPage – The current page number.

It looks like there's no property for the "current element number" and you need to do some math to output it:

{% paginate craft.entries.limit(10) as pageInfo, pageEntries %}
    {% for entry in pageEntries %}

        {% set index = (pageInfo.currentPage - 1) * 10 + loop.index0 %}

        {{ pageInfo.total - index }} of
        {{ pageInfo.total }}

    {% endfor %}
{% endpaginate %}


You best bet would be to start by knowing all the exisiting default attribute types in this file:

craft/app/enums/AttributeType.php

Then look in

craft/app/helpers/ModelHelper.php
and
craft/app/helpers/DbHelper.php

There you will find all sorts of properties for column types and their default configs options like maxLength. Here is all the ColumnTypes defaults:

public static $attributeTypeDefaults = array(
    AttributeType::Mixed      => array('model' => null, 'column' => ColumnType::Text),
    AttributeType::Bool       => array('maxLength' => 1, 'default' => false, 'required' => true, 'column' => ColumnType::TinyInt, 'unsigned' => true),
    AttributeType::ClassName  => array('maxLength' => 150, 'column' => ColumnType::Varchar),
    AttributeType::DateTime   => array('column' => ColumnType::DateTime),
    AttributeType::Email      => array('minLength' => 5, 'column' => ColumnType::Varchar),
    AttributeType::Enum       => array('values' => array(), 'column' => ColumnType::Enum),
    AttributeType::Handle     => array('maxLength' => 255, 'reservedWords' => 'id,dateCreated,dateUpdated,uid,title', 'column' => ColumnType::Varchar),
    AttributeType::Locale     => array('column' => ColumnType::Locale),
    AttributeType::Name       => array('maxLength' => 255, 'column' => ColumnType::Varchar),
    AttributeType::Number     => array('min' => null, 'max' => null, 'decimals' => 0),
    AttributeType::SortOrder  => array('column' => ColumnType::TinyInt),
    AttributeType::Template   => array('maxLength' => 500, 'column' => ColumnType::Varchar),
    AttributeType::Url        => array('maxLength' => 255, 'column' => ColumnType::Varchar),
);

You will also see in the DbHelper.php how the column types map into the mysql definition of the table like so:

case ColumnType::Decimal:
            {
                $def = 'DECIMAL('.$config['length'].','.$config['decimals'].')';
                break;
            }

Hope that helps. I would encourage you to look at all the defineAttributes() methods in the craft/app/records directory.


An unknown error occurred - no log entry

Clear your Cache manually going into the Storage folder. It happens when you add new entries and the code is not written properly or any other issue may reflect this error. So the best thing to clear the storage part manually.

To do this; Delete the entire folder \craft\storage\runtime


All Craft CMS updates are free of charge - including major versions. In other words, Craft 3 will be a free upgrade.

Edit

As announced under DotAll 2017, following the release of Craft 3 in April 2018, P&T is changing the pricing model for Craft CMS. In order to stay updated, Craft 3 sites will have to renew their license yearly (for a reduced fee; $39/year for Client edition, $59/year for Pro) in order to continue to receive updates after the first year.

Note that Craft 3 will still be a free upgrade for Craft 2 licenses purchased before the release of Craft 3, as these licenses will be exempt from the yearly updating fee and will continue to receive free updates indefinitely.

Source: https://craftcms.com/news/dot-all-2017-announcements


The good news in the upcoming Craft 3 this isn't an issue.  404's get logged to their own separate log files and won't clutter up the main Craft log files specifically for this reason.

In Craft 2, I think you'd have to do something like write a plugin that listens for Yii's onException event, makes sure it's a 404 status code, then go through Yii's CLogger to get the full list of log entries and remove the last one.


Moved server (centOS7) "Please ensure that $craftPath is set correctly"

So as it turns out Vesta has a funny way of handing httpd config files.
There was another one tucked away somewhere where "open_basedir"
They are kept in "/home/admin(username)/conf/web/httpd.conf"

Removing that fixed it.

Such a pain, tooks me hours to figure out something so simple.
I had already removed it from the httpd.conf in the default location.

Something to keep in mind if anyone has the error and is running VESTA CP!


Performance issues from matrix vs rich text?

Matrix does have additional overhead, but it's unlikely that it is the sole reason for any slowdown.

If you enable devMode, you can see profiling information for SQL queries as well as code execution in your browser's console to try and track down where any slowness is occurring.

If it is ultimately coming from you template, you can look into the {% cache %} tag to help with initial load time.


Email Messages – If current email type is html or text

There currently isn't a native way to do what you're looking for, but you should consider voting for this feature request which would make it natively possible.

As a workaround, you could write a plugin that listened to the onBeforeSendEmail event, checked to make sure it's the email you're looking for, then modify the body property of the EmailModel however you wish.


The error messages are returned to the template as flash messages.

Handling those is documented here:
https://craftcms.com/docs/templating/craft.session

One thing to watch out for is that flash messages are only available once, and are by default 'consumed' when you retrieve them:

{{ craft.session.getFlashes() }}
...some other template code here....
{{ craft.session.getFlashes() }}

...if there is a message, the first tag will output it, but the second one won't as it has been consumed.  So best to set the message to a variable if you want to save it, or you can call craft.session.getFlashes(false) to stop the message from being consumed if you'll want to use it later in your template.

During development it is worth having some code to always display the flash messages at the top or bottom of your main layout template, so you can see them as they are occurring, and thus anticipate what you might need to handle.  I use something like this:

    {% if craft.config.devMode and (craft.session.hasFlash('notice') or craft.session.hasFlash('error')) %}

    {% set noticeFlash = craft.session.getFlash('notice')|join('|') %}
    {% set errorFlash = craft.session.getFlash('error')|join('|') %}

    Notice: [{{  noticeFlash }}]
    Error: [{{  errorFlash }}]

    {% endif %}

Now, if you're doing your payment operations via ajax, things are a little different...that case you'll get back results in json.  If there is an error, it will look something like:

{"error":["Credit Card Invalid"]}

So in your js you would check for the lack of response.success and then look for this error message.


Search Plus - How to skip an entry in mapping?

I've done this, and I believe the trick was to return true.

UPDATE: Looks like this was fixed in version 1.5.2, returning false will skip the entry as expected.


Well... the answer was quite simple.

'siteUrl' => array(
    'en_ca' => 'http://localhost/mysite',
    'fr_ca' => 'http://localhost/mysite/fr',
),

The _ca part was what was missing.  Now my site works amazingly.

Sorry for the run around and I hope this can help someone.


This page isn’t working // I think it's my .env?

Yes, the .env file holds the environmental-specific settings/"secrets" that Craft needs to run. So you'll need to recreate it; here's a template:

https://github.com/craftcms/craft/blob/master/.env.example

More information can be found here: Environmental Configuration


Hooking into event when record deleted from custom plugin

Because that's a Yii event, it doesn't follow the same component.eventName syntax that the other Craft events use and you can't use craft->on() to register to listen to it.

Completely untested, but you should be able to use the traditional Yii method, though. Something like this:

$myRecord->onAfterDelete = function (Event $event) {
    // Do your thing.
};


Is there a way to define a global var within a twig block?

Twig variables are only accessible inside their own scope.

.

What is a scope:

Tags like {% block %}, {% for %}, {% nav %} create a 'scope', which means that variables defined inside them, can't be accessed from outside. This is similar to local variables inside php-functions:

{% block A %}
    {% set var = 'apple' %}
    {{ var }} {# This prints apple #}
{% endblock %}

{% block B %}
    {{ var }} {# This doesn't prints anything, since var isn't defined #}
{% endblock %}

.

Variables outside their scope:

To make variables accessible outside their scope you have to define them before:

{% set var = 'apple' %}

{% block A %}
    {{ var }} {# This prints apple #}
{% endblock %}

{% block B %}
    {% set var = 'banana' %}
    {{ var }} {# This prints banana #}
{% endblock %}

{% block A %}
    {{ var }} {# This prints banana #}
{% endblock %}

.


Render template from Module in twig template

Now working. Turned out to be user error on my part. I had neglected the alias that I had created so the path to the template directory was incorrect.


GoogleMaps plugin marker setOptions error

Icon management is handled a bit differently in the new Google Maps plugin. Now, you set icons before the map is rendered, even in Twig!

Official guide for Setting Marker Icons

{# Get all bars & restaurants #}
{% set bars        = craft.entries.section('locations').type('bars').all() %}
{% set restaurants = craft.entries.section('locations').type('restaurants').all() %}

{# Create a dynamic map (with no markers) #}
{% set map = googleMaps.map() %}

{# Add all bar markers #}
{% do map.markers(bars, {
    'icon': '/images/bar-icon.png'
}) %}

{# Add all restaurant markers #}
{% do map.markers(restaurants, {
    'icon': '/images/restaurant-icon.png'
}) %}

{# Display map #}
{{ map.tag() }}


Is it possible to use Update Asset Indexes on a target subfolder or subfolders?

There is no good solution in Craft 2.x, but you probably can put together a plugin or a console app that does what you want it to do. Here's all the background info you, hopefully, need.

The whole indexing process is controlled by javascript as well but let's just pretend you've instantiated the AssetIndexTool class and are operating on that via performAction()

Craft Asset indexer operates strictly on the data in craft_assetindexdata table. When you start an indexing task, the very first thing it does is query the Asset Sources for all the actual files that are there, stores a list of them in the said table and from that point on uses that table to reference what files have been indexed and which not. As it does it, Craft also creates all the folders already (because, apparently, a long time ago it seemed like a good idea to me).

After that, the tool returns an array for each of the steps it needs to take, where one step is generated per file and also an additional "overview" step at the end. Each array entry basically contains parameters that you should throw back at the Index Tool.

What you're interested in each of those "step" arrays (if you want to understand how the whole process works) is sessionId variable there to track the indexing session in the indexing table, the sourceId variable so you know which source you're operating on and the offset variable that tells the Index Tool which file in the indexing table to look up and actually index.

You should definitely also follow through with the last overview step. Never mind that it presents the user with a HTML dialog for all the files that are in the DB but are not present in the source, but, more importantly, it cleans up the asset indexing table and removes the obsolete data in there.

The great news is that it will be significantly less convoluted and way more accessible programmatically in Craft 3.


Localization - Getting page not found from CP when trying to edit new locale

When a new locale is added to an existing site, Craft re-saves the entries in the background. If you're unable to edit the entry in the new locale, it would indicate that the task has not completed. Check the craft_tasks table in your database to see if this is the case. More info on stuck tasks here.


You can use the striptags filter to remove all HTML tags from your string. With the trim filter you can strip all whitespace from the beginning and the end of it:

{% if entry.poorText|striptags|trim %}
    {{ entry.poorText }}
{% else %}
    Here could be a nicely formatted text!
{% endif %}


How do I setup an assets feed using the FeedMe plugin?

I believe they've added the documentation you're wanting here: https://verbb.io/craft-plugins/feed-me/docs/content-mapping/field-types#assets

Assets
Accepts single or multiple values. You should supply the filename only, excluding the full path to the asset, but including the filename. If you're uploading remote assets, you'll need to produce fully-qualified URLs.
Additional Options

Upload remote asset (choose how to handle existing assets - Replace/Keep/Ignore)
Inner-element fields

<Asset>my_filename.jpg</Asset>
// Or
<Assets>
    <Asset>my_filename.jpg</Asset>
    <Asset>my_other_filename.jpg</Asset>
</Assets>

//
// When selecting upload
//
<Asset>http://mydomain.com/my_filename.jpg</Asset>

// Or
<Assets>
    <Asset>http://mydomain.com/my_filename.jpg</Asset>
    <Asset>http://mydomain.com/my_other_filename.jpg</Asset>
</Assets>


You don't need a plugin for this task. You are free to do whatever you like in your templates. There is a template folder in your Craft directory where your html/twig files live and you are free to create the html you like.

So if you want to have a site wide banner, just include the required html in your layout template and that's basically it.

Craft is not made for non-developers so if you are going to create a site with craft you should have basic knowledge in html/css to write your layout at least.

I suggest you to read the docs or some other tutorials


Setting up load balancing for Craft on Laravel Forge

I figured out a solution, though I'm not totally clear why it works.

Adjusting the server statement below

server {
    listen 80;
    listen [::]:443 ssl;
    ...

to read

server {
    listen 80;
    listen 443 ssl;
    listen [::]:443 ssl;
    ...

Solved my problem and allowed my load balancer to direct to my application servers.


Asset field empty in graphql query response

Check that the schema you're querying has permissions to access the asset volumes that your asset field is pulling from.

For images to be returned, the schema you are querying must have permissions for every asset volume that your asset field can pull from. If there are any assets selected in the field which the schema does not have permission to access, then the field will return an empty array.


In a plugin, how do I save an entry with a related entry

Relations fields can store multiple related values (even if you only have one item).  Perhaps try to pass an array to the 'quiz' value:

'quiz' => array($data['itemId'])

Alternatively, if you are submitting all of your content, in the correct format, you can get rid of your $entry->getContent()->setAttributes line and use the setContentFromPost method.

All you need to pass to the setContentFromPost method is the name of the custom content fields array you are submitting to the content table.  For example, if your fields above were structured as follows in your front-end form template (this is a bit simplified for your complex field types like relations, but as long as your submitting the right values this should work):

<input type="text" name="title" value="My New Entry">
<input type="text" name="fields[score]" value="101">
<input type="text" name="fields[quiz][]" value="101">

Note that in the input field name of quiz relations field we are passing an array: fields[quiz][].

You can then receive your submitted data and hand it off to the ContentModel tied to your EntryModel. Your title is handled slightly differently than your custom content as the title field is a default attribute of the ContentModel:

$entry->getContent()->title = craft()->request->getPost('title');

And your array of submitted custom content can be handed off silently to the setContentFromPost field by just passing it the name of all of the fields.

$entry->setContentFromPost('fields');

You don't even need to capture your post data using something like craft()->request->getPost('fields'), just passing the 'fields' value to the function does all the heavy lifting for you.


There aren't specific User element save events in Craft 3, but you can listen to EVENT_AFTER_SAVE_ELEMENT and check if the element is a user like so:

Event::on(\craft\services\Elements::class, \craft\services\Elements::EVENT_AFTER_SAVE_ELEMENT, function(Event $event) {
    if ($event->element instanceof \craft\elements\User) {
        // Do your thing.
    }
});

For user activation, there's EVENT_AFTER_VERIFY_EMAIL:

Event::on(\craft\services\Users::class, \craft\services\Users::EVENT_AFTER_VERIFY_EMAIL, function(UserEvent $event) {
    $user = $event->user
});


Cannot see local or s3 image asset source

For anyone else experiencing this issue, there wasn't actually any error shown in the Craft log file. Craft was trying to index the S3 access log files on the bucket and treating them as image files. Reindexing images didn't solve the issue either but I got my images back by deleting all entries from the craft_assetfiles table for files have the dateModified field set to NULL (these were not image files but Craft had added them to the table). [Solved by Craft Support]


How do I include record relationships in validation?

Yii/Active Record won't do this by default.  You'd need to manually add an exists validation rule to the typeId attribute to get it to behave like you're looking for.


Search only in entries with own urls checked

Got this solution from Andrew Welch/nystudio107 over on Discord:

Query for ':notempty:' in the URI, for example:

craft.entries().uri(':notempty:').all()

Docs: ':empty:' and ':notempty:'


What search engine does Craft CMS come with?

The Craft CMS documentation has some technical information about how searching works with the various Craft ElementTypes.

There is also documentation on setting up a search form.

If you're looking for a more complete and full-featured search solution, SquareBit's Search Plus is an excellent option.


Updating PHP on the server to at least 5.4 fixed the issue. This is apparently a known Imagick issue with PHP 5.3.


You can also get it with:

{% set nextYear = now.year + 1 %}


If I recall, they should get created on S3 and also cached locally.

But if I try to load https://s3-eu-west-1.amazonaws.com/rallyagency/_200x200_crop_center-center_75/princess-leia-princess-leia-walking-in-new-york-is-just-plain-awesome.jpeg?mtime=20141217123237 directly, I'm getting an "Access Denied" error, so it looks like you've got some S3 permission issues.


Get parent entry from a section using the Element API

A couple of issues:

First, the EntryModel::getParent() method returns an EntryModel, not an ElementCriteriaModel, which means that calling getParent()->first() will throw an exception. In other words, you'll need to remove the call to first().

Second, you'll need to be specific about which fields you want to return from your parent entry – just passing in the raw EntryModel won't work – so your code should look something like this:

'transformer' => function(EntryModel $entry) {
    $parent = $entry->getParent();
    return [
        'title' => $entry->title,
        'url' => $entry->url,
        'level' => $entry->level,
        'parent' => $parent ? [
            'title' => $parent->title,
            'url' => $parent->url,
            'someCustomField' => $parent->someCustomField,
        ] : null,
    ];
  },

In the above, I'm using a ternary operator to conditionally include the array containing the parent entry's data (the condition being if the parent entry exists or not). If you want your code to be less "inline", you could also do something like this:

'transformer' => function (EntryModel $entry) {
    $parent = $entry->getParent();
    $return = [
        'title' => $entry->title,
        'url' => $entry->url,
        'level' => $entry->level
    ];
    if ($parent) {
        $return['parent'] = [
            'title' => $parent->title,
            'url' => $parent->url,
            'someCustomField' => $parent->someCustomField,
        ];
    }
    return $return;
},

Finally, if you need to be specific about the parent entry's level, you'll need to swap out the getParent() method for EntryMode::getAncestors() (which does return an ElementCriteriaModel). Here's how you'd get the top level parent:

$parent = $entry->getAncestors()->first();

...and since getAncestors() returns an ECM, pulling a parent entry with a specific level is trivial:

$parent = $entry->getAncestors()->level(2)->first();


The browser reads user.userWebsite as a relative URL, not an absolute one, I guess because your user.userWebsite field does not store the protocol, i.e.: http or https.

If you don't specify a protocol in a URL a browser must assume that it is a link to a resource on your own site. The solution is to either store the protocol within userWebsite (probably the best option), or prepend it in your template, e.g.:

href="https://{{ user.userWebsite }}"


If I understand you correctly, you’d basically need it to store separate caches depending on the limit.

The way to do that would be to set a custom key on the {% cache %} tag with the using key param:

{% if postCount is not defined or not postCount %}
    {% set postCount = 12 %}
{% endif %}

{% cache using key "homepage/_latest:"~postCount %}
    {% set latest = craft.entries.section('blog').limit(postCount) %}
    ...
{% endcache %}


Custom module that can define and have settings referenced (Craft 3)

So based on a bit of research. I don't think you necessarily have to create a settings model, if the settings are purely required from a config file. You could use something like:

$settings = Craft::$app->config->getConfigFromFile('configfilename');
$exampleSettings = $settings['exampleSomething'];

$settings would be an array, which you could then access each array key.


Disabling caches in Safari results in server errors while developing Craft 3 site

If I change the mode to "production" from "dev," the errors go away,
  and as far as I can see no new error is created in the server or Craft
  log. So I can develop in production mode but I do find the dev mode
  useful.

It sounds like you're changing the environment variable ENVIRONMENT, e.g.:

ENVIRONMENT="dev"

This actually doesn't do much, it's just an arbitrary name for the environment that Craft is running in. You could call it fluffybunny and no one would mind. The only thing it affects is what settings might be used in you multi-environment config files like config/general.php.

I'd suggest reading over the Flat Multi-Environment Config for Craft CMS 3 article

Also for log file reading, the article Zen and the Art of Craft CMS Log File Reading may be useful as well.


How can I change CP language in Craft 3 after installation?

The language of CP depends on user. Therefore, you have to set Users -> admin -> Preferences and set prefered language.


How to remove Link To Category from Redactor

I don't think there's an easy way to do this natively in Craft.

Maybe you could pull it off with combination of https://github.com/lindseydiloreto/craft-cpcss and/or https://github.com/lindseydiloreto/craft-cpcjs and manipulate the DOM directly.

Or maybe by going from the Redactor site and listening to their click event.


How to implement radiobuttons field on frontend registration form?

Because radio inputs are a "single value field", meaning that when the form submits, only one value actually goes through, you don't need the extra [] array brackets at the end of each fields[] array.  In fact, you don't even need the hidden field above it.  That setup would work for checkboxes, where any number of values could be submitted. A great reference for how to format HTML form fields correctly to submit to Craft can be found on this StraightUpCraft article.

Your code should look like this:

<label>
    <input type="radio" value="yes" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>Yes
</label>
<label>
    <input type="radio" value="no" name="fields[areYouBeekeeper]" {%- if account is defined %}value="{{ account.areYouBeekeeper }}"{% endif -%}>No
</label>

And the input values yes and no need to be exactly the same (lowercase in this case) as they are in the Values column of the respective custom radio field created in the CMS.


Something like this should get you started, q is the querystring in your results url:

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query).level(1).order('score') %}
{% set grouped = entries|group('section') %}

Results for &ldquo;{{ query }}&rdquo;

        {% if entries|length %}
        {% for section, entriesInGroup in grouped %}

{{ section }}

            {% for entry in entriesInGroup %}

{{ entry.title }}

            {% endfor %}

        {% endfor %}
{% endif %}

Not sure how pagination fits in here but I'm sure others will chime in.


How would I change "disabledElementIds" when using createElementSelectorModal()?

Elements can be manually enabled/disabled from the modal after it has been initialized using the following methods:

myModal.elementIndex.enableElementsById(elementIds);

and

myModal.elementIndex.disableElementsById(elementIds);

Both functions accept a number (single element ID) or an array of numbers (multiple element IDs).


Matrix field validation on guest entry submission

To grab validation error of a matrix field -> first block type -> field, you must access entry's matrix field with the function first() and than access block type field using getError("fieldHandle") function at the end of ElementCriteriaModel like so.

{{ entry.matrixField.first().getError("customFieldHandle") }}

or to the question related problem

{{ entryError.cart.first().getError("productQuantity") }}

Doing this way you don't have to loop through Matrix's blocks and it make sense if you need to access first block type only or you have only one block type.

To show validation error under each block.type of a custom field you'll have to loop in MatrixBlockModel of the cart channel like so.

{% if entryError is defined %}
    {% for block in entryError.cart %}
        {% if block.getErrors() %}
            {{ block.getError('productQuantity') }}
        {% endif %}
    {% endfor %}
{% endif %}

Like Brad pointed out to me in support ticket "you can decide how you want to display them".


Custom element index page (cp) sortable on dateCreated?

The issue was in the modifyElementsQuery function. When you select all columns addSelect('*') to the query your SQL will select the dateCreated and dateUpdated columns of your custom table as well.
As soon as you want to order by one of those columns the database does not know which dateCreated should be sorted.

You need to select only the unique attribute columns in your custom element table.

To debug your score sorting issue the best thing is to go into craft/app/elementtypes/BaseElementType.php and check the function getIndexHtml. You can var_dump the results of the following variables

// Combine them, accounting for the possibility that $order could contain multiple values,
// and be defensive about the possibility that the first value actually has "asc" or "desc"

// typeId             => typeId [sort]
// typeId, title      => typeId [sort], title
// typeId, title desc => typeId [sort], title desc
// typeId desc        => typeId [sort]

$criteria->order = preg_replace('/^(.*?)(?:\s+(?:asc|desc))?(,.*)?$/i', "$1 {$sort}$2", $order);

and compare the output with default Entry fields.


How can I output a list of categories that are not empty?

To get all categories that are related to an entry you would do this:

{% set allEntries = craft.entries.limit(null) %}
{% set categoriesInUse = craft.categories.relatedTo(allEntries) %}

If you want to narrow down to a specific category group or any other category property you can do it like so:

{% set newsCategories = craft.categories.group('newsCategories').limit(null) %}
{% set entriesWithNewsCategories = craft.entries.relatedTo(allCategories).limit(null) %}
{% set newsCategoriesInUse = craft.categories.relatedTo(entriesWithNewsCategories) %}

And yes, you probably want to wrap it together with the loop to print the categories in cache tags!


In order to pull this off, you'll need to take advantage of the not very well  documented _context variable in Twig.  This should do it:

{% set language = 'fr' %}

{% set foobar = _context[language ~ "_foobar"] is defined ? _context[language ~ "_foobar"] : null %}

{% if foobar %}
    {{ foobar.globalAddress }}
{% endif %}


Plugin Settings UI for saving an array of values

You can use the EditableTable template component (i.e. the same UI component that Table fields use).

Note that this will only work inside the Control Panel – not on the front end. The title of this question says "Plugin settings", so I'm assuming that's your actual use case.

Here's how:

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

{{ forms.editableTableField({
    label: 'Some setting',
    instructions: 'Some instructions here',
    id: 'someSetting',
    name: 'someSetting',
    cols: [
        {
            heading : 'Some column',
            type: 'select',
            options: [{label: 'Foo', value: 'foo'}, {label: 'Bar', value: 'bar'}]
        },
        {
            heading : 'Some other column',
            type: 'singleline'
         },
    ],
    rows: settings['someSetting']
}) }}

As long as the setting you use with the table (someSetting in the example above) has AttributeType::Mixed, Craft will automatically handle serialization for you (the rows you input in the table will be stored as a simple JSON object in the database, just like Table fields are stored).

Note that each column entry can have a type of singleline, multiline, number, select or checkbox. If you don't declare a type, the column will render as a PlainText field.

Also note that the variable settings (which is passed to the rows parameter) refers to an array of your plugin's current settings – meaning you'll need to pass those to your settings.html template like this (the following method should go in your plugin's primary class):

public function getSettingsHtml ()
{
    return craft()->templates->render('yourpluginhandle/settings', array(
        'settings' => $this->getSettings(),
    ));
}

Of course, you can pass additional variables to the settings template – such as a pre-populated array of label/value pairs to use for any dropdown (select) fields inside the table.

If you're unfamiliar with Twig macros, I recommend taking a look at the official docs on the subject (if only to understand the syntax used, and the import statement).

Also, here's the source for the editableTableField macro, which could prove useful.


Is there any way of converting an existing field to a Matrix?

Unless each time an Entry is selected the name needs to be different (to other times that same Entry is chosen), then I would suggest using your latter approach of adding an secondary Title field as it would be more efficient in the long term because the secondary Title would only need to be added once.

If it's about an Entry, consider keeping it 'with' the Entry.

I use a similar approach for Meta Titles to override the Entry title for SEO purposes.


How to limit selected items that appear on special page

Just add an Entries field to the home page Single and limit it to 5? That also allows designated users to decide what appears on the home page.


Return entries where custom field partially contains

You could use the Preparse plugin to save the product ID part of your field in a new hidden field.

Add a new "productId" Preparse field to your entry type with this code in the field's settings:

{{ entry.customField|split('-')|first }}

To update all existing entries, re-save them by going into Settings → Sections → Section Name and click Save.
You can now set up a criteria model exactly like you mentioned in your question, except that you now use the
Preparse field as your custom field parameter:

{% set entries = craft.entries.section('sectionName').productId(pluginIds) %}


Images missing from Entries, but still on server

Clear the caches after updating the assets index, asset indexing data at the very least, though I'd normally clear everything to be sure.


Craft Migration fails (SuperTable propagationMethod)

On the chance that anyone is having this same issue, here is what I needed to do to fix the issue (based on help provided by Craft's Support -- many thanks to them):

The Super Table plugin was out of date. The admin panel didn't show the issue and a composer update didn't either. I had to manually update the composer.json file to reflect the current Super Table version, "verbb/super-table": "2.4.9". Then I was able to clear the composer cache and run an update. The migration then worked just fine.


How to display an asset (pdf) from both site languages on both sites?

You could try and fetch the other pdf by creating an entry query for the different language, and getting the pdf from there.
{# if you have only 2 languages: #}
{% set otherLanguage = craft.entries().id(entry.id).siteId(['not', entry.siteId).one() %}
{{ otherLanguage.PDF.url }}

{# if you have more languages (and want all the PDFs: #}
{% set otherLanguages = craft.entries().id(entry.id).siteId(['not', entry.siteId).all() %}
{% for $otherLanguage in $otherLanguages %}
    {{ otherLanguage.PDF.url }}
{% endfor %}


It looks as if there is a Content-Security-Policy header that may also do what you want. You should be able to use the header tag to set this:

{% header "script-src: 'self' https://api.github.com/;" %}


Get data from another loop from outside the current loop

Interesting. I'm not able to test this right now, but I think this should work...

You could first loop through the results, adding them to an array as you go...

{% set guestNameValues = [] %}

{% for row in partnerGuestList.guestNames %}
    {% set guestNameValues = guestNameValues|merge([row.guestName]) %}
{% endfor %}

And then within your loop that displays the fields set the value as...

{{ guestNameValues[loop.index0] }}

That should get the corresponding name from the array you previously set.


Craft creates an EntryModel for each Single Section, that allows you to access the URL property you are after. You can get the (one) EntryModel using the Section's ID and the first() method:

{% set singleSectionEntry = craft.entries.sectionId(singleSection.id).first() %}

{{ singleSectionEntry.title }}


Assets Uploader Just Spins and Does Nothing Else

The solution was to use MAMP Pro instead of MAMP free. i cannot answer with complete authority why, but MAMP Pro has abilities that MAMP free doesn't.


How to determine source of Elements save event

First, you'll want to check if what is being saved is a draft or revision, and if so, ignore it for your purposes. You can check via:

use craft\helpers\ElementHelper;

if (!ElementHelper::isDraftOrRevision($element)) {
}

Next if you want to avoid doing anything during "bulk saving events", on Craft 3.1.22 or later there is:

if (!$element->resaving) {
}

...which was added in Craft CMS 3.1.22

Some additional discussion that might be useful: Improve behaviour for automatic resaving of entries when saving an entry type


Might I suggest that a Craft task might not be the best way to pull off what you're trying to achieve.

By default, they will be triggered by the next control panel request, no matter when that occurs.

Sure you could build in some timing logic in your plugin, or set the runTasksAutomatically config setting to false and have a cron job hit the task at your set schedule, but that all seems overly complicated.

Just setup an independent cron job to fire when you need your logic to run and have it hit a custom plugin's controller's action and run your logic directly outside of Craft's task implementation.


It's tempting to use the Matrix block for things that might actually be better as a a channel or a structure.  I thing this might be the case here.

The way you've set it up is fine, relating each FAQ to a category is a good approach.

In any event, the plugin groupBy should help you:

https://github.com/timkelty/groupby-craft

Or you can look at this example:

http://craftcookbook.net/recipes/279


How do I pass existing template variables on to an action controller?

Not really a direct answer to your question, but you could also perhaps remove the additional controller routing business and move your conditional logic into a plugin variable (or service method called from your variable).

{% if craft.myPlugin.everythingsOk(entry) %}
    // everything's ok, render template
{% endif %}

Your variable:

public function everythingsOk($entry)
{
    // Do some conditional checks

    if (craft()->myPlugin->doChecks($userId, $entry))
    {
        return true;
    }
    return false;
}


How could I have a plugin hook into when I edit or update a post?

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

Example:

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

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

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

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

        }
    });
}

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


How is "craft()->fileCache" different from using cookies?

Correct... craft()->fileCache will save to your craft/storage/runtime/cache folder by default, which will have a .bin file that has a hash of the key you provided when calling set() and the contents will be a serialized version of the value you passed in.

Also worth noting that while craft()->fileCache still exists, as of Craft 2.0, it is simply a shortcut to craft()->cache, when the cacheMethod config setting is set to file.


Zero dollar Commerce orders - payment how-to?

Stripe, like most payment providers will most likely not allow $0 payments.

In this case, the typical approach is to set up the manual gateway in addition to stripe,  and detect if order.totalPrice is $0, then simply change the paymentMethodId to the manual gateway id as you submit. The manual gateway will happily complete with a $0 total.


Add custom column to Entry Type index page

Unfortunately, that's not possible currently.

If you feel that a hook for customizing the Entry Type listing/index should exist, you can add a feature request.


Is there a way to treat variants in a similar way as products?

Put simply, if you define the url for your product type as, say,

products/{categories.first().slug}/{slug}

...then if you visit this url (products/pillows/my-pretty-pillow) you would perhaps loop through and show all variants.

When they hit a url like products/pillows/my-pretty-pillow/green (to make this url work you'd need to define a route to point at the same template I think -> products/pillows/*/*)

....then you can simple look at craft.request.getSegment(4) and use that to determine which specific variant to show at that url.

(This is  much the same question actually:
How do I select a specific product variant by element/field/entry?)


How to get all images from entries including Matrix field

I doubt there is a good solution in twig but you can fetch the entries with php.

First you have to get all used asset Ids. So you'll check in the relations table for all used assets with your 2 fields and for entries with your section ids

public function getAllAssetsRelatedToEntries(){
    // list the ids of the sections, so you need the id of news, information and events
    $sectionIds = [2, 7];
    // id of your insertedImage field
    $fieldIdMatrixContent = 6;
    // id of your imageGallery field
    $fieldIdImageGallery = 7;

    // fetches all assets that have a relation in the matrix field
    $imagesFromMatrixContent =  craft()->db->createCommand()
        ->select('craft_relations.targetId')
        ->from('relations')
        ->join('matrixblocks', 'craft_matrixblocks.id = craft_relations.sourceId')
        ->join('entries', 'craft_entries.id = craft_matrixblocks.ownerId')
        ->where('craft_relations.fieldId = :fieldId', ['fieldId' => $fieldIdMatrixContent])
        ->andWhere(['in', 'craft_entries.sectionId', $sectionIds])
        ->queryColumn();

    // fetches all assets that are related with the ImageGallery Field
    $imagesFromNormalField = craft()->db->createCommand()
        ->select('craft_relations.targetId')
        ->from('relations')
        ->where('craft_relations.fieldId = :fieldId', ['fieldId' => $fieldIdImageGallery])
        ->join('entries', 'craft_entries.id = craft_relations.sourceId')
        ->andWhere(['in', 'craft_entries.sectionId', $sectionIds])
        ->queryColumn();

    return array_unique(array_merge($imagesFromMatrixContent,$imagesFromNormalField));
}

This will return you an array of all ids, thus you can build your paginate or other queries like you want and change the sort order or include other conditions

{% set allAssetIds = craft.pFplugin.getAllAssetsRelatedToEntries() %}
{% paginate craft.assets.id(allAssetIds).kind('image').limit('30') as pageInfo, usedPhotos %}

The next step will be to search the entries for each asset

public function getAllEntriesForAsset($assetId)
{
    // list the ids of the sections, so you need the id of news, information and events
    $sectionIds = [2, 7];
    // id of your insertedImage field
    $fieldIdMatrixContent = 6;
    // id of your imageGallery field
    $fieldIdImageGallery = 7;

    $entryIdsFromMatrix = craft()->db->createCommand()
        ->select('craft_matrixblocks.ownerId')
        ->from('relations')
        ->join('matrixblocks', 'craft_matrixblocks.id = craft_relations.sourceId')
        ->where('craft_relations.targetId = :assetId', ['assetId' => $assetId])
        ->join('entries', 'craft_entries.id = craft_matrixblocks.ownerId')
        ->andWhere('craft_relations.fieldId = :fieldId', ['fieldId' => $fieldIdMatrixContent])
        ->andWhere(['in', 'craft_entries.sectionId', $sectionIds])
        ->queryColumn();

    $entryIdsImageGallery = craft()->db->createCommand()
        ->select('craft_relations.sourceId')
        ->from('relations')
        ->where('craft_relations.targetId = :assetId', ['assetId' => $assetId])
        ->join('entries', 'craft_entries.id = craft_relations.sourceId')
        ->andWhere(['in', 'craft_entries.sectionId', $sectionIds])
        ->andWhere('craft_relations.fieldId = :fieldId', ['fieldId' => $fieldIdImageGallery])
        ->queryColumn();

    return array_unique(array_merge($entryIdsFromMatrix,$entryIdsImageGallery));
}

In your template

{% set entriesForAsset = craft.pFplugin.getAllEntriesForAsset(asset.id) %}
{% for entry in craft.entries().id(entriesForAsset).order('title') %}
    {{ entry.id }} {{ entry.title }}
{% endfor %}

In total it could look like this I just did not use the paginate

{% set allAssetIds = craft.pFplugin.getAllAssetsRelatedToEntries() %}
{% for asset in craft.entries.id(allAssetIds).find() %}
    {{ asset.id }} {{ asset.title }}
    Entries for Image<br>
    {% set entriesForAsset = craft.pFplugin.getAllEntriesForAsset(asset.id) %}
        {% for entry in craft.entries().id(entriesForAsset).order('title') %}
        {{ entry.id }} {{ entry.title }}
    {% endfor %}
{% endfor %}


Import large number of entries every day - 1 million

You could write a service method that reads the import file and divides it into chunks, then it could dispatch a queue job for each chunk which does the actual entry creation/update. This way you could scale the resources and amount of queue workers available to work through the queue and even Play with the chunk size.
In the queue job you might want to implement proper exception handling to keep track of unsuccessful entry operations to handle them somehow.


You can get the current section handle from the entry like so

{{ entry.section.handle }}


How to pull entries with Date Created > start and < end?

Here is syntax you can use to search a date field between two dates.

$startDate = date('Y-m-d', strtotime($settings["start_date"]["date"]));
$endDate = date('Y-m-d', strtotime($settings["end_date"]["date"]));

$criteria->dateCreated = ['and','>= '.$startDate, '<= '.$endDate];


Not currently, I'm afraid as that config setting is taken into account on a per-element (i.e. entry), basis.

Feel free to make a feature request for it here, though: https://github.com/craftcms/cms/issues


You can certainly restrict user's access to specific sections on a Craft site, using Craft Pro's user and user group permissions, both in the control panel and on the front-end.

Lots of different ways to setup these "sub-sites", but it sounds like you'll be wanting them to share the same Craft installation.


How do I use the Element API to search via entry title?

Following is an example of using the search feature in a GET request with parameter 'search'.

return [
    'elementType' => 'Entry',
    'criteria' => ['search' => (craft()->request->getParam('search')) ? 'title:'.craft()->request->getParam('search') : '' ],
    'paginate' => true,
    'elementsPerPage' => 10,
    'pageParam' => 'pg',
    'transformer' => new ListTransformer(),
];`

I assume you can use this instead of the custom transformer class that is being used in the above example:

'transformer' => function(EntryModel $entry) {
    return [
        'title' => $entry->title,
        'url' => $entry->url,
        'summary' => $entry->summary,
        'body' => $entry->body,
    ];
},


Craft Commerce Trigger Event to Re-save All Products

There are probably many approaches, but you could write a simple console command (great guide here: https://spin.atomicobject.com/2015/06/16/craft-console-plugin/) in a plugin to do this.

Here's one I prepared earlier to use as an example...in my case I am doing this because I am using a pre-parse field that pulls in some external markdown content, but the principle is the same (assuming re-saving the entries updates the title field as you hope - but should take only a few mins to try!) - you'll need to adapt for commerce (Commerce_Product I think):

<?php
namespace Craft;

class BusinessLogicCommand extends BaseCommand
{
public function actionResaveFODEntries()
{
    print("### Resaving entries for Fundamentals Of Digital\n(So search indexes are updated by causing PreParse to re-pull in the generated content).\n\n");

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

    foreach ($criteria as $entry)
    {
        $success = craft()->entries->saveEntry($entry);

        if (!$success)
        {
            print("Failed to save entry $entry->title\n");
        }
        else
        {
            print("Saved $entry->title\n");
        }
    }
  }

}

To actually run the command I do this:

php yiic-env.php --env="console" businesslogic resaveFODEntries

...note the use of a specific environment, console in there - this is defined in my config/general.php with appropriate settings


How can I reduce the number of queries when including a related item within a for loop

Update:

I'll leave the original answer because they're certainly still viable options, this is now probably best solved by using the eager loading features that Craft 2.6 added.

A bit difficult to properly debug without seeing things like your content architecture, database profiling information, logs, etc.

But using the {% cache %} tag is certainly an option here.

If you're adverse to that, then you could also use a template hook that goes to a plugin method that would "eager load" the data you know you'll be needing for this particular page directly from PHP.

You can search Craft's app folder for '{% hook' to see how we're using that for the CP in a few places as well.


Help with the latest Redactor, removing formatting options

Inside the buttons array, you should only mention formatting.
The actual styles you want to put inside an array with key "formatting".
{
  "buttons": [
    "html",
    "formatting",
    "bold",
    "italic",
    "unorderedlist",
    "orderedlist",
    "link",
    "image",
    "video"
  ],
  "formatting": ["p", "h2", "h3", "h4", "h5"],
  "plugins": [
    "fullscreen",
    "video"
  ],
  "linkNewTab": true,
  "toolbarFixed": true
}

Reading a bit further in the docs, you could also remove the styles you don't want, instead of stating the ones you do want:
formattingHide: ["blockquote", "pre", "h1"]


How can retrieve users custom fields only?

You can do this by going via the element's field layout:

$user = \craft\elements\User::find()->id(1)->one();

$fields = $user->getFieldLayout()->getFields();

This will return you an array of all the fields (fields, not values) attached to your user.


Is there a CacheService equivalent in Craft 3?

It's still there, but you're working at the Yii2 layer: The Definitive Guide to Yii 2.0: Data Caching


How can I link to an Asset from the Rich Text editor?

This isn't really related to Craft specifically, but to allow a user to link to an asset, you will need to enable the feature in the redactor configuration file.

For example, within this file:

/craft/config/redactor/Standard.json

You will see something like this:

{
    "buttons": [
    "html",
    "formatting",
    "bold",
    "italic",
    ...

You will need to add file to that list so that it looks like this:

    {
    "buttons": [
    "html",
    "formatting",
    "bold",
    "italic",
    "file"
    ...

Make sure to clear out your cache to make sure that Craft can see your updated file.

Now when you highlight some text, you can choose "file" and then select an asset from one of your asset sources.


Filtering/Searching fields with enumerated data (e.g. Smart Map) in an ElementCriteria model

UPDATE
As of Smart Map 2.3.0, this is now possible!

https://plugins.doublesecretagency.com/smart-map/filtering-entries-by-subfield-value/

ORIGINAL
Currently, this isn't possible. However, it's a popular feature request which is rising quickly on the priority list.
The current workaround (as you noted) is to simply filter the results afterward.


How do you import tags from EE (solspace tags) along with entries?

I would use the "Feed Me" plugin which allows to import entries including tags from feeds (XML, RSS, Atom). So you only have to create an XML feed with all the information you want to transfer (which is in EE quite easy).


If you're talking about querying using SQL directly, then the craft_elements_i18n table is where all of the slugs are kept.


I take it you are on the category template as defined in admin/settings/categories/:id.

You should have a model representation of the category assigned to category in the template, so you should be able to get the current category id by simply doing {{ category.id }} in the template.

Your code could look like:

for cat in craft.categories.group('productCategories').descendantOf(category.id)


Building a nav from the top level page of a structure

Untested, but you should be able to do this by using the merge filter in Twig to join the two results together.

Get the top level 'landing page' for this section:

{% set landingPage = entry.getAncestors().level(1) %}

Get the descendants for this section:

{% set childPages = entry.getAncestors().level(1).getDescendants() %}

Merge the two results together:

{% set sectionPages = [ landingPage ]|merge(childPages) %}

Now create the navigation for the section using the sectionPages variable:

        {% nav page in sectionPages %}

                {{ page.getLink() }}

                {% ifchildren %}

                        {% children %}

                {% endifchildren %}

        {% endnav %}


Looking to export product listings from Salesforce and importing into Craft Commerce?

Generally speaking, it looks like you'd need to create a Craft plugin that imported the Salesforce PHP Tookit library/classes.  From there you'd query your Salesforce web endpoint for the data you're looking for.

Once the data gets back, you'd programatically create the products using Commerce's service layer API.  You can see any example of that Commerce uses itself to populate default content on a fresh installation in the Commerce_InstallSeeder class in commerce/Commerce/Seed.


Getting orders by property in Commerce 2 from Plugin

use craft\commerce\elements\Product;

$products = Product::find()->orderStatus(1)->all();


How to find number of assets inside a matrix block?

Yeah you should be able to do something like

{{ block.assetField|length }}


How can I interact with Users via the ElementAPI?

Change

function (EntryModel $user)

to

function (UserModel $user)

You were passing in a user to a function that’s expecting an EntryModel. That’s the reason for the error you are getting.


Multiple issues with User Registration from frontend

The form submits and the user is created, but no verification email is sent and the user is not assigned to the group I selected in User Settings.

That sounds like there is a validation error is happening in your form on the UserModel.  Perhaps on a required custom field. You didn't share your form, but is it checking for errors?

  If I manually send a verification email, following the link causes the user to be verified, but still not added to any Group.

Make sure you're not running any plugins that might be interfering listening to the onSaveUser event.

  Further, the user is redirected to http://sitename/dashboard, despite having a redirect set in the Config > General file.

That's a bug that's been fixed for the next (post 2.6.2791) release.


Why am I getting error: Object of class Craft\ElementCriteriaModel could not be converted to int

The ElementCriteriaModel is an object that prepares your queries. For example when you do craft.entries you'll receive an ElementCriteriaModel where you can insert ids, sections, relations and many other attributes until you finally fetch your entries with find(), first() or ids().

When you have a relation field attached to the entry the values of these fields are objects of type ElementCriteriaModel too, so you have a ready to use query that can be executed.

This class has an iterator interface, that means the method find() is executed when you loop through it, that being said for image in entry.images does actually for image in entry.images.find(). Thus many people think entry.images contains an array of elements rather than one single element.

So - for future reference - when you ever receive an error like

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

It's likely you treated your ElementCriteriaModel as an array or element or string or whatever the error explains.

In your special case it was just a syntax error: change gridImages.length to gridImages|length


Dynamic link to same entry but in alternate language

Both SEOmatic for Craft 2 and SEOmatic for Craft 3 have built-in functions to give you these URLs. I'm not sure which you are using so...

For Craft 2: https://github.com/nystudio107/seomatic/wiki/15.-Utility-Filters-&-Functions#getlocalizedurls

For Craft 3: https://github.com/nystudio107/craft-seomatic#helper-functions-seomatichelper


Show entries by a certain category AND certain lightswitch

You can add the lightswitch filter to the entries query like so:

{% set category = craft.categories.slug('copier') %}
{% set entries = craft.entries()
                      .section('products')
                      .relatedTo(category)
                      .color(true)
                      .all() %}

{# If there are any entries, loop through them #}
{% if entries | length %}

    {# For each entry we find, do this #}
    {% for entry in entries %}
        <p>{{ entry.title }}</p>
    {% endfor %}

{% endif %}


Your MySQL configuration has its max_allowed_packet config setting set to the default 42M (4194304).

There's a query that executed for database backup that is slightly larger than that (about 44M).

You'll need to increase that value in your MySQL config or ask your host if they can do it for you if you want to import the backup without any errors.


Does Craft have a styleguide for the admin, like Bootstrap?

Already found the answer, it seems it has a js lib called Garnish for UI interaction, and some grid system. Both are undocumented as of yet.


It’s not currently possible to disable that behavior altogether, but you can increase the number of times the user can enter the incorrect password before their account gets locked using the maxInvalidLogins config setting.

You can also customize how long Craft will track invalid logins before that maxInvalidLogins counter resets using the invalidLoginWindowDuration config setting.

For example you, if you wanted the users to get locked out if they entered more than two* incorrect passwords in 10 seconds, you could set these in craft/config/general.php:

'maxInvalidLogins' => 3, // see the note below
'invalidLoginWindowDuration' => 'PT10S',

You can also customize what happens when a user gets locked out with the cooldownDuration config setting. By default they will only be locked out for 5 minutes, so it’s not actually necessary for an admin to log in and unlock their account. That would only happen if the config setting was set to 0.

*There’s actually a bug in Craft right now where a user will get locked out as soon as they’ve hit the maxInvalidLogins count, which I think is incorrect; if the setting is set to 2, they should be able to login incorrectly 2 times, and still have a 6th chance to get it right. I’ve just adjusted that behavior for the upcoming 2.2 release.


How to remove entire Craft CMS folder? or rather uninstall it

To delete craft, all you need to do is delete the craft/app folder, so you don't lose all your templates/plugins etc. That said, this won't affect your site url as siteUrl stored in the database.

Here are a few options:

You would need to go into the database under the table craft_info and then change siteUrl back to localhost or whatever you need it to be.
If you have only just gone through the installation page then you can just delete the database and start again.

My most preferred thing to do to avoid these sort of issues is to set the siteUrl within a config file and simply reference it.

For example in craft/config/general.php you would have:

return array(
 '*' => array(
   'environmentVariables' => array(
     'siteUrl' => 'localhost'
   )
 ),
 '.com' => array(
   'environmentVariables' => array(
     'siteUrl' => 'http://somedomain.com'
   )
 )
);

So basically here we are setting the siteUrl config within a wildcard config using * which means it gets applied to all environments.

Straight after we are then overriding the siteUrl config for just .com domains.

See Multi environment config and Multi environment variables

The beauty of this is now when you install Craft (or change siteUrl in the database) you only need to put {siteUrl} within the input and Craft will automatically fetch the value from your config file, based on your environment.

Hope that helps!


Site will not load. Asking me to save "login" as a file

You need to remove this when running local.  The following piece of code is added on servers running the EasyApache4 PHP Handler.

# php -- BEGIN cPanel-generated handler, do not edit
# Set the "ea-php70" package as the default "PHP" programming language.

  AddType application/x-httpd-ea-php70 .php .php7 .phtml

# php -- END cPanel-generated handler, do not edit


htaccess non-www rewrite showing index.php in URL

Check out the official Apache documentation on Canonical domain rewrites: https://httpd.apache.org/docs/2.4/rewrite/remapping.html#canonicalhost