Ordering homepage posts by date, but give customized ordering option in CP I'm looking to combine three different channels on the homepage, ordered by date, unless the client rearranges the hierarchy in the CP.

Low Reorder for EE had this customization, where entries would come into the plugin ordered by date, but you could drag and drop entries to the top if you wanted to rearrange the hierarchy.

Craft Structures is close, but 1) I need to combine three different channels into one hierarchy, and 2) these channels will grow immensely over time, so Structures will become cumbersome.

What are my options, if any? Is there a Low Reorder-type plugin out there?

For me this looks like a perfect fit for one structure with different entry types for each of your content types (text, video and recipes). Each entry type can have it's own set of fields, so there's no difference to individual channels (with one entry type each).

You can simply have the entry type's handle in your URIs, as the {type} tag is available in section URL settings (→ see help article), or you'd set up custom dynamic routes.

Via the entry's entry.type property you can include individual template partials for each entry type on your index page:

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

{{ entry.title }}

        {% include '/blog/_partials/' ~ entry.type %}

{% endfor %}

Same for your _entry.html file:

{% include '/blog/' ~ entry.type %}

And I've heard that structures with many hundreds or thousands of entries is no problem for the control panel. I think it was Craft 2.0 that had many optimizations in that respect.


Renaming files on Amazon S3 through Craft backend I've read somewhere you can't rename files on Amazon S3, which might explain my not being able to rename assets hosted on S3? Or, have P&T found a way around this and I've just not set the right user permissions?

My current permissions for this user are:

        "Action": [
            "s3:ListAllMyBuckets",
            "s3:PutObject",
            "s3:PutObjectAcl",
            "s3:DeleteObject"
        ],

Thanks,
Clive

This is definitely possible in Craft PRO -- I just tested with fine results (latest ver. 2.4.2670). So I would look at your IAM policy. If you have your policy statement scoped to the one bucket in question (and not to all buckets in your account), you could use some wildcard permissions for your main actions, like this, and I think you should be able to rename:

"Action": [
    "s3:Delete*",
    "s3:Get*",
    "s3:List*",
    "s3:Put*"
],

There is no "Update" call into S3 since it is object storage, and any change means a full rewrite of the file.


Class 'GuzzleHttp\Client' not found A plugin that is using a Guzzle request is now throwing an exception that the class cannot be found.

I'm running Craft CMS 2.6.3000. Where is Guzzle being pulled from? I can see it within craft/app/vendor/guzzle and also within plugins/oauth/vendor but for some reason this plugin cannot cannot use this class anymore.

It is being referenced as $client = new \GuzzleHttp\Client();

Why can't the class be used?

Just a quick guess, but here is what I have on a project I am working on.

$client = new \Guzzle\Http\Client();
$request = $client->get($url);

yours

$client = new \GuzzleHttp\Client();

mine

$client = new \Guzzle\Http\Client();

I have \Http\Client - maybe you are just missing the slash?


Search and link to Entries Matrix Field I'm trying to create somewhat of a clever search for which only searches through certain pages of my site. At the moment, it can search those pages, but instead of the result returning the page name, I want it to return a field within the matrix field which the search query can be found in.
As an example below, if a user were to search for Lorem Ipsum, I want it to return the page name as well as the matrix field title.

This is my title
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.

Desired result:

Page Name: This is my title

So far, the code I have can be found here, but I'm unsure how to access to exact matrix field title and add it to the query.
{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.search(query).order('score').section(['pageOne', 'pageTwo', 'pageThree']) %}

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

Is this possible to achieve?

I assume, that title is a subfield of a matrix field, because title is a reserved name in craft. So as far as I understand your Question, you want to get some results out of a matrix field thats in one of your pages ('pageOne', 'pageTwo', 'pageThree'). That means you have to loop over this field as well.

{% if entries|length %}
   {% for entry in entries %}
       {% for block in entry.matrixFieldHandle %}
          {{ entry.title }} - {{ block.matrixTitle }}
       {% endfor %}
   {% endfor %}
{% endif %}


How do I add a subcategory to the URL slug for a channel entry? I'm trying to mimic the URL structure exactly how I have it in my old CMS. If I select an entry to have both a category and subcategory I would like to have the subcategory in the URL along with the category and the entry slug.

For Example

http://example.com/cat1/subcat1/entry

Right now I have the Entry URL Format set to be {category.first().slug}/{slug}, but that only shows the first category. How do I access that optional subcat1 subcategory in that field?

EDIT

I have tried the following but it doesn't work

{category.first.slug }/{ category.first.children.first.slug ? category.first.children.first.slug ~ '/' : '' }{slug}

I have also tried

{category[0].slug}/{ category[1] ? category[1].slug ~ '/': ''}{slug}

If you go into your Category Group’s settings and set the following settings:

Craft 2

Top Level URL Format: {slug}
Nested URL Format: {parent.uri}/{slug}

Craft 3

Category URI Format: {parent.uri}/{slug}

then you would be able to set your section’s Entry URL Format to this:

Craft 2

{myCategoryField.last.uri}/{slug}

Craft 3

{myCategoryField.inReverse().one().uri}/{slug}


How to get a proper tag Url I use the code "Link to the Tag URLs" from the following article:
https://craftcms.com/support/tag-urls

{% if entry.tags | length %}

This entry is tagged with:

    {% for tag in entry.tags %}

{{ tag.title }}

    {% endfor %}

{% endif %}

One thing is that the "url_encode" doesnt really apply as if I expected. The URL looks like this:
http://domain.dev/tags/My%20Tag%20Name

But when I click on it, there are still spaces in the address line.

So my question is: is that ok like this?

I was also thinking about using the kebab filter. There I receive this url:
http://domain.dev/tags/my-tag-name

which looks prettier. But I now I get an error with the routing when I want fetch the tag:

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

This post helped me with my issue with a different approach (except of using the kebab filter the slug of the tag is used for the route)

Use of tag.slug instead of tag.title in a custom route

as I think that makes lot more sense then using the title, maybe it would be a good idea to update the article in the support section of the craftcms website.


Where can I find someone to help build my Craft website? We're looking to hire a talented developer to help us complete and/or maintain a project in Craft.

We'd like to hire them for a limited contract, or possibly full-time employment.

Where can I find a person or agency to work on my Craft project?

UPDATE

As of July 2016, there is now a new jobs board dedicated exclusively to Craft CMS!

  Work With Craft

* Disclaimer: I run the WWC site.

ORIGINAL

There are a few great resources out there for finding Craft developers... Any of these methods should help you track down someone to help you with your website:

Post on the Jobs board at Straight Up Craft
Mention it on Craft Discord, specifically the #jobs channel
Tweet about it on Twitter, using the #craftcms hash tag

To be clear, you won't find anyone here on Stack Exchange. This is typically a resource for developers trying to resolve their programming and architecture issues.

Good luck! :)


Get "Internal Server Error Undefined index: handle" Hi I was trying to save the matrix field and got the error:
"Internal Server Error

Undefined index: handle"

I checked out all fields' handles and they are all in place.

Is there any reason causing the error?

Thank you!

This ended up being an environmental issue with semi-largish Matrix fields.

The three most common culprits are your php.ini file's max_input_vars, max_input_nesting_level and post_max_size would would need to be adjusted upwards, but other settings might come into play depending on your environment an Matrix configuration.

Also, if your server is running anything like mod_security or Suhosin, they have additional settings that might need to be adjusted higher that could affect this.


Getting Entries that were updated after a certain day? I need to get all the entries that were updated after a certain date, I tried a couple things, but it doesn't seem to work, does anyone know how I can accomplish this?

This seems wrong to me, but it doesn't throw any error, neither does it accomplish what I want.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->dateUpdated("> '2015-09-02'");

$query = craft()->elements->buildElementsQuery($criteria);
$queryResults = $query->queryAll();

$affiliates = EntryModel::populateModels($queryResults);

Your criteria for the date updated was written in the wrong syntax. It should be:

$criteria->dateUpdated = '> 2015-09-02';

You can also simplify the way you query your Element Criteria Model like so:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'affiliates';
$criteria->dateUpdated = '> 2015-09-02';
$affiliates = $criteria->find();

Take a look at the Working with Elements documentation for more info.


What's the difference? SQL_MODE error in one site and not the other I have 2 Craft sites that share the same Craft codebase. For both sites, i was getting the following error:

Internal Server Error CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #18 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'creighton_mma_craft.structureelements.root' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

I found this Craft Stack Exchange solution and implemented Brad's second suggestion ('initSQLs' array) on both sites (see config/db.php below). It seems to have fixed it in the site called 'craft' but not the site called 'pc'. Though the question referenced above says that he can reach his control panel, i cannot reach the site or the control panel. What am I doing wrong? As far as I know, there are no differences between the 2 sites. All configuration details listed below.

O/S:

O/S: GNU/Linux

Issue: Ubuntu 16.04.1 LTS

Kernel Release: 4.4.0-43-generic

Kernel Version: #63-Ubuntu SMP Wed Oct 12 13:50:36 UTC 2016

Apache:

Server version: Apache/2.4.18 (Ubuntu)

Server built:   2016-07-14T12:32:26

MySQL:

mysql  Ver 14.14 Distrib 5.7.15, for Linux (i686) using  EditLine wrapper

PHP:

PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies

Craft:

define('CRAFT_VERSION', '2.6');

define('CRAFT_BUILD', '2949');

define('CRAFT_SCHEMA_VERSION', '2.6.7');

define('CRAFT_RELEASE_DATE', '1475689624');

define('CRAFT_MIN_BUILD_REQUIRED', '2570');

define('CRAFT_MIN_BUILD_URL', 'https://download.craftcdn.com/craft/2.1/2.1.2570/Craft-2.1.2570.zip');

define('CRAFT_TRACK', 'stable');

Craft's db.php:

<?php

return array(
        '*' => array(
                // The database server name or IP address. Usually this is 'localhost' or '127.0.0.1'.
                'server' => 'localhost',

                // The database username to connect with.
                'user' => '<redacted>',

                // The database password to connect with.
                'password' => '<redacted>',
        ),

        'devappsCraft' => array(
                // The name of the database to select.
                'database' => 'craft',

                // The prefix to use when naming tables. This can be no more than 5 characters.
                'tablePrefix' => 'path',

                // Work-around for newer version of MySQL
                'initSQLs' => array("SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';"),
        ),

        'devappsPc' => array(
                // The name of the database to select.
                'database' => 'craftPc',

                // The prefix to use when naming tables. This can be no more than 5 characters.
                'tablePrefix' => 'pc',

                // Work-around for newer version of MySQL
                'initSQLs' => array("SET SESSION sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';"),
        ),
); ?>

Answering my own question:
We ended up configuring MySQL as Routh suggests here:
Getting this SQL Error: GROUP BY incompatible with sql_mode=only_full_group_by

Problem solved.


Modify Craft locale inside Element API plugin? I’m using the Element API plugin to retrieve my entries as JSON. It is available under the /api route. For getting entries in a different locale I pass a locale query param and use it inside the ElementQuery.

All works fine so far, BUT when I want to use Craft::t inside of a transformer, I get the translations from the main locale, because this is where my /api namespace lives.

Is it possible to modify the locale that Craft is set to, from inside the Element API plugin?

Craft::t() has a whole bunch of parameters you can pass into it.

public static function t($message, $variables = array(), $source = null, $language = null, $category = 'craft')

It sounds like what you're looking for is the 4th one.

Craft::t('my string', null, null, 'es')

Where 'es' would be a target locale other than your main one.


Displaying a month name in an archive I'm trying to figure out how I can print the month name i.e April in the below. Currently, it's printing the last three months that contain entries.

{% set year = craft.request.segment(4) %}
{% set month = craft.request.segment(5) %}

{% set entriesInYear = craft.entries.section('bulletinOnline').limit(null).after(year).before(year+1) %}
{% set groupedEntries =  entriesInYear | group("postDate|date('m')") %}

{% for year, entriesInYear in allEntries | group("postDate.year") %}
    {% set counter = ( counter | default(0) ) + 1 %}

    {% for month, entries in entriesInYear | group("postDate|date('m')") %}

            {% for monthWord, entries in entriesInYear|group("postDate|date('F')") %}
                {{ monthWord }}
            {% endfor %}
            &nbsp;({{ entries|length }})

    {% endfor %}
{% endfor %}

Example output:

MarchAprilMay(2)

Try this:

{% set year = craft.request.segment(4) %}
{% set month = craft.request.segment(5) %}

{% set entriesInYear = craft.entries.section('bulletinOnline').limit(null).after(year).before(year+1) %}
{% set groupedEntries =  entriesInYear | group("postDate|date('m')") %}

{% for year, entriesInYear in allEntries | group("postDate.year") %}
    {% for month, entries in entriesInYear | group("postDate|date('m')") %}

        {{ month |date((year + 1) ~ '-' ~ month ~ '-01')|date('M') }}&nbsp;({{ entries|length }})
    {% endfor %}
{% endfor %}


Should I pluralize a channel's index slug? Lets say I have a channel called places, which has the following URL :

http://example.com/places

The url points to a directory of individual places.

However, when you click into an entry, each entry is a place, so it might make more sense to have each entry's url to be :

http:/example.com/place/place-name

Am I right in assuming that the best way to go about this would be to use a route for entries? Or is it best practice to keep things the same for consistency?

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/.


How to add locales in Craft 3 I'm getting started with Craft, using version 3 beta, and I don't find the menu option for adding locales so I guess it's not yet ready but there must be another option.

Could anyone guide me through the process of creating a multi-language Craft 3 site?

"Sites" in Craft 3 replaces the old "Locales" concept in Craft 2.

There's not much documentation on them yet, but the setup process is virtually the same as it is in Craft 2 for locales.  The main difference is that a "site" isn't necessarily tied to a language code, like it is in Craft 2.

https://craftcms.com/news/craft-3-multi-site

  Update: Localization docs for Craft 3


How to do smart upselling and cross-selling in Craft Commerce I want to have the following features on my Craft Commerce site:

Often bought together: Bundling
You may also like: Upselling/cross-selling/personal recommendations
Accessories

I realize that it's easy to define custom fields that let me associate products with each other - but I am not looking for a manual method.

I did a search on "ai powered cross selling ecommerce" and found a few stand alone solutions and some specifically tailored to e-commerce solutions like Magento.

But what would you do? Have any of you experiences with this kind of machine learning/ai algorithm for cross-selling/product recommendations/personalization?

Maybe The purchase Patterns Plugin Could Solve your problem.
https://github.com/ethercreative/purchase-patterns/blob/v1/README.md


What is the expected data type to be returned when using the prepValue() method? So while building a field type (FT), what is the expected data type of the returned value from the prepValue method? I am not sure I am using this method right, as I am running into a PHP error when trying to save the FT.

My FT stores data in two ways, the first as a JSON string stored in the element content table. When my FT is saved, I used the onAfterElementSave() method for additional processing. During this method, I am creating rows in a db table created by my plugin. What I desire to happen is when I call my field from the template on the front-end, it returns a data model which I can then pass to other methods for further manipulation (in the template). All this works great.

Here is my prepValue() code in my FT.

public function prepValue($value)
{
    $value = json_decode($value);

    return new MyPlugin_MyModelNameModel((array) $value);
}

All this works fine until I go to save my entry, which is producing this error "Internal Server Error - Object of class stdClass could not be converted to string". When I return the data from the prepValue() method as a string, it works fine when saving but then break in the template because it's expecting to be a model.

I even added a __toString() method to my model in hopes that if the data needs to be a string, my model could dynamically pass the JSON back as a string but that isn't working either.

Here is the stack trace from the craft.log

2014/08/14 19:28:35 [error] [php] Object of class stdClass could not be converted to string (/Users/justinkimbrell/Sites/craft_dev/craft/app/helpers/StringHelper.php:61)
Stack trace:
#0 /Users/justinkimbrell/Sites/craft_dev/craft/app/fieldtypes/BaseFieldType.php(148): arrayToString()
#1 /Users/justinkimbrell/Sites/craft_dev/craft/app/services/ContentService.php(366): Craft\GoogleMaps_GoogleMapFieldType->getSearchKeywords()
#2 /Users/justinkimbrell/Sites/craft_dev/craft/app/services/ContentService.php(137): Craft\ContentService->_updateSearchIndexes()
#3 /Users/justinkimbrell/Sites/craft_dev/craft/app/services/ElementsService.php(898): Craft\ContentService->saveContent()
#4 /Users/justinkimbrell/Sites/craft_dev/craft/app/services/EntriesService.php(141): Craft\ElementsService->saveElement()
#5 /Users/justinkimbrell/Sites/craft_dev/craft/app/controllers/EntriesController.php(440): Craft\EntriesService->saveEntry()
#6 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/web/actions/CInlineAction.php(49): Craft\EntriesController->actionSaveEntry()
#7 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/web/CController.php(308): CInlineAction->runWithParams()
#8 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/web/CController.php(286): Craft\EntriesController->runAction()
#9 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/web/CController.php(265): Craft\EntriesController->runActionWithFilters()
#10 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/web/CWebApplication.php(282): Craft\EntriesController->run()
#11 /Users/justinkimbrell/Sites/craft_dev/craft/app/etc/web/WebApp.php(865): Craft\WebApp->runController()
#12 /Users/justinkimbrell/Sites/craft_dev/craft/app/etc/web/WebApp.php(254): Craft\WebApp->_processActionRequest()
#13 /Users/justinkimbrell/Sites/craft_dev/craft/app/framework/base/CApplication.php(180): Craft\WebApp->processRequest()
#14 /Users/justinkimbrell/Sites/craft_dev/craft/app/index.php(196): Craft\WebApp->run()
#15 /Users/justinkimbrell/Sites/craft_dev/public/index.php(14): require_once()
REQUEST_URI=/index.php/admin/entries/news/47

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

Hopefully the issue is clear. I am just unsure of how to properly use this method, and wondering how I can return data in a model and not as a string.

Looks like the error is occurring when your field type’s getSearchKeywords() function is called. The value that’s passed into that function will have already been run through prepValue(), so at that point it looks like it will be a MyPlugin_MyModelNameModel instance (whatever the actual class name is).

If your field type doesn’t override getSearchKeywords(), the BaseFieldType version will just pass the value off to StringHelper::arrayToString(), which will do its best to convert whatever variable it was passed into a string. Something in there must be tripping it up.

Your best bet here is probably to just override getSearchKeywords() in your field type. It should be returning a space-delimited list of keywords you want to be stored for the current field value.


Affiliate link system Has anybody implemented an affiliate program system ? If yes, how ?
I saw that Superbig has a plugin in his pipeline, but it's not out yet.
Thanks a lot for your feedback !
Antoine

This probably isn't the answer you need but what features are you actually needing it to do? Affiliate systems can range the gamut from simply dropping a cookie to tracking commissions.
Even a very basic system using coupon codes tracked in Craft Commerce could technically be considered an "affiliate" program. (Coupon codes happen to be relatively reliable since they hold up across devices, cookies etc.)
I've done a bit of this before, when a request comes in that has the UTM or whatever parameters you need, you set a cookie on the request. When someone checks out, you can check for the cookie and set a custom field on the order.
Seeing as Craft is pretty flexible, it's also possible you may also want to consider an out-of-the-box system that works in conjunction with Craft.


How do I perform a critical update if my Craft site relies on older plugins? I recently came across a website in this situation and am curious to here how others approach this problem.  Here's the scenario:

A client had a website built on Craft 2.4 with a lot of integration work. The site has 10 custom plugins, integrating with several different systems and services. The relationship with the original development firm did not work out and a new development firm is picking up where the old one left off.  This means, the new team initially has limited knowledge of the 10 custom plugins on the site.

The new development firm inherits this project just as Craft discovers and releases a critical update with a fix for a security vulnerability (Craft 2.6.2791). It's in the website owners interest to upgrade to the latest version of Craft.

However, as mentioned, the site has 10 custom plugins that have not yet been updated to Craft 2.5. And, for fun, let's just say Craft 3.0 is also on the horizon.

If you are the development firm that inherits this project:

What options do you present to the new client for them to move forward?
How do you explain the costs (and the value) of why 10 plugins will need to be updated to Craft 2.5 and to Craft 3?
How do you respond if the client expresses concern that this work doesn't relate to value toward their business objectives?

I'd want the client knowingly and enthusiastically on board with a sensible plan that'd support business goals and the nature of evolving software.

Either a) do with fewer plugins/integrations, b) invest in privately upgrading the plugins, c) open source the work if possible and ask for improvements with fingers crossed, or d) rethink the site so it's less directly dependent on these plugins and thus safer from a repeat of this scenario should a-c seem unattractive. (Freezing the Craft version and avoiding software updates should be unacceptable as it's risky and invites compounding future problems—might as well pick e) move to a static site.) Re-affirm the importance of the CMS and each plugin, or remove the cruft from the equation.
The solid and ongoing work behind Craft, and the support that comes with it, is a steal and having a well-tailored CMS likely empowers employees in various ways—decreasing dependency on (and cost of) web nerds or additional training to update content. If nothing else, staying up to date takes advantage of lots and lots of work that's included in the price of a license while keeping the site as fast and secure as possible.
I'd encourage the line of thought and compare other ways of meeting those objectives. For example, I might contrast the (nonexistent) maintenance costs of running a SquareSpace site compared to the freedom and flexibility of hosting a Craft install. The site, as it is, is most likely supporting current business objectives and keeping it up to date will make it possible to quickly and elegantly support future business objectives with great agility. It may not be worth it, but I'd try and help them understand how much versatility they have for the (un-sexy) cost of maintenance and burden of technical diligence. Odds are they chose Craft and their custom plugins for a reason and those reasons are still vitally relevant, as is the ability to stay nimble in the future.

You might also try to get Ben Parizek on the horn and submit the whole site for a Straight Up Craft code review. In my experience, that can be one way to get rid of unnecessary plugins.


How to log info from an onSaveEntry event? Having problems logging to the console using log from within an onSaveEntry or onSaveUser event. Just a simple test below, but will be critical for error logs.

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

    BusinessLogicPlugin::log('init');

    craft()->on('entries.saveEntry', function(Event $event)
    {
        Craft::log('onSaveEntry');
        BusinessLogicPlugin::log('onSaveEntry');
    });

}

'init' gets logged fine, but not 'onSaveEntry'. I seem to be able to log other events fine, like plugins.loadPlugins. I have also confirmed that the event is firing via other tests. Is the log function not available when the onSaveEntry event fires? Scope issue? bug? Or am I missing something else? Thanks.

After wasting all of Brad's time (sorry brad!) by sending him an incomplete plugin file with a missing line, I have discovered why I wasn't seeing logs in the console as expected.

Craft::log('...') or MyPlugin::log('...') function calls within onSaveEntry or onSaveUser events are in fact properly saved to the log files (craft/app/storage/runtime/logs/). They are just not available in the browser's console, because the event is taking place on the server, while the page is in the process of being redirected when the event fires.

Lesson learned: don't rely on the console for debugging!

The log files can be watched from the command line using tail -F /full/path/to/log/file rather than having to constantly reload the log in a text editor. Although apparently some text editors also support live updates as well.

Feel free to delete this question or leave it here in case others run into the same problem.


Workflow for re-using data structures and setups across projects? I am wondering if there is a way to re-use pre defined field types and image crops over various Craft projects. I currently in the process of e.g. manually defining 20 different image crops I already defined for another project, which is a tedious task.

I am not really familiar with SQL and database structures, so I am not sure if there is a way to simply copy fields from one projects database to another or if this would corrupt my database?

You have several options to solve this issue.

Import fields via plugin

You could create a plugin that handles all these function in it's installation callback so you would install the plugin and have all the things you need. But this requires basic knowledge in plugin development.

Advantage When Pixel and Tonic make any changes in their install process it won't infect your code and if you are going to make multiple plugins you'll be able to import the required fields whenever you use them. That's the way we handle it and when someone installs my Form Builder Plugin it includes a form relation field to each entries with type pages and some crop rules automatically.

Disadvantage You need to learn php

Import via SQL

Install a new Craft instance, insert all your default values you would like to have for a new project and export the entire database. When you start a new project you would skip the installation process but import your included database and the files of your "default" instance.

Advantage This is an easy and really fast way to achieve your goal. It does not require any knowledge or skills

Disadvantage You should pay attention when Pixel and Tonic makes core changes in their default structure or things could eventually break in the future (even if it is really unlikely because they are really careful with those things)

Search for a plugin from someone else that handles it

I know there is a Feed Me Plugin maybe this does what you want but I never really used plugins that are not created in my company so I can't tell something about it


Unable to edit my Craft 3 Plugin I've managed to create a simple plugin for craft and get it into my project. It shows up just fine but I can't make any edits. I've tried editing the original plugin files and updating via composer and that doesn't work, and I've tried to edit the plugin files directly in my craft project and that doesn't seem to work as well. I'm sure there is a simple answer but I'm pretty lost.

What you need is a "host" project for your plugin, and then use a repository path to point to your plugin as described here: So You Wanna Make a Craft 3 Plugin?


Filter entries with AJAX How would I sort blog entries displayed using AJAX?

What I want to achieve is initially show all posts from a channel (All) but then let my users sort through these posts with a sub navigation using the categories I've applied to the channel entries.

I can doing basic templating in CraftCMS but there seems to be very little clear documentation on how to this.

Thank you

For filtering entries using JS, you could use Isotope JS

First, in your markup give each entry class attribute representing id of category that entry has:

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

Then, you will be able to show entries related only to a specific category using JS code like this:

$grid.isotope({ filter: '.category-5' });

..assuming you defined your isotope grid earlier as $grid. In this example, Isotope will show all entries related to the category with id 5.


Sort entries by best match to multiple categories I've got a channel where entries will be tagged with multiple categories. I want to use those categories to show related content for each entry.

So if an entry has cat_a, cat_b and cat_c, I want to pull in any entry that has cat_a, cat_b or cat_c, then order by how many categories they have in common – so an entry matching two of those categories would come before and entry only matching one.

Finally, I want to also sort by date. So I'd first show entries matching all 3 categories (newest first), then entries matching 2 categories (newest first) etc...

Any thoughts on how to do this?

Have a look at the Similar plugin https://github.com/aelvan/Similar-Craft, it should do exactly what you’re looking for.

{% set baseCriteria = craft.entries({
    order: 'postDate desc',
    limit: 5,
}) %}

{% set similarEntries = craft.similar.find({
    element: entry,
    context: entry.myCategoriesField,
    criteria: baseCriteria,
}) %}


Can we define routes (non-CP) in plugins? I don't suspect it's currently possible but  I would be pleasantly surprised to find that it is.

I'm going to use an example from Django because I've seen it used there and a similar implementation would be handy to have in Craft. Annnnd it would be helpful for what we're trying to achieve with my current project.

Example:
In Django you have your project-wide urls.py (think of this as routes.php in Craft). Additionally you can have app-specific URLs (an App might be a Blog or a Portfolio). You can define the app-specific paths in the app-specific urls.py file and then you can include those URLs in the project-wide URL file. That might look like this (example from the Django docs):

urlpatterns = [
    # ... snip ...
    url(r'^community/', include('django_website.aggregator.urls')),
    url(r'^contact/', include('django_website.contact.urls')),
    # ... snip ...
]

So a use-case:

We're developing a REST API and right now all of our routes are defined in routes.php. That's an ok solution, but we have a lot of plugin-specific routes. It would be nice to be able to define a base such as /api/ and pass the rest of the request to a plugin-specific routes file.

An idea of what this might look like:

return array(
    'api'   => array('pluginRoutes' => 'apiPluginName'),
);

And then in craft/plugins/apiPluginName/routes.php would be a routes file similar to the project-wide routes.php file in craft/config

Is the registerSiteRoutes hook what you're looking for?


entries.saveEntry not triggered by ResaveElements task I've got a plugin that does a thing when an entry is resaved. It works great. However I need it to fire for every single entry to build some data.

craft()->on('entries.saveEntry', function(Event $event) {
    // Do the thing
});

Why does running a ResaveElements task not fire this yet saving an entry does? Updating a section to cause all of the entries in that section to update doesn't either.

Is there a way I can bulk trigger this to fire outside of me having to write my own script to manually do it.

Thanks!

It's because the ResaveElements task calls craft()->elements->saveElement() directly, instead of going through the element specific save method (like craft()->entries->saveEntry().

You'll want to listen to the onSaveElement event, check that it's an Entry you're looking at, then perform any specific business logic that you need.


Can't link to entries or assets via a Redactor field When using a Redactor field for a section, I can’t upload assets or link to entries. I just get an empty modal with no ability to select a section or asset folder. Thoughts on what I’m doing wrong?

[UPDATED] See video: https://drive.google.com/file/d/1hKKKKizSfmr1-QeblzfSbQ1B3Pf6Bybv/view?usp=sharing

Currently, there is no Craft 3.1 compatible version of the Redactor plugin. There's a branch in the Redactor plugin repository that has such a version, but that will be released only when Craft 3.1 is released as well.


Redirect user based on group after Craft login I have a plugin that checks for the current user on login and should redirect the user if they are part of a particular user group. When I do this I get the following "An unknown error occurred." and the redirect doesn't work. See init function below:

function init()
{
    craft()->on( 'userSession.onLogin', function( Event $event ){
        $user = craft()->userSession->getUser();
        if ($user && $user->isInGroup('sales')){
          $url = "new.url";
          craft()->request->redirect($url);
        }
    });
}

Please advise.

This is an alternate solution to what you're trying to do, and only applies if the login is coming and being directed to front end templates, but you could do something similar directly in your twig template, rather than having to use a plugin.

You could put something like...

{% if currentUser and currentUser.isInGroup('sales') %}
{% redirect "new.url" %}
{% endif %}

...somewhere on the page that logged in users will land on by default.


siteUrl not updating Experiencing a headache on a client site where the siteUrl declared in general.php is not being reflected in the Control Panel (which is always showing the local siteUrl) and therefore also the template on the site.

An abridged/edited config file here: https://gist.github.com/cole007/68382039e9ebedceabf7

Thoughts appreciated

When setting siteUrl in config.php, it overrides the "Site URL" setting in CP → Settings → General. It doesn't show the settings in that field.

  This is being overridden by the siteUrl config setting.


Composer conflict when installing craftcms/plugin-installer I have installed composer successfully but when I try to add:

composer require craftcms/plugin-installer

I get the following:

Your requirements could not be resolved to an installable set of packages.

Problem 1
- craftcms/cms 3.0.0-RC4 requires craftcms/plugin-installer ~1.5.0 -> satisfiable by craftcms/plugin-installer[1.5.0, 1.5.1, 1.5.2] but these conflict with your requirements or minimum-stability.
- craftcms/cms 3.0.0-RC4 requires craftcms/plugin-installer ~1.5.0 -> satisfiable by craftcms/plugin-installer[1.5.0, 1.5.1, 1.5.2] but these conflict with your requirements or minimum-stability.
- craftcms/cms 3.0.0-RC4 requires craftcms/plugin-installer ~1.5.0 -> satisfiable by craftcms/plugin-installer[1.5.0, 1.5.1, 1.5.2] but these conflict with your requirements or minimum-stability.
- Installation request for craftcms/cms 3.0.0-RC4 -> satisfiable by craftcms/cms[3.0.0-RC4].

Installation failed, reverting ./composer.json to its original content.

I have also tried the following with no luck:

composer require craftcms/plugin-installer --ignore-platform-regs

Note my composer.json file shows the following:

{

"minimum-stability": "dev",
"repositories": [
    {
        "type": "composer",
        "url": "https://asset-packagist.org"
    }
],
"config": {
    "optimize-autoloader": true,
    "platform":{
        "php":"7.1.1"
    }
},
"require": {
    "craftcms/cms": "3.0.0-RC4"
}
}

Any help would be appreciated! On a side note this is a local install using Mamp Pro.

I had the same problem following that video, i assume the ReleaseCandidate upgrade differs from the beta upgrade. Following the instructions from the craftcms github repo worked for me. https://docs.craftcms.com/v3/upgrade.html


'Unable to find component class 'FocusPoint_FocusPoint' - Craft CMS 3 Migrating from Focus Point Fields I am migrating from Craft 2 to Craft 3 where images have Focus Point fields.

I've followed Dan Hoerr's FocalPoint Migration (migration guide)
And the php migrate script seems to have run successfully, however entries are still showing:

Opening the field under Settings > Fields > Matrix Block > Image shows:

How do I remove old FocusPoint field data and regain these image fields?
Will I need to manually re-add all the images?

I have tried:

Clearing Caches
Updating asset indexes

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


Error when trying to send HTML email on event onActivateUser Background:

I'm working on a site that has frontend registration with some custom fields. The client would like to have a notification email whenever someone activates their account, containing the info on that user (so name, email and the custom fields).

Issue at hand:

For some reason, I'm getting the following error when I try to send an HTML email on the 'onActivateUser':

  Unable to find the template “_emails/customer-service-notification”.

If however I try to send a plain text email, it all goes without problem.

I'd prefer to send out an HTML email so I'd like to resolve this.

What I already tried:

Triggering the service function in another way (via custom controller action) sends the html email just fine
Sending the mail by just setting the content as string in the function works just fine

Code:

Main plugin file - init function

craft()->on('users.onActivateUser', function (Event $event){
    $user = $event->params['user'];
    craft()->plugin_customerServiceNotification->sendNotificationMail($user);
});

customerServiceNotification

public function sendNotificationMail(UserModel $user){
    $mailer = craft()->email;
    $mailToBeSent = new EmailModel();

    $mailToBeSent->subject = Craft::t('Nieuwe gebruiker geregistreerd');
    $mailToBeSent->fromName = 'xyz';
    $mailToBeSent->sender = 'noreply@xyz.be';

    $mailToBeSent->toEmail = 'xyz@xyz.be';

    $content = craft()->templates->render(
        '_emails/customer-service-notification',
        [
            'userInfo' => [
                'email' => $user->email,
                'name' => $user->fullName,
            ],
        ]
    );
    $mailToBeSent->htmlBody = $content;

    $mailer->sendEmail($mailToBeSent);
}

Folder structure:

Changing sendNotificationEmail() to this should fix it for you:

public function sendNotificationMail(UserModel $user) {
    $mailer = craft()->email;
    $mailToBeSent = new EmailModel();

    $mailToBeSent->subject = Craft::t('Nieuwe gebruiker geregistreerd');
    $mailToBeSent->fromName = 'xyz';
    $mailToBeSent->sender = 'noreply@xyz.be';

    $mailToBeSent->toEmail = 'xyz@xyz.be';

    $originalTemplateMode = craft()->templates->getTemplateMode();
    craft()->template->setTemplateMode(TemplateMode::Site);

    $content = craft()->templates->render(
        '_emails/customer-service-notification',
        [
            'userInfo' => [
                'email' => $user->email,
                'name' => $user->fullName,
            ],
        ]
    );

    $mailToBeSent->htmlBody = $content;
    $mailer->sendEmail($mailToBeSent);

    craft()->templates->setTemplateMode($originalTemplateMode);
}


How to customize HTML Purifier? HTML Purifier is deleting a custom link attribute. As I understand the HTML Purifier docs, it should be possible to customize it to allow a defined attribute. Is there in Craft CMS a defined way for doing such a customizing (like the Redactor configuration)?

Thank you very much for your help!

Edit: Would probably possible in "RichTextFieldType.php" (Line 205ff)?

There's no way to configure the default Rich Text Field's use of HTMLPurifier, unfortunately, though it has been brought up before and is on our list to look at exposing to a config file post Craft 3 launch.

Your custom plugin could create it's own CHtmlPurifier instance and configure it however you want, though.

$purifier = new \CHtmlPurifier();
$purifier->setOptions(array(
    'Attr.AllowedFrameTargets' => array('_blank'),
    'HTML.AllowedComments' => array('pagebreak'),
    ...
));

$value = $purifier->purify($value);


Is there a way to check if any fields in a global set have content? I have a global set called socialNetworkContent.

Is there a way to setup a conditional to check whether any of the fields within this set have content?

So the section wouldn't display if all the fields were blank.

Something along these lines:

{% if socialNetworkContent|length %}

Follow Us

            {% if socialNetworkContent.branchFacebookProfile|length %}

{% endif %}
            {% if socialNetworkContent.branchTwitterAccount|length %}

{% endif %}
            {% if socialNetworkContent.branchLinkedInAccount|length %}

{% endif %}
            {% if socialNetworkContent.branchGooglePlusAccount|length %}

{% endif %}
            {% if socialNetworkContent.branchInstagramAccount|length %}

{% endif %}
            {% if socialNetworkContent.branchYoutubeAccount|length %}

{% endif %}

{% endif %}

It's not exactly "quick", you'll have to do something like this:

{% if socialNetworkContent.branchFacebookProfile|length
       or socialNetworkContent.branchTwitterAccount|length
       or socialNetworkContent.branchLinkedInAccount|length
       ...
%}

Which is probably exactly what you're trying to avoid.

If you want to just make it a little easier to read, you can do something like this:

{% set x = socialNetworkContent %}

{% if x.branchFacebookProfile|length
       or x.branchTwitterAccount|length
       or x.branchLinkedInAccount|length
       ...
%}

The hurdle that you're dealing with is the fact that the socialNetworkContent object contains many other attributes besides just your custom field names. So there's not really any efficient way to "loop through" your custom fields without dealing with a bunch of extra junk.

Of course, you could build a plugin to create a simple boolean variable, but that sounds like overkill for this situation.


onBeforeSaveUser validation for existing user but not new user I am trying to validate first name and last name on my user registration form. I have tested and the following works for existing users when updating their profile via the form. Both use the onBeforeSaveUser event.

Any ideas why this wouldn't validate for registering users?

public function init()
{
    craft()->on('users.onBeforeSaveUser', function(Event $event)
    {
        craft()->businessLogic_events->onBeforeSaveUser($event);
    });
}

public function onBeforeSaveUser(Event $event)
{
    $user = $event->params['user'];

    if (empty($user->firstName))
    {
        $user->addError('firstName', Craft::t('Name cannot be empty.'));
        $event->performAction = false;
    }

    if (empty($user->lastName))
    {
        $user->addError('lastName', Craft::t('Last Name cannot be empty.'));
        $event->performAction = false;
    }
}

If you hit the submit button and don't fill out any fields. Then the only errors back are Email and Password (standard and set out by Craft). If you do enter an email and password then my validation code works and it errors again this time with the firstName and lastName errors. But these don't trigger on first submit when all fields are blank.

This is a known issue (specifically with the UserModel when saving a user) because "First Name" and "Last Name" aren't true fields in Craft, but more special case fields.

When saving a user, the UserModel validation runs first and immediately bails when the validation error occurs before the onBeforeSaveUser event fires not giving any plugins a chance to participate.

This will be fixed in the upcoming Craft 3 release.


Delete fieldgroup when deleting plugin I'm making a plugin that stores elements in fields and fieldGroups. When deleting one the elements with  the fields/field groups are being removed too.

But when deleting the whole plugin, those fields are still in the database. When reinstalling the plugin this makes it impossible to add the field with the same title again.

I've already added 'onDelete' things in all the records like this:

public function defineRelations()
{
  return array(
    'form'        => array(static::BELONGS_TO, 'PluginHandle_FormRecord', 'onDelete' => static::CASCADE),
    'fieldGroup'  => array(static::BELONGS_TO, 'FieldGroupRecord', 'onDelete' => static::CASCADE),
    'field'       => array(static::BELONGS_TO, 'FieldRecord', 'onDelete' => static::CASCADE)
  );
}

I've been searching the docs to see what actually happens when a plugin is being deleted, but can't find anything. Any ideas?

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

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

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


Custom Plugin Field Using Wrong Template Path I'm trying to build a simple dropdown field with a pre-populated set of options, so I figured I'd just import most of the methods from Craft's native Dropdown field. The plugin name is siteutilities and the field name is Regionselect:

namespace kgrote\siteutilities\fields;

use kgrote\siteutilities\SiteUtilities;

use Craft;
use craft\base\ElementInterface;
use craft\fields\BaseOptionsField;

This pulls in the code from craft/vendor/craftcms/cms/src/fields/BaseOptionsField.php.

So now I want to render a custom settings template for my plugin:

public function getSettingsHtml()
{
    return Craft::$app->getView()->renderTemplate(
        '_components/fields/Regionselect_settings',
        [
            'field' => $this,
        ]
    );
}

But I get a Twig error:

  Unable to find the template
  “_components/fields/Regionselect_settings”.

My plugin file structure looks like this:

kgrote
|-siteutilities
  |-src
    |-fields
    |  |-Regionselect.php
    |-templates
    |  |-_components
    |    |-fields
    |      |-Regionselect_settings.html
    |-SiteUtilities.php

In order to render a template within your custom plugin you need to include your plugin handle in front of your template path. For example

plugin-handle/_components/fields/Regionselect_settings


Multiple Site Manager Homepages and Fields Apologies if this is a simple question :/

I'm using Multiple Site Manager for the first time and although I get it in principle i'm struggling to understand how to setup homepages.  Here's what I have got so far and then what i'm trying to do...

Done
1. Created multiple sites in CP (done)
2. Created templates/siteHandle directories (done)
3. Pointed webserver (done)
4. Confirmed correct index.twig is loaded on correct url (done)

I have then created a 'Single' section called 'Homepage' and checked both available sites to recognise this as the 'homepage'.  I then assigned a field called 'Introduction'.

My instinct is that any content applied to this 'Introduction' field should be different depending on which site was selected in the CP when adding and saving the content. So I can have a different homepage per website... because they use different index.twig which are loaded depending on url.

No... what actually happens is that any content I add or change in the homepage entry under 'Site One' in the CP immediately overwrites whatever was in 'Site Two' homepage entry and vice-versa!?

I did see a (untried) solution from a couple of years ago which was to create 'Homepage One', 'Homepage Two', ... and only assign each to the appropriate 'Site'.  But surely if Craft is loading a template based on a url and an assigned index.twig via 'siteHandle' directory, one 'Homepage' under each 'Site' should work?

Thank you for any explanation and/or guidance :)

What you're actually looking for here are the translation settings. These are stored against each field: in a multi-site installation, each field can be "translated" per site, per language or per site-group. ("Translated" is perhaps a confusing label here if your two sites are technically in the same language).

Set your Introduction field to be translatable for each site and it will be able to store unique content for each site.

This approach gives us lots of flexibility to have some fields with shared content and others with unique content, which cuts down the amount of duplicate editorial effort considerably on large multi-site installations where, for example, each site may want to use the same banner image but have different captions etc.


What is the max # of version history for any given entry? I can't seem to find anywhere mentioning what the max # of versions a given entry can have--I would assume its unlimited (given unlimited DB space).

There is no set maximum number of versions an entry can have, assuming you have unlimited database space.

Take a look at the source code in the EntryRevisionsService for more information: https://github.com/craftcms/cms/tree/master-v2/src/services/EntryRevisionsService.php#L148


How to relate a long survey to a user and later query by values I'm working on a new project that requires users to fill out a lengthy survey to assess their skills. These skills will then be used to query for users with a front-end interface. My question has to do with how to store these ~120 skills and query them later.

Each skill with have a range of values such as:

Skill: Crosscut Saw Experience
Possible values: 0) none 1) performed with supervision 2) performed independently 3) Have Supervised 4) Trainer

So, that first makes me thing of radio button fields. The issue is that there is about 120 of these skills that need to be recorded for each user with a front-end form. And, the must be the ability to quickly query user based on skill/skill level.

At first I considered a static Super Table, but I don't believe querying that is easy or efficient, based on other questions I've browsed.

Plan B is to create a Skills channel, creating ~120 skill records, related to each user. This would make querying simple a matter of finding records relatedTo a skill. But how to create all these records on the front end as the user is filling out a form?

I've not used any of the form plugins, such as Sprout Forms or Freeform. Anyone have any experience with these that might shed some light?

Any other suggestions on how to best go about this?

Thank you for any ideas or advice.

When you're dealing with that many fields it's definitely a non-trivial undertaking but Craft does have all the tools you need to pull it off.

Your plan B is probably the most solid option. Make a new section that houses the skill entries and then set up all the radio buttons on it you'll need.

You can put fields on Users directly but it gets weird as they don't act like entries in some respects.

Getting all the fields into Craft is probably another topic that you'll probably want to do programatically.  However,  after you have them all in the CMS, it's relatively straightforward to spit out all the fields for a particular entry type in a section.

To do that:

{# get the section by handle #}
{% set section = craft.sections.getSectionByHandle('skillRecords') %}

{# fields are set on entry types of sections to get all the entry types #}
{% set entryType = section.getEntryTypes %}

{# loop through the fields in the first entryType's fieldLayout Model #}
{# if you have more than one entry type, use 1, 2..etc #}

{% for fieldLayoutField in entryType[0].getFieldLayout().getFields() %}

    {# get the field from the id #}
    {% set field = craft.fields.getFieldById(fieldLayoutField.id) %}

    {# grab the type of field from its className #}
    {% set fieldType = field.className|replace({'craft\\fields\\':''}) %}

    {# output the field #}

    {% switch fieldType %}

     {% case 'RadioButtons' %}
     <fieldset>
     <legend>{{ field.name }}</legend>

    {% for option in field.options %}

        {% set selected = entry is defined ?
                          field.value == option.value : option.default %}

        <label>
            <input type="radio"
                name="fields[field.handle]" value="{{ option.value }}"
                {% if selected %}checked{% endif %}>
            {{ option.label }}
        </label><br>

       {# you'll probably  want to make other cases depending on what you're doing #}
    {% endfor %}
    </fieldset>

  {%endswitch%}

{% endfor %}

That's a pretty simple example with zero styling so you'll obviously want to make it your own. As with anything in Craft, the front end and the UI is up to you.

You might consider splitting up the questions into pages (eg 30 per page) and save the form after every page (either in the user's browser or to Craft itself). Vue or even jQuery can help you do that.

I'm not sure what the performance aspect is going to be when it comes to 120 fields. The most performant way would be to setup your own table with its own values but that goes down the rabbit hole of plugin development.


Edit a single address in Commerce I've read the docs but I can't seem to get this to work properly. I want to edit a single address on a separate page from where all addresses for a customer are listed. I have the link to the edit page, which looks like this:

Edit

Then on that edit-address template I have the following:

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

<form method="post">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="commerce/customerAddresses/save">
    <input type="hidden" name="redirect" value="account/address-book">

    {% if addressId %}
        <input type="hidden" name="address[id]" value="{{ addressId }}">
    {% endif %}

    <input type="text" name="address[firstName]" value="{{ address ? address[firstName] : '' }}">
    <input type="text" name="address[lastName]" value="{{ address ? address[lastName] : '' }}">
</form>

That leads to a "Variable 'address' does not exist" error. I understand why I get that error but I'm not sure how to get the value field to show the address info. Having a blank form field isn't going to cut it.

Are you looking for something like this? The second example will ensure an address variable exists, even if it is set to null.

{% set address = craft.commerce.customer.address(addressId) %}

or

{% set address = address is defined ? address : null %}

As for accessing the data, you would just do this:

{{ address ? address.firstName : '' }}

Another way to do it (without needing to define a null address variable) is:

{{ address.firstName ?? '' }}


Image transforms not working I have setup an asset pool for all files our customer wants to upload using {basePath} and {baseUrl} variables which are defined in the configuration file.

Uploading files works
Selecting files to assign them to content works
displaying the files on the front page works
thumbnail generation in the backend does not work - returning 404 for the resized url
custom transforms for thumbnails on the front page do not work - 0-byte images get created which are of course empty

Nothing gets logged in the errorlog - everything seems to work fine.

I'm kind of lost currently - Project working nicely local but not on our server.
Any help on how to debug and solve this problem? Looks like an inconsistency problem inside of craft as some methods are accessing the assets correctly while others don't.

Here some files:

general.php

<?php return [
    'allowAutoUpdates'     => false, // Using shared craft, disable update triggering for customer - TODO: Completely hide update stuff in backend.
    'omitScriptNameInUrls' => true,
    'environmentVariables' => [
        'baseUrl' => CRAFT_SITE_URL,
        'basePath' => CRAFT_SITE_PATH
    ]
];

index.php

<?php

define('CRAFT_CONFIG_PATH',       'assets/configs/');
define('CRAFT_PLUGINS_PATH',      'assets/plugins/');
define('CRAFT_TEMPLATES_PATH',    'assets/templates/');
define('CRAFT_TRANSLATIONS_PATH', 'assets/translations/');
define('CRAFT_STORAGE_PATH',      'cache/');

define('CRAFT_SITE_URL',  substr($_SERVER['SCRIPT_NAME'], 0, -9));
define('CRAFT_SITE_PATH', substr(__FILE__, 0, -9));

require '../_craft/app/index.php';

.htaccess

# Compression
SetOutputFilter DEFLATE

RewriteEngine On

# No duplicate rewriting.
#TODO Remove and use [END] when Apache 2.4 is available on production.
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# Sass and JavaScript compilation and minification - except for admin backend.
RewriteCond %{REQUEST_URI} !admin/ [NC]
RewriteRule \.css$ scss.php [L]
RewriteCond %{REQUEST_URI} !admin/ [NC]
RewriteRule \.js$ js.php [L]

# Make bootstrap fonts available.
RewriteRule ^assets/bootstrap/(.+)$ vendor/twbs/bootstrap-sass/assets/fonts/bootstrap/$1 [L]

# Let craft handle everything else.
RewriteRule ^assets/icons/ - [L]
RewriteRule ^assets/images/ - [L]
RewriteRule .* index.php [L]

Both Environments have Imagick and GD available.

Environment Development: Ubuntu, Apache 2.4, PHP 5.6, MySQL 5.6

Environment Production: Debian, Apache 2.2, PHP 5.5, MySQL 5.5

It sounds like you're running into a bug in the latest version of Craft (2.4.2675) where transforms are broken for source asset files that end in an uppercase file extension (.JPG, .GIF, etc.).

It's already been fixed for the next release, but as a workaround you can rename the extensions to be lowercase and re-index your assets.


Get a page URL using only the Slug? Wondered what the best approach would be to get the url for a given entry page using only a slug for reference? I imagined it being something like this:

 public function getPageURL($slug) {
    $page = craft()->elements->slug($slug);
    @return getURL($page);
  }

Usage example:

Staff

Completely untested, but something like this should work:

public function getPageUrl($slug)
{
    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->slug = $slug;
    $entry = $criteria->first();

    if ($entry)
    {
        return UrlHelper::getUrl($entry->uri);
    }
}


Loading assets cross-domain with SSL or non-SSL option Here's a unique situation. I have three websites. All assets are stored at the domain of the first site:
domain.com/files/*
The first two sites run completely over SSL. No problem.
The third site needs to have the option to load either over SSL or non-SSL. This is entirely thanks to the authoritarian governments of countries like China, which may block a site, no matter the content, if it can only load over SSL.
In my config.php, I have this:
'@assetBaseUrl' => 'https://site1.domain.org/files'

If I change this to exclude https://, Craft does not create proper URLs for images and files. I also tried //site1.domain.org, but that doesn't work either.
Is there some setting I can use for @assetBaseUrl that will work across the board?

You could try something like '@assetBaseUrl' => $_SERVER['HTTPS'] ? 'https://site1.domain.org/files' : 'http://site1.domain.org/files' which checks for a secure request.


How can I have a dynamic uri segment for a single? I am trying to have a dynamic uri segment for a single. I have this uri in the CP settings:

offers/listing/{slug}

Where {slug} is the entryId. For example, offers/listing/1234

I have a template at templates/listing/make-offer.twig

For the template path i have: listing/make-offer

If I navigate to site.com/offers/listing/1234 I get a 404.

However, if I make a custom route:

URI looks like: offers/listing/(slug)
Loads template: listing/make-offer

Everything works. The downside is I would like to control the content on the top of the page through the CP.

I realize, this is something more of a channel (which I still get a 404), but this page will never go anywhere. It's a content page at the top with a contact form at the bottom.

Thank you for any suggestions!

Assuming that a Single is the right thing to use here (and I'm not sold on that but I trust your judment) the following is what I would do to accomplish what you want.

// config/routes.php
'offers/listing/(?P<entryId>\d)' => 'listing/make-offer'

// templates/listing/make-offer.twig
{% set entry = entry is defined ? entry : craft.entries.id(entryId) %}

Explanation

First, we create an Advanced Route to make the (single) entryId available to the template that will be loaded when the route matches.

Then, in the template, we set the entry variable to either the entry that Craft makes available to the template via its own routing or we fetch one explicitly by using the entryId passed to the template from the custom route. Our route may take precedence over default routing, so the entry is defined check may be removed and rely instead on craft.entries.id(entryId)

End Result

You should be able to navigate to /offers/listing/1234, which will load the templates/listing/make-offer.twig template with the entryId set to 1234.

Hope this helps, feel free to follow up if something isn't clear.


What does {{ hiddenInput('enabled', '1') }} in an entry form do? What's the purpose of {{ hiddenInput('enabled', '1') }} in an entry form?

<form method="post" accept-charset="UTF-8">
{{ csrfInput() }}
{{ actionInput('entries/save-entry') }}
{{ redirectInput('viewentry/{slug}') }}
{{ hiddenInput('sectionId', '2') }}
{{ hiddenInput('enabled', '1') }}

It is to generate an HTML input tag with type of hidden.
This will not appear on the screen like a normal input does.
For more information related to input type hidden, you can refer to this.

enabled means that the entry will be saved with its status toggle set to the “enabled” (green) position.


CSRF in plugin dashboard widget 400 error Yes, it's another csrf question, the standard, 400 Error - Bad Request: Unable to verify your data submission.

If in config/general.php I set 'enableCsrfProtection' => false, then everything works nicely. So it's definitely a csrf problem.

Here's the twig template for the widget:

src/templates/_components/widgets/Livestream_body.twig
---------------------
<script type="text/javascript">
    window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName|e('js') }}";
    window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js') }}";
</script>

and the Javascript:

src/assetbundles/livestreamwidget/dist/js/Livestream.js
-------------------
$(document).ready(function () {
   var data = [];
   data[window.csrfTokenName] = window.csrfTokenValue;
   $.post('actions/livestream/main/manage-get', data, function(response, textStatus, jqXHR) {
       alert('Posted OK!');
   });
});

I can see the csrf token value changes on page load, and as I said, without csrf enabled, the js successfully loads the widget, so, what am I doing wrong on the csrf? I don't have any  element. Would that make a difference?

as jQuery docs says you have to pass data object or string via data.
so you should change

var data = [];

to

 var data = {};

in your code


Seomatic - disable tag manager from inside template I am using Seomatic and i want to conditionally render google tag manager trancking code - or not.

How do I disable it using some Twig template code?

This code will let you disable the inclusion of the tag:

{% do seomatic.script.get('googleTagManager').include(false) %}

For more, check out the SEOmatic Twig Templating documentation

If you're changing the inclusion of the tag or not based on some other variable such that the tag may be included or not for the exact same URI, you'll want to bust the cache, too (which is URI-based):

{% do seomatic.script.container().clearCache(true) %}

Also check out the Advanced SEOmatic Tips article for some deeper reading.


How do I display entries depending on multiple relations? In this example, I'm trying to show entries with the category "Beer". This works:
{% set myCategory = craft.categories.slug('beer') %}
 {% if entry.relatedDrinks.relatedTo(myCategory)|length %}

Beers

  {% for beer in entry.relatedDrinks.relatedTo(myCategory) %}
   {{beer.title }}
  {% endfor %}
{% endif %}

I also want to limit these entries to a certain year (not defined by Entry Date). I've created a Section called "Product Year" with entries such as "2020" and "2021". Within the entry for the beer, I've added an Entries field to select the year defined in the Product Year section. I'm not sure how to use that Product Year relation as a filter.
I'm essentially trying to say {% if entry.relatedDrinks.relatedTo(myCategory)|length "and product year is 2020 "%}

This is not a full fletched solution, but might kickstart you.
One solution would be to add a "vintage" or "brewYear" date field to your entry's section. In twig, you can then use the contents of this field to do you further selections.
Another solution would be to use a second category group containing the years you need. Then, adding another category field (for the years) to the beer section would allow you to relate the entry to this category and subsequently in Twig you are able to filter based on this relation.
If you checkout the documentation for Craft 3 relations, you might see how you can query entry records based on multiple relations.
There is also a demo website on http://barkeeper.parhelia.ch which is based on code published by Pixel & Tonic here. Its not a 100% fit for what you try to achieve, but has some nice concepts – although it also uses the SuperTable plugin for the drink incredients.


Image transforms getting applied even when image is smaller than the transform's width I have a detail transform setup and here's my template code:

{% if block.type == 'image' %}
    {% for asset in block.image %}
        <img src="{{ asset.url('detail') }}" alt="{{ asset.title }}" class="{% if block.position in ['left'] %}pull-left{% endif %}">
    {% endfor %}
{% endif %}

But on the front end it's taking a smaller image and stretching it and it's become distorted. If I remove 'detail' from the url() parameter it's fine.

Here's what my Detail Transform looks like:

Any thoughts?

It also looks like all transforms are doing the same thing as well. So it's not just related to the detail transform.

I think you're confusing the "Width" setting to mean "Max Width", which it doesn’t. The image will get sized to match your transform's Width setting, regardless of whether it's bigger or smaller than that width beforehand.

If you want to conditionally apply the transform, only if it's larger than the transform's width, you can do this:

{% if asset.width > asset.getWidth('detail') %}
    {% do asset.setTransform('detail') %}
{% endif %}

<img src="{{ asset.url }}" alt="{{ asset.title }}" class="{% if block.position in ['left'] %}pull-left{% endif %}">


Variable to check if viewing an entry? How would I write a variable to detect if the current page/Url I'm viewing is for an entry, rather than a section home page or a single?

i.e

{% if I'm currently viewing an entry %}
    do this
{% else %}
    do this
{% endif %}

There are three types of sections in Craft: singles, structures, and channels. You can use entry.section.type to test if the current page is displaying one of these section types.

{% if entry.section.type == "channel" %}

This is a channel

{% elseif entry.section.type == "single" %}

This is a single

 {% elseif entry.section.type == "structure" %}

This is a structure

 {% endif %}


Close bootstrap row and start a new row Matrix I need to figure out how to close out the columns if it equals 12 and then open a new row. I have a Matrix field set up with rows, but it needs to break with a new row if the columns equal 12.

Any suggestions?

You could track the total used columns in a var and check if its less than 12.

{% set col_count = 0 %}
{% for item in items %}
    {% switch item.type %}
        {% case "value1" %}
            {% set col_size = 4 %}
        {% case "value2" %}
            {% set col_size = 6 %}
    {% endswitch %}

    {% if not loop.first and (col_count + col_size) > 12 %}

        {% set col_count = 0 %}
    {% endif %}

    {% if col_count == 0 %}

    {% endif %}

    {% set col_count = col_count + col_size %}

        {{ item.title }}

    {% if loop.last %}

    {% endif %}

{% endfor %}


permissions userphotos "an unknown error occurred" On my production server, each time I try to change or upload a user photo I get the "an unknown error occurred" message. If I check the logs, the error says it couldn't delete the folder of the userphotos because it is not writable.

Now I checked the settings and everything is set to 755, the same as the assets folder where I have no problems uploading. The only way I got the userphotos to work is to set the permission on the folder to 777, but that's not the best solution security-wise.

So why isn't the userphotos folder writeable but the assets folder is?

Changing the userphotos folder's owner to be the same as the user:group Apache was running as solved the issue.  i.e.

chown -R www-data:www-data userphotos


How to get image url from matrix field I have an image in a matrix-field, but can't get the url from it.
dump(block.image.one().url) says NULL. My code is:

{% if entry.hero %}
  {% for block in entry.hero %}
    {% if block.type == 'hero' %}
      {% set heroImage = block.image.one() %}
      <div class="cell hero center padding-1" style="background-image: url({{ heroImage.url }});">
      </div>
    {% endif %}
  {% endfor %}
{% endif %}

image.one() or image.first(), as well as .url or .getUrl() doesn't work the same.

What works though is {{ block.image.one().folderPath }}{{ block.image.one().filename }}

Does anyone know why? I'm on Craft CMS 3.3.15

The asset volume needs to have public urls enabled. Thanks seb.


Why is the summary and body returning an empty object using the Element API? I'm not sure what I'm missing, but I'm getting an empty object back from the Element API for the summary and/or body for any given entry.

elementapi.php

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

Here is the json I am getting back:

{"data":[{"title":"My Title","url":"http:\/\/local.mysite.dev\/section\/my-entry","summary":{}}

EDIT/SOLUTION

Thank you again @Oliver!

I wanted to update my post in the event someone else came across it. I am using mustache.js to render my html from the json that is getting output via the ElementAPI.

By casting the summary as a string, you will need to tell mustache to parse the html by using three curly-brackets instead of the usual two.

mustache

Title: {{title}}

URL: {{url}}

{{{ summary }}}

Otherwise you will end up with something that looks like this:

Title: My Title
URL: www.mysite.com

This is my summary

Try this:

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


Craft 3: Get Data from a custom Table via createCommand() In Craft 2 you could creat a query with:

craft()->db->createCommand()->select() .... etc.

But in Craft 3 there is no select() Method in Craft::$app->db->createCommand().

Am I overlooking something?

You can use either an activeRecord  for it

$customer = Customer::find()
    ->where(['id' => 123])
    ->one();

Or a query

$rows = (new \craft\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->limit(10)
     ->all();


Does Redactor have a button that adds a horizontal rule ( tag)? Does Redactor have a setting for a button that adds a <hr> tag?

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

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


Query to element criteria Is it possible to turn a query into an element criteria model? Currently I'm doing this:

$criteria = craft()->elements->getCriteria('Conference_Session');
$criteria->conferenceId = $conferenceModel->id;

$query = craft()->elements->buildElementsQuery($criteria);
$query->order("conference_session.cs_start_time ASC");

$queryResult = $query->queryAll();

I would prefer to be able to be able to add my MySQL commands then turn it back into a element criteria. I don't have to do this but I want to know if I could.

I think you want to have the same result as with an ElementCriteriaModel, instead of getting an ElementCriteriaModel.

What you want to do is mimic craft()->elements->findElements(), and put your own $query in it. This will more or less put the results in their models. You can just copy this function and replace the second line (where $query is defined) with your logics.

You could also do something like Conference_SessionModel::populateModels($queryResult), but by the way Craft joins the content table in findElements this would be rather slow, as it would make a new query for every content field.

What would be really nice is if you could specify $query in findElements, too bad Craft doesn't support this (yet?)


Is there a way to return the number of columns in a table? Is there a way to return the number of columns in a table?

I tried {{ entry.tableHandle | length }} but this seems to return the number of rows rather than columns.

I've got a site with a couple of tables and I'm trying to output the number of columns in a given table to use for my CSS responsive column width.

I.E. If table was 2 columns, it would output a 2 and I would use that to set column width to 50% etc...

entry.tableHandle is an array of all of the rows, and each row is an array with keys that are the column names and values that are the column values AND keys that are col1, col2, etc. and values that are the column values.

So you can do entry.tableHandle[0]|keys to get the keys, entry.tableHandle[0]|keys|length to get the number of keys, and finally (entry.tableHandle[0]|keys|length)/2 to get the number of columns.

You will want to check first that there is a row in the table - this won't work if there is no row 0.


Craft 3 wont update in Laravel Valet development enviornment I'm using Laravel Valet with Craft 3 (Craft 3.0.0-RC13) and Sequel Pro.

I can't seem to get Craft to update. I just get a warning sign and a message saying that it couldn't back up the database.

When I looked at my log file, it contained the following:

  FROM craft_info
  2018-03-27 09:54:43 [127.0.0.1][1][-][error][craft\controllers\UpdaterController::actionBackup] Error backing up the database: The shell command "mysqldump --defaults-extra-file="/Users/richardclark/Sites/lorindafontainefarris/storage/runtime/temp/my.cnf" --add-drop-table --comments --create-options --dump-date --no-autocommit --routines --set-charset --triggers --single-transaction --no-data --result-file="/Users/richardclark/Sites/lorindafontainefarris/storage/backups/lorinda-fontaine-farris_180327_135443_jfivi9ibwf_v3.0.0-rc16.1.sql" lorindafontainefarris && mysqldump --defaults-extra-file="/Users/richardclark/Sites/lorindafontainefarris/storage/runtime/temp/my.cnf" --add-drop-table --comments --create-options --dump-date --no-autocommit --routines --set-charset --triggers --no-create-info --ignore-table=lorindafontainefarris.craft_assetindexdata --ignore-table=lorindafontainefarris.craft_assettransformindex --ignore-table=lorindafontainefarris.craft_cache --ignore-table=lorindafontainefarris.craft_sessions --ignore-table=lorindafontainefarris.craft_templatecaches --ignore-table=lorindafontainefarris.craft_templatecachecriteria --ignore-table=lorindafontainefarris.craft_templatecacheelements lorindafontainefarris >> "/Users/richardclark/Sites/lorindafontainefarris/storage/backups/lorinda-fontaine-farris_180327_135443_jfivi9ibwf_v3.0.0-rc16.1.sql"" failed with exit code 127: sh: mysqldump: command not found
  2018-03-27 09:54:43 [127.0.0.1][1][-][info][application] $_GET = [
      'p' => 'admin/actions/updater/backup'

I tried adding a PATH reference to my export PATH=$PATH:~/.local/bin/mysqldump in the .bash_profile file, but that didn't seem to do anything. Do I have to add something to the CraftValetDriver file, or is my PATH reference incorrect?

Any help would be greatly appreciated.

Thanks,

Richard

I believe we were conversing via Medium yesterday on this issue.

Regarding your question, I know for a fact your PATH reference is incorrect. The path to mysqldump is never ~/.local/bin/mysqldump; mine is located at /usr/local/bin/mysqldump (I'm using MariaDB).

BUT since you said on Medium that you're using MySQL (instead of MariaDB or another database option), you should use this instead: export PATH="/usr/local/mysql/bin:$PATH".

After you add that to your .bash_profile and either source the file or quit and relaunch terminal, mysqldump should be working.


Redactor won't allow simple styling in heading tags On a fairly fresh site (and also on some more built up sites) I noticed that Redactor is preventing you from doing the following:

Create a heading such as an H1 or H2 with two or more words
Select only one of the words in the heading
Attempt to apply styling, such as bold or italic to that word

This should result in some simple markup such as:

My list of words

But it does not apply this styling.

Is this a bug with redactor? Intended behavior? Do you know a clever work around that would utilize Redactor's native buttons?

Edit:

The Clean Up HTML? field is unchecked on this redactor settings type.
This bug seems to be a redactor bug, it exists on http://imperavi.com/redactor/

Rich Text fields in Craft have several options to them that can affect code output. In your field settings, make sure you don't have Clean up HTML? ticked. As the description reads, this option:

  Removes spans, empty tags, and most style attributes on save.

Without seeing your field, this is a wild guess at what could be the problem.


How to fetch specific users OR admins with the ElementCriteriaModel? I'm getting all Users from specific UserGroups like this:

$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->groupId = array(1, 3);
$users = $criteria->find();

But how can I additionally fetch all admin Users?

I tried to add the admin attribute, but this hasn't changed anything:

$criteria->admin = array(false, true);

I assume that's because the ElementCriteriaModel has to match all attributes, but there isn't an admin which has a UserGroup with the ID 1 or 3. But how can I tell the criteria to perform a "OR" fetch?

P.S. I know I could merge two fetched criterias but I want to use a "clean" solution.

You won't be able to do that using the ElementCriteriaModel or a single query (unless you use craft ()-> db-> createCommand() or \CDbCriteria to perform a conditional JOIN).

You will either have to 1) do post filtering or 2) get the ids for users in the groups you want and the ids for all admin users (which I would recommend). You can then merge both arrays and use the resulting array to get all users that match the containing ids.

You mentioned that you wanted to do it the clean way and doing a couple of queries using the public Element Query API is definitely the clean way to do it and the fact that you're doing a couple of queries to get the users you want should not feel "unclean" because that is happening in a lot of different places behind the scenes when you use the API instead of raw queries.

For example, when you add the $ criteria->groupId = array(1, 3); to a user query, Craft will hit the db once to get all ids for users in those groups and then hit it again as many times as necessary to do what it needs to do, like perform searches and such.

My point is, using the API means that you might not be able get everything in one go but your plugin won't break if Craft changes any internal APIs.


FreeForm fields: Need access to customAttributes Pretty much a duplicate of FreeForm: Accessing a fields customAttributes but to answer Solspace's comment "Can you think of a use-case where you would apply attributes to a field but then render those manually?", yes I can.

My current project has Company entries and Equipment entries. Each user belongs to a single Company.

When a user fills out a form with a select field where source=entries and target=Equipment, I don't want the user to see all equipment in the system. Only equipment belonging to user's company.

I thought a clever idea would be to add field class "filterEquipment". When rendering my form

if field.type=select and field class contains "filterEquipment" I want to loop through field options and only display equipment that belongs to user's company
else render select field as normal

I'm open to other suggestions.

A suggestion from Freeform support:

  The only way you might be able to achieve this would be if you used a regular Text field (inside of Composer), and then override the formatting template to manually render the field as a select dropdown and populate the options dynamically. Actual fields with options such as Select fields need to have all of their options pre-defined inside Composer, which is why it wouldn't work otherwise. Using the element populators could almost get you there, but it doesn't allow dynamic filtering like what you'd need.


Help needed with 2 node setup I am setting up 2 node cluster with GlusterFS for shared file system. I have mounted the shared mount on each of the nodes but when I try to access login page I get this

/data/websites/websiteapp/craft/storage/ doesn't exist or isn't writable by PHP. Please fix that.

The folder permissions are lrwxrwxrwrx. Is there anything I need to do make it work?

So I figured out the issue, it is related to Ubuntu and how the mount process works using Upstart. I had a line in fstab to load the network drive but Ubuntu fails. Because of that failure, craft couldn't find the shared path which points to craft/storage/


Fetching Unique Categories related to Entries via GraphQL Suppose I have some entries in a section called 'product' that are related to a category call 'brand' - I know I can get the brands that are related to each product that match a search term using GraphQL like so:
query Query($searchTerm: String) {
  entries(search: $searchTerm, section: "product") {
    ... on product_product_Entry {
      brand {
        id
      }
    }
  }
}

Which returns something like this:
{
  "data": {
    "entries": [
      {
        "brand": [
          {
            "id": "3"
          }
        ]
      },
      {
        "brand": [
          {
            "id": "5"
          }
        ]
      },
      {
        "brand": [
          {
            "id": "3"
          }
        ]
      },
      ...

What I'm looking to do is get all the brands that are related to the products matching the search, but obviously if I use the above query then the response will get very big very quick. Is it possible to get just the distinct brand id values returned from the above GraphQL query? Or am I better off making a module with a controller action and querying the database that way?

You can run a categories query and pass it your product id(s) as well as the category group id (though that's not necessary) to fetch all categories related to your products.
The query:
query getRelatedBrands($relatedTo: [QueryArgument] = "", $groupId: [QueryArgument] = "") {
  categories(groupId: $groupId, relatedTo: $relatedTo) {
    id
  }
}

and the variables:
{
  "relatedTo": [13306, 13638],
  "groupId": [1]
}

Which would return:
{
  "data": {
    "categories": [
      {
        "id": "3"
      },
      {
        "id": "234"
      }
    ]
  }
}


Is there a way to retrieve discounts for a product in Craft Commerce v2? I would like to retrieve all available discounts for an eshop using the Craft Commerce v2.
In Craft Commerce v1, I could use the following:

craft.commerce.discounts.all()

However, I can't find an equivalent method for Commerce v2

Can anyone please help?

This should do what you're looking for:

craft.commerce.discounts.getAllDiscounts()

craft.commerce.discounts is a reference to services/Discounts, so you've got access to all of the public methods in there, of which getAllDiscounts() is one.


How to check if a user's new email has been verified Background
When the user setting Verify email addresses? is enabled, and the user's email is reset by a non-admin the address requires verification before being used  as explained here. This does not seem to show any sort of confirmation anywhere that the email reset has been made until the user verifies it. The account seems to stay live also, so checking pending users does not help.
Question
Is there an attribute or function I can call to find out if the email is verified?

This might not be what you are looking for, but one way to approach the problem:

You are able to set the STMP, IMAP credentials for the email service that Craft uses. Maybe use a service that has read receipts and use that to see if the new user has checked the confirmation email?


Filter Search Craft 3 Does anyone know or have a solution for a live search filter on the frontend for Craft.  I can muscle through putting something together but if you have used something that is friendly enough, would like to see the solution for Craft.

maybe this article will help! https://nystudio107.com/blog/autocomplete-search-with-the-element-api-vuejs


Craft Commerce: Add to Cart and then Redirect to Product Page? On my product page I have the default button that "Adds to cart" which adds a line item to the cart and take you to the cart page.

How do I create a second button alongside the default that adds the line item to the cart BUT then redirects the customer to the same page to select and customise another line item to add to cart?

Note: Ill very likely change the styling and text on the button (just in case anyone is concerned about usability) ;)

You would need to use javascript to change the redirect input's value

<input type="hidden" name="redirect" value="commerce/cart">

For example on the 'add and create new item' button you could do something like this using jQuery:

   $('.addAndCreateNewBtn').click(function(e){
       e.preventDefault();
       var $form = $(this).closest('form');
       $form.find("input[name='redirect']").val('anotherUrl');
       $form.submit();
   });

The above is untested, but should replace the redirect value then submit the form.


Where do we get the SMTP Authentication information? We are trying to get Office 365 working with a Craft website.  How do we know what the host name and port number is.  Plus, under SMTP authentication setting is asking for a username & password, where do I find this?

According to Microsoft, the Office 365 SMTP server is smtp.office365.com using port 587 and TLS encryption. Your username and password you'd get from your hosting provider as it's not Craft-specific information.


Updated To Craft 3, How To Delete Craft 2 Plugins I moved from Craft 2 to 3 but some of the plugins I used at one-time and are no longer compatible with Craft 3.  Those old plugins are now ghosts.  Meaning they are listed in the database and some have their own tables.

How to best get rid of old Craft 2 plugins?

It partially depends on the plugin. The one guarantee you have is that there will be a row in the plugins table. Go ahead and delete that row.

Some plugins create 3rd party tables. For most of those plugins, it's probably safe to just delete those tables as well.

I know you can't go back in time, but... the best solution would have been to remove those plugins before updating. Virtually all Craft 2 plugins did a good job cleaning up after themselves in the database.

Based on your comment...

  "Form Builder 2, AmForms, Hacksaw, Shortener"

Form Builder 2 - Not very familiar with this, but looks like it has 5 tables. Probably safe to delete them.
AmForms - Another one with 5 tables. Probably safe to delete these as well.
Hacksaw - No DB tables
Shortener - No DB tables


Display entries sharing the same nested category on an entry page I'm trying to show the other entries assigned to the same nested category (on an entry template)
but get an error if I use .last() which I was hoping would show the nested category assigned entries (and not all assigned to all levels of the same category,

Any ideas?

{# set the category group #}
{% set categoryGroup = craft.categories.group('products') %}

{% set entries = craft.entries.relatedTo(categoryGroup)  %}

{# only show entries assigned to the same nested category #}
{% for sameCat in entries.last()  %}
    <p>{{ sameCat.title }}</p>
{% endfor %}

{# note: using .last throws error – Impossible to access an attribute ("title") on a string variable ("1").
 #}

Get the first category of the entry you're currently on :

{% set currentEntryCategory = entry.categoryHandle.one().id %}

This assumes you limited the category to only be assigned once to the entry, otherwise you'll have to loop through all assigned categories to find the nested one you want.

Use that category ID to get the other entries that are relatedTo it :

{% set entries = craft.entries.relatedTo(currentEntryCategory).all() %}
{% for relatedEntry in entries %}
    {{ relatedEntry.title }}
{% endfor %}

If you want to exclude the current entry that you're on from the query :

{% set entries = craft.entries.relatedTo(currentEntryCategory).id('not ' ~ entry.id).all() %}


Set custom field true email link I'm working on a website where members can add entries with the frontend form.

After creating the entry I want them to change the "status" with custom field by sending them an email link. The link is send with postmaster after x amount of days.

How can I do this in a safe way? Using GET (if user is logged in)?

site.com/status/?entry_id=200&status=new_status

Is it possible with just a twig template?

Is [updating an entry] possible with just a twig template?

No. You'll need to write a plugin.

  How can I [let users update an entry via an URL]

There's a few ways to approach this. My recommendation would be to have your plugin expose a site route pointing to a controller method. That controller method would then take care of updating the entry, and possibly redirect the user back to the entry URI.

Assuming you want to send your users links that look like http://example.com/status/1234/live, here's what the route could look like:

'status/(?P<entryId>\d+)/(?P<status>[-\w]+)' => array( 'action' => 'myPlugin/status/updateStatus' )

With the above route, all matching URLs will be pointed to a actionUpdateStatus() action method in a controller named MyPlugin_StatusController. The controller would then need to handle the following:

Update the status for the entry matching the $entryId route variable (look at Working with Elements for ways to approach this
(Presumably) redirect the request back to the entry URI

  How can I do this in a safe way?

The URLs should probably include some sort of unique key (either as another route variable, or as a query string variable) to verify the request. For example, you could opt to include a hash of the author's email address; the controller could then decrypt the hash before updating the entry, verifying that the given email address matches the one on file for the entry's author.

Additionally, you should probably verify that the status route variable matches with a set of allowed statuses, such as "live", "pending" etc.


Flat pricing for different currencies with sales I am trying to implement flat pricing for Craft (ie. different fixed prices for products, based on the currency).  I have it working thanks to this post (Craft Commerce: Hard code different product prices based on currency?), but where I am having problems is with applying sales.

The site I am working on has different prices for different currencies.  These are fixed prices that are not based on Craft’s built-in exchange rates for different currencies. For example, a product in Currency A has a price of $100, which is stored in the Commerce’s default price field. However, the price for that product in Currency B has a price of $1000 - and that is stored in a custom text field for that product.

When a person orders a product in Currency B, I intervene on the LineItems::EVENT_POPULATE_LINE_ITEM event and manually set the price to Currency B’s price (from the custom text field on that product).  This works except for when there are sales for that product.

If there is a sale which applies a 10% discount to the product, then Currency A’s price would be $90 (reduced by $10). However, when someone ordering with Currency B buys that product (which is $1000), that price gets reduced by only $10 (instead of $100).  So it appears Commerce is calculating the discount based on Currency A’s price of $100 and applying that to whatever is the line item’s price.

I’ve written a method to calculate Currency B’s final sale price based on the discounts applied to Currency A.

However, it seems the sale’s discount is applied again after the populate line item event so even if I use my method to apply and calculate the correct Currency B sale price, Craft still applies the $10 sales discount again.

Is there a way for me to tell Craft not to apply the sale discount and let me do it manually if a product is being ordered in Currency B?

Setting the saleAmount in addition to setting the price prevents Craft from applying the sale amount later.


Filtering orders by date bring wrong results I'm having a problem with wrong results when filtering order by date.

I use this code:

{% set orders = craft.commerce.orders.dateOrdered(' >= 2016-07-01 00:00:00').dateOrdered(' <= 2016-07-01 23:59:59').find() %}

The last order has been placed on 2016-06-29, and there has been no orders placed on 2016-07-01, so I would expect order to have no results. However it just lists all orders in the system.

If I change the date to 2016-06-10, the result is empty - as expected.

Is this bug in Craft / Craft Commerce, or do I miss something?

How do I make sure I get no results, if there have been no orders on this date?

Try something like:

{% set firstDayOfMonth = year ~ "-" ~ month ~ "-01" %}
{% set daysInThisMonth = firstDayOfMonth|date('t') %}
{% set lastDayOfMonth  = year ~ "-" ~ month ~ "-" ~ daysInThisMonth %}

{% set thisMonthsOrders = craft.commerce.orders.dateOrdered('and', '>= ' ~ firstDayOfMonth, '<= ' ~ lastDayOfMonth) %}