Saving entry from Sprout Forms into channel entry I'm basically wanting to manipulate user-submitted forms through the use of SproutForms. Basically, the user enters their form data, submits it, where it's recorded as a SproutForm entry. When that happens, I also want it to create an entry in a channel with the same data, so that I can freely use them in templates (showing users a list of their submissions).

All this would be simpler if SproutForms had some templating tags to output entries, but from looking through the plugin, I don't think thats possible.

Anyway, so an additional plugin could have something like this:

public function init() {

    // Support Sprout Forms plugin
    craft()->on('sproutForms.saveEntry', function(Event $event) {
        $entry = $event->params['entry'];
        craft()->entries->saveEntry($entry);
    });

}

But that doesn't seem to work. Any ideas, or a better suggestion?

As of Sprout Forms 0.8.4 this is not possible.  It is on our list to allow more customization over the form entries and how they are output on the front end so this will be possible in the future.  If you'd like us to prioritize this functionality, drop us a note and we're happy to have that conversation.

If you wish to save a Craft Entry after the Form Entry is saved, you're using the right Event above.  One thing you will want to be careful of is that the Sprout Forms $entry value is a SproutForms_EntryModel and the variable you need to pass to the craft()->entries->saveEntry($entry) method is a Craft EntryModel.

To do this you'll need some code to hand off the field values on the Form Entry to the field values on the Craft Entry:

public function init() {

    // Support Sprout Forms plugin
    craft()->on('sproutForms.saveEntry', function(Event $event) {

        // SproutForms_EntryModel
        $formEntry = $event->params['entry'];

        // Craft EntryModel
        $craftEntry = new EntryModel;

        // Map your Form field values to the Entry field values
        $craftEntry->fieldName = $formEntry->fieldName;

        craft()->entries->saveEntry($craftEntry);
    });

}

That said, this method feels pretty messy to me.  Duplicating data is a great way to create great pains for yourself down the road. If you're set on doing this on your own, I'd recommend to create a custom plugin with and a variable that queries the Sprout Forms data how you'd like.

{% set userFormSubmissions = craft.myCustomPlugin.sproutFormsQuery(userId) %}

When Sprout Forms gets around to adding this functionality, you can swap out your custom tag for the native Sprout Forms one and ditch the custom plugin.


Keeping order of blocks like in backend Fairly new user here.
I am kinda confused how to template. I want to rearrange the order of blocks in my backend and show them in the right order in the front.

Here is how i am currently writing a template.

Created a section called "Homepage"
Then I made a matrix block "content blocks"
After that I created 3 Blocks and called them "Image left", "Image right", "Full Text"
Went into my _entry.html and wrote some for loops. Example

{% for block in entry.contentblocks.type('imageLeft') % }
    do something
{% endfor %}

Now when I order those fields in my backend it won't show the right order on my frontend.

Example:

Backend order:

imageLeft
imageRight
imageLeft

Frontent view:

imageLeft
imageLeft
imageRight

I know this is happening because the first for loop will check all first and print them one after another before moving to the next for loop.

How do I prevent this?

I seriously hope somebody understands my issue.  I am fairly new to Twig and Craft so I take every pointer I can get.

I wrote a switch condition in my for loop and everything went well. My bad!


Multi-environment database config being ignored The 'localhost' array is not being recognized. If I add :3307 to the '*' array's server attribute, it works. Here's the contents of my db.php:

return array(

  '*' => array(
    'server' => 'localhost',
    'user' => 'av01759',
    'password' => '*******',
    'database' => 'av01759_maltaministries',
    'tablePrefix' => 'craft',
  ),

  'localhost' => array(
    'server' => 'localhost:3307'
  )

);

This a fresh Craft install with no tweaks. Any ideas?

The environment-specific array that Craft uses is determined by the $_SERVER['SERVER_NAME'] variable (usuall your domain name), not the database hostname. Instead of using localhost to trigger the env-specific settings, you should use your domain. Your db.php should looks more like this:

return array(

  // default
  '*' => array(
    'server' => 'localhost',
    'user' => 'av01759',
    'password' => '*******',
    'database' => 'av01759_maltaministries',
    'tablePrefix' => 'craft',
  ),

  // production-specific (use your domain instead of example.com)
  'example.com' => array(
    'server' => 'localhost:3307'
  )

);

UPDATE: Since in this case, $_SERVER['SERVER_NAME'] actually is "localhost" for you and I understand you are connecting to a remote db, you could try using this for your db.php (swapped the value for server in my above example, this way you make the exception for production).

return array(

  // default
  '*' => array(
    'server' => 'localhost:3307',
    'user' => 'av01759',
    'password' => '*******',
    'database' => 'av01759_maltaministries',
    'tablePrefix' => 'craft',
  ),

  // production-specific
  'production-site-domain-here.com' => array(
    'server' => 'localhost'
  )

);


Element API - Filter on a value from a multi value field I am looking for some assistance with the Element API plugin. I need to filter on the bannerPageCategories field which is a multi select checkbox field. The value will be passed via a querystring value. I can filter on a field with a single value but how do I do this for fields which has an array of values.

Any suggestions will be greatly appreciated.

Sample code and json response is below.

Json Response:

    {
      title:"Test Banner 4",
      url:"http://localhost:8888/banners/test-banner-4",
      jsonUrl:"http://localhost:8888/api/banners/17",
      content:"Test.",
       page-categories:[
       {
         label:"ADSL",
         value:"adsl",
         selected:true
       },
       {
        label:"Fibre",
        value:"fibre",
        selected:true
       }
    ],
   campaignId:"sHKJJK",
   targetUrl:"http://xyx.xaws.co.za",
   image1:"//xyx.xaws.co.za/dev/images/banners/banner-lg.png",
   image2:"//xyx.xaws.co.za/dev/images/banners/banner-md.png",
   image3:"//xyx.xaws.co.za/dev/images/banners/banner-sm.png",
   date_published:"2018-05-22T14:06:05+02:00",
   date_modified:"2018-05-22T14:06:05+02:00"
  }

Code:

    'api/banners' => function () {
        \Craft::$app->response->headers->set('Access-Control-Allow-Origin', '*');
        $target = \Craft::$app->request->getQueryParam('target');
        $campaign = \Craft::$app->request->getQueryParam('campaign');
        return [
            'elementType' => Entry::class,
            'criteria' => [
                'section' => 'banners',
                'bannerPageCategories' => $target,
                'campaignId' => $campaign
            ],
            'transformer' => function (Entry $entry) {
                $image1 = $entry->image1->first();
                $image2 = $entry->image2->first();
                $image3 = $entry->image3->first();

                return [
                    'title' => $entry->title,
                    'url' => $entry->url,
                    'jsonUrl' => UrlHelper::url("api/banners/{$entry->id}"),
                    'content' => $entry->htmlcontent,
                    'page-categories' => $entry->bannerPageCategories,
                    'campaignId' => $entry->campaignId,
                    'targetUrl' => $entry->targetUrl,
                    'image1' => $image1 ? $image1->url : null,
                    'image2' => $image2 ? $image2->url : null,
                    'image3' => $image3 ? $image3->url : null,
                    'date_published' => $entry->postDate->format(\DateTime::ATOM),
                    'date_modified' => $entry->dateUpdated->format(\DateTime::ATOM),
                ];
            },
        ];
    },

Many thanks!

When you wrap your term in asterisks, e.g. *news*, the generated SQL for this query parameter uses a LIKE operator for the ANDWHERE condition is uses (see Element Queries).

Make sure that the values for the Select field don’t overlap (sportnews and news both matching *news*).

'bannerPageCategories' => "*{$target}*"


Change currency in Craft CMS using the Charge plugin Okay so I have Charge setup with Stripe. I have entered in the connection details and selected the currency to pounds in the Stripe credentials in the plugin settings. However when I view the charges the money is correct in pounds but the symbol is a dollar sign... I need to change it to the pound symbol.

Has anyone come across with this issue and have I missed something of.. EG. Config file needs currency symbol override etc.

Hope this makes sense.

Developer of Charge here.

It sounds like you could be running an older version of the Charge.  There was a display bug on the overview page that would set the currency symbol incorrectly for some setups.

This is fixed in the latest versions, so make sure you're running 2.2.0 or above.

Note - this fix won't affect any previously recorded payments that were in a non-default currency, but this is purely a display bug on the overview page - if you go into the detail view for the specific Charges, they'll be correctly showing the relevant currency, and all the details visible to the end-customers and on Stripe will also be correct.


Craft Commerce — Billing / Shipping Address validation / required Fields As default Craft has only First Name and Last Name as required. Is it possible to set more as this two fields as required fields? And is it also possible to set custom Fields as required too?

It will be possible in the next release (commerce 2-beta.5):

https://github.com/craftcms/commerce/issues/342


Adding markers to map from field in entries within section I feel like I'm overlooking something simple here, but I can't for the life of me figure out how to add markers to a map. I had this working with the Google Maps for Craft plugin but since switching to Smart Map I get as far as rendering a map and that's it.
My set up is such: I have a structure with multiple same-level entries, each of which has an address. I have an index page that's rendering a map which should be populated with markers based on the the addresses from each entry's address field.
Historically, I looped through the entries, defined each marker's address and then added that to the map variable like so:
{# Look for each location listed #}
{% for entry in craft.entries.section('locations').limit(null) %}
    {# For each location found, set the map marker properties to have an
       address and a link to the location page within the pop-out menu that
       shows on-click #}
    {% set marker = {
        address: entry.locationAddress,
        content: '...'
    } %}
    {# Then we add the marker to our map variable #}
    {{ craft.googleMaps.marker('map', marker) }}
{% endfor %}

However, now with Smart Map, I can't figure out how to recreate this. I don't quite understand how to set the locations for the {{ craft.smartMap.map(locations, options) }} call. The docs show that one can pass an array into it via craft.entries.section('myLocations') but since my address fields are not entries in a section I'm not sure how to parse that out.
Any help or insight would be greatly appreciated, thanks!

Author of Smart Map here...

It sounds like your locations are in a section (a Structure is a type of section). The first line of your solution is exactly what you'd need to get the locations value.

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

{{ craft.smartMap.map(locations) }}

Just to clarify...

Are you using the "Address (Smart Map)" field to store your addresses?
And do each of those addresses contain "Latitude" and "Longitude" values?

If so, the code example above should definitely work for you!


Filter products by custom boolean field I'm working on a online store website and we need a filter to hide some products based on the country. I created a lightswitch field called "Hide in Europe" (default false) and added it to the categories, and set it to true on some products to test.

This is the block of code that creates the query params to filter the products.

<!-- START QUERYPARAMS -->
        <!-- Initialize query paramaters array -->
        {% set queryParams = {} %}

        <!-- Add sale parameter to query paramaters array if searching for sale items -->
        {% if craft.request.getSegment(2) == "sale" %}
          {% set queryParams = queryParams|merge({ hasSales: true }) %}
        {% endif %}

        <!-- If on new arrivals page, add new arrivals to query parameters array -->
        {% if craft.request.getSegment(2) == "new-arrivals" %}
          {% set queryParams = queryParams|merge({ newArrival: true }) %}
        {% endif %}

        <!-- If order parameter passed in, merge it to the query parameters array -->
        {% if craft.request.getParam('order') != "" and craft.request.getParam('order') != "default-sorting" %}
          {% set queryParams = queryParams|merge({ order: craft.request.getParam('order') }) %}
        {% endif %}

        <!-- Initiating rate variable -->
        {% set rate = 0 %}

        <!-- Setting rate according to current currency -->
        {% for currency in craft.commerce.paymentCurrencies %}
          {% if currency == cart.paymentCurrency %}
            {% set rate = currency.rate %}
          {% endif %}
        {% endfor %}

        <!-- Set price variables to default values if none are passed in -->
        {% if (craft.request.getParam('lowPrice') != "" and craft.request.getParam('highPrice')) != "" %}
          {% set lowPrice = (craft.request.getParam('lowPrice')) / rate %}
          {% set highPrice = (craft.request.getParam('highPrice')) / rate %}
        {% else %}
          {% set lowPrice = 0 %}
          {% set highPrice = 1500 * rate %}
        {% endif %}

        <!-- Add price paramaters to queryParams array -->
        {% set queryParams = queryParams|merge({
          defaultPrice: [
            'and',
          '>= ' ~ lowPrice,
          '<= ' ~ highPrice,
          ]
        })
        %}

        {% set queryParams = queryParams|merge({ hideInEurope: false }) %}
        <!-- END QUERYPARAMS -->

        <!-- Perform query and store results in results array -->
        {% paginate craft.commerce.products(queryParams).type(typesArray).search(queryString ~ (q is defined ? ' ~ ' ~ q : '')).limit(productLimit) as pageInfo, products %}

As you can see, we have:

{% set queryParams = queryParams|merge({ hideInEurope: false }) %}

But for some reason, the products that I set as TRUE are still showing on the list. On the other hand, if I set hideInEurope: true, only the products that I set the field as true show, so it seems to be working. Looks like when I set the param to false, it gets "ignored". Am I missing something?

Found the answer. When creating the where clauses for the query, there's a line that checks empty($str), so passing a false boolean value, PHP interprets it as an empty string, so the where clause doesn't get created. So I fixed it by changing the query param to hideInEurope: 'false'.


How does a plugin include it's own config options? When building a plugin, how does one define user editable config files? Would it be better to create a settings UI in the plugin and have the user edit those variables in the CP? Or is there a way to do it properly with a config file?

The reason I want to opt for a config option is so the value can be localized for the specific environment to set different options. I need to add the ability to define a public directory that will be used to store generated images and obviously that path could be different on local and production environments.

You can add a config.php file in the root of your plugin's folder (craft/plugins/pluginhandle/config.php) that specifies the default values of your config items by returning an array of key value pairs for config settings and values.

If a user wants to change any of those settings, they can add a pluginhandle.php config file to craft/config/pluginhandle.php that returns an array with the overridden key value pairs.

From your plugin, if you call:

craft()->config->get('key', 'pluginhandle')

then Craft will return the user supplied value, if it exists, and fallback on the plugin supplied default value, if it does not.

Also worth nothing that all of Craft's multi-environment config stuff will work in this context for the plugin, too.


Front end authentication on an entry and its related entries I am looking to implement a website where access to pages and their related pages is restricted to certain users.

How I thought it might work is that a user (or users) would be assigned to the entry. This user should then have front end access to this entry and its related entries.

So, the template would check the currentUser value against the user in the entry, and also against the relatedTo entries.

Is there a better, more efficient way? I feel this may suffer from performance problems as the number of related entries grows. Any advice or guidance would be greatly appreciated!

From experience, in terms of ui/ux AND ease in front end stages, If you can do things the other way round, do that.

So attached entries to users basically. When you have a new user, you add entries in one place vs adding the user on every single entries which, if you have loads of could turn into a bit of a mission.. You'll find this way round easier to maintain, in the front end, you can just access related entries through the currentUser very easily instead of going through entries.

This is my personal preference based on recent experience but I don't know how much flexibility you have in terms of development so it may not be possible for you.


Easy way to copy sections to a new install Is there an way way to copy sections I have in an existing site to a new website I am doing with a fresh install?
E.g. To Copy the News Channel Section and all the field types
Also copy the structure section and all it's entry types etc?

I suppose I could copy the full database to the new install but then all the entries would need to be deleted, e.g. all the news articles etc.

Depends on your definition of "easy". :)

Probably the easiest way would be to do what you describe and import the full database.  From there, you can write SQL to find all of the entries that you don't want to keep around from the craft_entries table.  If you get the IDs for those, you can remove the equivalent rows from the craft_elements, and Craft's cascading deletes will take care of deleting the appropriate data in the other tables.

It is on our long-term list to provide a way to import and export content between Craft installations for situations like what you're describing.


How do I query data using the Element API Plugin based on a custom field? I have a channel called "offers".

My Offers channel contains a field called "Users".

The Users field is the "users" field type. It allows me to select 1 or more users that the Offer is for.

I want to get JSON output for this data based on the "Users" name.

'users/<username:{handle}>/offers.json' => function($username) {
            return [
                'elementType' => 'Entry',
                'criteria' => ['section' => 'specialOffers', 'relatedTo' => $username],
            'transformer' => function(EntryModel $entry) {
                return [
                    'title' => $entry->title,
                    'category' => $entry->category->label,

                ];
              },
            ];
        },

You’re close. But the relatedTo param can’t just be set to some username. It has to either be an element ID or an actual element model (more specifically, a user ID or UserModel in this case).

'users/<username:{handle}>/offers.json' => function($username) {
    // Get the actual user model
    $criteria = craft()->elements->getCriteria('User');
    $criteria->username = $username;
    $user = $criteria->first();

    // If there was no user, return no results
    if (!$user) {
        return [
            'elementType' => 'Entry',
            'criteria' => ['id' => false],
        ];
    }

    return [
        'elementType' => 'Entry',
        'criteria' => [
            'section' => 'specialOffers',
            'relatedTo' => ['targetElement' => $user]
        ],
        // ...
    ];
},


Content / fields of newly created single don't show up After a fresh install of Craft on my localhost, two problems occur:

1) The modal window to upgrade Craft only says "An unknown error occured."

2) Newly created singles are not editable, the edit pane stays empty with no input fields at all.

I looked into craft.log and there seems to be an issue with CHttpRequest.php, but I can't say if this is a local config problem or if it's a bug:

******************************************************************************************************
2015/02/25 13:08:35 [error] [php] Cannot modify header information - headers already sent (/Users/me/Sites/test-dev-craft/app/framework/web/CHttpRequest.php:1392)
Stack trace:
#0 /Users/me/Sites/test-dev-craft/app/framework/web/CHttpRequest.php(1329): Craft\CookieCollection->remove()
#1 /Users/me/Sites/test-dev-craft/app/services/UserSessionService.php(1170): Craft\CookieCollection->add()
#2 /Users/me/Sites/test-dev-craft/app/framework/web/auth/CWebUser.php(203): Craft\UserSessionService->renewCookie()
#3 /Users/me/Sites/test-dev-craft/app/services/UserSessionService.php(91): Craft\UserSessionService->init()
#4 /Users/me/Sites/test-dev-craft/app/framework/base/CModule.php(387): Craft\UserSessionService->init()
#5 /Users/me/Sites/test-dev-craft/app/etc/web/WebApp.php(569): Craft\WebApp->getComponent()
#6 /Users/me/Sites/test-dev-craft/app/framework/base/CModule.php(103): Craft\WebApp->getComponent()
#7 /Users/me/Sites/test-dev-craft/app/etc/web/WebApp.php(160): Craft\WebApp->__get()
#8 /Users/me/Sites/test-dev-craft/app/framework/base/CApplication.php(180): Craft\WebApp->processRequest()
#9 /Users/me/Sites/test-dev-craft/app/index.php(62): Craft\WebApp->run()
#10 /Users/me/Sites/test.dev/index.php(19): require_once()
REQUEST_URI=/test.dev/index.php/admin/actions/tasks/getRunningTaskInfo

This is my local setup:

Mac OS X 10.10.2
Apache/2.2.29 (Unix) DAV/2 mod_fastcgi/2.4.6 mod_ssl/2.2.29 OpenSSL/1.0.2
PHP Version 5.6.5
MySQL 5.6.22 - Homebrew

Any help would be highly appreciated!

I was having a similar issue and found a solution that worked for my setup:  https://craftcms.stackexchange.com/a/9016/831


Parse variables into twig email template from custom module I'm trying to send an email from my module and am trying to pass some vars into my module template that I can render using twig. Please note that this is a module template not a front end template.

$first = "john";
$last = "doe";
$mailTo = "john@example.co.uk";
$mailer = Craft::$app->getMailer();
$mailer->htmlLayout = false;
$mailer->textLayout = false;
$mailer->setViewPath('@modules/businessmodule/templates/emails');
$mailer->compose('failed_payment.twig', ['first' => $first, 'last' => $last])
        ->setTo($mailTo)
        ->setSubject('Failed Payment')
        ->setTextBody('Text fallback')
        ->send();

But I cannot access the vars in my twig template like {{ first }}.

i.e

<p>
    Hi, sorry it didn't work out {{ first }} {{ last }}
</p>

Am i missing some parse method somewhere?

You can define your module's template root with the following:

Event::on(View::class, View::EVENT_REGISTER_CP_TEMPLATE_ROOTS, function (craft\events\RegisterTemplateRootsEvent $e) {
    if (is_dir($baseDir = $this->getBasePath() . DIRECTORY_SEPARATOR . 'templates')) {
        $e->roots[$this->id] = $baseDir;
    }
});

You then compose emails like so:

$first = "john";
$last = "doe";
$params = ['first' => $first, 'last' => $last];
$mailTo = "john@example.co.uk";

$mailer = Craft::$app->getMailer();
$mailer->compose()
        ->setTo($mailTo)
        ->setSubject('Failed Payment')
        ->setHtmlBody(
            Craft::$app->getView()->renderTemplate('module-id/emails/failed_payment.twig',
            ['user' => $params])
        )
        ->send();

Replace module-id with your module id as defined in your config/app.php (business-module for you I guess?).

With this in place, you can access the variables in your template by doing:

<p>
    Hi, sorry it didn't work out {{ user.first }} {{ user.last }}
</p>


Directories and files being created by "root" user, inaccessible to CMS I'm new to Craft and have been asked to support a live site that is running on it. I've run into a problem that seems to be due to files on the server being created by the wrong user.

The vast majority of files are owned by the user skillsadmin in group psacln, but randomly some directories and files are being created by user "root", group "root".

Some of these root files are causing errors because they can't be accessed by Craft.

So far this only seems to be happening within the /storage directory.

One example is a single directory in the /storage/runtime/compiled_templates directory (along with its contents) that is causing an internal server error with the preview feature of the Campaign plugin. Another example (though I haven't seen any errors caused by it yet) is apparently random log archive files being created by "root".

The site is running on a VM. I asked the provider's support desk for help but they just said it's an application issue and not their responsibility.

What can I do to ensure that all files written by Craft are created by the correct user?

I'm assuming the web server isn't running as root:root.  The normal cause of this is someone SSH/(s)FTP'ing into the box as root:root and executing some command (directly or with sudo) that generate files on the file system that are owned by root.


Can you get only fields marked as required via a plugin? Is it possible, on a model, to get only the fields that were marked as required?

For example I have an entry which has just been saved and I can get it's content like:

$entry->getContent()->getAttributes()

But I need to filter it out by the only the fields that were required, because it already has a section assigned and is saved I thought this might be possible...I tried $entry->getRequiredFields() but that didn't work.

So then I tried these to no avail

$entry->getContent()->getRequiredAttributes()
$entry->getContent()->getRequiredFields()
$entry->getRequiredAttributes()

Is this actually achievable? any help or pointers would be much appreciated! :)

Your $entry variable – i.e. an instance of EntryModel – has an attribute called fieldLayout, which will return the field layout (FieldLayoutModel) for this entry.

Via the field layout, you can loop over all fields for the entry (each field will be an instance of FieldLayoutFieldModel), checking their required attribute:

// Get all fields for this entry
$fields = $entry->fieldLayout->fields;

// Loop over fields, check required attribute
$requiredFields = array();
foreach ($fields as $fieldModel) {
    if ($fieldModel->required) {
        $requiredFields[] = $fieldModel->field;
    }
}

In the above example, $requiredFields will be an array of required fields, i.e. FieldLayoutFieldModels. If you only need an array of the required attribute names for your entry, you can opt to only store the field handles:

$requiredAttributes = array();
foreach ($fields as $fieldModel) {
    if ($fieldModel->required) {
        $requiredAttributes[] = $fieldModel->field->handle;
    }
}


Disable or hide an entry field in the CMS Is there a way to hide or disable an entry field in the CMS so that the field still exists in the database but can not be edited by a user. The field will only ever be altered dynamically from a plugin?

You could inject some CSS to hide it specifically.


execute Yii2 console command from Yii2 extension with Craft Does anyone know if and how a console command from a Yii2 extension can be used with Craft?
To be more specific, I would like to use
https://www.yiiframework.com/extension/yii2-migration-creator
which is a yii2 extension providing a command to create migrations from existing tables.
However when I composer-require the extension, its command do not appear in Craft console command's list of commands.

ok, found out how this works:

it's not sufficient to composer-require the extension
it needs to be activated. for bizley/migration this is done via controllerMap in e.g. app.php (see documentation)
you can now create migrations for existing tables, but they are saved to Craft's vendor director (vendor/craftcms/cms/src/migrations/)
since this is not the right place, I manually created a migration via Craft's console command, copied the code from vendor/craftcms/cms/src/migrations/, removed the automatically created migration and pasted it into the manually created one.


Craft Commerce returned orders stock and refund handling Is there a simple way to handle returned or partially returned orders in Craft Commerce?
I'm building a site for a shop that has to deal with a lot of returned orders (woman's dresses).

A very common situation would be:
- A customer orders a product in 3 different sizes
- The customer returns 2 of those sizes and keeps the correct size

What would be a good way to handle this in Craft Commerce?

Since all the items in the shop have a limited stock it's a lot of manual work to go to every individual single item and change the stock quantity for every returned item. Is the possible to re-add the returns items to the stock in an easier way?

Is it possible to partially refund and order?

Also, the total revenue overview on the dashboard displays the total amount of all orders and doesn't keep track of refunded items. Can this be changed?

Update:

Commerce 2 now supports partial refunds for payment gateways that support partial refunds.

Partial refunds on Commerce is definitely on our radar... it's the 8th most requested feature here: https://github.com/craftcms/commerce/issues

Unfortunately, it's pretty impractical right now in Commerce 1 with our reliance on the Omnipay  ibrary for all of our payment gateways. They support the "lowest common denominator" and since many of the gateways they support don't support partial refunds, they don't support it at all.

The upcoming Commerce 2 makes Onmipay an optional requirement... meaning that it's much easier to write a plugin for an arbitrary gateway and add support for the ones that support partial refunds.  For example, the 1st party Commerce 2 Stripe plugin implements it and can be used as an example for other payment gateway plugis.

None of that doesn't help you now, though. You can always do a partial refund directly with the gateway if they support it (Stripe, Sagepay, etc.), but the downside is that won't sync back to Commerce 1 so order totals/inventory/etc. won't be updated on our end.

If the payment gateway has callback hooks for that type of thing, you can write a plugin that helps alleviate some of these issues, but none of it is a really clean solution.


How can I set shipping address same as billing? By default all users fill out shipping information first, and then can select "Use same address for billing".

Because 95% of items I am selling are digital, 9 out of 10 sales will be digital and have no shipping.

What I would like to do is ask for a billing address, and then user the <input type="hidden" name="sameAddress" value="1"> to set the shipping address.

This is what I have now which works...

shop/checkout/addresses

    {% include 'shop/_includes/addresses/fieldset' with {
        title: "Billing Information"|t,
        class: 'ShippingAddress',
        name: 'shippingAddress'
    } %}

    {% include 'shop/_includes/addresses/fieldset' with {
        title: "Shipping Information"|t,
        class: 'BillingAddress hidden',
        name: 'billingAddress'
    } %}

...

{% if freeShipping %}
    <input type="hidden" name="sameAddress" value="1">
{% else %}
    <input type="hidden" name="sameAddress" value="0">

    <input type="checkbox" name="sameAddress" id="sameAddress" checked="checked"> Use same address for shipping

{% endif %}

As you can see I'm still setting the shipping first, To the user it just looks like I am asking for billing first. This works until I have something that requires shipping. If a user un-checks "Use same address", then I show what looks like the Shipping Address. But in reality, it's the billing address they are changing.

TL;DR

By default, shipping drives billing. I would like billing to drive shipping.

Thank you for any suggestions!

Unfortunately, I found myself in the exact same situation.

What I ended up doing was including both the billing and shipping form on the same page but the billing form hidden. I used vue.js form/model binding to ensure the values were copied to the billing form. This way it captures two identical addresses, but at least they have the opportunity to edit the information separately at final checkout if shipping is required.


Error in case of nested for loops I have a comment section with comments and subcomments. A comment relates directly to the blog post while a subcomment relates to a comment.

Now, I have the following problem on the entry page: Showing the comments only is not a problem:

{% for comment in craft.entries({
    section: comments,
    relatedTo: { targetElement: entry, field: "relentry" },
    order:     "sortOrder",
    limit:     null
}) %}

X

{% endfor %}

But when I insert the subcomments, I get the error message Unexpected "}":

{% for comment in craft.entries({
    section: comments,
    relatedTo: { targetElement: entry, field: "relentry" },
    order:     "sortOrder",
    limit:     null
}) %}

X

    {% for subcomment in craft.entries({
        section: comments,
        relatedTo: { targetElement: comment, field: "relentry" },
        order:     "sortOrder",
        limit:     null
    }) %}

Y

    {% endfor % }
{% endfor %}

Thank you very much for your help!

It's probably your second-from-last line:

{% endfor % }

should be:

{% endfor %}


JPG upload not completing in Craft 2.6.2789 When uploading a new asset the loading bar appears complete but does not actually upload the JPG. I've investigated the Craft logs and cannot find any errors regarding this.

In the Javascript console I can see the error:

http://your-domain.com/index.php/admin/actions/assets/uploadFile 500 (Internal Server Error)

I'm using MAMP but this also happens on our development servers running apache.

This issue does not happen with PNG's.

After further investigation I found the Preview for the uploadFile "thing".

This Preview had the content

PHP Error [500]

include(/Users/you/Sites/your-domain/craft/app/vendor/lsolesen/pel/src/PelInvalidDataException.php):
failed to open stream: No such file or directory
(/Users/you/Sites/your-domain/craft/app/vendor/composer/ClassLoader.php:412)

I then looked in the lsolesen vendor folder (which happens to handle stuff for Jpg and Tiff files) and the PelInvalidDataException.php file is missing.

I've copied this file from the git repo into the vendor folder and this now works. However this feels sketchy as hell.

I'm wondering whether it could be a composer install issue

Anyone got any ideas?

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

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


How to create entry from external app webhook? I want to create an entry in an existing channel via a webhook from zoho crm. It's pretty straightforward. Like many apps, Zoho's webhook allows you to specify destination url, the method (get or post), and what parameters to pass.

Do I need to create a plugin to receive this form post or is there another way?

I'm a plugin newbie, so any links on where to start would be helpful.

You would need to set this up using a plugin. The plugin would, at a minimum, contain a controller, with an 'action' method designed to handle the url request and generate an entry; using 'post' or 'get' to pass parameters to the controller action.

public function actionAddEntry()
{
    // retrieve parameters
    $title             = craft()->request->getParam('title');
    $customField1      = craft()->request->getParam('customField1');
    $customField2      = craft()->request->getParam('customField2');

    // create a new entry model and set content attributes
    $entry = new entryModel();
    $entry->sectionId  = 2;
    $entry->typeId     = 2;
    $entry->authorId   = 1;
    $entry->enabled    = true;

    $entry->getContent()->setAttributes(array(
        'title'        => $title,
        'customField1' => $customField1,
        'customField2' => $customField2,
    ));

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

    // handle success or failure
    if ($success) {
        // log result or send yourself an email or whatever
    } else {
        // log error
    }
};

By default however, controller actions are only accessible to logged-in users. If you want to allow anonymous access you would need to specifically allow it using the $allowAnonymous property. This definitely introduces some security issues, so proceed with caution. Ideally you would want to set up some kind of authentication, or only accept requests from known hosts.


Importing a Craft database error I dumped from Craft my database from server A and am trying to install it to a fresh copy of Craft on server B.

I've got Craft up and running, and when I try importing my Craft SQL file in PHPmyAdmin, I get an error every time:

Is there something I need to setup in Craft regarding asset files before my import will work?

MySQL exports only include the tables, not the database settings. You need to create a database first, open it and then import the tables.


Using a loop in a loop, how do I check if child loop is empty to not display parent loop? I'm trying to display a list of names alphabetically ordered. This is working fine, but I also want to check if the name is intoCollection or not (using a Lightswitch).

If it is intoCollection, it displays the letter + the list of names related. If there is no name related to the letter, I need to display nothing (= no letter).

Here is the code which seems good for me, but is not correct:

{% set artists = craft.entries.section('artists').limit(null).order('title') %}
{% for letter, letterEntries in artists | group('title|upper|slice(0, 1)') %}

    {% for entry in letterEntries %}
        {% if entry.intoCollection | length %}

{{ letter | upper }}

            {% for entry in letterEntries %}
                {% if entry.intoCollection %}

{{ entry.title }}

                {% endif %}
            {% endfor %}

        {% endif %}
    {% endfor %}

{% endfor %}

It displays letters duplicated, but also letters that contain no names...

Any idea? Thanks!

You'd further filter your returned artist entries down like this:

{% set artists = craft.entries.section('artists').intoCollection('1') %}

Then remove all the unnecessary "intoCollection" conditionals in your loop.


Category archive page isn't filtering by current category Ok all - this is bound to be ridiculously simple, as it's one of the most basic things you can do (https://craftcms.com/support/entries-related-to-category) - but I am ill and I can not figure out what I've done wrong.

I have a category group 'Things To Do'. That group is set to allow categories in it to have their own URLs. The URL format is: things-to-do/{slug} and it uses the template 'things-to-do/category'.

I also have a channel Things To Do, the URL format being 'things-to-do/{slug}' and using a different template 'things-to-do'.

If I go to the url for a category that exists, it loads the correct template and I can output the correct fields attached to the category itself; e.g., {{ category.title }} or {{ category.myCustomField }}

However, trying to output entries related to the category I'm viewing is instead just listing all entries regardless of their lack of association with the category...

{% set thingsToDo = craft.entries.relatedTo(category) %}
{% for thingToDo in thingsToDo %}
    ...
{% endfor %}

This should only be listing one entry for a given category, but it's listing all entries.

What have a screwed up?

Mystery solved; the relation code was too general; some of the entries were related to the category on the homepage, and the example code doesn't care about how or where the entries are related to the category as long as they are somewhere somehow.

I needed to be more specific:

{% set thingsToDo = craft.entries.relatedTo({
    targetElement: category,
    field: 'typeOfThing'
}) %}

Works.


How is a typical frontend request output generated? Long story short: I've been trying to find out how Craft processes the request and eventually create the output. The search is going deeper and deeper into the core, but it feels like I'm missing out on something.

Is it possible for a plugin to 'fetch' the (full) output of a page generated by Craft?

Craft is an MVC application, so most requests initially will get routed to a controller action. Steps 3-6 in our Routing docs page show the various ways that the target controller action is decided.

Controller actions can really do whatever they want with the request at that point, but typically they will perform some level of authorization, and then either perform an action and/or define + send the response.

For example, if you request a template path directly, the request will get routed to the templates/render action, which will verify that the template actually exists, and then render and return it, otherwise throw a 404 exception.

Template rendering is ultimately performed by TemplatesService::render(), which is where Twig gets invoked.


Element query: find entries where a field's value is greater than, or less than another field's value? I would like to do something like this:

craft.entries.section('mySection').field1('> field2').all()

And it should return all the entries in mySection whose field1 value is greater than their field2 value.

Is it possible?

I agree that any solution where you run a query and then conditionally render the result isn't very efficient.
You can do this in SQL by using the where() condition.
craft.entries
    .section('mySection')
    .where('content.field_field1 > content.field_field2')
    .all()

Documentation on the where() condition can be found here.


Craft Commerce: Duplicate Input for Address State? In the Address section I have been defining UK counties to populate the State field when a Country is selected. I noticed that there is a standard text input when there is no defined states/regions/areas for a country and a drop down field for states when there is defined states.

When a country like the US or the UK is selected both fields are shown however ideally it should only be the dropdown. See image of the problem:

Is there any logic that can be added to toggle it on/off ?

<label for="{{ modelName }}-state">County / State / Region</label>

{% set options = (model and states[model.countryId] is defined ? states[model.countryId] : []) %}
<select id="{{ modelName }}-stateId" data-modelname="{{ modelName }}" class="address-stateId u-full-width {% if options|length == 0 or (model and model.stateName) %}hidden{% endif %}" name="{{ modelName }}[stateValue]">
  {% for key, option in options %}
    {% set optionValue = (model ? model.stateId : '') %}
    <option value="{{ key }}" {% if key == optionValue %}selected{% endif %}>{{ option }}</option>
  {% endfor %}
</select>

<input type="text" data-modelname="{{ modelName }}" id="{{ modelName }}-stateName" class="address-stateName {% if options|length > 0 or (model and model.stateId) %}hidden{% endif %} u-full-width" {% if model and model.stateName %}name="{{ modelName }}[stateValue]" value="{{ model.stateName}}"{% endif %}>

This ended up being a css issue. In the CSS I had to create the following rule.

input[type="text"].hidden { display: none; }


Requesting SVGs from a plugins resources directory doesn't work I have an SVG file in my plugins resources, I'd like to use the asset in the front end.

{{ resourceUrl('cocktailrecipes/images/gin.svg') }

It seems using the resourceURL() only allows a select few image types.

Is there a way to extend the permitted image types to include '.svg'?

Actually, the resourceUrl() method doesn't care about the resource file's extension and is able to serve up SVGs (and any other filetype) just fine, so there must be something else wrong. Most likely, the path (i.e. cocktailrecipes/images/gin.svg) to the file isn't correct.

If your plugin has the handle cocktailrecipes (all lowercase; the handle should be identical to your plugin's folder under /craft/plugins), for your particular example Craft will expect to find your file under /craft/plugins/cocktailrecipes/resources/images/gin.svg – first thing to check, is if that file is actually in that location.


What purpose does the site-selector under assets fulfill? I'm kind of confused about the site selector under Assets, because from what I can gather it actually doesn't do anything? See this screenshot, top left:

I was first under the impression that I would only see assets that have been uploaded for a specific site, but that doesn't seem to be the case. Every user seem to see all content for a volume, meaning I would have to create a volume per site in order to separate them?

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

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


How to Prevent Composer from Updating Plugin? I have a plugin installed from a well known Craft developer. I have made significant tweaks and changes to the plugin and need to prevent it from updating. Is there an easy line of code to add to the composer.json file to prevent it from updating? I may have to go the route of breaking it out into our my plugin but for time reasons I am looking for simple ways to prevent updating.

If you have version 1.2.3 of the plugin installed and you don't want to Composer to update past that version, you'd just modify your composer.json file so it's locked to that exact version.

"require": {
    "plugindeveloper/pluginhandle": "1.2.3"
}


sort by checkbox field with multiple options and by postDate desc Section handle: players
field handle: teamName
The checkbox field has two options:

Cubs
Tigers

Not all players will have the teamName field checked.
I want to order players who are Cubs or Tigers first and order those players by their postDate desc, while ordering the non Cubs/Tigers players by their postDate desc.
{% set players = craft.entries.section('players').orderBy('teamName, postDate desc').all() %}

This kind of works, but it orders Cubs players before Tigers players, regardless of their postDate, so a Cubs player could of been added 30 days ago and still show up before a Tigers player who was added 2 days ago.
I know the teamName is being ordered, I don't know how to add the postDate desc to the teamName logic. It needs to support pagination.

The equivalent SQL would be something like
SELECT * FROM players ORDER BY teamName IS NOT NULL DESC, postDate DESC;
but I'm not sure how that would translate in a simple element query. It'd be something like:
{% set players = craft.entries.section('players').orderBy('teamName IS NOT NULL DESC, postDate desc').all() %}


How to add time for repeats date with Solspace Calendar I using Solspace Calendar on Craft 2. (I can upgrade for Craft 3 soon.)

How to add time for the recurring date?

My english not so good, sorry.

Thanks your help.

I don't think it's possible at all to set a different time for each recurrance. In that case, you'd have to add each date and time as a separate calendar entry.


Unknown Errors when trying to select category Just like the post says, I'm getting unknown errors when selecting a category from a field. Nothing shows up in the craft error logs but here's what the console says:

Just wondering if anyone else experienced this or if it's just a problem with our build.

Looks like the server didn't like the .htaccess file we use for Craft 2 - specifically this part:

<IfModule mod_mime.c>
   AddCharset utf-8 .atom \
                    .bbaw \
                    .css \
                    .geojson \
                    .ics \
                    .js \
                    .json \
                    .jsonld \
                    .manifest \
                    .markdown \
                    .md \
                    .mjs \
                    .rdf \
                    .rss \
                    .topojson \
                    .webapp \
                    .webmanifest \
                    .xloc \
                    .xml
</IfModule>

There weren't any errors in Craft but the PHP logs did have some information that helped us track this down.


Can I use a structure without slugs? I'm making a portfolio website, where the url's look like "projects/project-name".
There is also an overview page with all the projects that is under "projects" on itself.

I'm using a Structure for this, but I go to the 404 page when I'm just trying to go to "projects" without the slugs.

Is there a way of using a structure without a slug?

You'll need to create a listing template for the base /projects URL, and make that template render for that URL.

The easiest way is to just add a template called /templates/projects/index.html, in which case Craft will automatically render that template whenever a user hits example.com/projects.

Another way is to create a dynamic route, and point it to whatever template you want rendered for the /projects URL.

Obviously, inside your listing template you'll need to pull the Structure entries manually, i.e. by doing something like this:

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

{{ entry.title }}

        ...

{% endfor %}

Note that if you don't pass an .order() parameter to your craft.entries query, Craft will use the default order, which is the "manual" structure order for Structure sections.

Also note that if your Structure is multi-level, you'll probably want to use the {% nav %} tag over the basic {% for %} loop:

{% nav entry in craft.entries.section('projects') %}

        {{ entry.title }}
        {% ifchildren %}

                {% children %}

        {% endifchildren %}

{% endnav %}


Is it possible to add an attachment to a Craft Commerce order status email? I'm trying to figure out a way to attach an asset file to a Craft Commerce order status email when a user purchases a product- the user would be purchasing the file and I'd like to attach it to the order status email that's sent upon completion of purchase.

I see that the Contact Form plugin has a similar functionality:

https://github.com/pixelandtonic/ContactForm/blob/master/contactform/services/ContactFormService.php#L54

Is it possible to do something similar in Craft Commerce?

According to How to attach an order PDF in an order confirmation email?, it is currently not natively possible as of Craft Commerce 1.1.


How do you save custom fields along with the user/saveUser action? We are building a simple user import plugin, saving the basic user is easy enough but how does one save data to the custom fields added to users

Basic exmaple:

$user = new UserModel();
$user->status = UserStatus::Active;
$user->firstName = 'Fruit';
$user->lastName = 'Studios';
$user->email = 'email@domain.com';
craft()->users->saveUser($user);

This all works great but i cant work out how I add the custom fields?? The following will abviously not work because 'postCode' is not part of the User Model:

$user->postCode = 'SO23 9UG';

Where am I going wrong?

Got it, just need to use the getContent() function exactly the same as entries:

$user->getContent()->setAttributes(array(
    'postCode' => 'SO23 9UG',
));


Craft Nitro PHP extension ext-zip * is missing I'm not particularly tech minded so MAMP has served me well for a good while.  However I more recently decided to give Craft Nitro a try.  I got everything (Multipass and Nitro) set up really easy.  I then went to create a project and got the error PHP extension ext-zip * is missing.  I've seen this before and worked around it guided by This post.
All good...  craft installed.   However, now i'm confused?  Why did I need to install an older version of PHP on my host machine (OSX) when Nitro is supposedly a self contained 'box' with everything needed for a Craft install?

You'll want to run that composer create-project command from inside of your Nitro VM. If you run it on your host machine, it'll use whatever version of PHP your host machine has installed.
Do this:

Make sure Composer is installed in the VM by running nitro install composer from the host machine. https://craftcms.com/docs/nitro/commands.html#install-composer

SSH into the box by running nitro ssh. https://craftcms.com/docs/nitro/commands.html#ssh

Run composer create-project craftcms/craft to get a fresh new Craft project inside the VM.


Search going to /index.php?q= instead of results I've pushed my site to Digital Ocean from Localhost, the site is all up and running - URL's are all working. But when I try and search the site it seems to be heading to

  http://123.456.789/index.php?q=test

Instead of

  http://123.456.789/search/results?q=ariz

I have manually entered the second page in and I get to the search results page, so it does exist but Craft's routes seem to be breaking? Any help would be brilliant!

        <form action="{{ url('search/results') }}">
          <input class="text-field w-input" type="search" name="q" placeholder="Search for any University...">
          <input type="submit" style="position: absolute; left: -9999px; width: 1px; height: 1px;" tabindex="-1" />
        </form>

I was missing the typical '/' within the URL

The correct URL for this path should be:

  {{ url('/search/results') }}


Select all entries with asset field attribute criteria OK so I got entries articles with an asset field documents.
This asset field has an attribute called docType which is a dropdown with 5 values (A, B, C, D, E).

I d like to select all articles entries that have documents with docType=A criteria.

How can I dot that?
Should I make a relatedTo selection?
I tried multiple things but nothing works.

You can do it like explained in this answer, only that you also add your dropdown field parameter to your craft.assets criteria model:

{% set assets = craft.assets.docType('A').limit(null) %}

and then:

{% set entries = craft.entries.section('articles').relatedTo({
    targetElement: assets,
    field: 'documents'
}) %}


How to overwrite base controller beforeAction method How do you override the beforeAction method of Craft's base controller? I'm disabling CSRF for a specific route.

public function beforeAction($action): bool
{
    $requestOrigin = \Craft::$app->getRequest()->headers->get('Origin');
    $origin = getenv('ENVIRONMENT') === 'dev' ? getenv('ORIGIN_DEV') :getenv('ORIGIN_PRODUCTION');

    / Disable CSRF validation for valid origins
    if ($requestOrigin === $origin) {
      $this->enableCsrfValidation = false;
    }

    if (!parent::beforeAction($action)) {
      return false;
    }

    return true;
}

I know that there have been similar questions asked before on overriding plugin methods and there's also the blueprint inside the controller itself. Just struggling to understand how to override the craft\web\Controller's method for this

Solution is to create a custom controller in a module that extends the cart controller.
This gives the functionality to overwrite the beforeAction method, while keeping all other functionality.

As an example:

<?php

namespace modules\controllers;

use craft\commerce\controllers\CartController;

class FooController extends CartController
{
    public function beforeAction($action)
    {
        // Your overwritten logic here
        $something = 'test';

        return $something;
    }
}

Instead of posting to commerce/cart/update-cart you would then (in the example above) post to  my-module/foo/update-cart. There is some useful documentation in the Craft docs on building a custom module and how to create customer controllers and actions.

[Answered by Nathaniel Hammond Pixel & Tonic]


Reset password with MySQL Is there a way to reset an admin account's password by modifying the MySQL directly?

I've found the craft_users table where the hashed password is stored but I don't know how to hash a string so that it will be read correctly by Craft.

Future me, looks like you forgot your password again and locked yourself out of Craft. You also made your way back to this Stack Exchange question with @chris' perfect answer. Good! And to make your life really easy this time around, I've already generated a password/hash combos for you that works:
|--------------|---------------------------------------------------------------|
|  *Password*  |                        *Resulting Hash*                       |
|--------------|---------------------------------------------------------------|
|  password    | $2y$13$i1fEVeKiboWR/Hx07N9JtuSZj46KNueAg0IgpwL2TId0sXN.oyibC  |
|--------------|---------------------------------------------------------------|
|  NewPassword | $2y$13$YA.7RIgllODUDcmQPf/.FuXjOmKJYot5QxpFhhf4og9fdJWsIPWK6  |
|--------------|---------------------------------------------------------------|
|  admin       | $2y$13$Nlvh.kEu8FLIITusfjzQgOIIDryqLnJ3TsV/1UINRCFLfVnjJtILK  |
|--------------|---------------------------------------------------------------|

Update: The hashing algorithm didn’t change in Craft 3, so the above combo still works.


Extending user validation Hi I've created a plugin that has an action in the controller that looks at a user registration form when submitted and if the username is empty creates a unique username for the user. This works fine and saves the user with the random name or with their chosen name if a username is entered. My problem is I am not getting any errors returned to the form or a success message when the user is registered. Validation appears to be happening as the user is not being registered if errors are found. Although the only error I see printed is invalid email if entered incorrectly, if the password is missing there is no error returned but the user is not registered.

My code to add the model is as follows. Can anyone point me in the right direction so that the errors are returned. The template is the standard registration form from the craft documentation.

$newUser = new UserModel();
$newUser->username = $username;
$newUser->email = $email;
$newUser->newPassword = $password;

if ($newUser->validate())
{
    craft()->users->saveUser($newUser);
}
else
{
    return $newUser->getErrors();
}

Most user validation happens in UsersService::saveUser(), so restructure your code to this:

$success = craft()->users->saveUser($newUser);

if (!$success)
{
    return $newUser->getErrors();
}

If this is happening in a controller action, you’ll want to make the UserModel available to the original template, so it can access and display those errors.

$success = craft()->users->saveUser($newUser);

if ($success)
{
    // Redirect to whatever URL the 'redirect' param specified
    $this->redirectToPostedUrl($newUser);
}
else
{
    // Make the UserModel available to the original template
    // so it can access the submitted values and validation errors
    craft()->urlManager->setRouteVariables(array(
        'account' => $newUser
    ));
}


How to upload a template in Craft CMS 3 on an Ubuntu web server Really new to this platform and could use some help with how to upload a theme/template which I downloaded from ThemeForest.  The files are compatible with HTML 5 and Craft 3 is on an Ubuntu server.

The answer will depend on the extent of your web development skills.

Do you have access to the web server via FTP?
If so, upload the template files to the templates folder where you installed craft. The templates will have to be edited to bring in your sections, entries, and content that you add in the Craft dashboard.

Check out these docs to learning templating and converting templates to twig/Craft templates.

https://docs.craftcms.com/v3/dev/


Order confirmation emails not being sent to guests For some reason, order confirmation emails are being sent to customers who create an account during checkout but not if they checkout as a guest. I also see the error: Email error. No email address found for order. in the commerce.log file. Anyone know how to get the order confirmations to go out to guest users too? The emails are getting captured, as they show up in the backend. I'm using the latest versions of Craft and Commerce. Thanks!

Update: Even changing the order in the admin to another status and back still does not trigger an email to the user.

Fixed by updating to 1.2.1350

https://craftcommerce.com/changelog#build1350


In a large set of entries across multiple sections, how can I loop through each section type in the set? I have a set of entries from multiple channels and I want to loop through each section type that is in the set.

Something like

{% set entries = craft.entries.search(query).order('score') %}

{% for entrySection in entries.sections %}
    {{ entrySection.name }}
{% endfor %}

So basically if I have 100 results from across 8 sections, is there a way I can list out those 8 sections separately?

Try using the group filter

{% set entries = craft.entries.search(query).order('score') %}

{% for sectionName, sectionEntries in entries | group('section.name') %}

{{ sectionName }}

        {% for entry in sectionEntries %}

{{ entry.title }}

        {% endfor %}

{% endfor %}


Deleted Locale, Entries all gone now I deleted a locale and checked to transfer all its contents to a different locale, but now the other locale still shows no entries.  I'm sure all the entries are still in the database.

Any help?

I'm having the same problem for assets and globals.

When craft thinks there are no globals, the entire tab isn't showed.
For the globals i created a new temporary global, so i could access the existing (hidden) ones (they were still connected to one locale).
After that i could open and save them.
After saving they worked for other locales again.

I later found out that setting the admin account to the locale that is working also allows access. Opening and saving each entry works.

Still did not find a solution when content is disconnected from all locales.


301 Redirects Appends ?p=original/url/path - how can I remove? Whether I'm using the Reroute plugin or plugging it in .htaccess, changing the path elsewhere appends the query in the end. How can I remove?

Redirect 301 /blog/category /blog/archive

Is the line I have in my .htaccess

So if I go to:

http://domain.com/blog/category/category-name

it takes me to:

http://domain.com/blog/archive/category-name?p=blog/category/category-name

What's going on here?

The issue here is that your Redirect directive is conflicting with Craft’s index.php-hiding RewriteRule directive. (Redirect is a mod_alias directive and RewriteRule is a mod_rewrite directive. They’re two separate modules that can be used for the same thing, but lead to unexpected consequences when used together.)

To fix this, use a RewriteRule directive for your own custom redirects as well, rather than Redirect.

RewriteRule ^blog/category(/.*)?$ /blog/archive$1 [R=301,L]

Make sure that you place that before Craft’s redirect.


Product Categories, Structures and Channels We are currently updating a brochure website, separating a single list of products into a series of sub-categories. Currently, we have a "single" section to display all products, and then a "channel" which has two entry types (products & accessories). I am trying to work out how best to create the new site structure.

I would like to display a parent page which lists all products, but then 6 sub-pages which show only the products in that category. I use the word category without specifically meaning the Craft CMS category.

I have read other posts such as Structure(s) vs. Categories for product catalog and Difference between categories and structures but these don't seem to help. There seems to be a bit of confusion surrounding Craft categories, structures and using singles to divide the content.

How could we re-organise the existing content into this new structure?

Typically, I will create a single for each product "home" page, and then a channel for my products or sub-pages. I will generally use a channel vs. a structure unless I know I want to manually control the order or nest entries.

Let's say I have a website about automobiles. I would create a section (single) called cars. That section would have the url of site.com/cars and the template would be located at /templates/cars/index.html. This is the template that would be responsible for pulling in all of the cars I have.

This is where things can get tricky, or not...all depends on how you want to roll.

If you created a channel called automobiles (or whatever you like), you could enter each car you have as an entry within the channel. Then on your cars single, you can tell Craft to loop through all entries in the automobiles channel.

Since you can't nest a channel entry, I would use categories to "tag" your cars. For example, I would create a category called Sports Cars and relate any sports cars I have to that category. You could also create a category for Trucks or Vans to help group/classify each car you had.

This would also allow you to create sudo-landing pages for each type of car. For example, site.com/cars/sports-cars would get all entries that are tagged as a sports car. You could do this for trucks, or you could even divide categories up into trucks/4-wheel-drive so not only would a truck show when I requested trucks, it would also show in my 4-wheel-drive options.

From an authoring experience, this is great. I don't care specifically where I have to create the entry - all I know is that I have a car, and it goes in the cars "bucket" (automobiles channel). It's within that entry (the car entry itself) you are choosing where it is available to the end user.

You could even create different entry types for the kind of automobile you are creating. This would allow you to have a cleaner screen as some fields don't apply for all automobiles.

To illustrate a structure, think about the staff who is in charge of this car-selling company.

I would create a structure called staff. It would have the url of site.com/about/staff and a template of /templates/about/staff/_entry

From there you could create an entry for each person. You can then create "parent" entries for the hierarchy of the office.

For example:

- Management
    |-- Bob McKenzie
    |-- Doug McKenzie
- Sales Team
    |-- Tyler Durden
    |-- Agent Smith

By using a structure here, you can not only manually set the order of which group (management or sales) is first, but you can also arrange the order of the team members within.

So to answer your question directly:

  I would like to display a parent page which lists all products, but then 6 sub-pages which show only the products in that category. I use the word category without specifically meaning the Craft CMS category

I would do this:

Create a single and give it a name of the url that you would like to show all products on. To use my example, this would be cars.

Create a Category to relate your products to Ex: Sports Cars.

Then create a channel - called Products. Every product will go here. When you are creating these product entries, use a Channel Field type so you can select which category the given product belongs to (Sports Cars).

Then on your cars page, you would tell Craft "Hey, get every single product".
If I navigate to site.com/cars/sports-cars you can tell Craft "Hey, only get me cars that are related to sports cars".

Kind of a long-winded answer, hope it helps get you going.


Craft loading SCSS references rather than CSS I am looking at a site at the moment which uses SASS to compile its CSS file. All styling references appear to be referencing the styling from the SCSS file, rather than the CSS file. Previously, all references pointed to main.css, but now points to the .scss file where the class is defined. Moving the .scss file on the server, or changing the filepath for the folder doesn't seem to stop it loading. My concern is that the site is now loading the multitude of .scss files rather than a single, minimized, .css file. Can anyone offer any insight on what is going on here?

The site is http://spiffingcovers.com/

The references to .scss files are just to help you find and debug any changes you would like to make - the browsers developer tools are trying to help you by pointing you at the relevant file.

If I 'view source' of your home page I can see that only main.css is loading :)


Craft Commerce Currency - Email template not showing currency Is there something else you have to add to Craft Commerce Email templates to show the amounts in the order currency used? It always shows the default currency (i.e. GBP) when it was ordered in USD.

The email template has been updated to the new tag of commerceCurrency.

Thanks for any help.

You need to pass the currency to the conversion filter.

The order is always made in the primary currency, but the payment currency that they made the payment in might be different, so you need to pass order.paymentCurrency to the conversion filter.

You can read about using different currencies here:
https://craftcommerce.com/docs/payment-currencies

In addition to just changing the filter to |commerceCurrency take a look at the docs for the filter for the optional formatting and conversion options:
https://craftcommerce.com/docs/twig-filters


Programatically add lines to a Super Table field I am trying to add new lines into a SuperTable field of an entry from my plugin.
Following the Developper sample, I am able to change set lines to this SuperTable field.
But it is replacing the existing content.
What should I do to be able to keep existing lines in my SuperTable and add new ones?
Thanks for your help!

Got it!

In case you just want to add lines (or Blocks) to a SuperTable field of an entry, no need to update the entry itself, you "just" have to create new Blocks with correct type, field and entry.

    $field = craft()->fields->getFieldByHandle('mySuperTableField');
    $blockTypes = craft()->superTable->getBlockTypesByFieldId($field->id);
    $blockType = $blockTypes[0]; //Only 1 Type of Blocks in the SuperTable
    $typeId = $blockType['id'];

    $block = new SuperTable_BlockModel();
    $block->fieldId = $field->id;
    $block->typeId = $typeId;
    $block->ownerId = $entryId; //this is the entry id

    $block->setContentFromPost(array(
        'categoryOne' => [$catOne->id],
        'categoryTwo' => [$catTwo->id],
        'textField' => 'blablable...'
    ));

    $success = craft()->superTable->saveBlock($block);


How do I add a new item or object to an existing object? I'm using the Imager plugin and Craft for image compression.

Currently, I have something like this:

{% set imagerConfig = { jpegQuality: 80, pngCompressionLevel: 4 } %}

In another part of my code, I want to do something like:

 {% set largeLogo = craft.imager.transformImage((logo.getUrl('LargeLogo')), imagerConfig) %}

Where I want to do something like this to imagerConfig above:

{% set width = {width: 1000} %} or {%set widthRatio = {width: 1000, ratio: 4/2} %}
imagerConfig.Add(width) //what's the proper syntax for adding an item or even another object(like widthRatio above) to imagerConfig here?

When you use the Twig curly brace {}, key/value pair syntax like you've got imagerConfig set to, you're using the Twig hash literal.

In Twig, if you want to add to an array or hash after it has already been created, you can use the merge filter.

Something like this should do what you're looking for:

{% set imagerConfig = { jpegQuality: 80, pngCompressionLevel: 4 } %}

{% set width = { width: 1000 } %}

{% set imagerConfig = imagerConfig|merge(width) %}

{% set largeLogo = craft.imager.transformImage((logo.getUrl('LargeLogo')), imagerConfig) %}


Display events that appear at certain venue I'm trying to work out how to query some channel posts (events) that take place at a certain venue.

{% set params = {
    section: 'events',
} %}

I have a 'eventVenue' field in my events section which is an entries field powered by a channel called venues. I want to query by venue ID?

When using an Entries field, you're "relating" the entry to other entries.
The ElementCriteriaModel parameter to filter by related entries is the relatedTo parameter.

Something like this should do the trick:

{% set params = {
    section: 'events',
    order: 'eventShowtime desc',
    relatedTo: venueId
} %}


How to create a static JSON files with Element API and cache it with Varnish Is it possible to create static JSON file using the Element API plugin?

What I then want to do was cache that file probably using Varnish or push it to an S3 bucket.

If I was to cache it I would need to look at purging the URL when an entry is added or edited.
If I pushed it to S3, then I would either need to overwrite the file or manage it another way.

What would be the best way to handle this, and could you easily create a static JSON file with caching and purging abilities?

Not sure how you can do this, but you could manually print the response to a file yourself on a regular basis (as a cron job) using wget:

This:

wget -S http://craft.fira/fullmembers.json

…saves the JSON into a file named fullmembers.json into the directory it was run from.

Here is the solution that I have used in a cron job that runs every minute:

wget -O - http://www.fira.co.uk/fullmembers.json > /home/forge/www.fira.co.uk/public/jsoncache/fullmembers-temp.json
rm /home/forge/www.fira.co.uk/public/jsoncache/fullmembers.json
mv /home/forge/www.fira.co.uk/public/jsoncache/fullmembers-temp.json /home/forge/www.fira.co.uk/public/jsoncache/fullmembers.json


Entry FieldType - Get the EntryModel of the entry chosen in the field? So I have some entries and one of the fields is for a "hotline". The hotlines are all entries. The CMS part works, I can click the field and choose an entry from the hotlines channel, however this is where I'm stuck.

In my plugin code I cannot seem to figure out a way to actually get the hotline that was chosen.

I have a $center variable which is an EntryModel of the entry that has the field for "hotlines" attached to it, with the value set (according to the admin).

$center->hotline and $center->getFieldValue('hotline') just return an ElementCriteriaModel and when I inspect that object inside xdebug there is nothing there that would be usable in getting the actual hotline that's selected. No ID. No object. No nothing. Just information about the field it self, not the value.

What the heck am I doing wrong here? This is so "unintuitive" compared to the rest of craft!

Nevermind.

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

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

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


Pass variable in Twig tag My template has this line that I want to update from a field in craft:

{% set form = craft.formBuilder2.getFormByHandle('schoolTrip') %}

I want 'schoolTrip' to be replaceable by a plain text field in craft. My plain text field is named 'formName'.

{% set form = craft.formBuilder2.getFormByHandle('block.formName') %}

just gives me errors.

It's giving you errors because you put the variable in quotes. Ditch the quotes and try it like this...

{% set form = craft.formBuilder2.getFormByHandle(entry.formName) %}


Invalid Verification Code Customization? When a user attempts to reset their password, they're emailed a link -- if they click on this link late, or click on it twice, they're shown the "Oops! Invalid verification code. Please login or reset your password."

Any chance this can be sent to a custom template, ala the loginPath or setPasswordPath configs?

There's not a native way I can see to do this.

Neither of these are clean workarounds, but assuming you're referring to Craft 3, you could either write a plugin that extended Craft's ErrorHandler class and overwrote the handleException class, inspected for that particular error messae and swapped it with one of your own. You'd need to tell Craft to use your ErrorHandler in craft/config/app.php.

Alternatively, you write a plugin that mimics Craft's UsersController's setPassword method doing your own custom logic and have the user related emails point to your plugin's controller instead of the native Craft one.


Why am I getting error: Object of class Craft\ElementCriteriaModel could not be converted to int We just created an entry and hit save.  When we go to the front end of site we get a popup error that reads:

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

What does this mean and how do I troubleshoot it

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

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

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

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

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

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

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


Is there a way to import recipients into a list in Sprout Email? I have a couple of excel sheets with a list each of recipients for my e-mail campaigns. Is there a way to import that into Sprout Email? If not, I would really appreciate a pointer to where I could look to start hacking/building my own importer.

Sprout Email 2.x is not designed to be sending bulk email on it's own (September 2016). The feature is on our list to explore in future releases, and currently, Sprout Email can be used to manage sending bulk email via a third party mailer such as MailChimp or Campaign Monitor.

The current incarnation of "Recipient Lists" in Sprout Email is meant to be for very simple use cases where you may need to send Notification emails to a small list of people.  We will be revisiting the Recipient List feature to handle larger lists and integrations in the future.


Import-Export Matrixfield data Have used the pretty neat Import and Export plugins from Bob Olde Hamsink.

But, those two do not handle Matrix data.

The question is basically:

What is the 'most common way' to import and export data to/from Matrix fields in Craft CMS.

Doesn't handle exporting data, but FeedMe can handle importing XML or JSON content for most element types.


Is it possible to exclude entry from search index? I have some pages that I want to exclude from search results. How can I do this?

If you mean entire sections you could define which sections you want to display like this:

{% set query = craft.request.getParam('q') %}
{% set entries = craft.entries.craft.entries.section('section1, section2, section3').search(query).order('score') %}


Ordering entries by custom field (integer) I'm new to craft so may it be a basic question, however I can't find an answer for it :-/

I have custom field 'width' in my entry type defined as integer.
What I need to achieve is quite simple:

{% set entries = craft.entries.section('windows').find({'width':'> 0'}).order(width) %}

The important now is the .order part it's not working right now :-(. What is correct way to do this? I have found some plugins but I believe craft can do this somehow… It always does (so far).

Thanks for any info on this.

Craft 2
Either of these should work (they are equivalent):
{% set entries = craft.entries.width('> 0').section('windows').order('width') %}

or
{% set entries = craft.entries({
  section: 'windows',
  order: 'width',
  width: '> 0'
}) %}

The reason you are getting "Array to string conversion" error is that find has turned your ElementCriteriaModel into an array.
Craft 3
order is now orderBy
Craft 3 Docs: Element Queries


How to get an input value without refreshing with twig? One way to read a dynamically inserted value is to refresh the page and get it in a twig variable through the url, something like this:
{% set amount = craft.app.request.getQueryParam('amount') %}

But I am looking for a solution to get a value inserted into an input without refreshing the page, of course, after sending the form (i thing). Do you know if thats possible? Maybe with javascript.

Yes you would do this using Javascript so is a little outside the scope of this StackExchange site but here's something that might help get you moving...
Getting the value is easy with something like
document.querySelector('#myElement').value

You'd need to trigger that in some way, perhaps when the user leaves the field. So (assuming your input has an ID of "myElement"...
document.querySelector('#myElement').addEventListener('blur', function(el){
    let theValue = el.value
})

What this is doing...
Get the element on the page with an ID of 'myElement'
Adds a listener to it for the 'blur' event (when the user leaves the element)
When that happens it executes a function and passes the element into it
Sets a variable (theValue) with the value of the element.
You now have a javascript variable named 'theValue', but what do you want to do with it?


Can you host a Craft site on 1984 Hosting? Does anyone have experience hosting a Craft site on 1984 Hosting? It's an Icelandic company whose ethos I like and I'm considering making my new site in Craft, so would be good to hear of anyone who's managed it.

https://www.1984.is/

As long as a host meets Craft's minimum requirements listed here: https://craftcms.com/docs/requirements#server-requirements, then Craft should run fine.

Based on their shared hosting server specs here: https://www.1984.is/product/hosting/ (PHP 7, MySQL 5.5+), my guess is it'll run fine.


Define email environment-specific email settings? I'd like to define the SMTP server deets in my local config as I regularly need to push/pull databases between environments and will have different settings.

There doesn't seem to be any of doing this currently. Are there any workarounds? I thought maybe I could just put the SMTP deets in my code (testing for current enviroment) but the EmailModel class doesn't accept any of the SMTP-related properties of PHPMailer.

Currently email settings aren't multi-environment aware, so there is no native way to do this.

Probably worth adding to the feedback site, as this has come up before, though.


Editorial workflow / custom status Currently my editors do not know when new content submitted by a user without publishing permissions is ready to be reviewed. The status of "disabled" could refer to an in-progress draft or a completed draft ready to be reviewed by an editor. There is no way the user can flag their article as ready and for this to be easily exposed to the editors in the admin panel.

How could this be addressed.

One solution that comes to mind is to add your own custom status field (i.e. 'reviewStatus') as a drop-down menu (or checkbox perhaps if only one status). Then add this field as a column in your list view via a small plugin, using the new modifyEntryTableAttributes hook.

public function modifyEntryTableAttributes(&$attributes, $source)
{
    if ($source == 'section:3')
    {
        {# remove a column if desired #}
        //unset($attributes['expiryDate']);

        {# add a column #}
        $attributes['reviewStatus'] = Craft::t('Review Status');
    }
}

Might also check out getEntryTableAttributeHtml hook (to customize the HTML display of that column), and modifyEntrySortableAttributes hook (to add this field to the sort options).

To change the column display order you would need to unset all of the native attributes and reset them in the desired order (see this answer for example).


Get entries related to selected category only and not it's ancestors The following is using commerce product entries, but I'm reasonably sure it could be any entry.

With the following category taxonomy:

- Category 1
    - Category 1A
- Category 2
- Category 3
...

If I have a product entry "Product 1" with a category field selected to "Category 1A", when looping though
all categories to return products for that category, how can I list the entry ONLY for "Category 1A" and not it's any of its ancestors e.g. "Category 1"?

Currently, I'm using the following:

{% nav category in productCategories %}

        {{ category.title }}
        {% set products = craft.products().relatedTo(category).all() %}
        {% for product in products %}
            {{ product.title }}
        {% endfor %}
        {% ifchildren %}

                {% children %}

        {% endifchildren %}

{% endnav %}

Which returns

- Category 1
    Product 1
    - Category 1A
        Product 1
- Category 2
- Category 3
...

But what I want is for it to only be visible on the selected category.

- Category 1
    - Category 1A
        Product 1
- Category 2
- Category 3
...

Is there a way to do this using categories? or am I best using a structure?

Instead of using nav, you can just use your own code for getting children. I.e. loop through level 1, then within that loop check if they have ancestors at level 2, then within that loop check if they have ancestors for level 3 etc.


Dynamic Navigation with Condition to check slug I'm trying to achieve one pretty simple thing, but putting it into my dynamic nav is making it a little difficult. I want to have a little number of the total amount of entries in my channel "listings" and keep it on one of the links "Our Properties".

I currently have this code that is displaying the total amount of entries

{% set totalListings = craft.entries.section('listings').total() %}
{{ totalListings }}

How can I make this work: {% if link == "properties" single entry %} {{ totalListings}} {% endif %}

{% set menu = craft.entries.section('navigation') %}

    {% nav link in menu.all %}

           {{ link.title }}

    {% endnav %}

Got it to work! I don't know why I made it so complicated in my head, but I ended up using the link id to match with the properties link.

{% nav link in menu.all %}

        {{ link.title }}{% if link.id == 15 %}{% set totalListings = craft.entries.section('listings').total() %}{{ totalListings }}{% endif %}

{% endnav %}

If someone can show me how to get it by slug that would be awesome! Thanks & hope this will help someone in the future.


Create mini-site community with Craft We are creating a new website using Craft CMS.

The main functionality of it is to let user to create their own mini-site.

All the users should have their own control panel and manage their pages and menu.
There should be url per user like username.site-name.com/nameofthepage
The administrator should be able to manage all mini-site

Does anyone already done something like this? Is there any plugin already done for this kind of functionality ?

Thanks!

There is no plugin that provides this type of functionality but there really isn't any need for one either. Depending on how many pages their mini-sites needs to be, this really can all be handled with front-end entry forms and how complicated it can get is entirely up to you.

You should create their control-panel's using routes (possibly not even necessary depending on how you structure it). There you'd allow for any of the entry forms, etc.

In order to give more advice on how to go about this we'd really need more detail on exactly what each of these multi-sites needs to be capable of but this just seems like a standard site allowing unique front-end entry creation which is all able to be done without the use of any plugins, even while allowing it to get quite advanced and complicated.


Is it possible to populate admin form with data supplied by an external API? I've been tasked with reviewing Craft as a potential solution for the company I work for and one of the requirements is that we need to be able to provide data from a external API in the page creating/editing interface in the backend.

Is this possible and if so how?

Short answer: yes it is

Long answer: there are quite a few ways to achieve that. You can create a custom plugin with a custom element type to create a list just like the normal entries in craft filled with your data. You can then - during the saving process - update the data with your api to sync it with whatever you want.

If you are kind of lazy you could just create a normal section for your entries with all the required fields from your api and create a cronjob/task/function to download/fetch all entries with your api and hook into a onBeforeSaveEntry to validate the data and upload it to your api.

So all in all yes. It's relative easy and can be done in quite a few hours/days once you get used to Craft because the CMS does many things for you. It renders all lists/forms and manages the entire saving, sorting, filtering and searching processes for you. You just have to import the data (easy thing) and export the data. If you require some special sort validations you can include those rules too and Craft displays all errors


Showing categories in Channel Entry URLs I have a site which has two blog-like sections, which I'll call Blog and News. Each has a few categories. The categories are different in each section. An article always has (only) 1 category assigned to it. I want the URLs to be like:

/blog/                            # index page
/blog/category-slug               # listing all articles in category
/blog/category-slug/article-slug  # an article
/news/
/news/category-slug
/news/category-slug/article-slug

I'm struggling with how to construct this nicely out of Craft's Fields, Sections, Channels, Entries... I imagine I may need some custom routing, but haven't even got that far. Should I have two separate Channels and two separate Category sets? One Channel with two Entry Types and two Category sets? One Category structure with 'blog' and 'news' at the top level? How do I generate URLs for an Entry that will include /news/category-slug/...?

I'm going round and round in circles. I've tried things from answers here but haven't yet managed to display an entry at any URLs I expect.

(As an added wrinkle, I want the /blog/ and /news/ pages to appear to the user to be pages within a separate Structure... but I was going to worry about that once I've got the basic channel/category/entry stuff working!)

There's a lot here but I'd start by create 2 different channel sections: Blog and News.

From the front end, that makes it easy to see which entries are associated with what sections and easy to post content into each one. It also makes it easy to filter in your templates what section you're after.

To get your entry URLs setup, it's a little tricker but you can pull it off with some Craft/Twig magic. Setup a new field, make the handle blogCategory, make it a Category relational field, lock it down to 1 category that pulls from your Blog Category Group, and assign it as a field to your Blog section.

When you're creating the channel, set the URL format in your Channel to this:

blog/{blogCategory.first().slug}/{slug}

That little bit of code basically tells Craft to use the category slug of the blogCategorycustom field we just created in part of the url and the slug of the current entry to make the url. Craft treats categories, assets, entries, etc. and other relational fields as an "array" even if you only have one selected so we need to use .first() to use the first one Craft sees.

Now when you go create your blog entry, you're able to set a blog category and Craft will also use it as part of the URL.

BTW: There's no problem routing the Blog/News index pages to a page in a structure but you have to do the heavy lifting that Craft usually automatically routes for you.

In your _layout.html template, you could do something like:

{%if craft.request.firstSegment() is "news" %}
    {#load up news template #}
    {% include '_news/index.html' %}
{%elseif craft.request.firstSegment() is "blog" %}
    {#load up news template #}
    {% include '_blog/index.html' %}
{%endif%}

There's more to it than that, of course but hopefully that might get you started. It takes a little while to get your head around Twig and how powerful it is to use in Craft.

You'll want to also setup URLs for your Categories to have Craft load the appropriate template for each. Understanding the basics of how Craft routes requests is helpful as well.


Is it possible to disable token expiration? Or prevent follow from bots? So I have some gated content entries and need to prevent these from being indexed by search engines etc. Currently using draft pages but the tokens expire which then causes a 404 if someone is to land on that entry.

Anyway to prevent these tokens from expiring? Or does anyone have any suggestions on a field to prevent specific entries from being indexed by search engines. Or any options for saving as hidden entry, would be nice if this was built into craft as it seems like a pretty common feature.

I ended up adding a lightswitch for do not index. I am checking if this value exists in _layout.html if it does I am adding

{% if entry.noIndex %}<meta name="robots" content="noindex,nofollow">{% endif %}

I also updated my search results, sitemap entry template to check for the same thing and not include it in the sitemap file or the search results. As well as the dynamic sitemap.xml file. I believe this should be good.

Also I extended the token expiration but I think with the above approach, we will just publish like normal and remove the token expiration.


How to set multiple 'active' classes from query string I'm outputting all tags that are in use and then allowing the user to click these build up a query string to filter and display the results. It's all working fine.

Except, I'm having difficulty understanding what can I use to set an 'active' class on all the selected tags that are being added to the query string.

Setting 1 tag as active is simple enough, but when multiple are selected, I'm not so sure.

The URL looks like this: domain.com/learning/resources?tags=Video+Maths

Setting tags via getParam:

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

Listing all tags in use like this:

{% set resourceTags = craft.entries.section('resources').limit(null) %}
{% for tag in craft.tags.relatedTo(resourceTags) %}

Outputting results like this:

{% craft.entries.section('resources').limit(craft.config.paginateLimit).search(tags) as entries %}`

Perhaps not the most elegant solution, but this works:

{% set queryTags = craft.request.getQuery('tags') %}

{% for tag in craft.tags.relatedTo(resourceTags) %}
   <a
     href="{% if tags == "" %}/learning/resources?tags={{ tag.title|kebab }}{% else %}/learning/resources?tags={{ tags|replace(' ', '+') }}+{{ tag.title|kebab }}{% endif %}"
     class="btn btn-default{% if tag.title|kebab in queryTags %} disabled{% endif %}"
   >{{ tag.title }}</a>
{% endfor %}

Adding disabled rather than active.


How to best warm the cache I have a site with some poorly written code which creates the desired left hand menu from a structure with several hundred entries. Page generation on the server for uncached requests takes 3-5 seconds. Longer term I know I need to fix the code, but short term I have cached the section of code using {% cache %} and this works really well - until the cache is cleared.

Now I have tried Cache Warmer and on running the script I get the presumable success message "All urls are all warmed up". However all caches are clearly not warmed up when I test the pages - the first load is still slow (and it isn't local caching that helps). There are some numbers in the Cache Warmer plugin configuration screen that suggest there may be a maximum. Furthermore I have certain pages that are not based on their own entries e.g. A site map which runs straight off its own template. This page is particularly slow until it has been run once. So I am not entirely sure how Cache Warmer works and what I need to do to ensure that it warms the entire cache.

I am not using anything else. Varnish seems like a solution but for me its implementation might be a bit too complex (I don't have full server access and I am not very skilled on the server end).

Varnish is sometimes used to paint over poorly written code.  It's not horrible to get it up and running, but it seems to me that in this case, it might just be easier to fix the poorly written code.

I believe that what cache warmer does is it pings all of the URLs to get the caches to regenerate... but that just triggers the cache rebuilding process, which isn't instantaneous with Craft CMS.  Did you try waiting a little bit?

Does the data in the large structure change that often?  Something else you could consider too is putting the left menu in a its own template that you cache and load via AJAX so that the rest of the page isn't waiting for it.