Accessing array/object attributes in Twig

{{ entry.title }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 19, $this->source); })()), "title", []), "html", null, true);

...and
    {{ entry['title'] }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 20, $this->source); })()), "title"), "html", null, true);

...and
    {{ attribute(entry, 'title') }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 21, $this->source); })()), "title", [], "array"), "html", null, true);

If they look similar, that's because... they are identical in terms of the PHP code they compile down to.
So the difference is... whichever one uses the fewest keystrokes to type.


Is it possible to output Profiling Summary Report (devMode)

Off the top of my head, I don't think it's going to be possible, at least in the context of outputting it from a Twig variable.  That info comes from Yii's CProfileLogRoute class, which Craft extends at etc\logging\ProfileLogRoute.

But with all of Yii's logging, that stuff doesn't get flushed to disk (for FileLogRoute) or to the browser's console (for ProfileLogRoute) until the very end of the request, which will be after the template has already rendered.

If you view source with devMode enabled, you can see they just append it to the very end of the DOM.

Maybe you could write a plugin that used craft()->log->addLogRoute() that added your own custom ProfileLogRoute that extended Craft's and instead of appending to the end of the DOM, added it to some other part of the template, but seems like a pretty brittle solution.


Asset upload fails with progress bar at full, but images in tempuploads folder

My own fault – I had set a subpath in the field type, so it tried to save to a folder that didn't exist.

I had first thought it was here the asset path was set, and when I figured out I needed asset types, I forgot to delete the subpath.

Now it works! Both with Imagemagick (local) and GD (live server).


I think you just need to get rid of the [] on the field name, so your field becomes:

<input type="hidden" name="fields[questionStatus]" value="answered">

As long as the value is the same as the value in the dropdown, it should change.

I think the issue you are getting is because you are telling the field that its value is an array, where you just need to pass the actual value as a string and Craft will figure out the rest :)


The answer to this is that in the general.php I had a setup which somehow was giving trouble when setting siteUrl. Things were like this:

return array(
    '*' => array(
        'omitScriptNameInUrls' => true,
    ),
    'siteUrl' => array(
        'ru' => 'http://www.mysite.com/',
        'en_us' => 'http://www.mysite.com/en/'
    )
);

While seemingly correct, in this setup siteUrl should be moved into '*' block, otherwise there comes the problem that I described earlier. So the correct version is this:

return array(
    '*' => array(
        'omitScriptNameInUrls' => true,
        'siteUrl' => array(
            'ru' => 'http://www.issuesinlinguistics.ru/',
            'en_us' => 'http://www.issuesinlinguistics.ru/en/'
        )
    )
);


Craft 3 Plugin: Saved image asset has no width / height

As Andris Sevcenko pointed out, the problem is Craft 3 Beta 22 and a Multisite Configuration. Fixed in Beta 23.


Empty relation field validation failed with Guest Entries plugin

It looks like it's doing what it should. When you set a field to 'required', you are basically telling the system to not let the entry be saved if you haven't filled out the field you've set 'required' on. That's what this error saying (albeit at a database level).

Two quick solutions as I see it...

Always make sure you have a default value that can be used for this
field. So you aren't violating the 'required' setting.
Remove the 'required' option from the field in the CP.

EDIT: In the Plugin settings in the CP, have you turned on the Validate Entry lightswitch for the section you are adding to on the front end? Only I've just had a quick play around with the plugin myself, and I get a validation error when I don't submit an entryId for the related section on the front end form. So it looks as though it's working as expected.

I used this to get the errors...

{%for error in guestEntry.getAllErrors %}
    {{ error }}
{% endfor %}

I also just used the default config file guestEntries.php as suggested in the README...

<?php

return array(
    'entryVariable' => 'guestEntry',
);


Options not rendering on Sprout Reports report

It looks like the issue here is that the Results Template and Options Template include the file extension .twig. Removing the extension .twig should get things working:

_reports/dealer-export/options

I've added it to our list to improve this functionality in the future. We should be able to strip off the extension behind the scenes or do what we need to do with it regardless of whether you add it or not. Sprout Reports does loop through and check for all supported extension types for your site on the back end when no extension is provided.


Import body field into a matrix text block

Nevermind. Clearbold's Craft Import plugin has the starting code for it.

// new entry
$entry = new EntryModel();
$entry->sectionId = 1;
$entry->typeId    = 12;
$entry->authorId  = 123;
$entry->enabled   = true;
$entry->getContent()->title = "Here goes my title!";

// new matrix and matrix block
$block = array();
$block['new1'] = array(
    'type' => 'body',
    'enabled' => true,
    'fields' => array(
        'text' => 'Here goes my article.'
    )
);

// add content to entry including created matrix
$entry->setContentFromPost(array(
    'description' => "And of course the description...",
    'matriz' => $block,
));

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


Calling an event from a third party plugin in my plugin

craft()->on('amForms_submissions.saveSubmission', function(Event $event) {
    BusinessLogicPlugin::log(print_r($event, true));
});

Pay attention to the casing
Craft\AmForms_SubmissionsService → amForms_submissions

https://craftcms.com/docs/plugins/hooks-and-events#listening-for-events


How would I pull in the first Matrix block including certain blocks only

Give this ago.

It will grab the first block that is either "Text" or "Text Image" and then you can use a switch statement to output your template depending on the block type.

{% set firstTextBlock = entry.body.type(['text', 'textImage']).first() %}

{% switch firstTextBlock.type %}

    {% case 'text' %}

{{ firstTextBlock.textContent|hacksaw(chars='100', append='...') }}

    {% case 'textImage' %}

{{ firstTextBlock.text|hacksaw(chars='100', append='...') }}

{% endswitch %}


No, that’s the whole point of Live Preview, to update and preview the changes “live”.

If that’s not what you want you can save the entry via “Save an continue editing” (keyboard shortcut CMD+S) and then view the changes by clicking the “Entry link” button.


MAMP: Craft can’t connect to the database with the credentials in craft/config/db.php

The default MAMP DB credentials are indeed root:root, as you have already, so you should check that you did indeed create a database (set up as detailed here) and that it is indeed called ‘mycraft’.

Also check in your MAMP control panel that the MySQL is actually running:


This is a known behavioral issue. PHP considers 0, "0", false, and similar values to be “empty”, and Craft only factors most criteria param values into the query if they are not empty. So setting a Lightswitch field’s criteria param to '0' is the same as not setting it at all.

The workaround is to use not 1:

{% set results = craft.entries.section('events').lightSwitchField('not 1') %}


Why can't I log in anymore when I change primary site manually in database?

Craft 3.6.10 is out now with a fix for #7657. Note that the fix is not retroactive, so if you already have multiple sites in your project config YAML with primary: true, you should run php craft project-config/rebuild to fix that.


Use global values in the Entry URL Format field

Your CraftCMS global can be accessed using the code

{{craft.globals.getSetByHandle('siteDefaults').artworksList.first.uri|default}}/{slug}

I believe the issue is that the Entry URL field requires you to use craft.globals to prevent issues with the routing custom variables.


Add fields/custom fields to page in the admin page (backend)

Craft CMS is a full-featured CMS. You should not need to use PHP at all unless you need very custom functionality.

It sounds like what you should do is create an "Articles" Section, and add whatever fields you need for articles into that section's layout. Then you'll have a nice user-friendly way to enter content on the backend.

Please see: Sections and Entries


This recently tripped me up. 'true' (with quotes) is not the same as true (without the quotes).

Lose the quotes in the config file, clear Craft's caches, and it should stick.

Also make sure your siteUrl is the same as what your web server is configured as. If you have a redirect in there, say www.example.com goes to example.com, and your siteUrl is configured to use the former, that seems to trip up Craft's check too.


Can admin receive email notifications of new user registrations?

I believe you would need a plugin for this — but the plugin can be really basic. In your plugin's main file simply add an 'init' method that listens to the 'users.saverUser' event and checks the 'isNewUser' event attribute; then prepare and send your email.

The process is outlined in this answer that sends out an email to members of a userGroup when an entry is saved. Same principle would apply, just using users.saveUser instead.

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

    craft()->on('users.saveUser', function(Event $event)
    {
        $user = $event->params['user'];
        $isNewUser = $event->params['isNewUser'];

        if ($isNewUser) {
            // Send Mail
            $email = new EmailModel();
            $email->toEmail = "user@email.com;
            $email->subject = 'New User Registration';
            $email->body    = 'New User: '.$user->firstName.' '.$user->lastName;

            craft()->email->sendEmail($email);
        }

    });
}


The Craft Plugin Store is where you'd go to look for existing plugins/solutions for this.
The two I'm aware of that are related are:
https://plugins.craftcms.com/star-ratings
https://plugins.craftcms.com/upvote
Otherwise, you'd probably be looking at some custom plugin development.


Craft 3 best way/steps to create a login client area in frontend

I don't know any plugins that do that for you since it's integrated in Craft by default. There are Registration forms as well as Login form examples and you can create Entry forms as well.

For gating content behind logins there is the requireLogin tag which will automatically redirect you to your login route and after a successful login return to the url you wanted to visit.
Not sure what else you might need since your question is really broad.

After a registration Craft will certain system messages (utilities -> systemmessages) with activation links for their account (double-opt-in). In case a user lost/forgot his/her password you can send them a new one automatically.

You can check certain config values such as loginPath or postLoginRedirects as well.


With a categories field, how do I query only the *selected* categories?

Here's how to isolate only your chosen categories. This works off the premise that if a related category is a parent of one of the other related categories, it is not a category you chose.
{% set relatedCategories = entry.myCategoryField.with(['parent']).all() %}
{% set parentCategories = relatedCategories | map(c => c.parent) %}
{% set chosenCategories = relatedCategories | diff(parentCategories) %}


Craft front-end forms not working with Angularjs app

Okay so I figured it out. Turns out a form won't submit in an Angular app if it doesn't have an action specified.


Prevent to upload any kind of file on Asset menu

The ability to restrict the allowed file types is defined on a per-field level.

In order to do what you're looking for, it would have to be defined on a per-asset source level, so no... it's currently not possible natively.


Rotate image according to EXIF orientation not working from a plugin

The best way to do this would be to follow the same flow that Craft does - clean the filename, move to a temporary location, operate from there and afterwards delete the temporary file.

Craft has an example in it's codebase to help you out. Just remember to delete the temp file afterwards.


Dashboard Widget: Access widget settings from controller / service

found a way to solve the problem.

feels a bit 'dirty' to iterate over all active widgets to get the one i need (in the service class). the other option is craft()->dashboard->getUserWidgetById(), but how the heck can i get the id of the widget by given type in a simple way?

how ever, this solution works:

controller method (requested through ajax)

public function actionUpdateWidget()
{
    $this->requireAjaxRequest();

    try
    {
        echo craft()->showcase_widget->get()->getBodyHtml();
    }
    catch (Exception $ex)
    {
        echo $ex->getMessage();
    }

    craft()->end();
}

service class

<?

namespace craft;

use Exception;

class Showcase_WidgetService extends BaseApplicationComponent
{
    protected $widgetType = 'Showcase_Feedback';

    public function get()
    {
        $widget = null;
        $userWidgets = craft()->dashboard->getUserWidgets();

        foreach ($userWidgets as $userWidget)
        {
            if ($userWidget->type === $this->widgetType)
            {
                $widget = craft()->dashboard->populateWidgetType($userWidget);
                break;
            }
        }

        if (!$widget)
        {
             throw new Exception(craft::t('Widget not found'));
        }

        return $widget;
    }
}


In my case, my url routing wasn't functional because the mod_rewrite module in Apache was disabled. I enabled it with a2enmod, restarted Apache, and my problem was solved.


Looking to create a dropdown field to select an icon

What you are describing sounds a lot like the Position Fieldtype. I would look at that plugin for guidance.


When I'm trying to get past my initial errors, here are some of the things I try. This is assuming you have the usual directory setup, with the webroot public on the same level as craft

Create foo.html in public, and visit yourdomain.com/foo.html. Good for mamp problems, virtual host problems, permissions problems.
edit public\index.php and add die('made it to index'); right at the top (after the <php?). Visit yourdomain.com. Good for some .htaccess problems.
edit public\index.php and add die('index is about to require '.$path); right above the require at the bottom (and of course take out the earlier die). Make sure the craft path is right.
edit craft/app/index.php and add die('made it to craft/app/index'); right at the top. Can expose some php problems (open_basedir e.g.)

That's usually enough to get me started.


Get the fields (fieldLayout) of the section. Not the entry

You can't get the fields from a section since sections have no field layout. Sections have several entry types and those are responsible for the fields.

$entryType->getFieldLayout()->getFields();

You can get all types in a section with

$section->getEntryTypes();


How to display itemCount using the Shortlist plugin?

From the documentation is looks like the correct syntax to use is:

{{ craft.shortlist.itemCount }}


I might be wrong on this but...
After running composer, did you have to go through an install process? If so, the DB/site you were given might have been configured to use a database table prefix.
If you look in your database, do you see some tables call assets then a second one called xxx_assets (xxx_ could be anything)?
If so, in your .env file, make sure have DB_TABLE_PREFIX= set to whatever prefix (the xxx_ part) you are seeing on your tables.


Why is Craft CMS attempting to connect with SSL3

The error is coming from when Craft tries to send out an activation email for the new user.

In Craft's email settings (Settings->Email), you're telling Craft to connect to your email provider over SSL (TLS), but it looks like your local OpenSSL certificate config is setup improperly on your box.

More info here: https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting#php-56-certificate-verification-failure

I definitely wouldn't recommend their workaround of disabling SSL certificate verification as that opens up a slew of security issues, but would fix the local OpenSSL configuration.


Getting a phpmailerException error due to my attachments when my plugin runs

PHPMailer is only going work with local files for attachments, so you'll need to download the file from S3 into a known location, and pass that location in as the first parameter to addAttachment.


Loop through an entry's fields and if the field type is "Categories" get that fields value/s

I believe I have found the answer.

if(array_key_exists('byCategory', $filterAttributes))
{
  foreach ($entry->getFieldLayout()->getFields() as $key)
  {
      $field = $key->getField();
      if($field->type == "Categories"){

         if(!$this->addFilterdCategories($entry[$field->handle],$filterAttributes))
         {
             continue;
         }
      }
   }
}


Moving to another database: "Specified key was too long"

I bumped into this last week, and it is exactly as you suspect... your new database does not support InnoDB, which is a requirement of Craft.

I'd suggest discussing the matter with your hosting company. In my case, the hosting company was unable to offer InnoDB support in any form, therefore disqualifying them as a viable hosting option for our new site.


How do you handle routes in CP with Query Parameters?

Routes can't include query strings. A route is a path to a template file (or a controller action, if you've written a custom plugin).

You can retrieve a query string value from within a template using the craft.request.getParam method.

For example:

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

Update

Following the conversation in the comments, here is an example of this working with a standard Craft route.

My example route /querystring/test points to the template _views/querystring-test.twig, which contains the following example code.

Query String Test

{% if craft.request.getParam('example') %}

The query string value for example is "{{ craft.request.getParam('example') }}",

{% else %}

There is no query string parameter.

{% endif %}

Here is a screenshot of the page without a query string:

And here is a screenshot of the page with a query string:


I do not see anything obviously wrong with your code, but something that has caught me out many times is a misspelling of field names, so be sure your twig code matches your field names exactly. One thing that is a bit odd is the error message references "footerContent", but that does not appear in your code.


TWIG dataUrl function for resized images

Found it, this works:
<img src="{{ dataUrl('@webroot' ~ myAsset.getUrl({width: 200, height: 200}, true)) }}" />

Two important things:

prepend the @webroot alias to the myAsset.getUrl(...)
set the second parameter of getUrl(...) to true: myAsset.getUrl({...}, true). This ensures that a real file path is returned by getUrl, because the image is transformed immediately on call. This is necessary for the dataUrl function to work. If it is not present, Craft might return a URL pointing to the image transformation controller (which transforms when called for the first time, this might go wrong here).


Quoting Brad Bell in a recent thread:

  If you're on Craft 2.6.2950 or greater, it includes Redactor II 1.3.1,
  where they re-introduced image resizing and positioning support.

  You'll just need to add:

  imageResizable: true, imagePosition: true to whatever
  craft/config/redactor config file your Rich Text field is set to use
  under its settings.

This combined with the mentioned 3rd party plugins creates a bullet proof and front-end friendly setup.


Your block.headshots is not an array of all images, you have to understand what craft does in order to work properly with it.

block.headshots and all other relations (Matrix elements, images, category links...) are all elementCriteriaModels so instead of having an array of objects - your block.headshots is just a single object that has an iterator interface.

So when you execute {% for headshot in block.headshots %} it performs the .find() function and returns an array.
Unfortunately I'm not on my computer currently so I can't provide the exact code so maybe the syntax of something of the following might be wrong, but if you know how to search entries with craft.entries.find() click you can correct it, here you have more examples elementCriteriaModel. Your code should look like

{% for headshot in block.headshots.find({limit: 10}) %}

It does not matter if you are searching pages (entries), assets, matrix blocks, sections, categories or whatever.. Craft does always the same, building an elementCriteriaModel that is executed as soon as you loop through it.

edit: your controller to load the assets could look like this

public function actionLoadAssets(){
    $this->requireAjaxRequest();
    $response = array(
        'success'   => false,
        'message'   => ''
    );

    // config how many entries should be loaded
    $config = craft()->globals->getSetByHandle('config');
    $limit = $config['countReloadImages'];
    // offset.. how many did we load already
    $offset = craft()->request->getPost('offset');
    // which block is it
    $matrixIndex = craft()->request->getPost('matrixIndex');
    // entryId
    $entryId = craft()->request->getPost('entryId');

    if($entry = craft()->elements->getElementById($entryId)){
        // search for the correct field -> we just insert an offset
        // this is untested, maybe you have to play around with the correct number
        // I'm not sure if you can just send the id of the matrixfield and use 'id' => $matrixIndex
        // you could to try it out...
        $matrix = $entry->team->find([
            'offset'    => $matrixIndex
        ]);
        $html = '';
        if($matrix && ($assets = $matrix->headshot->find(['offset' => $offset, 'limit' => $limit]))){
            // build a template to render the images, you'll return the html
            $html = $this->renderTemplate('some tempalte here', array(
                'asset' => $assets
            ));
        }
        // you could include your logic if you found less entries than configured ($limit) and return a "hide reload button"
        $response['html'] = $html;
        $response['success'] = true;
    }else{
        $response['message'] = Craft::t('could not find entry with Id ' . $entryId);
    }

    return $response;
}

Edit2: I found a better solution:

public function actionLoadMore(){
    $criteria = craft()->elements->getCriteria(ElementType::Asset);
    // id of your field headtshot
    $field = craft()->fields->getFieldById(5);

    $criteria->relatedTo = array(
        'sourceElement' => //your matrix ID,
        'field'         => $field->id
    );
    $criteria->offset = //your offset;
    $criteria->limit = //your limit;
    $assets = $criteria->find();

    // render template -> return html look at the first example
}


Display entries with matching checkbox field values

After I posted my question I ended up coming with something that works:

 {% for entry in craft.entries.section('Vegetables') if entry.Vitamins.contains('a') %}

{{ entry.title }}

 {% endfor %}


How to subscribe to an entry and get notified by email in case of new comments?

I really like the idea of using a simple plugin like Like to keep track of what entries users are interested in.

But instead of writing the code to integrate with Postmaster, I’d probably just use Craft’s API directly to send the mail after new entries are saved in your comments section.

The Like plugin and Craft API you need to look into:

entries.onSaveEntry event
getLikesByElementId()
sendEmailByKey()


File upload error. Cannot upload .key (keynote) files

It looks like .key files are not included in the default allowed file extensions. But you can manually add it with the extraAllowedFileExtensions setting in your config/general.php file:

'extraAllowedFileExtensions' => 'key'


EVENT_AFTER_CREATE_SUBSCRIPTION can someone confirm this means successful purchase?

I've looked into this in more detail now, and whilst it used to be the case that EVENT_AFTER_CREATE_SUBSCRIPTION only worked for successful payments, it's now (post Commerce 2.2.0), no longer the case due to the fact that a subscription can get created in a "Suspended" status, which still triggers that event (https://github.com/craftcms/commerce/issues/1105).

I'm still using that event, but in Commerce 2.2.7 (and beyond unless they change it again!), you'll need to make an additional check inside your code to make sure the subscription is not Suspended.

Event::on(
    Subscriptions::class,
    Subscriptions::EVENT_AFTER_CREATE_SUBSCRIPTION,
    function(SubscriptionEvent $e) {

        // --------------------------------------------
        // BAIL OUT on Suspended subs!
        // --------------------------------------------

        if ($e->subscription->isSuspended){
            return;
        }

        // --------------------------------------------
        // Continue...
        // --------------------------------------------

        ...
    }
);


Your above code is not working because you are using "block" instead of "item" in your children. So...

{% for item in block.children %}
    {% switch item.type.handle %}

You don't necessarily need to do a switch here, you could do a series of includes and make their file names match your block type... so "_includes/neo/box.twig" and "_includes/neo/image.twig"

In the example below I am replacing "item" with "child" to explain it better.

{% for block in entry.MatrixNeo.level(1) %}
      <h2>{{ block.mainTitle }}</h2>
      {% for child in block.children %}
           {% include "_includes/neo/" ~ child.type %}
      {% endfor %}
    {% endfor %}


Failed to load resource: net::ERR_CACHE_MISS

Nothing related to Craft at all, but a Chrome bug.  Has been fixed in v40 in the dev channel and will eventually make it into stable.

https://stackoverflow.com/questions/26408931/bizarre-error-in-chrome-developer-console-failed-to-load-resource-neterr-ca

But I agree, it's a really annoying bug.


Getting `modifyUserSortableAttributes` to work during plugin development

The underlying issue you're running into is this, which is an issue on both Craft 2 and 3 currently: https://github.com/craftcms/cms/issues/859

Can't think of a clean way to work around it, either.


Have a look at the Dashboard Widget section in the Craft docs. It’ll walk you through defining your “Start Date” and “End Date” settings, and how to render the settings template, where you can make use of the dateTimeField Twig macros to render the Date and Time fields.

An important step to make your widget save the values properly to the database. You’ll have to convert them DateTime objects to string before save in the prepSettings(), and convert them back in the getSettingsHtml() before rendering the settings template. There’s this convenient DateTime::createFromString() helper that you should proabably want to use.

Another thing that you’ll probably find useful is the mySqlDateTime() method that prepares a DateTime object for use in criteria model parameters.

Have a look at P&T Store Hours plugin, that shows some of these methods in code context.


How can multiple fieldtype instances without a content column be attached to the same entry type and still be uniquely identifiable?

Since you're saving your data in a separate table, you basically need two fields within your custom table to help you identify which field & element originally saved the content:

The element id (which you're already storing)
The field id (missing from your current setup)

You could even create an index on your custom table that would be a combo of those two fields.

In theory, you should be able to retrieve your data with a combination of the $field->model->id and $field->element->id.

When saving:

$attr['elementId'] = $field->element->id;
$attr['fieldId']   = $field->model->id;

$fieldRecord->setAttributes($attr);

When retrieving:

$fieldRecord = MyPlugin_FieldRecord::model()->findByAttributes(array(
    'elementId' => $field->element->id,
    'fieldId'   => $field->model->id,
));


How to get current site (locale) api / plugin

I don't know if this was the problem you were having but I was not including the site's first URL segment like /en/ (in your example) with the controller action URL. So you'd want to post to /en/actions/pluginHandle/controllerClass/actionMethod to get the English site back when using Craft::$app->getSites()->getCurrentSite() in your plugin.

I posted a more thorough answer to the same problem in another ticket:
https://craftcms.stackexchange.com/a/33941/4433


what does {% set order = 'pin desc, postDate desc' %} do?

Craft uses the the template engine twig and there is a set tag that is the same as it's php equivalent for $order = 'pin...'

So you just set/declare a variable - in this case you set the string.


Cannot connect to outside mssql database in production

Answer:
The server I was trying to connect to didn't have a CNAME set up in my corporate dns. So when I would switch environments some environments could see the server and others could not.


Feed Me: How to format JSON for a table field?

You can do this a number of ways, and essentially just need an array-like structure to represent the rows.

"Table": [
  {
    "one": "Option1",
    "two": "Option2"
  },
  {
    "one": "Option3",
    "two": "Option4"
  }
]

This issue might be related to your feed however. In the dropdown, you have <altTitles> eg: - there should be a value from your feed in there. According to your example, you should also be mapping to altTitles/title.

My example above shows:


Linking to channel via structure section

I don't think that carlcs was suggesting that you incorporate individual blog posts into the 'pages' structure. He was only suggesting that you place those pages into the structure that you would want in your main navigation (using different entryTypes defined for each page layout); like your blog index page for example. In your case, what you would likely want to do (assuming you are following this strategy at all), is to create an entry for 'blog' in your structure, with a unique entryType called 'blogIndex' for example, and a matching template called '_blog.html' or '_blog.twig' which will be your blog landing/index page.

You would then create a channel for your individual blog entries, also called 'blog'.

In this way the urls will sync up nicely, such that the uri '/blog' will display your structure entry (which is designed to render, for example, a summary of the first 20 blog entries from your 'blog' channel); and the uri '/blog/my-blog-entry-title' will display your blog entry detail page from your 'blog' channel (assuming the blog entries are long enough that you even need a detail page).

Check out this answer for a more specific example with code examples.


I think I figured it out ... I guess since I'm only getting one results I can't actually loop through.  Eg: the following works.

{% set feed = craft.feedme.feed(params) %}
id: {{ feed.id }}
form: {{ feed.form }}


I'm not a huge fan of it but for this situation it might be more appropriate to use init(), Looking at Craft\BaseController:

/**
 * Initializes the controller.  This method is called by the Craft before the controller starts to execute.
 *
 * @throws HttpException
 * @return null
 */
public function init()
{

}

It seems a little odd to me to have a constructor for a controller though, what is it you're doing in it? Yii's Controller filters might be a better fit.


Emoji mb_detect_encoding() error when updating to latest Craft 2.6.x

Solved it. The problem was with this field:

<input type="hidden" name="fields[gdprPermissionsList][permissionSales][fields][lastChangedDate][date]" value="{{ now|date("m/d/Y") }}">

The [date] part was to much and it saved the value in Craft as a literal string: {"date":"07\/11\/2018"} instead of the formatted date.

In one of the Craft updates that throws an error, maybe because it ses it as an object/array due to the curly brackets or maybe because that string has an emoji shortcut in it?


As of Craft 3, there is a RegisterElementSearchableAttributesEvent event that a plugin can listen to to change modify what gets saved to the search index table when an element is saved.


You have to select that config file you edited in your Richtext field's settings. See the settings options for "Rich Text fields" in the Craft Docs.


Entry FieldType - Get the EntryModel of the entry chosen in the field?

Nevermind.

Apparently I have to grab first() which will give me the selected entry.

I know I tried this before and it didn't work. I must have been in the wrong context or something.

$center->getFieldValue('hotline')->first();
or
$center->hotline->first(); is what I needed.


Is defined conditional passing, yet causes a "do not have a method or closure named" error

This is a weird twig behavior. You have to do if   stRow['caption'] is defined to make it work because of the object syntax of twig.

Sometimes the if defined statement becomes true when you don't use the array syntax


provide a 'back' or 'cancel' or 'close' button to return to whatever page that particular template was accessed from

You could use the Cookies plugin to store the last visited URL before the user hits one of the "step" templates, i.e. by putting something like the following in every template where the links to the "steps" template occurs:

{{ setCookie( 'lastUrlBeforeStepStuff', craft.request.url) }}

Then, inside your "step" templates, you could render the "cancel" links like this:

Cancel


You could always use a meta refresh

<meta http-equiv="refresh" content="5; url=http://example.com/">

With the number being the amount of time in seconds until the redirect


Updating large database from Craft 2 > 3 via command line

Turns out the Craft needed to run another set of migrations for Commerce, so I ran the ./craft migrate/all a couple more times to fully update the database.

If anyone is doing this, it's worth backing up the DB after each set of migrations to save running them again if you run into an error.


How to check if a user has any entries they're an author of... in a plugin?

Getting entries in plugins is slightly different from within templates and you should read the details on Working with Elements in a plugin in the Craft docs.

Taking that as a guide, you need to create an ElementCriteriaModel instance which selects the entries you are interested in:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->authorId = 10;

Note that the ElementCriteriaModel won't pull disabled entries by default. If you want to pull both enabled and disabled entries, you can add the status parameter to your query:

$criteria->status = null;

Finally, you need to call find() on the ElementCriteriaModel to fetch the entries matching your criteria:

$entries = $criteria->find();


Set a route for all requests within a plugin

You can use the catch all route

'catchAll' => ['site/offline'],

For yii1 you can also do

'<url:(.*)>' => 'controller/action'


Category Nav tag with control over the depth that {% children %} goes

i did {% set categories = craft.categories.descendantOf(1066) %}

And then i did

{% nav category in categories.level(2) %}
{% endnav %}

Always get the answer myself just after i post these damn things.


Updating just a single content field from a plugin

I don't have much experience using tasks, but I often write plugin methods to move data around. Typically, I just use the EntriesService saveEntry or RelationService saveRelation as needed.

Here is a sample from a recent data move:

    // Assign category and save entries
    foreach($unassignedEntries as $entry) {

        $success = craft()->relations->saveRelations($field, $entry, array($categoryId));

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


Can't install plugin - Could not find plugin folder in zip

As Brad mentioned in his comments, make sure you have the latest version of the plugin uploaded to the craft/plugins directory on your production server. I just tried it for testing sake and it seemed to work fine for me!

If you are sure they are in the right spot, check out this answer from a different question, stating to make sure the directory names are all lowercase, so "downloadassets" and not "downloadAssets" or "DownloadAssets," as many production environments are case-sensitive.


Looks like it is failing in local development on a Mac. My experience with native MySQL on OS X 10.9.3 is that the MySQL server just stops working once every few weeks, and I have to restart it. Since it's only occasional and I don't use it for anything really critical, I just live with the restarts.


How to build a multipage form using Freeform?

Actually, the templates that are provided in the docs over here are a pretty good place to start. You can change the markup, but you need the javascript:; tag in the a href=to get the multi-steps working.

Like any other form, I would suggest that you use some front-end validation. There are some nice libraries out there that get you up and running pretty quickly.

Are there any specifics you're struggling with?


Caching Issue "unserialize(): Error at offset 0 of 24 bytes"

Sounds like something just got corrupted when saving to craft/storage/runtime/cache and now PHP/Craft is having a problem reading the corrupted data from cache.

No idea how it happened, but clearing craft/storage/runtime/cache should resolve the issue for now.


Show a table field's column headers in template?

You don't get table headings with the entry model data (use the dump() function while in dev mode to see yourself). But there's the method getFieldByHandle() that returns a field model containing info to any field settings.

This is how you access the headings of a table field

Craft 2

{% set field = craft.fields.getFieldByHandle('myTableField') %}

{% for column in field.settings.columns %}

{{ column.heading }}

{% endfor %}

Craft 3

{% set field = craft.app.fields.getFieldByHandle('myTableField') %}

{% for column in field.settings.columns %}

{{ column.heading }}

{% endfor %}

Table field in Matrix block:

As fields within matrix blocks don't necessarily have unique field handles, you can't use the getFieldByHandle() method to get the field model. Use the unique field ID with the method getFieldById() instead. To look that ID up, open up the source code of the field in the matrix field's field settings. There's a div with the class matrixconfigitem and a data attribute data-id, which is the ID you are looking for.

(PS: use the code in your matrix loop for the block type containing your table "sub" field to output in the right place, but it actually works everywhere!)


Feed Me import from CSV ignores decimal point

With the help of the Craft Support Team, i solved this problem for me.
Two ways to solve this:

Change Number field to text field.
Change Language under users/user/preferences/language from Deutsch to english.


On the Transactions tab of the order, there should be a payment attempt with a failed status. There's a small information icon which returns the gateway response.


What's the best way to link to an entry in a template?

First, you'll want to retrieve that entry specifically...

{% set entry = craft.entries.slug('get-a-quote').first %}

Once you've got the entry that you want to target, you can easily link to it like this:

request a quote


I believe we figured this out over Slack, but the issue here was that you need to actually import your Line Id column into your lineId field, otherwise Feed Me doesn't know anything about that.

The checkbox to tell Feed Me to use a certain field's value to match existing elements on is one half of the problem - you've already correctly chosen Line Id. The issue is you need the other half - what data in your feed is supposed to match up with Line Id and lineId.

I suppose a less confusing UI would be to have an accompanying dropdown field near those checkboxes to say which bit of data in your feed should you be comparing with.


Currently, the postDate of an entry is not indexed for search.

Kind of hacky, but you could make a custom DateTime field with duplicate information (i.e. myPostDate) and do a search based on that.


There's a plugin for that by Josh Crawford
https://github.com/engram-design/CPNav


Craft Commerce: make address phone telephone field required without JavaScript

The way to do address validation with Commerce in gneral is using a plugin and listening to the onBeforeSaveAddress event.

Set up a listener with something like this:

    craft()->on('commerce_addresses.onBeforeSaveAddress',
        [
            craft()->businessLogic_logic,
            'onBeforeSaveAddressHandler'
        ]
    );

And here's an example of a function that does some validation:

public function onBeforeSaveAddressHandler($event){

    $address = $event->params['address'];

    if(!$address->firstName){
        $address->addError('firstName','First name must not be empty');
        $event->performAction = false;
    }
    if(!$address->lastName){
        $address->addError('lastName','Last name must not be empty');
        $event->performAction = false;
    }
    if(!$address->phone){
        $address->addError('phone','Phone number must not be empty');
        $event->performAction = false;
    }
    if(!$address->address1){
        $address->addError('address1','Street Address line 1 must not be empty');
        $event->performAction = false;
    }
    if(!$address->city){
        $address->addError('city','Suburb must not be empty');
        $event->performAction = false;
    }
    if(!$address->zipCode){
        $address->addError('zipCode','Postcode must not be empty');
        $event->performAction = false;
    }
    if(!$address->countryId){
        $address->addError('countryId','Country ID must not be empty');
        $event->performAction = false;
    }
}


Craft 2: Exception: CException: Alias "ext.alpha" is invalid

Please download below extension and put alpha.php file in your craft extension folder:
https://www.yiiframework.com/extension/alpha

Best of luck..!!


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


Combining custom field filters on craft.entries

It's currently not possible to combine criteria params like this (see Complex logic on a ElementCriteriaModel parameter?).
As a workaround you'd prepare an idParam object, similar to your relatedToParam and collect all matching element IDs
making use of additional criteria models and the ids method.

{# Prep the id param #}
{% set idParam = [] %}

{% if formats is null %}
    {% set ebookEntryIds = craft.entries({
        section: 'books',
        ebookRrp: 'and, > '~price_from~', < '~price_to
    }).ids() %}

    {% set pbackEntryIds = craft.entries({
        section: 'books',
        paperbackRrp: 'and, > '~price_from~', < '~price_to
    }).ids() %}

    {% set idParam = ebookEntryIds|merge(pbackEntryIds) %}
{% endif %}

{# Merge in the id param #}
{% if idParam|length %}
    {% set params = params|merge({ id: idParam }) %}
{% endif %}


EVENT_BEFORE_SAVE event not getting $entry-id when creating an entry

I did some looking into how the EVENT_BEFORE_SAVE is being used and whether or not we can get the entry ID, without having to over complicate things, it was better to use EVENT_AFTER_SAVE, this does mean you will have to resave the entry after saving it, in this case that is very little overhead and it is only for a certain section, if heavier stuff was happening you may want to check on the impact.
I also placed in a check to detect if the action was happening or not, to stop any loops.
Here is what I ended up doing for anyone who wants to know for reference.
use craft\elements\Entry;
use craft\events\ModelEvent;

const SECTION_ID = 4;
public static $entrySlugRenaming = false;

Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE,
    function (ModelEvent $event) {
        $this->handleEventAfterSave($event);
    }
);

private function handleEventAfterSave($event)
{
    // Get entry
    $entry = $event->sender;

    // Don't worry about draft or revisions
    if (ElementHelper::isDraftOrRevision($entry)) {
        return;
    }

    // Test if entry renaming is already running
    if (!self::$entrySlugRenaming) {
        self::$entrySlugRenaming = true;

        // Check if there is an entry
        if ($entry !== null) {
            // Test for entry section
            switch ($entry->sectionId) {
                case self::SECTION_ID:
                    // Update slug here
                break;
            }
        }

        // Resave event
        $elements = Craft::$app->getElements();
        $elements->saveElement($entry);

        // Reset $entrySlugRenaming
        self::$entrySlugRenaming = false;
    }
}


Craft Commerce > 2.2: How can you order line items?

I am posting the answer of Craft Commerce Support in case somebody stumbles over the same thing:

It is possible to order them differently if required. The code example below shows how to order them alphabetically by SKU.

{% set lineItems = cart.lineItems|sort((a,  b) => a.sku <=> b.sku)  %}

    {% for item in lineItems %}

{{ item.description }} - [{{ item.sku }}]

    {% endfor %}

Thanks Nathaniel


In this situation you don't want to use a config file and instead you want to use plugin settings. The settings have a UI and save to the db, which does exactly what you want. The config files are meant to only be updated manually updating them.

http://buildwithcraft.com/docs/plugins/plugin-settings


You need to join the matrixblocks and the specific content table

$query->join('{{%matrixblocks}}, 'matrixblocks.ownerId = elements.id);
$query->join('{{%matrixcontent_your_table_name}}, 'matrixcontent_your_table_name.elementId = matrixblocks.id);
$query->andWhere([
    '>=',
    'matrixcontent_your_table_name.name-of-the-column',
    new Expression('NOW()')
]);

Edit: if you have multiple blocks with the same field handle you'll need to wrap all those in a new OrCondition

$now = new Expression('NOW()');
$query->andWhere(
    new OrCondition([
        ['>=', 'column1', $now],
        ['>=', 'column2', $now],
        ['>=', 'column3', $now],
    ])
);

Edit2: I would suggest you to only fetch ids in that query because it's likely to have more results when you join these tables


linking to staff page, how to setup entry

You could have two sections:

Staff
Videos

In the videos channel, create a Staff entries field type, select the Staff channel in that field's options.

When you create a new video, you can relate that video to a staff entry.

When displaying a video entry, you could reference that staff that is tied to that video entry like so:

{{ entry.staff }}

If you wanted to be more specific, you would do something like:

{{ entry.staff.title }}

and to get a link to the staff entry that is related to the video entry:

{{ entry.staff.url }}

Here is an article explaining relationships further: https://straightupcraft.com/articles/introduction-to-relations-and-reverse-relations-in-craft-cms-with-examples and documentation on the Entries field type: https://craftcms.com/docs/entries-fields


asset.getUrl() not correct: missing subfolder directory

Go to setting, then try to click Update Assets Indexes.


How can I use asset select modal in utility?

The field is just a normal ElementSelect field with the element type craft\\elements\\Asset

{{ forms.elementSelectField({
    label: "Asset"|t('app'),
    id: 'assetSelect',
    name: 'assetSelect',
    elementType: 'craft\\elements\\Asset',
   selectionLabel: "Choose"|t('app'),
   elements: elements, //array of selected elements
 }) }}


I believe you are looking for the Assets Field


There are a number of ways to organize this using any combination of channels, structures, or categories — it's hard to give a recommendation on which way is better without knowing a little more about your site requirements.

Much will depend on things like:

Will there be pages for both 'focus-areas' and 'initiatives' (or is one just used for organization)?
How the uri's should look? (i.e. 'focus-area/initiative/' or '/focus-areas/focus-area/' & '/initiatives/initiative')
Are the relationships 'one-to-one' or 'many-to-one'?
Are the pages hierarchical and/or need a specific order defined?
Do the pages need entryTypes (because the layout and/or field requirements are unique for different pages)?
Do you need to generate site-navigation dynamically?

Answering these questions will generally narrow down the options.

  On each Focus Area page, I would like to show all Initiatives associated. Currently, for each Initiative, I have a Radio Button for each Focus Area it fits under.

Typically, instead of a radioButton, you would create a relationship between any two channels/structures/categories using the EntriesFieldType. Once you have added the field to your focus-areas field layout, and added some related initiative entries, you can access the related initiatives using:

{% for initiative in entry.initiatives %}

{{ initiative.title }}

{% endfor %}

or

{% set initiatives = craft.entries.section('initiatives').relatedTo(entry) %}
{% for initiative in initiatives %}

{{ initiative.title }}

{% endfor %}

  Would this be an appropriate use case for Categories?

Maybe. If you want to conceptually consider them as categories (and categories fit all your other needs) then go for it. Otherwise the difference between categories and structures/channels is pretty minor (with the exception that categories do not support entryTypes).

  Should I instead be using Entry Types for each Focus area?

Maybe. EntryTypes are generally used when the field and/or layout requirements are unique in some way for the various entries. If the relationship between 'focus-areas' and 'initiatives' is one-to-one, and if you want the uri's to be 'focus-area/initiative' then a good option might be to combine the two structures together hierarchically and use EntryTypes to define the unique layout and fields requirements for each. In your template you would then check the entry's type and change the layout or include a sub-template.

{% if entry.type = "initiative" %}
    {% include '_initiative.html' %}
{% endif %}

You can also use this approach site-wide to generate more dynamic site navigation, using craft's nav tag.


How to use LDAP for authentication in Craft CP (back end)

There's a feature request here that would allow custom login forms for the Craft Control Panel login page you might want to add a comment to.

In the meantime, there is a userSession.onBeforeAuthenticate event a plugin can listen to to perform any 3rd party authentication.

You can see how a similar plugin did this for front-end LDAP logins here:
 https://github.com/thepitagroup/adldap_craftcms


Have a look at One Dashboard which works nicely. I've used it to set each users Dashboard to show a collection of pre-defined Analytics widgets.


Can I get Assets from a specific Matrix block?

You should be able to do this like so:

{% for block in entry.productIndo.type('specifications') %}
    {% for download in block.downloads %}
        {{ download.url }}
    {% endfor %}
{% endfor %}

Of if the nested loops don't suit you:

{% set specificationBlock = entry.productIndo.type('specifications').first() %}

{% if specificationBlock %}
    {% for download in block.specificationBlock %}
        {{ download.url }}
    {% endfor %}
{% endif %}


What is the typical owner:group for Craft files and folders?

It really depends on your hosting environment, but the article Hardening Craft CMS Permissions might be useful to you.


The elementCriteriaModel is a class/object that handles your search. It's a class that combines multiple methods to fetch entries from your database with an iterable interface on it.

That means: when you receive an entry you get all the queries you need attached to it to pull all the relationship instead of loading all the other entries all the time. So entry.matrix is nothing but database command to pull the other entries which makes craft fast. Otherwise you would take much more time.

To make it short: when you loop through your elementCriteriaModel the method .find() is executed, that fetches all your entries and return them as an array. The method first() returns only the first element, last() returns only the last element.

In order to pull all you just need to loop block.page
{% for entry in block.page %} will to it


How do I force a 301 http status code using the redirect tag?

Although it is (as of today) not yet documented, looking through the redirect twig extension revealed that the redirect tag can accept a second parameter for the http status code. So forcing a 301 is done as follows:

{% redirect 'pricing' 301 %}

I've sent a request to P&T to add this to the docs.


Commerce - How do I add the purchaser of a specific product to a user group?

Create a business logic plugin if you haven't already.

Two good ways of doing that are : Business Logic Plugin or via http://pluginfactory.io

Then, in your plugin's main file in the init method, register a listener method:

public function init()
{
    craft()->on('commerce_variants.onOrderVariant',
        [
            craft()->businessLogic_logic,
            "onOrderVariantHandler"
        ]
    );
}

Then, implement the method (I do this in my class BusinessLogic_Logic Service):

public function onOrderVariantHandler($event){

    $variant = $event->params['variant'];
    if ($variant->product->id == "4194" ){
        $user = craft()->userSession->getUser();
        craft()->userGroups->assignUserToGroups($user->id, [3]);
    }

}

Obviously make sure you use the right ids for your particular products & groups!

Note you can also just implement the method directly in init() if you want to keep things very simple - but the above method makes for a cleaner main plugin file and once you start doing a lot of this sort of thing (which is where a lot of the real power of Commerce lies I think) - separating the logic into a service and just registering the handlers is a more ordered way to go I think.

craft()->on('commerce_variants.onOrderVariant', function($event){
    $variant = $event->params['variant'];
    if ($variant->product->id == "4194" ){
        $user = craft()->userSession->getUser();
        craft()->userGroups->assignUserToGroups($user->id, [3]);
    }
});


How to restrict uploads to currently edited site

Oli Bon from Craft Support suggested to use {site.handle} when you define your field (not the volume), which have worked perfectly fine.


How do I create a locale dropdown to switch between languages?

This is because you loop through all but the current locales. Remove the without filter to loop them all.

  {% set otherLocales = craft.i18n.getSiteLocaleIds()|without(craft.locale) %}

.

Add "current" class:

To assign the current locale's link a class of "current", compare the looped locale to the current locale and set a variable that you can later test for. (In the example code I use the ternary operator for short output syntax.)

.

Example Code:

With my example code below you first create an array of all the locales you want the language switch to include, and then loop through it. With this technique you can define the order of the output manually or exclude locales from the loop.

{# Configure and loop through selected site locales #}
{% set locales = ['en', 'hu'] %}
{% for locale in locales %}

    {# Check if locale equals the requested page locale #}
    {% set current = false %}
    {% if locale == craft.locale %}
        {% set current = true %}
    {% endif %}

    {# Is this an entry page? #}
    {% if entry is defined %}

        {# Find the current entry in the other locale #}
        {% set localeEntry = craft.entries.id(entry.id).locale(locale).first() %}

        {# Make sure that it's actually localized to this locale #}
        {% if localeEntry and localeEntry.locale == locale %}

            {# Output a link to it #}
            {{ craft.i18n.getLocaleById(locale).name }}

        {% else %}

            {# Output a link to the hompage #}
            {{ craft.i18n.getLocaleById(locale).name }}

        {% endif %}

    {# Not an entry page #}
    {% else %}

        {# Output the same path with the locale's base URL (`siteUrl`) #}
        {{ craft.i18n.getLocaleById(locale).name }}

    {% endif %}

{% endfor %}

Code edits done to implement a lookup of the (translated) locale name as described here by Brandon Kelly

.

Notes:

The easiest (and recommended) way to use this language switch is to exclusively use    entry pages (channel entries, structure entries, or singles) on your site.
All non entry pages have to have the same URL path / slug for each locale (eg. http://craft.dev/de/meineindexseite/ and http://craft.dev/en/meineindexseite/), translated URL parts won't work for non entry pages with this code.
If you only use entry pages or if you are using localized template folders you should be save to remove the entry is defined conditional (incl. the else part) altogether.
craft.config.siteUrl[localeId] only works if siteUrl is configured to take care of localized URLs


Get HTML of rendered template inside module

I figured it out. I will paste it here in case someone needs it:

$html = Craft::$app->getView()->renderTemplate('template.twig', $variables);


How can I validate a Redactor rich text field in a front-end form using the VeeValidate Vue.js plugin?

Solution

Add the Redactor Sync callback function to the Vue.js instance to synchronize code/data between Redactor’s visual layer (UI) and the form’s <textarea> element.

As per the Redactor documentation:

  Visual layer contains multiple temporary tags that allow visual editing. Synchronization with textarea inserts clean code to the textarea, removing all temporary tags, styles and attributes.

Solution source: Validate Redactor WYSIWYG Textarea Field #603

Vue.js/VeeValidate Component

// in your component.
export default {
    mounted() {
        var vm = this;
        $('#redactor').redactor({
            callbacks: {
                sync: function () {
                    vm.$validator.validate('fieldName',  this.code.get());
                }
            }
        });
    }
}

Vue.js/VeeValidate CDN

<script>
    Vue.use(VeeValidate);

    new Vue({
        el: '#app',
        delimiters: ['${', '}'],

        mounted: function() {
            var vm = this;
            $('#redactor').redactor({
                callbacks: {
                    sync: function () {
                        vm.$validator.validate('fieldName',  this.code.get());
                    }
                }
            });
        }
    });
</script>


Current assets don't display in Add an Asset modal for matrix field; using {owner.slug} in path

It's because of how Craft resolves dynamic paths (paths with {variables}) in them. For freshly created Matrix blocks haven't been saved yet and therefore don't have an {owner} yet.

If a dynamic path cannot be resolved, then Craft will point it to a temporary folder that is unique per user per field, but, as soon as you save the Entry and the Matrix block has an {owner}, it will resolve to where it should and all the Assets from the temporary folder that were selected will be move to the resolved folder.

Any Assets that have not been selected will remain in the temporary folder. This also holds true for unsaved Entries if you're using {slug}, for example.


Search Assets in Matrix fields, if they appear in a Section

Managed to make this work, corrected a couple of things and tidied up, but the main issue was realising the field param has to be a string (duh), not a variable. My code now looks like this:

{% set entries = craft.entries.type('artistFolio').limit(null) %}

{% set imagesInUse = craft.assets.relatedTo({
    sourceElement: entries,
    field: 'imageList'
}) %}

This gives me a model with all images appearing inside the Matrix field 'imageList' within the entry type 'artistFolio'. I can then search these as so:

{% set searchTerm = craft.request.getParam('q') %}
{% set results = imagesInUse.search('*' ~ searchTerm ~ '*').order('score') %}

{% for image in results %}
    ...
{ % endfor %}


I haven't tried Commerce myself but I think something like this should work:

{% set products = craft.commerce.products.type(yourType) %}

//make an empty array
{% set filteredProducts = [] %}

{% for entry in products %}
    //check for your conditions
    {% if (entry.checkboxFieldhandle) or (entry.hasStock) %}
        //add each entry to your products array
        {% set filteredProducts = filteredProducts|merge([entry]) %}
    {% endif %}
{% endfor %}


How do I set this up the right way, transferring from Wordpress as CMS?

Macros are intended to output to the page, rather than return data to the caller. If you must return the data, I'd suggest writing a custom plugin (although that's where my knowledge stops!).


Best way to access getPrev and getNext asset fields

If you need only one image, you can use the first() function instead of a for loop.

I recommend to check always if a image or entry exists, befor use it. Otherwise you risk to get an error. During development you should turn on the devMode, to see all errors (https://craftcms.com/docs/config-settings).

Here is a code example i would use in your case:

{% if prevEntry %}

    {% set asset = prevEntry.featuredImage.first() %}

    {% if asset|length %}

        {% set thumb = {
            mode: 'crop',
            width: 200,
            height: 200,
            quality: 75,
            position: 'center-center'
        } %}

    {% else %}

    {% endif %}
{% else %}

{% endif %}


Display entries related to Category Field

You want to use the relatedTo filter. See the docs here: https://craftcms.com/support/entries-related-to-category where category is your last URL segment (eg red).

Just a quick addition... if your category URL for the category group matches what you've used above mysite/colors/red and you are using the category template for that group then you will have a category variable already to use in the relatedTo filter.


Foud the answer after digging a bit, in fact I missed a little detail.

The base javascript code was correct :

$modal = new Garnish.Modal($('#my-modal')); //create a new modal
$modal.show(); //shows the modal
$modal.hide(); //hides the modal

Everything is in the HTML code, you need to declare something like this :

Modal header

Go check the modal sources for api methods.


How do I display entries, grouped by distinct categories where the entries share a relationship to both the category and an entry in another channel

Set up a criteria model with both of your relatedTo conditions and add the hierarchy to the list of returned entries using Craft's group filter.

{% set relatedEntries = craft.entries({
    section: 'survivorContent',
    relatedTo: [
        'and',
        {targetElement: entry.themesField},
        {targetElement: entry.survivorsField}
    ]
}) %}

{% set relatedEntriesGrouped = relatedEntries|group('themesField.first().title') %}

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

In case you don't have a "max. 1 element" limit set on your relationship fields, you might also want to look into something like the following.

{% for theme in entry.themesField %}

    {% set relatedEntries = craft.entries({
        section: 'survivorContent',
        relatedTo: [
            'and',
            {targetElement: theme},
            {targetElement: entry.survivorsField}
        ]
    }) %}

    {% if relatedEntries|length %}
        {{ theme.title }}
        {% for entries in relatedEntries %}
            {{ entry.title }}
        {% endfor %}
    {% endif %}

{% endfor %}


Dynamically populating select input fields using jquery $.load and twig template

Your code looks fine and worked for me when testing locally. However it could be failing due to the fact that you're not url-encoding the parameter before you send the request. If the values contain spaces or other special characters, for example, this would make it fail. To fix that issue, try using encodeURI() like this:

$("#second-choice").load("{{ distUrl }}data.twig?brand=" + encodeURI($("#first-choice").val()));

This works for me when testing with values that contain spaces at least.


I need to embed some forms into a new site

You can always make a 'Plain Text' field, named iframe and allow it to have multiple lines. You can put your embed code in there.
Then you can add the iframe in your template with {{ entry.iframe|raw }}.
For (a little) more info about the raw filter: Here's the twig docs


Resolved! So, the console clearly showed which files were broken.

I've downloaded those files again from production server, and uploaded on my test server. Login succeed without any problems now!

I guess it has something to do with transfer mode (auto, binary, text etc) when transferring files via FTP. Transfer mode should be on auto, otherwise files might get corrupted which can cause all kind of (weird) problems. Thanks to Brad for help!


How can I remove all text content and assets from a duplicated site?

You can delete all of your existing entries and assets by executing this SQL query:

DELETE FROM craft_elements
WHERE type IN ('Entry', 'Category', 'Tag', 'Asset')

All associated content, relationships, etc., will automatically be deleted.

If you have a bunch of users you want to delete, you should at least spare your own admin account, so figure out your user ID and do this:

DELETE FROM craft_elements
WHERE type IN ('Entry', 'Category', 'Tag', 'Asset', 'User')
AND id != 1

(The admin account created during installation will have the ID of 1, assuming you haven’t deleted the account.)

You should also delete existing asset sources, assuming those are going to need to change and will have their own sets of files. You can either do that from the Control Panel, or execute this SQL query:

DELETE FROM craft_assetsources


Control Panel or admin dashboard not found

You need to set the web server to host from the /web directory. At present it looks like you are serving a folder that contains the Craft folder.


How to link to prev/next entry depending on related data?

Add the relatedTo param to your criteria


SEOmatic Errors in Debug - Can they be fixed?

These errors will only appear with devMode on, and they are intended to help you diagnose potential problems with the meta tags and other information that you are rendering.

These are all soft errors, though. You can safely ignore them if they are a result of you not filling in things that you don't intend to fill in.

You can read more about it here: https://github.com/nystudio107/craft-seomatic#meta-object-validation


Actually, reading from the Craft 2 docs it's:

craft.request.getQueryString()      // returns the whole query string
craft.request.getQuery('success')   // returns only the value of 'success'


Craft Commerce: Creating Customer Accounts?

Yes, if you want users to be able to register, you would need to allow public registrations and implement your own standard registration form:

https://craftcms.com/docs/templating/user-registration-form

When they enter their email as a guest (anonymous) user a 'guest' customer record is created and related to the current cart, but it is not associated with a craft user account. This customer record is not retrievable and is only created for the purpose of having a related customer to the current order. There is no way to see this customer record in the back-end.

If the user is logged in a related customer record is created that has a 1:1 relationship with the user. The same customer record is used every time the useris logged in. This customer is the central place that addresses and orders are related to. If you want to see the previous orders for a customer, add the "Customer Info" field to your user profile custom fields.


You should be able to get it with the getURL() method?

Something like this should work (NB! have not tested the code myself):

$image = $entry->image->first();
if ($image) {
    $url = $image->getUrl();
}


How to handle search results that point to a page of aggregated entries?

I guess I'll answer my own question. Use a conditional in search results and overwrite the value of the entry's URL:

{% if getSection() == 'mySection' %}
  {% set entry.url = '/mySectionUrl' %}
{% endif %}


Find the nth top-level category in a nav tag

Maybe you can add in a little counting magic of your own:

{# before the nav tag #}
{% set topLevelIndex = 1 %}

{# inside nav loop #}
{% if category.level == 1 and topLevelIndex == 10 %}

Zoiks! That‘s a lot of categories!

{% endif %}
{% if category.level == 1 %}
    {% set topLevelIndex = topLevelIndex + 1 %}
{% endif %}

This code hasn't been tested...


You don't need to use the search parameter in this case. I'd avoid using it where ever possible.

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


You can access the default variant using {{ product.defaultVariant }}.

Because product.variants isn't an ElementCriteriaModel you can't sort it like one. You'd have to retrieve the products variants as an ElementCriteriaModel first like so:

{% set lowestPriceVariant = craft.commerce.variants({
  productId: product.id,
  order: 'variants.price'
}).first() %}

{{ lowestPriceVariant.title }}


Turns out it WAS a file encoding issue. It was UTF BOM (?), and had a weird hidden character right at the beginning of the file. I was able to open the file up in Notepad++ (Thanks Brad) and was able to convert the file to "normal" UTF8.


Problem setting security key when installing Craft 3

Add this line to your ~/.bash_profile file

export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php/php7.0.0/bin:${PATH}"

Assuming your php7 version in mamp is 7.0.0 of course.

Here is a link with a few more steps if you aren't sure how to edit that file - https://gist.github.com/irazasyed/5987693


Send freeform email notification to manually entered recipient address

The recipientsEmail field should be an Email fieldtype, and in Composer you need to set the notification template in the Field Property Editor column (on right) for that field and it'll send an email to the email that is entered in that field when the form is submitted. :)

View the documentation page here for more information about email notification options:
https://solspace.com/craft/freeform/docs/email-notifications/


To get a user by a custom field, you would need to create a ElementCriteriaModel like this:

$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->fieldName = craft()->request->getPost('fieldName');

$users = $criteria->find();

you could then loop over $users and use getAttributes() to get the user data, and if you need the attribute names use attributeNames() if you need the users fields.


Image transform that only crops if image is larger than set dimensions

You can easily do this in twig with a conditional that checks if the width of the image is larger than your target transforms width. Try something like this:

{% if image.getWidth()>600 %}

{% else %}

{% endif %}


It looks like it doesn't updated the variables passed to the event directly (referenced) and you have to access the value from the $event object.

public function setTest()
{
    // ...

    $test = $event->params['test']

    return $test;
}


How to render an entry type of a Matrix in HTML?

If you change the entry type then you're going to lose content for sure.

If changing that field type to an entry is really what you want, great. You could do something like

{# grab the first entry that we've selected #}
{% set learnMoreLink = box.learnMoreLink.first() %}
{# spit out the url for the first entry #}
{{ box.learnMoreText }}


You can actually use the StringHelper::toKebabCase  function for this:

$string = 'Hello there';
$result = StringHelper::toKebabCase($string);
// => 'hello-there'


Commerce 1: Different default order status based on product types

Edit: I'm sorry! I missed Commerce 1 in the title! This answer only applies to Commerce 2.

Take a look at the defaultOrderStatus event!

The description is a bit misleading—it's actually used to do exactly what you've described: alter the "default" completed order status in situations where it might not be desirable.

From the docs:

use craft\commerce\Plugin as Commerce;
use craft\commerce\events\DefaultOrderStatusEvent;
use craft\commerce\services\OrderStatuses;
use yii\base\Event;

Event::on(
    OrderStatuses::class,
    OrderStatuses::EVENT_DEFAULT_ORDER_STATUS,
    function (DefaultOrderStatusEvent $e) {
        $myOverriddenOrderStatus = Commerce::getInstance()->getOrderStatuses()->getOrderStatusByHandle('myCustomStatusHandle');

        $lineItems = $e->order->getLineItems();

        foreach ($lineItems as $lineItem) {
            // Your logic for checking the ProductType would
            // replace this basic test:
            if ($lineItem->price > 500) {
                $e->orderStatus = $myOverriddenOrderStatus;
            }
        }

        // Whatever `$e->orderStatus` ends up being by the time we exit
        // this event listener will be used as the new `OrderStatus`.
    });


To output variables inside an array like that you'd simply omit the twig braces.. at the moment the ' are telling whatever is inside them to output as a string.

UPDATE: try adding parentheses around each variables like so

{'name':(entry.title),'url':(entry.Url),'lat':(entry.latitude),'lng':(entry.longitude)} ] %}


Displaying a list of fields in a form select

I've got a solution, though I'd be interested to know if there is a better way of doing it. In the plugin file:

public function getSettingsHtml()
{
    $options = [[
        'label' => 'Please select',
        'value' => ''
    ]];

    foreach (craft()->fields->getAllFields() as $field)
    {
        $options[] = [
            'label' => $field['name'],
            'value' => $field['handle']
        ];
    }

    return craft()->templates->render('broadbean/settings', array(
        'settings' => $this->getSettings(),
        'options' => $options
    ));
}

And then in the settings template:

{{ forms.selectField({
    label:          'Salary Mapping'|t,
    id:             'broadbeanSalaryMapping',
    name:           'broadbeanSalaryMapping',
    instructions:   'Choose a field in which to store this value.'|t,
    value:          settings.broadbeanSalaryMapping,
    options:        options,
    errors:         settings.getErrors('broadbeanSalaryMapping')
}) }}


You can't do that with core Craft functionality or Twig filters, but as Mats already suggested in the comments, you can do it with a plugin like "Super Sort".

The template code to sort the array returned from the table field with that plugin would be:

{% for row in entry.tablefield|supersort('sortAs', '{{ object.firstName }}') %}


Testing all Craft versions:

  If you would like to try out Craft Client or Craft Pro before buying,
  you can do so by running your site from the host name craft.dev.
  Subdomains work as well, e.g. site1.craft.dev.

See: How can I try Craft Client or Craft Pro before buying?

Tutorials:

Mijingo's Learning
Craft - Most comprehensive tutorial
Basic of templating in Craft
Twig Primer
Twig for Designers - A work-in-progress book from Brandon Kelly
Templating in EE vs. Craft

Examples:

P&T has demo files for two sites on github, which you can install locally:

HappyLager
On the Rocks

Resources:

Craft Cookbook - Code Snippets
Straight up Craft - Articles / Link lists / Tweets / Plugin List


Plugin template's are not available from console commands

is it simply a case that hasn't been needed for the command line interface yet?

Most likely this one.

Can you send your plugin over to support@buildwithcraft.com and point us to a command that will reproduce it so we can look into it?

Will update the answer here with what we find.


Sprout Forms Payload Forwarding empty value

Sprout Forms 3.2.0 added an Integrations API and the previously named 'Payload Forwarding' is now handled via the Custom Endpoint Integration.

The new Integrations feature also improves tracking of Integration submissions so you should have more data to help monitor or troubleshoot if any requests are behaving as expected.

LEGACY ANSWER:

Every API you submit data to is different and Payload Forwarding may need to be implemented differently depending on what service you are trying to submit to.

By default, the data that gets forwarded is in the same format that it would be in if you were submitting it to Craft. Many services may require data to be in a different format, so we'd need to know more about where you are trying to submit the data and how to help troubleshoot further.

See a brief overview of Payload Forwarding in the docs. If you need to submit the data in another format, you could consider overriding how the fields are structured in the templates with Template Overrides.

We do have on our list to refactor the Payload Forwarding API to make customizing the payload for different services more accessible.


Why would Craft produce a template loader error (TemplateLoaderException) when rendering its default error pages?

As it turns out, I had made a configuration change that broke Craft's default behavior:

'defaultTemplateExtensions' => array('twig', 'xml')

All of Craft's internal templates use .html, and HTML templates are included in the default value of that config item. By overriding it, I had rendered Craft unable to find its stock error template.

Moral of the story — When you override defaultTemplateExtensions, make sure to include the default file extensions ('html','twig') in the new list that you set.


Can I change TEXT to MEDIUMTEXT/LONGTEXT in database?

The underlying database column for the plain text field type is defined by it's Max Length setting under it's field settings.

If you set that to something crazy high (like greater than 4294967295), it should use Long Text.

This means that Craft will adapt and change the column type dynamic from how much "data" you need to store/define for the field. Very powerful!

Note or warning (from Brad Bell at P&T support)
I'd make sure that you really need that much storage space (up to 4GB per row!). You can really start to choke MySQL by abusing that data type. Medium Text stores a very healthy 16MB, which is still a lot of data.


currentUser: Impossible to invoke a method ("isInGroup") on a null variable

Yes, that's expected behavior.  currentUser will not exist if there is not a currently logged in user.

{% if currentUser.isInGroup('verified') is defined %}

That's one workaround for it.

Another would be:

{%if currentUser is defined and currentUser.isInGroup('verified') %}

which to me reads a little better even though it's more verbose.


You can combine multiple relationship criteria by passing an array to the relatedTo parameter with the keyword 'and' or 'or' as the first array element. You want your entries to be related to any of the tags, so this should work for you:

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

{# Make sure selectedTagIds is an array #}
{% set selectedTagIds = query.tags ?? [] %}

<form action="">
    {% for tag in craft.tags.group('colorTag') %}
        {% set checkedAttr = tag.id in selectedTagIds ? 'checked' : '' %}
        <input type="checkbox" name="tags[]" value="{{ tag.id }}" {{ checkedAttr }}>{{ tag.name }}</input>
    {% endfor %}

    {% for tag in craft.tags.group('shapeTag') %}
        {% set checkedAttr = tag.id in selectedTagIds ? 'checked' : '' %}
        <input type="checkbox" name="tags[]" value="{{ tag.id }}" {{ checkedAttr }}>{{ tag.name }}</input>
    {% endfor %}

    <button type="submit">Search</button>
</form>

{# Prepare our relatedTo parameter #}
{% set relatedToParam = ['or'] %}

{% for id in selectedTagIds %}
    {% set relatedToParam = relatedToParam|merge([{
        targetElement: id
    }]) %}
{% endfor %}

{# Make sure to not pass the param with just the 'or' in the array #}
{% set relatedToParam = relatedToParam|length > 1 ? relatedToParam : null %}

{% set entries = craft.entries({
    section: 'foo',
    relatedTo: relatedToParam,
}) %}

{# Query for the entries and return them #}
{% for entry in entries %}
{% endfor %}


Order Entries in a Section by Category Titles

After some further research this http://craftcookbook.net/recipes/279 was a better fit for my needs.  The code I ended up using based on the link is below.

{% set beer = [] %}
{% set beerBrands = craft.categories.group('brandCategory').level(1).find() %}
    {% for category in beerBrands %}
         {% set beerRelatedCategories = craft.entries.section('beers').relatedTo(category).find() %}
         {% set beer = beer|merge(beerRelatedCategories) %}
    {% endfor %}


Is there a way to speed up password hashing?

There is a general config setting for this:

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

Setting this to the minimum value:

'blowfishHashCost' => 4

made the hashing time negligible.


Should I pluralize a channel's index slug?

It doesn’t matter to Craft, but generally I think it’s better to have consistent URLs, so they can be discoverable. For example if you land on /places/place-name, it would be reasonable to assume that you could chop off “place-name” and find an index of all the places at /places/.


Try adding this option to your config file (craft/config/general.php)

'preserveImageColorProfiles' => true


Craft actually has its own built-in support for tokenized requests, which is activated if there's a "token" param. if that param is set, Craft will refer to the craft_tokens table for instructions in how to route the request, ignoring the normal routing steps.

The name of that param can be customized using the tokenParam config setting, but you should probably just have PayPal use a different query string param if you can.


Assuming it's the field portfolioImage that can have multiple assets, try this:

{% for block in entry.portfolio %}
    {% switch block.type %}

    {% case "images" %}

    {% for image in block.portfolioImage %}
        {% set transformedImages = craft.imager.transformImage(image,
            [
                { width: 1200, ratio: 4/3 },
                { width: 992, ratio: 4/3 },
                { width: 768, ratio: 4/3, jpegQuality: 60 },
            ],
            {
                format: 'jpg',
                allowUpscale: false,
                mode: 'crop',
                jpegQuality: 80,
                interlace: true
            }
        ) %}
        <img class="img-responsive"
             src="{{ transformedImages[1].url }}"
             sizes="50vw"
             srcset="{{ craft.imager.srcset(transformedImages) }}"
             alt="{{ image.title }}">
    {% endfor %}

    {% endswitch %}
{% endfor %}


This would be up to the FeedMe plugin.

It looks like they're using cURL directly, so they would need to either directly set CURLOPT_USERAGENT or allow for it to be configured via a setting.

Feel free to create an issue / pull request on their repo.


Finding corresponding category in different subtrees of a category group

I would just split that category group, if possible, and offer one group for the region and one for the “A1” type of categories.

If this is out of question, you need to find a way to link your categories. Give them the same slug or use another field to make the connection (e.g. a Categories field) and use the corresponding criteria param to filter for the entry in the new locale.

$currentLocaleCategory = $entry->myCategoriesField->last();

if ($currentLocaleCategory) {
    $criteria = craft()->elements->getCriteria(ElementType::Category);
    $criteria->locale = $locale;
    $criteria->descendantOf = $descendantOfParam;
    $criteria->slug = $currentLocaleCategory->slug;

    $newLocaleCategory = $criteria->first();
}


Is there an easy way to download the assets directory to a local install?

I use rsync with grunt. There is a grunt rsync task, which is just a wrapper for raw rsync. If all I used grunt for was the rsync I don't think it would be worth it, but I use it to compile my sass, and to reload my browser (grunt-contrib-sass, grunt-contrib-watch) among other things.


List Entries in a section that are referenced as a relation in another

You could use the without filter for this:

{% set entryParams = {
    section: mySection1
} %}

{% set relationParams = {
    sourceElement: mySection2,
    field: myEntriesField
} %}

{% set entriesWithRelation = craft.entries(params).relatedTo(relationParams).find() %}
{% set entriesWithoutRelation = craft.entries(params)|without(entriesWithRelation) %}


How to reference a user related to entry input in if statement

You could do:

{% set otherEntry = craft.entries().section('other').userFieldInOtherEntry("{externalVariable}").one() %}

{% if currentUser in otherEntry.userFieldInOtherEntry %}
    do something
{% endif %}


Set up Craft 3 when the craft folder is above public_html on shared hosting

Finally figured out how to edit this index.php file if you're not able to point your document root to the web folder, or if you are forced to put craft in the folder private_html that shared hosters tend to use (or any other given structure above root)

In the index.php file you only need to edit this line:

define('CRAFT_BASE_PATH', dirname(__DIR__));

If your index.php file resides in public_html, __DIR__ will be something like:

/home/hostname.com

To point the index.php to the hidden craft folder, above root, in my case I had to add the folders after the CRAFT_BASE_PATH:

define('CRAFT_BASE_PATH', dirname(__DIR__).'/private_html/craft');


Installing Craft 3 RC on MAMP Pro - Pointing to the file directory

Craft 3 does not come up with templates or default entries like Craft 2 so your templates directory is probably empty. As soon as you create some files there and link them to your entries you won't see the error when you enter your home url


Regardless of the number of elements involved, Craft will return an iterable ElementCriteriaModel whenever you query for content (e.g. via craft.entries, or using relational FieldTypes like Assets, Entries or Categories).

This means that even if you know that there'll only be a single element returned (e.g. when you query for a Single section entry, or have a relational field restricted to a single element) using a for loop to actually access that element is totally viable and whether to actually use a loop or not in such cases, is mostly a matter of personal preference.

Looping on single-element query results may seem counter-intuitive, although you're not actually looping on a single element, but the ElementCriteriaModel (which just happens to "contain" a single element and not several). Personally I tend to only use loops when I actually need loops (i.e. there is or could be more than one element returned), but its up to you.

In any case, beyond personal preference there are a few minor differences to each approach.

Using a {% for %} loop, it's easy to render alternative content if the query doesn't return anything, by adding an {% else %} statement:

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

{{ entry.title }}

{% else %}

Sorry, the entry wasn't found!

{% endfor %}

Using .first() and {% set %}, you should – in most cases – add an {% if %} statement testing the value returned, to avoid template errors if the query doesn't return a valid element:

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

{{ entry.title }}

{% endif %}

Also using .first() and {% set %}, it's easy to declare fallback data if the query doesn't return anything, using the |default filter – this may negate the need for an {% if %} statement:

{% set imageUrl = entry.assetsField.first().url|default('/assets/fallback.jpg') %}

Performance-wise, I doubt there'll be any real-world difference between the two methods, with only a single element involved.

As for the query part of your question; even if you're using a for loop, Craft won't run the craft.entries query in your example more than once – which is why you're seeing the same amount of queries in your profiling report. When talking about queries and performance, it's however worth noting that both the amount of queries and the efficiency of those queries are relevant. In your example, the first query will probably be a tiny, tiny bit faster than the second (Gustavs' answer explains why).


How to differentiate between positive and negative numbers in search

The reason it's happening:

When Craft's SearchService indexes the keywords for a field, they go though a normalization process that specifically removes punctuation and diacritics before being saved to the craft_searchindex table in the database.

In the case of numeric values, that's going to include things like decimals, grouping separators and negation symbols.

A workaround if you're doing this on a front-end search form, is to query the field's value directly, bypassing the SearchService. So...

{% set results = craft.entries.fieldName('-2').find() %}

Which is going to try and do a direct match against that field's actual value in the craft_content table.

There are a few feature requests you might want to add your voice to that would make your situation better as well:

https://github.com/craftcms/cms/issues/1630

https://github.com/craftcms/cms/issues/833


Upload failed for filename. The path doesn't exist

I suspect your public root is something else/more than just /public_html. Try adding the following to your index.php file, and refresh your site:

die($_SERVER['DOCUMENT_ROOT']);

Your real public root path should now display in your browser.


Selecting all parent users and their related children

One option would be to use leftJoin() instead of join(), which will still return the record if the joining table row doesn't exist. The values will be joined as NULL.

  The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.

http://www.w3schools.com/sql/sql_join_left.asp

If you needed more control, you could always incorporate some aggregate functions in SQL to do a count an the records found, and you could perform additional conditional statements with the HAVING, instead of WHERE (which won't work) since aggregate data isn't stored in the db.


Can you run Craft CP on one webserver and serve the front end content on a separate one?

It looks like this question was resolved via some extended sleuthing in the comments above:

Can I disable the control panel?
How can I run the Control Panel from a separate domain?

Overall, it looks like the answer is yes, however some part of the solution lies in settings around the server environment and routing rules outside of Craft.


How to create a new subfolder to an asset with plugin

I’ve had the problem with storeFolder() that it doesn’t create a folder that is accessible via the control panel or the file system.

I find createFolder() much easier to use and it did what I expected:

$response = craft()->assets->createFolder($parentFolderId, $folderName);
$folderId = $response->getResponseData()['folderId'];


To assign a related Element (i.e. related User, Category, Entry, Tag, Asset) the value should be set to an array of element ids (even if there is only one element).

public function post(UserModel $user, EntryModel $ticket, $body)
{
    $comment = new EntryModel();
    $comment->sectionId = craft()->sections->getSectionByHandle('comments')->id;

    $comment->setContent(array(
        'createdBy' => array($user->id),
        'ticket'    => array($ticket->id),
        'body'      => $body
    ));

    return craft()->entries->saveEntry($comment);
}


Minor math in template, display result before logic in DOM

Just do a {% set myEntries = craft.entries.whatever.find() %} to load the entries into an array. Then do two loops, the first to get whatever totals you want, the second to display the players stats.

Yes, you're doing two loops. But you're only hitting the database once to load into the array, which is where the performance bottleneck will be unless there are a ton of entries.

In any event, wrap it all in a cache tag.


So you can definitely do this via Dynamic Twig Meta


I was able to trace my particular issue to an old PCRE version which resulted in long regular expression strings to silently fail... causing the 'preg_match' to not match the edit entries string found here:

craft/app/etc/web/UrlManager.php:387

A quick test:

<?php
$path = 'entries/homepage/1-homepage';
$regexPattern = 'entries\/(?P<sectionHandle>(?:[a-zA-Z][a-zA-Z0-9_]*))\/(?P<entryId>\d+)(?:-(?:[\p{L}\p{N}\._\-]+))?';

var_dump(preg_match('/^'.$regexPattern.'$/u', $path, $match));

Should output in: 1 but was resulting in 0

The server is running a very old (from 2006) version of PCRE (PHP 5.3.3).

Running the following command:

pcretest -C

Resulted in the following version:

PCRE version 6.6 06-Feb-2006
Compiled with
  UTF-8 support
  No Unicode properties support
  Newline character is LF
  Internal link size = 2
  POSIX malloc threshold = 10
  Default match limit = 10000000
  Default recursion depth limit = 10000000
  Match recursion uses stack

This issue does not persist with the following version of PCRE (from a local Vagrant box):

PCRE version 7.8 2008-09-05
Compiled with
  UTF-8 support
  Unicode properties support
  Newline sequence is LF
  \R matches all Unicode newlines
  Internal link size = 2
  POSIX malloc threshold = 10
  Default match limit = 10000000
  Default recursion depth limit = 10000000
  Match recursion uses stack

I ended up solving this issue by migrating the sever to an AWS instance running PHP v5.6  You could also upgrade/rebuild PHP, but there are too many dependencies on the server.  I also tried increasing the backtrace and recursion limits, without success:

I tried adding this to my .htaccess file (FYI: I do not recommend setting this to 2Mb):

php_value pcre.backtrack_limit 2097152
php_value pcre.recursion_limit 2097152

Hope this helps


Call to Craft Users Login Function from Plugin

What you're attempting to do is very doable.  This should be of help to you:

https://craftcms.com/classreference/services/UsersService

You can use the Yii forward function to pass along a request to another action handler:

    $this->forward('users/sendNewEmailVerifyEmail', false);


Craft Commerce Digital Products delete multiples

I don't believe there is a technical reason for this, but feel free to make a feature request requesting it: https://github.com/craftcms/digital-products/issues


Sprout Email trigger when entry goes live

The docs state that the following events are available from Sprout Email:

When a new entry is created
When an existing entry is updated
When a new user is created
When a existing user is updated
When a user is activated
When a user is deleted
When a user logs in

I think changing the status of an entry would trigger the "existing entry is updated". Not tested though.


Seeking information on the largest Craft sites built

Stack Exchange is generally for more technical questions, so you might not get many replies here.

Have you contacted the folks at Pixel & Tonic directly?

You could also join the Craft CMS Slack. Plenty of developers hang out on there that might not look here, so it'd be worth your while asking the same question there.


How can we move a Craft-built website to a new web designer?

The Craft Pro accounts are per domain, not per user. If you want all the features of Craft Pro, you will need your own license. (http://buildwithcraft.com/pricing)


It's certainly doable, but I think there will be some significant plugin and templating work needed, even when starting with something like the the Guest Entries plugin that Jamie mentioned.


Transform: Image {file} cannot be found with

As i was working on a localised website I had to use the full path,
in my case on MAMP PRO that was:
/Users/davedriesmans/Documents/Sites/website.dev/public/uploads/photos/

guess i'll have to change then when going into production

use environmentVariables like Mats Mikkel Rummelhoff suggests


Plug-In Store doesn't have the option for adding / trying plugins (post upgrade 2.6 -> 3.5)

If you look in your config/general.php, you will probably find that you have 'allowUpdates' => false set for the environment you are trying to trial the plugin on (stage/prod?).
Change that to 'allowUpdates' => true and you will be able to install what you want.


Is there a way to hook into the current request before the template gets rendered?

Sure, Craft does this in several places in the Control Panel itself.

A plugin can registerCpRoutes hook.  From there, you'd define an action route like so:

return array(
    'cocktails/(?P<widgetId>\d+)' => array('action' => 'cocktails/editCocktail'),
);

That will send the request to your plugin's CocktailsController's actionEditCocktail.  There you can prep any data that you want and pass it off to a template to render:

$variables['name'] = 'Martini';
$variables['ingredients'] = array('Gin', 'Olives');

$this->renderTemplate('cocktails/_edit', $variables);

And access those from the template via {{ entry.name }} or:

{% for ingredient in entry.ingredients %}
    {{ ingredient }}
{% endfor %}

  Additionally this would allow me to use another template engine then twig.

I'm not seeing how you'd easily be able to do this, though.

Update:

There is also the Template Hooks, which might get you where you're going.