This is absolutely possible with Craft & Commerce.

First, you would set up your categories group - say, Product categories.  You can add custom fields to these categories, for example an image field for an image that represents the category.

Then, you'd enter your category data - categories are inherently hierarchical (well, taxonomical really) - so it's easy to set up Parent -> Child structures.

Next, you would add a categories field as a custom field to your products when setting them up in Commerce.

Then, when you enter your products you can choose which category (or categories) the product should be in.

Finally, you would set up templates to actually display all this: probably one template to display the parent categories list, another to display which user chosen sub-category is required, and then finally templates for your product grid and most likely another for your actual product pages.

It sounds like a bit of a process spelled out like that, but if you step through setting up the fields and entering some data, and then start with very simple templates to just list out the things at each stage, you will find it is quite easy to set all this up - the only complexity really comes from the design angle -> i.e. making it look and work nicely!

Good luck with it!


Best method to update Craft on a live site to avoid losing data

I think you're asking the IT equivalent of "If I go outside when it's storming, how can I not be hit by lightning?" There's always going to be that chance. When you run a public server, that's pretty similar.
I'm not a high availability expert but as someone's who ran servers on behalf for clients, what you're really asking is 2 questions:

How much downtime can we afford?
How do we engineer a solution to minimize that downtime?

As you alluded to, how you answer question 1) is going to inform 2). Properly answering question 2) is probably beyond the scope of this Q&A format, but since we're going the down the rabbit hole...
If your answer to question 1 is next to zero, then you need to evaluate how much time/effort/money will required to do this.  Does it matter if your mom and pop's brochure based site is down for half a minute while you update? Probably not.
If you're running a multiple server setup for a largish organization, then this is also a question for them and what they're willing to throw at IT to make that happen. No server is 100% available, 24/7 and responsive to users.  The companies who do this well are also compensated accordingly. When you add redundancy to the mix, you also double your potential for failure so it's a double edged sword.
You can minimize that chance of messing up a user's work by doing a few things to proactively protect against downtime and just as importantly, frame the user's expectations:
Communication
When do your users usually work on the site? If the site's users and authors are typically 9-5 corporate in nature, update the site off-hours when less people are going to be working or visiting on the site. And if you think downtime is going to more than a few minutes, inform them of the maintenance window.
At least in terms of Craft, updating takes seconds usually. I liken updates to a frog jumping from lily pad to lily pad. The lily pads are point updates.  The smaller jumps are going to be a lot easier to make then jumping from one side of the pond to the other.
You're also spreading out your uptime with multiple smaller jumps instead of huge leaps. If you put off updating, you're increasing the risk of something blowing up later on (schema updates, etc).
Updating software is not like updating hardware where you know the hardware is going to fail at some point, so you plan for it. Writing bug-free software is harder. Being agile here is important. You also run less of a risk of having unplanned downtime because you didn't jump and now there's a huge security update.
Engineering
The other important piece of uptime is if something does go wrong during the update, how do you recover? When Craft updates, unless you've turned off automatic database backup, it'll save a copy in case things go hairy and then revert back so you're not stuck in a weird state.
I would also question the need for a long form to begin with. Can we engineer the form in such a way that it saves the user's work periodically (either to their browser or the server) as they fill it out?  Or make each form part shorter?
If someone is working on a long form, it's  counter intuitively also less likely they're going to be hit by server downtime, because they're spending more time on it before it gets submitted.
Lindsey D points out that how you deploy can make a difference as well. Deployment services (eg: DeployBot) in coordination with some VPS providers offer atomic deployment. This guarantees that your site remains "untouched" until the new files are 100% uploaded. Using something like Capistrano can do this as well. AWS offers their own set of deploy and server management tools to help manage your uptime too. (Again, you pay the piper for all of this, which is why AWS gives you a year for free in their free tier.)
There's probably a few things you can do but those are just off the top of my head.


You want something like this:

craft()->on('charge.onCharge', function($event)
{
    $charge = $event->params['charge'];

    $pounds = $charge->amount;
}


Call a public function within a FieldType file, from a variables files

From what I understand about plugin development on Craft, this isn’t possible. The idea of the variables file is to provide methods which are accessible from within your plugin or users templates.

The idea being that the methods you define here are actually references to your service methods (Taken from Craft docs)

  Many of your template variable methods will likely be simple wrappers for your service API methods. It’s important to remember not to expose state-changing methods, however.

So from that I would actually create a service class for your plugin and access the methods in your getInputHtml function from that.

For example:

services/MyPlugin_PluginService.php

<?php
namespace Craft;

class MyPlugin_PluginService extends BaseApplicationComponent
{
 public function helloWorld()
 {
   return ‘Hello World’;
  }
}

In your getInputHtml function

$testing = craft()->myPlugin_plugin->helloWorld();

Call the same method in your templates

Add this to your variables/MyPluginVariable.php file to call the method in your templates:

public function sayHello() {
  return craft()->myPlugin_plugin->helloWorld();
}

Then you could call the service method in your templates like so:

{{ craft.myPlugin.sayHello() }}

Hope that helps!


When you set up your category, you check the Categories in this group have their own URLs box, and you give the category a URL (suppose it is category/{slug}), and a template (suppose it is category/_entry). Now in the category/_entry.html template, category will be defined (the way entry is defined on the template for a section entry).

How do I list the entries related to a category? (tucked away in the Get Help section of the Craft website) describes how to fetch and list the entries related to a category:

{# Fetch all of the entries related to this category #}
{% set entries = craft.entries.relatedTo(category) %}

{# Output them #}
{% for entry in entries %}
    {{ entry.title }}
{% endfor %}

If you want to narrow the entries down to a single section, then fetch them like this:

{% set entries = craft.entries.section('mySectionHandle').relatedTo(category) %}


You could loop through the Matrix field on every entry save using the awesome Preparse plugin, to store the categories an entry contains in a new field.

https://github.com/aelvan/Preparse-Field-Craft

Here’s example code for your Preparse field, it would store strings like firstCategory,thirdCategory,secondCategory.

{%- set categories = [] %}

{%- for block in entry.myMatrixField.type('myRelevantBlockType') %}
    {%- if block.myDropdownField %}
        {%- set categories = categories|merge([ block.myDropdownField.value ]) %}
    {%- endif %}
{%- endfor %}

{{- categories|join(',') -}}

Once you have populated that field for all your entries, you can filter them by a category using this criteria model.

{% set categoryToSearch = 'secondCategory' %}

{% set entries = craft.entries({
    section: 'myEntriesSection',
    search: 'myPreparseFieldHandle:*' ~ categoryToSearch ~ '*',
}) %}

I have to say that I’m not very proud of this solution as it uses search which I usually try to avoid. But I wasn’t able to come up with a better idea.


Since I use email addresses as usernames, I don’t think it’s a good idea to expose the email addresses of all users on the web.

I agree, and that's something we overlooked when we added the 'useEmailAsUsername' config setting.

  Question: Is there a way to remove the username (in my case email address) from the photo path and replace it with the users ID for example?

Currently not, unfortunately.  And it's hard-coded so there really isn't a chance for a plugin to override the behavior.  And I don't think it's really any better to be displaying a user's ID or UID as well, since people wouldn't expect those to be publicly available by default.

  Bonus question: is there any way to protect user photos from access at all? It looks to me like the urls to the user photos could be guessed quite easily.

Again, no.

I think the proper solution to both problems would be, upon uploading a user profile photo, generate a random string and save that along with the user in the database.  The string would be used in the URL when retrieving the user's profile photo.

I'll add it to our list to address.


Site is inaccessible after updating plugin with new attribute/db column

Adding getSchemaVersion() to my main plugin file and returning a schema version did the trick.

public function getSchemaVersion()
{
    return '0.0.4';
}


Recommended way to provide user feedback in the control panel?

To me, this seems like a great use case for a custom dashboard widget.


Get entries related to tags with a score & order by

You can add custom properties to elements using behaviors. In this case you want to add your 'getSearchScore()' logic.

Here's a good article on how behaviors work in Craft CMS and a current PR on the documentation to have behaviors information added.


Does Craft have an installer error log I can check?

Typically the Craft logs are stored here:

/craft/storage/runtime/logs

I don't know how much logging the installer does, but if it does any at all, that's where you'll find the log data.

In the meantime, you can also try this script by Ben Croker which will check your server configuration to make sure it has everything it needs to proceed.


How to turn off application log in dev mode

Lifting from this answer to a similar question:

You'll have to write a simple, custom plugin, and add the following to the init() method in your plugin's primary class:

craft()->log->removeRoute('WebLogRoute');
craft()->log->removeRoute('ProfileLogRoute');

For instant success, you can scaffold your plugin by visiting the plugin factory – name it whatever you want and don't enable any components.


Craft 3.5.1 CLI Update Error: Failed to instantiate component or class "yii\shell\Bootstrap"

This ended up being a bug we were able to work-around on our side via our web service calls.
If you restore your site from a pre-update attempt database backup and composer.json file, then attempt the update again, it should go through fine.


Your first example essentially looks correct — and I don't know if it makes a difference, but the syntax that I have used in the past looks something like this, where I output the map after setting the data.

{% set options = {
    id: 'map',
    width: '950px',
    height: '500px',
} %}

{% set map = craft.googleMaps.map(options) %}

{% for entry in craft.entries.section('maps').limit(10) %}
    {{ craft.googleMaps.data('map', entry.mapData) }}
{% endfor %}

<div class="map">
    {{ map }}
</div>


PayPal Express not redirecting back to Craft Commerce

What's the output in your templates of:

{{ craft.config.tokenParam }}

If it isn't t suspect your config is not setting the tokenParam for some reason.

Can you test with a stripped out general.php with only hard-coded values (No multi-environment config, or if($_SERVER ... checks)

return array(
    'tokenParam' => 'myCraftToken'
    // ..other hard coded settings
);


Plugin - Possible path problem in MAMP - Could not find the task component type

My guess is it's a case sensitivity issue between your plugin class names and the names of those files on the file system.

If you're on an NTFS filesystem on Windows, it is case sensitive.  I recommend generating boilerplate plugin code from something like https://pluginfactory.io/ (they even have a tasks checkbox) to help avoid issues like this.


Custom Fieldtype with Checkboxes - Remove value and set to null when checkboxes are left blank

This isn't really an answer. But I think I do know what might be happening. The default browser behavior is that checkbox values only get submitted when it has the attribute 'checked' (why? I have no idea). In php you're essentially testing whether the post value exists or not. If it exists, true; if not, false. I assume for the built-in checkbox fieldtype that craft does this for you in the background (by somehow comparing with the original options). You'll have to figure out a way to perform this check yourself. Maybe take a look at the source files and see how craft is handling this.


So the problem was caused by a secret character, the character was not visible in code but it was noticed in the w3c validator for html.

So after removing that character issue solved.


How would you import content with embedded images, ideally using FeedMe?

There's nothing through Feed Me that handles this elegantly at the moment, and you'd need to either parse your html data before or after the import.

We've done this a few times on an import, where we've created a trivial PHP script which extracts images out of HTML content. Something like:

$html = '
Some text

More text
.';

// Start scraping!
$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);

// Extract all  tags from our HTML content
foreach ($xpath->query('//img') as $key => $node) {

    // Save the image for later - just get the filename though
    $contentImages[] = $node->getAttribute('src');

    // Remove the 'img' tag from the content node
    $node->parentNode->removeChild($node);
}

// Store our parse HTML content (without img tags)
$content = $doc->saveHTML();

$json[] = array(
    'contentImages' => $contentImages,
    'content' => $content,
);

echo json_encode($json);

Normally this is because most scenarios go from a single WYSIWYG content block (looking at your Wordpress), to a Matrix content-builder field. In our cases, we like to create a Rich Text 'Content' block, and an 'Image' content block. As such, they're two different bits of data, and extracted out as above.

If you're wanting to keep your images in your Redactor fields, but have them hooked up to Craft's Assets - thats much more complicated. You'd need to upload the asset to Craft, get the ID from the uploaded asset, and replace the  tags in your content with a Redactor Asset placeholder.


Checkbox profile fields front end show labels in cp

This is the expected behaviour. It makes perfect sense to display the human-friendly checkbox label on an admin screen, rather than the (potentially obtuse) checkbox value.

To confirm that this isn't simply an issue with your form, I did the following:

Created a test checkbox field with three options.
Added the test checkbox field to the custom user fields.
Set the checkbox field to display on the users list page.
Edited a user via the control panel, and selected some of the checkbox items.
Returned to the users list page to view the results.

As expected, the users list page displayed the labels of the selected items.

The only difference appears to be that in my installation the selected items are displayed in a single column, as a comma-delimited list, whereas in your example each checkbox item receives its own column.

Here's a screenshot:

It's also worth mentioning that you are correct in stating that the checkbox option fields need to include the [] in the name. That's exactly how the admin forms work too.


That looks perfect!

Obviously this code doesn't prompt the user to confirm deletion, but that can easily be added. (Or perhaps you stripped that out of your example.)

You are specifically doing two things right here:

Hitting deleteEntry directly. This ensures that Craft follows all of its necessary internal procedures to properly delete the entry (and kill any relationships it may have).
Including the CSRF token information. Not sure if it's currently required for hitting a native Craft method, but it certainly will be when Craft 3 rolls out. Good future-proofing!

Looks great Johannes, go for it!


Try using an array syntax instead of the object syntax:

{% set string = entry['fieldname' ~ 1] %}


Add a shippingCost per lineItem rather than per Order

You're right that the shipping calculator API doesn't lend itself to different rates per lineItem as such, but I'm pretty sure you can still make it do what you want.  (But longer term I agree that getLineItemRate(lineItem) or similar should be an option!).

Basically, for now, you can do anything you like in the getBaseRate() and return the total from that to the cart.  (Personally I implement all my shipping stuff as services so I can call them from controllers etc too (e.g. to do shipping quotes via a controller separate to the cart as such - but in this I'll do ti right here).  But you can also do stuff like save data to the order in here, which should be enough to make this work for you.

Basically, you'd loop through the lineItems, looking at the value in the dropdown for each and using that to sum up your shipping costs.  You probably want to list out the chosen options and costs for each lineitem separately on that payment page, so you'll also need to save that data somewhere too...so create a holder variable lineItemShippingOptions in your order for that data and set it as part of the process so you can refer to it in the later templates.

(I'd use a non-editable incognito field for that so your order processors can't accidentally change the data later - https://github.com/mmikkel/IncognitoField-Craft (I have PR-ed an improvement to that for just this sort of thing).

(Obviously - this is untested sketch code!)

public function getBaseRate()
{
   $shippingCost = 0;
   $dataToSave = [];

   $this->cart = craft()->commerce_cart->getCart();
   foreach ($cart->lineItems as $item){
        $shippingOptionChosen = item.options.whatever;
        if($shippingOptionChosen == "service1" ){
            $shippingCost = $20;
            $dataToSave[item.id] = ['chosenOption'=>$shippingOptionChosen, 'chosenPrice'=>20];
        }
        elseif ($shippingOptionChosen == "service2"){
            etc
        }
   }
   //Save this data in to the order
   $this->cart->setContentFromPost(['lineItemShippingOptions'=>$dataToSave]);
}

Then in your templates you can refer to lineItemShippingOptions to print the info out to the customer.  (That's probably not the ideal way to build the template data you're saving but should serve the purpose to demonstrate the idea...basically you can build any format array you like really).

I use this same approach in a very complicated custom shipping calculator (crazily this is some 2000 lines of php!) - that deals with multiple services (including some table data ones and some live quote ones), plus grouping & boxing services & caching to make it all work as quickly as possible (live rates always being much slower of course...).  Because at times the checkout flow gets awkward relying on Commerce's template tags, I also have an actionShippingOptions controller that calls the same services and returns the quotes & data that way (also very handy for debugging purposes!) - but you may well not need that.  But even with the existing API you can do damn near anything you like between setting the rate and saving data to the order and showing it later, basically.


The difference between username and loginName

Because you can login with either your email address or your username.  And some sites will be forcing the username to be the email address.


How to search by title OR tag using Craft CMS?

I think you need to make two separate queries, get two arrays, combine them using the merge method and leave them unique, since these are different searches, textual and by related elements. It's like a quick fix, if I find something I will answer.


Solspace Freeform: Looping through Radio group options in template

To manually generate multi-option fields like radios, your code would look something like this:

{% set yourFieldHandle = form.get("yourFieldHandle") %}

{{ yourFieldHandle.label }}
{% for option in yourFieldHandle.options %}

         <input type="radio" name="yourFieldHandle" value="{{ option.value }}" {{ option.checked ? "checked" }} />
         {{ option.label|raw }}

{% endfor %}


Creating entries from JSON feed - plugin?

Check out the FeedMe plugin. It's pretty similar to DataGrab and Importer.

From the README:

  Feed Me

  Feed Me is a Craft plugin to make it easy to import entries and entry data from XML, RSS, ATOM or JSON feeds. Feeds can be setup as a task in Craft's Control Panel, or called on-demand for use in your twig templates.

  A common use-case for this plugin is to consume external feeds (news, events), but can also be used as a once-off task for importing content when migrating from other sites.

  Features

  Import data from XML, RSS, ATOM or JSON feeds.
  Feeds are saved to allow easy re-processing on-demand, or to be used in a Cron job.
  Map feed data to your entry fields. See Supported Fieldtypes.
  Duplication handling - control what happens when feeds are processed again.
  Uses Craft's Task service to process feeds in the background.
  Database backups before each feed processing.
  Troubleshoot feed processing issues with logs.
  Grab feed data directly from your twig templates.
  Craft 2.5 compatible.

Disclosure: I authored this free plugin. Let me know if I can be of assistance!


Smart Map with multiple different markers based on a matrix field

I believe the problem is in this line of code:

var markerId = 'smartmap-mapcanvas-1.{{ entry.id }}.address';

Because you're generating markers from matrix blocks, you'll need to use the block ID instead of the entry ID. In your case, that may looks something like this:

var markerId = 'smartmap-mapcanvas-1.{{ item.id }}.address';


Blog Comments / EntryModel.owner is undefined

Somewhere in your template you are trying to access the owner attribute on an EntryModel. The example above doesn't show any details on where you might be trying to do that in your templates.

Try commenting out any area of your template where you may be trying to output values that relate to the Entry Model. Maybe even comment out your whole template. Comment things out until you get your page to load again. As you mentioned this error occurs when you try to send a comment, you may also want to comment things out on whatever template gets loaded after you submit the comments.

Once you're getting the page to load without errors, add your code back line by line until you get the error. This will help you isolate where the error is.

When you find it, you'll probably need to add a conditional check to the offending code to get things working:

{% if entry['owner'] is defined %}
    Then it's safe to try to output {{ entry.owner }}
{% endif %}


This will be possible in Craft 3, when the concept of "Assets" will get converted into "Volumes". Unlike Craft 2, it will be possible to create a custom Volume with a plugin.

Be aware though, everything you're describing will require a custom plugin. At this point, no such plugin exists.


Craft 3: admin is showing "500 Internal Server Error" (apache) after fresh install

(/usr/local/lib/php/extensions/no-debug-non-zts-20170718/imagick.so.so: cannot open shared object file: Permission denied))

Does that file exist on your server?  I'm asking because the .so.so extension seems odd.  If it does and it's just .so, it might be as simple as editing your php.ini file so it's loading imagick.so instead of imagick.so.so.

If you php.ini file is already loading imagick.so and that file exists on your server at that location, then check the permissions of that file and make sure that whatever user:group your web server is running as has permissions to read that file.


Can Auth0 be used for Craft Commerce user accounts?

Craft Commerce and Craft does not support that service out of the box. A Craft plugin would need to created using their PHP Package: https://github.com/auth0/auth0-PHP


Only allow signups from people with @___.com emails

One way of doing this is to write a custom plugin that intercepts the users.onBeforeSaveUser event.

You would check that the submitted email address matched your desired pattern and set $event->performAction = false if the criteria wasn't met. This would prevent the user from being saved.

So the init() method of your plugin might look something like this:

    public function init()
    {
        craft()->on('users.beforeSaveUser', function(Event $event) {

            // Retrieve the userModel from the event
            $user = $event->params['user'];
            $isNewUser = $event->params['isNewUser'];

            // Check if this is a front end request and that we are dealing with a new user
            if (craft()->request->isSiteRequest() && $isNewUser) {

                // Check for valid email address
                if (email address doesn't match required pattern) {
                    // Cancel user save
                    $event->preformAction = false;
                }
            }
        });
    }


If your website is showing the text of your index.php instead of the actual website code, something is misconfigured with your server setup. Anything .php should be passed along to php-fpm or whatever CGI handler you're using.


If you're using the Pixel & Tonic Contact Form plugin then there is a way to set your redirect using {{ redirectInput('contact/thanks') }} as seen here: https://github.com/craftcms/contact-form

However, I've just noticed you've tagged this question with plugin-sproutseo, but I'm not aware of that plugin interacting with contact forms in any way.

To more specifically try to answer your question, firstly to redirect and pass some information, I have used query params before so I've set my redirect link to be /thankyou?name={{ formstuff.name }} so I can access the user's name with:

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

Now when it comes to redirecting back to the user's previous page, have a read of this answer below. It's a few years old, but it'd potentially still give you an option to resolve your issue: https://craftcms.stackexchange.com/a/13488/5845

EDIT: After a look at some other questions, I've noticed this one has an almost identical wording so this one should be marked as duplicate. See dupe below:

How to redirect the page with params?


Demo repo for an Adjuster module for Commerce 2?

I've created a stub/reference Adjuster module, here.

This demonstrates how to register two Adjusters via a custom module—one that creates a 5% discount on each line item, and one that creates a 10% discount on the entire order.

These adjusters have their logic hard-coded, which is to say: in order to modify the behavior/value of the adjustments, you have to change PHP files. Part of the benefit of Craft's built-in adjusters (Taxes, Discounts) is that they base their calculations on input from the merchant/admin, in the control panel.

You can replace the two calls to $adjustment->amount = $myAmount; with anything you like—including Craft API calls that fetch values off of Elements, get plugin or environment settings, inspect LineItem options, etc.

This is where Adjusters become immensely powerful. As long as you can provide a positive or negative value, a label, and a description for your Adjustment, it doesn't matter how you derive it. ✌

This module is not meant to be installed as a plugin, or used as a submodule—it's probably best to just lift the code out and replace the generic classes and namespaces.

  A bit of context: James and I spoke in Slack earlier today, which prompted the creation of this repo. The code has been adapted from private projects, but is now available under the MIT license.


Apply discount on login during commerce checkout process

I have confirmed this would indeed appear to be a bug in Commerce.

A quick workaround would be to listen to login events and call some sort of update cart hack, but this is really a fix that should happen at the Commerce end of things.

I'll report it.

EDIT: Luke Holder comfirms he's found the bug and it will be fixed in the next point release coming soon.


Property "Craft\WebApp.assetUpload" is not defined

You won't need the enctype="multipart/form-data" part of the form, since you don't appear to be uploading any files when saving the user.

Other than that, I'd guess that maybe you've got an Asset field on your User's field layout that set to required and you're not taking that into account on the front-end?j


Why does craft.request.getQueryStringWithoutPath return an empty string?

Turns out this was a bug that only occurred if the existing URL didn't have an URI associated with it.  i.e. http://craft.dev?foo=bar.

It's been fixed and will be included in the next 2.5 beta release (or the first 2.5 public release if you don't want to swap to the beta track).


When saving an Entry, I receive a JSON response rather than returning to the Entry's edit page

IMO, the issue is with this line.

SetEnv HTTP_ACCEPT text/html,application/xhtml+xml,application/xml,application/json;q=0.9,*/*;q=0.8

With ACCEPT headers set to a fixed value, it's impossible for Craft 3 to distinguish between Json and HTML requests. This must have been a necessity with the nginx proxy setup.

I suggest removing this line from Apache and configure nginx to pass through the original request headers.

If you use proxy_pass, trying adding this line

location / {
    ...
    proxy_pass_request_headers on;
    ...
}

OR, if you prefer a more direct approach

location / {
    ...
    proxy_set_header Accept $http_accept;
    ...
}


How do I display the Image of an Author in a post?

That will get you the url of the current user's photo. To get an author's photo do this:

{{ author.photoUrl }}

If the author is not defined in your context but the entry is, then get the entry's author's photo as follows:

{{ entry.author.photoUrl }}


One way to do this, is use different environments for each domain and set a variable (for instance, an entry ID) for each environment. So, your config/general.php would look something like this:

return array(
   '*' => array(
       // Every config setting that's the same for all domains (like devMode, omitScriptNameInUrls, etc.
   ),
   'firstDomain.com' => array(
       'siteUrl' => 'http://www.firstDomain.com/',
       'environmentVariables' => array(
           'baseUrl' => 'http://www.firstDomain.com/', // For use in asset source, for example
           'basePath' => '/path/to/public/folder/', // Same for this
           'entryId' => 5 // Or whatever the ID of your entry is
       ),
   ),
   'secondDomain.com' => array(
       'siteUrl' => 'http://www.secondDomain.com/',
       'environmentVariables' => array(
           'baseUrl' => 'http://www.secondDomain.com/', // For use in asset source, for example
           'basePath' => '/path/to/public/folder/', // Same for this
           'entryId' => 8 // Or whatever the ID of your entry is
       ),
   ),
);

Then, in your template (entry.html or whatever file you use as your section's template), you get the data like this:

{% set entry = craft.entries.id(craft.config.environmentVariables['entryId']).first() %}

<h4>{{ entry.title }}</h4>


How to create CRUD operation in Craft CMS?

Everything you need for creating and updating content from the front end is covered here: https://docs.craftcms.com/v3/dev/examples/entry-form.html

For deleting you can use the entries/delete-entry action (goes without saying that you'll need to add some kind of security checks).


Craft 3 icons not found in craftcms/cms/src/icons

Gitignore had a line for Icon? which was causing the icon folder to not show up in git commit.


Craft 3: Error "variable now does not exist"

You need to convert the DateTime object via Filter:
 now|date('U')

or via function
now.format('U')

This will format the date as a UNIX timestamp which is sufficient for querying. MySQL datetime format will work too: date('Y-m-d H:i:s')
More info can be found in the upgrade documentation.


I believe HeaderHelper::setHeader() is what you're looking for in the context of a plugin.


You should have seen a warning that the license belongs to another domain (https://craftcms.com/support/license-transferring).

If not; are these duplicate sites still on a non-public (development) domain? That might explain why you did not see the warning. In either case: simply delete the license file for the duplicate sites and Craft will create a new one. You might need to clear the caches as well.


Craft and Plugins are licensed, but I'm still seeing warnings on Production

You probably just need to clear the Craft storage/cache folder on production.
Licensing info is cached for 24 hours at a time.


Craft 3 User Registration form errors not showing for custom fields

From the code

// Don't validate required custom fields if it's public registration
if (!$thisIsPublicRegistration) {
    $user->setScenario(Element::SCENARIO_LIVE);
}

You have to create a custom controller


How do I set up a section of text on my home page to rotate through, rather than stay static?

This should be relatively simple to implement, although depending on how the page was designed may require reworking some of the existing page layout and css.

As far as craft is concerned the data could be stored in a few different ways; perhaps in a separate channel, table, or matrix field. Setting this up on the craft-side is trivial, and would not require any special plugins.

On the front-end content could all be loaded when the template is initially rendered (by simply adding a few lines of code to the template), or loaded as needed using javascript and ajax (by creating a separate template used to render just the text segments as requested). Although if it's truly only text, I would opt for loading it all at once on initial page load. Transitions would normally be done using some fairly simple javascript and/or css transitions.

There shouldn't be any technical limit on the number of items you could display; but there probably are some practical limits where it would start to get clumsy for one reason or another.

If you need more specific code examples, please leave a comment, and I can add more detail.


How to use twig parent function on nested blocks

Try to keep the blocks separate in your child template. That's how it's done in a comparable example in the Twig Documentation.

Parent Template:

{% block breadcrumbs %}
    {% block crumb %}
    {% endblock %}
{% endblock %}

Child Template:

{% extends "parent.html" %}

{% block breadcrumbs %}
    {{ parent() }}
{% endblock %}

{% block crumb %}
    My custom content
{% endblock %}

.

Edit:

If you're not adding any content to your "breadcrumbs" block from the child template, you can also omit that block completely:

{% extends "parent.html" %}

{% block crumb %}
    My custom content
{% endblock %}


How long does the share link on the entry edit screen last?

24 hours by default, but it can be configured via the defaultTokenDuration config setting.

v2 documentation
v3 documentation


Edit FreeForm lite from front end in Craft 3

I don't know of a native way to edit Freeform submissions on the frontend, at the moment. Apparently Freeform 3 is coming out next week and it includes front end submission editing! Based on this edition comparison page it will only be available for Freeform Pro.

I did think of a way to accomplish this right now.

Setup an Element Connection for the form you wish to allow editing for. Make the connection to a new Craft section (e.g. User Submissions). Then you can use a standard Craft edit entry form to allow your users to make edits. When creating the Element Connection make sure you pass some sort of Craft user identification so the new entry is tied to the correct Craft user. That will make editing much safer and easier. The downside to this method is that Freeform will no longer hold the master version of the submission. That would limit your ability to use some of Freeform's features.


Redactor migration might fail with allowAdminChanges & useProjectConfigFile false

According to P&T this is expected behavior. Their solution is to put this in config/app.php:

'components' => [
    'projectConfig' => function() {
        $config = craft\helpers\App::projectConfigConfig();
        $config['readOnly'] = false;
        return Craft::createObject($config);
    },
],

(Thanks Oli, Brandon, Andris!)

Since I do all migration via Craft's console commands, this shorter solution works for me:

'allowAdminChanges' => (php_sapi_name() === 'cli')

It simply enables admin changes when using the console command.


For performance is using a macro better than using include with the 'with' statement?

If I had to guess, I'd say a macro would be faster because it's accessing the file system less.  In any case, unless you're dealing with hundreds of thousands of calls, I'd also guess that's the difference is going to be negligible for most use cases.


How to add a custom tab in the user editing page

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


How to improve performance of this nested entries/array template?

Have you considered to cache the whole output? https://craftcms.com/docs/templating/cache


Is it possible exclude an entry type from result of craft.entries?

Going through Craft's docs, I found no easy or official way to do this. Fastest possible way, in my opinion:

{# get all section IDs #}
{% set sections = craft.sections.getAllSections() %}

{# get all entry types for sections #}
{% set entryTypes = [] %}
{% for section in sections %}
    {# exclude the entry type you don't want, add the others to 'entryTypes' variable
       you could, of course, replace handle by ID or whatever you like #}
    {% for entryType in section.getEntryTypes() if entryType.handle != 'handleToExclude' %}
        {% set entryTypes = entryTypes | merge([entryType]) %}
    {% endfor %}
{% endfor %}

{% set entries = craft.entries.section('inhoud').type(entryTypes) %}


How can I use Ajax function in Craft CMS?

Since Craft makes no assumptions about the front-end content of your website, it's 100% up to you on how you want to implement AJAX functionality on your site.  So it wouldn't be any different if you were trying to use AJAX on a simple static page with no CMS managing the content.

For example, a popular method is to use jQuery's ajax method.


Changing status via entries list in one locale also (unexpectedly) changes status in other locale(s)

I agree this is confusing.

If you are editing the entry, you can change the status per/locale by selecting the locale in the box in the upper right corner, and then using the lightswitch next to the selected locale.


How to create a basic plugin front-end controller?

I solved the problem using Pascal Case for naming all my files and classes. I was using camel Case...

So all works fine with those filenames for my "foo" plugin :

FooPlugin.php
controllers/FooController.php

I used Pascal Case for the classes name too, mainly for consistency reason; but i noticed that :

using camelCase for controller class name if the filename is in PascalCase does not break anything
using camelCase for plugin classname breaks the controller.

Anyway, if you don't want issues, juste use Pascal Case (file names and class names) everywhere and you should be Ok.

Please note that with apache, this path is calling my controller correctly (all in lower case)

actions/foo/hello


Are there coding standards I can follow when writing my Craft plugin?

I would strongly suggest that you follow PSR-2 since that is what most of the craft source code adheres to and it is a pretty good standard for general PHP development. Just be aware that craft itself won't pass PSR-2 linting because there are places where it deviates from the standard, two of which are namespacing (craft has a global namespace) and indentation (tabs over spaces) but that is totally fine in my opinion.

Writing clean, readable, intuitive, and testable code should be the end goal of any developer and if that means you have to violate a standards rule here or there, go for it: )


Do dynamic routes depend on url rewriting?

I first attempted, with the link Mats posted, to edit my nginx config. That resulted in a rather terrifying "can't even find the index" error, but there was a silver lining: after destroying and recreating my Vagrant the urls mysteriously fixed themselves, and I no longer see querystrings on the index. Custom routes also now work. So that's mysterious but I'll take it for now.


Override a portion of an extends template

You could define a variable in you child template:

{% set bodyAttributes = 'onload="load()" onunload="GUnload()"' %}

And then output the value in your parent _layout.html template. Use the is defined test, so that not every template extending this file has to have that variable defined. I'm using ternary syntax here, to keep the code nice and lean:

<body {{ bodyAttributes is defined ? bodyAttributes : '' }}>

As I generally like to have as few logic in my Twig output tags as possible (in particular when they output classes and attributes to already cluttered HTML tags), I would write that code like so:

{% set bodyAttributes = bodyAttributes is defined ? bodyAttributes %}

<body {{ bodyAttributes }}>


Updating plugin/module config via template/controller

In short, no. If this is config or data which are environment specific, they are as likely not good candidates for project config. Perhaps consider moving them to a table and access them through a Record/Model?


When it comes to creating breadcrumbs, I can only offer advice when doing so within a structure.

Craft 3 still has .ancestors available on an entry so you can do:

{% set breadcrumbs = entry.ancestors.all() %}

Then check the length and loop through the ancestors for the structure entry.

{% if breadcrumbs|length %}

Home

        {% for crumb in breadcrumbs %}

{{ crumb.title }}

        {% endfor %}

{{ entry.title }}

{% endif %}

Then just add a little CSS to style as you choose.

This would use &raquo; between each entry.

Home » First Article » Another Article » Grandchild Article


Model and its behaviors do not have a method or closure named "optgroup"

Few things - you need to add the options to the render function so they are passed into the template. Also, check what I did below for the $widthsOptions. Each option needs a label and value key/value pair.

public function getInputHtml($name, $value)
{
    // call our service layer to get a current list of widths
    $widths = craft()->columnWidth_widths->getAllWidths();

    // create an array for the widths
    $widthsOptions = array();

    // populate the $widthsOptions array with $widths
    foreach ($widths as $width )
    {
        $widthsOptions[] = array(
            'label' => $width->name, //this should be whatever you want to display in dropdown
            'value' => $width->name //this should be the value you want passed to the database
        );
    }

    return craft()->templates->render('columnwidth/_fieldtypes/widths', array(
        'name'      => $name,
        'values'    => $value,
        'options'   => $widthsOptions
    ));
}

Your field type template should be something like this:

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

{{ forms.selectField({
    instructions: "Select the width of your column"|t,
    id: 'columnWidth',
    name: 'columnWidth',
    options: options,
    value: values
}) }}


Get a field's required attribute in frontend form

I could not find a way to get a specific field for a model but you can get all and loop through them

<!-- fetch all fields for your entryType -->
{% for field in craft.entries.section('yourSection').type('yourEntryType').first.getFieldLayout().getFields() %}
    <!-- loop them and check the handle if it is your field -->
    {% if field.getField().handle == "yourFieldHandle" %}
        <!-- the required attribute -->
        {% set required = field.required %}
        {{ field.getField().name }}
        {{ field.getField().instructions }}
    {% endif %}
{% endfor %}

Edit: if you really want to have only one field instead of the array I could create php code for you but since many people refuse to use php in craft I presented the "slower" twig method

Edit: There is a required property in both the FieldLayoutFieldModel (stored above in field) and in the FieldModel (field.getField() above). What we want as the required flag of the entry type is the first: field.required. This is what appears to be the little red asterisk in Craft's backend.


Ajax front-end user registration form - not returning JSON

EDIT

Craft 2.4 is now available, and the users/saveUser action will now return a JSON response for AJAX requests.

The original answer is still valid for <2.4 builds:

No, there's no way to trigger a JSON response for the users/saveUser action.

Other UsersController actions (such as users/login do return JSON for AJAX requests, so it might be an idea to submit this as a feature request – as a consistency measure, if nothing else.

For now, here's a couple of ideas for workarounds:

Write a plugin with a controller that wraps the UsersController->actionSaveUser() method somehow, or implements its own action (you could basically just copy paste the whole actionSaveUser() from the core UsersController, changing it to return some JSON at the end).
You can set the redirect parameter (using a hidden input field in your form) to point to a template where you build the JSON yourself.

Form:

<form method="post" action="" id="register-form" accept-charset="UTF-8">
     <!-- Your form code -->
     <input type="hidden" name="redirect" value="{{ url( 'path/to/your/template/or/a/route' }}">
</form>

Template for the redirect (notice the JSON header):

{% header "Content-Type: application/json" %}
{
    "success" : {{ account is defined and account.id ? true : false }}
}


How to include asset fields in query in php?

You can skip the asArray() part, as the object has all you need:

// This bit returns only the query that defines what objects to get
$entryQuery = Entry::find()->section('inventory');

/*
 * This will get you one object, based on the query.
 * Use all() if you want an array of objects
 */
$entry = $entryQuery->one();

// Of course, this could be written as
$entry = Entry::find()->section('inventory')->one();

/*
 * Thanks to Yii2's magic getters and setters,
 * and the way Craft uses them, any custom field can be
 * obtained by using the field's handle:
 */
$customFieldContent = $entry->customFieldHandle;

/*
 * If the custom field is any kind of relation field (assets, categories, tags ...),
 * this custom field attribute would return a new query object.
 * You'd need to call all() or one() again to get the actual related objects:
 */
 $images = $entry->customImagesFieldHandle->all();

/*
 * To improve performance, you can eager load the images:
 */
$entry = Entry::find()
    ->section('inventory')
    ->with(['customImagesFieldHandle'])
    ->one();

/*
 * ... which would result in an array of images as the value of the
 * customImagesFieldHandle attribute
 */
$images = $entry->customImagesFieldHandle;

Some light reading:

About entry queries

About eager loading

Addition, after seeing exactly what it is you want. Use Craft's (or actually Yii's) ArrayHelper map() function to loop through your entries and mapping entry content to what you want:

use craft\helpers\ArrayHelper

// Use the map() function to do what you want
$entries = Entry::find()->section('inventory')->all();

$entriesAsYouWantThem = ArrayHelper::map($entries, 'id', function($entry) {
    return (object)[
        'images' => $entry->images->all(), // or without all, if you use ->with()
        'price' => $entry->price,
        'year' => $entry->year,
        ... All other fields
    ];
});


Commerce: Template error: “Variable "option" does not exist

The option variable is only available in the pdf template, it is not available in the email template.

order variable available in both.


Query entries by matrix date fields for event calendar

I think that in order to do this you are going to need to loop through all events; find eventTimes (within the blocks) that are after the selected date; merge those into an array;  and then return the sorted array. However, by doing so you will loose the ability to easily use pagination.

Perhaps another solution would be to not use matrix blocks at all and instead create two channels: 1 for 'Shows' and 1 for 'Showtimes' (using your theatre analogy), where 'Showtimes' would be related to 'Shows' using an Entries field-type with limit set to 1. Then finding showtimes would be trivial, and would support pagination, etc. (You could even set the showtimes title to be auto-generated from 'related show title + datetime'.)

And if you wanted to display all the showtimes collected nicely on the Shows entry (for the sake of the client), you can use a nice plugin called 'introvert' to show reverse related entries.


Uploading to a date subfolder within a Matrix

You're probably looking for:

{owner.postDate|date("d-m-Y")}

See the note about dynamic subfolders on an Assets field inside of Matrix here: https://craftcms.com/docs/assets-fields#dynamic-subfolder-paths


Craft v3 gives 500 error on installation... how to get v2 instead

I definitely would not recommend trying to install v2. Craft CMS 3 has many improvements over v2, a strong plugin ecosystem, and it will be supported for significantly longer.

As for your setup issues, this is very likely some kind of a server config issue or Craft config issue. To find out which, we need to look at the error logs.

First, look to see if there are error logs in storage/logs/ (relative to your project root).

If not, then the request isn't even hitting Craft, so it's likely an Apache misconfiguration (usually the server root isn't pointing to the right place or such), and you can get more information by looking at your Apache logs.

If you do see logs there, then open up the web.log and search on [error] to see what the source of the error is. Often it is missing or incorrect database credentials.

c.f.:

Official Craft CMS Tutorial
Zen and the Art of Craft CMS Log File Reading
Setting up a New Craft CMS 3 Project


How do I redirect to a corresponding route when user switches languages?

This is a rather hacky workaround, but I have no idea what else you could do to handle it. What I do is to compose an array of "route objects" that basically mirror the routes set up in the CP. This array can then be compared to the URL segments (→ getSegments). Not nice but it works :)

{# Map the corresponding routes #}
{% set routes = [
    { en: 'news-events/tags', es: 'noticias-eventos/tags' },
    { en: 'news-events/categories', es: 'noticias-eventos/categorias' },
] %}

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

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

        {# ... Do entry stuff #}

    {# Not an entry page --> check the routes #}
    {% else %}

        {# Get URL segments #}
        {% set segments = craft.request.getSegments %}

        {# Set var before loop #}
        {% set noRoute = true %}

        {# Loop routes array #}
        {% for prop in routes %}

            {# Check if URL segments match a route #}
            {% if prop[craft.locale]|split('/') == segments %}

                {# Output link to the mapped route #}
                {{ craft.i18n.getLocaleById(locale).name }}

                {# Switch var value #}
                {% set noRoute = false %}

            {% endif %}

        {% endfor %}

        {# No route found --> output a link to the homepage #}
        {% if noRoute %}
            {{ craft.i18n.getLocaleById(locale).name }}
        {% endif %}

    {% endif %}

{% endfor %}


Excluding specific field value from search

The light switch value should be taken out of the search query and put into the entry query:

{% set query = 'title:"' ~ "myValue" ~ '"' %}
{% set results = craft.entries({
    section: querySections,
    search: query,
    excludeFromSearch: 'not 1',
    orderBy: 'score',
    }).limit(50) %}

Or slightly cleaner / Craft 3:

{% set query = 'title:"' ~ "myValue" ~ '"' %}
{% set entryQuery = craft.entries
    .section(querySections)
    .search(query)
    .excludeFromSearch('not 1')
    .orderBy('score')
    .limit(50)
%}

{% set entries = entryQuery.all() %}


Grouping by select - keep order of options

The group filter loops through the passed elements in the order that they are returned by your query and builds the groups array in the order that it encounters the values being grouped. So there’s no predictable way to control what order the array keys are ordered.

If you want to loop through all entries by dealStatus in a fixed order you could replace your for loop with:

{% for status in [‘InMarket’,’postBid’,’closing’,’closed’] %}
    {% if allDealsByStatus[status] is defined %}

        {% set entriesInStatus = allDealsByStatus[status] %}

        {# your list output code here #}

    {% endif %}
{% endfor %}


Nested Matrix functionality for one block type using Tags

I just tried to replicate your setup (in simplified form), because I thought this is in fact an interesting and creative approach
to do Matrix nesting that might come handy.

Here's my code that works great for me. I hope it helps, even though I actually don't see the difference to what you have?!

{# Go through our Main Matrix blocks #}
{% for block in entry.mainMatrix.type('mainRelationsBlock') %}

    {# Get the tags selected in the Main Matrix block #}
    {% set tagsToFind = block.mainTags %}

    {# Try filtering Matrix blocks of our Sub Matrix using `relatedTo` #}
    {% set relatedBlocks = entry.subMatrix.relatedTo({
        targetElement: tagsToFind
    }) %}

    {# Show them #}
    {% for relatedBlock in relatedBlocks %}
        <li>{{ relatedBlock.text }}</li>
    {% endfor %}

{% endfor %}


Check that the php ctype extension is installed or enabled.


List out all "Layout Tabs" in the frontend

Assuming you have an 'entry', this should work:
{% for tab in entry.getFieldLayout().getTabs() %}

{{ tab.name }}

                {% for field in tab.getFields() %}

{{ field.name }}

                {% endfor %}

{% endfor %}

if you don't need the fields then just:
{% for tab in entry.getFieldLayout.getTabs() %}

{{ tab.name }}

{% endfor %}


specifying section id manually while saving section

No you can't. Craft will throw an exception when you insert an id that does not exist into the form. Is there a certain reason for your question? Maybe we could provide help on that.


Is there a fieldtype in Craft like "Content Elements" or "Bloqs" for ExpressionEngine?

You should check out the Matrix fieldtype.


Adding cache headers to Nginx configuation file breaks the /admin area

Craft rewrites the location of those files using a query string, which is what's causing nginx to lose track of them. Using the try_files directive should force nginx to find and serve them properly.

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
  try_files $uri /index.php?$query_string;
  expires 7d;
  add_header Pragma "public";
  add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}


Updates on live server without using Control Panel

You probably need to chmod +x craft on the craft executable so it an execute: https://askubuntu.com/questions/443789/what-does-chmod-x-filename-do-and-how-do-i-use-it/443799


How can I search for entries that are enabled OR disabled?

I haven't tried this in php, but on the 'template' side there is an attribute called 'status' which you might try. I assume it would work in php as well.

$existing = craft()->elements->getCriteria($this->entry->elementType)->first(array(
    'someHandle' => 'someValue',
    'status' => null
));

Default is 'live'; other values would be 'live', 'pending', 'expired', 'disabled', and null. Here's the docs for craft.entries.status. Let us know if it works.


The safest way to edit core Craft files?

You should never edit the core files (i.e. anything below /app), because whatever changes you add might be overwritten any time Craft is updated – or even worse, your amendments might conflict with new features added in Craft updates to a different part of the codebase; crashing your entire site. Seriously, don't do it.

Whenever you need Craft to do something that it doesn't do out of the box, your options are:

– Installing an off-the-shelf plugin, of which there are many
– Writing a plugin yourself (which shouldn't be too hard, if you have PHP experience)
– Finding someone else to build your custom plugin
– Adding a feature request

If you do need to write a custom plugin, probably the most important thing to know about are hooks and events, which offer ways to hook into and act upon various parts of the Craft internals and request lifecycle.

Specifically, I believe your current use case could be easily solved by creating a small custom plugin with the defineAdditionalEntryTableAttributes hook.

Here's how that could look, assuming your custom property is named customProperty (the following would go into your plugin's primary class, e.g. myplugin/MyPluginPlugin.php):

public function defineAdditionalEntryTableAttributes()
{
    return array(
        'customProperty' => "Custom label",
    );
}

With the above, you'll be able to simply add your custom property to the relevant element indexes via the little cogwheel below your Sections, under Entries inside the CP.

If you need more control over how the custom property renders (for instance, if the property returns a non-String value, you want to wrap the property value in some HTML, or you need to account for the custom property not being set for all entries, etc), you can use the getEntryTableAttributeHtml hook to refine things:

public function getEntryTableAttributeHtml(EntryModel $entry, $attribute)
{
    if ($attribute == 'customProperty' && isset($entry->customProperty))
    {
        return ''.$entry->customProperty[0].'';
    }
}


How do I get just the first entry with a 'for' loop?

As you'll only ever be working with one entry I wouldn't bother with the for loop for the first part of your question. Just set a variable with your featured news article. Something like this (not tested though):

{% set featuredArticle = craft.entries.section('news').first() %}

{{ featuredArticle.title }}

{{ featuredArticle.postDate.format('F d, Y') }}

        {{ featuredArticle.body }}

    READ FULL STORY...

EDIT: Then for the second part of your question this other answer tells you how to exclude an Entry:

How can I exclude the current entry when I've structured my syntax like this?

So from the other article, you'd do:

{% set entries = craft.entries({
  section: 'news'
}).id('not ' ~ featuredArticle.id) %}


Prevent Asset Transforms from scaling Image past 100%

Yes.

getWidth will give you an image's width: {% set originalWidth = image.getWidth(false) %}. You want to apply the transform if desiredWidth is less than originalWidth. I would write a twig macro:

{% macro transform(image, desiredWidth) %}
  {% set originalWidth = image.getWidth(false) %}
  {% if desiredWidth < originalWidth %}
    {{ image.getUrl({mode: 'fit', width: desiredWidth}) }}
  {% else %}
    {{ image.getUrl() }}
  {% endif %}
{% endmacro %}

You could also do the same test, and then conditionally setTransform on the image.

If you define your transforms in the CP the macro would be like this:

{% macro transform(image, transformHandle) %}
  {% set originalWidth = image.getWidth(false) %}
  {% set transformedWidth = image.getWidth(transformHandle) %}
  {% if transformedWidth < originalWidth %}
    {{ image.getUrl(transformHandle) }}
  {% else %}
    {{ image.getUrl() }}
  {% endif %}
{% endmacro %}


Is it possible to create composite Primary Keys in Records?

It would appear not unfortunately.

Craft's BaseRecord (which a Record should inherit from) tries to uses the primaryKey() method call to help create the table, but assumes a single column name is returned, not an Array and so falls over on the isset call.

$pk = $this->primaryKey();

if (isset($columns[$pk]))
{
  $columns[$pk]['primaryKey'] = true;
  $addIdColumn = false;
}
else
{
  $addIdColumn = true;
}

I'm guessing it should work because the CActiveRecord (which the BaseRecord inherits from) states in it's comments for PrimaryKey:

@return mixed the primary key of the associated database table.

If the key is a composite one consisting of several columns, it should
return the array of the key column names.

EDIT: In the end I added the following to my Plugin file, and that seemed to do the trick:

public function onAfterInstall()
{
  craft()->db->createCommand()->dropColumn('myplugin_merchant_order', 'id');
  craft()->db->createCommand()->addPrimaryKey('myplugin_merchant_order', ['merchant_id', 'order_id']);
}

I also had to add this to my Record, to stop the validation failing because I'd removed the id column in the above step:

public function primaryKey()
{
    return null;
}


How do I store and retrieve elements for ElementSelectField? Getting error "Call to a member function getUiLabel() on array"

Well, I figured it out to an extent, I'm not sure why this works and I have a feeling it will break eventually, but here is my solution. Please let me know if there is a better one out there or something that is standard practice.

{{ forms.elementSelectField({
        label: "Products Allowed"|t('business-to-business'),
        instructions: "Leave blank if this voucher has no product limits",
        id: 'products',
        name: 'products',
        elementType: productElementType,
        selectionLabel: "Add Products"|t('business-to-business'),
        elements: (products is defined and products ? [products][0])
}) }}


I asked this in the issues for the plugin and got a very prompt reply, the solution offered works perfectly:

https://github.com/boboldehampsink/import/issues/15


Grouping entries by category - most efficient approach

One improvement I think could be made is to fetch only the ID's of your hotTubs entries at the start of your code. You're only using this to get the related categories and fetching ID's is faster than fetching the actual elements. The relatedTo parameter works perfectly with ID's. So that could speed up things.
You can drop the orderBy parameter also as this doesn't have any effect there.

{% set hotTubs = craft.entries()
  .section('newHotTubs')
  .ids()
%}


How can I use images from my live Craft Site when developing locally

You could set up your assets through Amazon S3 or another remote service then that wouldn't be a problem.

Alternatively you will need to download all the assets locally if you have relative paths /uploads/images/banners/banner1.jpg.

Though maybe another option is to set the path to include the domain then you can probably get the files from the server (so in your markup you would see the image would be linking to http://www.yousite.com/uploads/images/banners/banner1.jpg


How to limit sources for Entries field set up via migration

After getting some feedback from Craft support it turns out one has to use uid instead of id for this to work:

"sources" => ["section:" . $questionsSection->uid],

Since I had a lot of places in my migration where I needed to specify sources, I included a couple small functions:

/* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */

protected function _section_id($sectionHandle)
{
    return Craft::$app->sections->getSectionByHandle($sectionHandle)->uid;

} // _section_id()

/* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */

protected function _source($handle, $kind = 'section')
{
    $source = $kind . ':' . $this->_section_id($handle);
    return $source;

} // _source()

/* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */

You can then limit the entries field sources like so:

"source" => null,
"sources" => [
    $this->_source("sectionA"),
    $this->_source("sectionB"),
],

(Note that I'm additionally setting "source" => null as per a plugin-created migration I analyzed, but not sure if it's required.)


How to register a new System Message email

This will only register your message with Craft. To then send it you would do something like this:

Event::on(
    Elements::class,
    Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event) {
        if ($event->element instanceof \craft\elements\User) {
            $user = $event->element;
            if($event->isNew) {
                Craft::$app
                    ->getMailer()
                    ->composeFromKey('after_activate_user')
                    ->setTo($user)
                    ->send();
            }
        }
    }
);

This will listen for the EVENT_AFTER_SAVE_ELEMENT event, make sure it's a User being saved, check that it's a new user then send the message.


Yes it's absolutely possible, and available out of the box with craft.

In your public/index.php file you specify the different environments based on your server name.

With the environment set, inside your craft/config/db.php and craft/config/general.php files, you can create different configurations for each environment.

This article in the craft documentation goes over how to configure it. Let me know if you have any trouble, it's really just modifying those three files.

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


Can the Lightswitch field have a default 'on' setting?

For entries previously created, the lightswitch field will not be on even if you specified that as a field option. However, new entries should respect that field setting.

Are new entries not honoring your field settings?


I believe this link solves your issue.
https://docs.craftcms.com/v3/date-time-fields.html#settings


As mentioned in the comments, using a dynamic route is good method to create a date based uri (i.e. 'calendar/[year]-[month]'). See this answer for an example.

Adding 'category' into the route is a little more difficult, since there is no 'category' tag built into the dynamic route settings. However, you can use the wildcard * as part of the route for what would be the category (or anything else for that matter) — and then retrieve it using craft.request.segment method.

Dynamic route (which points to your 'calendar' template)

calendar/[*]/[year]-[month]

(note: using calendar/[slug]/[year]-[month] might also resolve to a category entry — don't know, but worth a try.)

Calendar template

{% set categorySlug = craft.request.segment(2) %}
{% set category = craft.category.slug(categorySlug).first %}
{% if year is defined and month is defined %}
    {% set startMonth = year ~ '-' ~ month ~ '-' ~ 1 %}
{% else %}
    {% set startMonth = now|date_modify("first day of this month") %}
{% endif %}
{% set nextMonth = startMonth|date_modify('+1 month')) %}
{% set previousMonth = startMonth|date_modify('-1 month')) %}

{% set entries = craft.entries.section('calendar').postDate('and', '>= ' ~ startMonth, '< ' ~ nextMonth).relatedTo(category) %}

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

    next month
    previous month

Advanced route method

If you want to be more specific in your route, then you can also set up an advanced route using named sub-patterns, which you can add to craft/config/routes.php, that will provide named variables to your template for 'category', 'year' and 'month'. Something like,

'calendar/(?P<category>\w+)/(?P<year>\d{4})/(?P<month>\d{2})' => 'calendar/_index',


How can I get field data for the current locale in a plugin?

You're pretty close... You'll need to do this in a Variable, not a Service.

If your method already exists in a Service, or if you'll need to access it via PHP as well, then you can keep it in the Service. In that case, you'll still need a Variable method, but it can simply be a wrapper for your existing Service method.


Is it a security risk to put Craft templates inside public root?

If you’re running Apache, you can put a .htaccess file in your templates/ folder with this in it:

Deny from all

and any HTTP traffic to that folder will be given an Apache 403 error.

Even better, you can put this in there:

# Send the request to Craft
RewriteEngine On
RewriteRule (.*) /index.php?p=$1 [QSA,L]

and the request will be redirected to Craft’s index.php file behind the scenes, the same way that would-be 404s are sent there. So even if you go to /templates/index.html, or any other URL that points to an actual file within your templates/ folder, it will end up as /index.php?p=templates/index.html, leaving Craft to handle the request, which will most likely result in a Craft-based 404.


Setting tab 'error' class for tab with error

I don't believe there is any 'built in code' you could use.

You have 2 options though.

You could either do this in twig by checking all fields in a tab and adding an error class to the tab:

{% set actionClasses = "" %}
{% if (sale.getErrors('discountAmount') or sale.getErrors('discountType')) %}
    {% set actionClasses = "error" %}
{% endif %}

{% set saleClasses = "" %}
{% if(sale.getErrors('name')) %}
    {% set saleClasses = "error" %}
{% endif %}

{% set tabs = {
    0: {'label':'Sale'|t,'url':'#sale','class': saleClasses},
    1: {'label':'Conditions'|t,'url':'#conditions'},
    2: {'label':'Actions'|t,'url':'#actions','class': actionClasses}
} %}

Or you could pre build the 'tabs' variable in the controller and add the errors there:

if ($variables['account']->hasErrors())
{
    // Add the 'error' class to any tabs that have errors
    $errors = $variables['account']->getErrors();
    $accountFields = array('username', 'firstName', 'lastName', 'email', 'password', 'newPassword', 'currentPassword', 'passwordResetRequired', 'preferredLocale');

    foreach ($errors as $attribute => $error)
    {
        if (isset($variables['tabs']['account']) && in_array($attribute, $accountFields))
        {
            $variables['tabs']['account']['class'] = 'error';
        }
        else if (isset($variables['tabs']['profile']))
        {
            $variables['tabs']['profile']['class'] = 'error';
        }
    }
}

Hope that helps.


Fetch entries with special characters in title

Have a look at DbHelper::parseParam docs:

  If the $value is a string, it will automatically be converted to an array, split on any commas within the string (via ArrayHelper::stringToArray()). If that is not desired behavior, you can escape the comma with a backslash before it.

To escape the comma and other characters treated as special in DbHelper::parseParam use the DbHelper::escapeParam helper:

$criteria->title = DbHelper::escapeParam("Title, with, commas");


Update Asset Indexes for new files in s3 not working

We ended up using this cli tool:
https://github.com/rsanchez/craft-cli

We still had to tweak the php memory limit in the php config: memory_limit 2048M

But eventually we managed to index 21.000+ images this way.


How do _you_ protect input against XSS? ("HtmlPurifier"?)

When dealing with XSS concerns, it's important to stay focused on the fact that this is a client-side issue... So in regards to Craft, Twig is the star of the show.

Fortunately, Twig takes measures by default to ensure that your output is safe. For example, any time you're outputting some HTML code via a Twig variable, you're required to add a raw filter to get the HTML to render properly. Otherwise, those special characters get encoded and simply rendered "as is" on the front-end. When you apply the raw filter to a Twig variable, you're essentially telling Twig that you trust whatever data may be coming out of that variable.

Here are a few other Twig filters which may help you out:

escape
striptags

Your question puts an emphasis on data input, which isn't typically where XSS issues are addressed. However, there are some things (as you noted) which can help you sort out incoming data.

Validating your data using Yii validation rules is a good start. And I believe the CHtmlPurifier can be useful to you as well. Skimming through the Yii documentation, I believe this helper method can be applied to input data:

$purifier = new \CHtmlPurifier();
$purifier->purify($html)

  http://www.yiiframework.com/doc/api/1.1/CHtmlPurifier

Simply apply that helper method to data as it's being stored in your Record, and that should make your data safe for future output.


List entries of documents in a section grouped by checkbox

Your assets variable is defined outside the entries loop so it is still referring to the page entry. If you move it inside the loop it should work as expected.

{% set entries = craft.entries.section('documentLibrary') %}
{% for entry in entries if entry.documentType.contains('Report') %}
    {% for asset in entry.documents %}
       {{ entry.title }}
    {% endfor %}
{% endfor %}

Rather than doing this manually however, you might also have a look at the group filter, which can group the entries array by document type.

{% set entries = craft.entries.section('documentLibrary').find() %}
{% set groupedEntries = entries|group('documentType') %}

{% for type, entriesByType in groupedEntries %}

{{ type }}

        {% for entry in entriesByType %}
            {% for asset in entry.documents %}
                {{ entry.title }}
            {% endfor %}
        {% endfor %}

{% endfor %}

Note: Also if each 'document' only contain one and only one 'asset' (i.e. pdf), then you can also get rid of the asset loop and just use {{ entry.document.first.url }}.


Is it possible to hook into image transforms?

Currently it’s not possible to hook into Craft’s own thumbnail/transform generation logic. Your best bet would be to write a plugin that independently adds the watermark.

You could give the plugin a Variable class that accepts the AssetFileModel object, grabs the image, stamps it with the watermark and saves it somewhere else, returning the URL to that watermarked image, or something like that.


Loop through entries with custom ordering, showing one from each category then start loop again

I'd suggest breaking your problem down into code which gathers the IDs of each of the types of entries first, then outputs them....roughly like this (very much untested!! - but should be enough to understand the approach):

{# Arrays to store the IDs of the entries as we find them #}
{% set noDateIDs = [] %}
{% set dateIDs = [] %}

{% for entry in craft.entries.section('heroes').order('date') %}

    {% if entry.date|length %}
        {% set dateIDs = dateIDs|merge([entry.id])} %}
        {# Or of course you could output the data you want here directly but I like to keep my building and output separate for clarity #}
    {% else %}
        {% set noDateIDs = noDateIDs|merge([entry.id])}  %}
    {% endif %}

{% endfor %}

{% set noDateIDsString = noDateIDs|join(', ') %}
{% set dateIDsString = dateIDs|join(', ')  %}

{# Now actually output the dated entries #}
{% for entry in craft.entries.section('heroes').id(noDateIDsString).find() %}

{{ entry.title }} - {{ entry.date|date("j") }}{{ entry.date|date("S") }} {{ entry.date|date("F") }} {{ entry.date|date("Y")}} - {% for category in entry.genre %}{{ category.title }}{% endfor %}

{% endfor %}

{# Output the undated ones ordered by postDate #}
{% for entry in craft.entries.section('heroes').id(dateIDsString).order('postDate') %}

{{ entry.title }}

{% endfor %}

This approach is very useful generally in Craft, and is documented really well here in 'Manipulating Craft's ElementCriteriaModel objects with Twig' by Jérôme Coupé of Webstoemp


help setting up web root to point to /web

You need to configure your webserver/virtualhost to point to the /web directory.

For apache you have DocumentRoot: your_disk_path/web

For nginx you have root: your_disk_path/web


Add or extend attributes (table column) to fields table

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

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


Is it possible to import the content of a rich text field into matrix using FeedMe without parsing reference tags to entries/assets?

After speaking with the always helpful Andrew Welch of https://nystudio107.com, I realize now that the answer to this is entry.myRichText.getRawContent() to output the exact information needed.


Image transform in inline background css not being generated

Try taking the apostrophes off your transform, e.g.

getUrl(storyMediaTransform)


How to display a flash message in a template

You can use the setFlash function in the userSession Service like this:

In your Controller:

craft()->userSession->setFlash('yourVariable', "Something happened yo!");

In your template (that the user gets redirected to):

{% set message = craft.session.getFlash('yourVariable') %}

After that just run an if-statement to see if the message is set or not.

EDIT:
In Craft 3 controller:

Craft::$app->session->setFlash('yourVariable', "Something happened yo!");

In template:

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


Can you host a Craft site on 1984 Hosting?

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.


Can’t run Craft CMS on my local machine, keep getting message "The Mcrypt extension is required"

Update:

As of Craft 2.7.0, Craft 2 can run on PHP 7.2.

You're probably trying to install Craft 2 using PHP 7.2 (which doesn't have mycrypt installed by default), which isn't supported (see here: https://docs.craftcms.com/v2/requirements.html).

Your options are to:

Use Craft 3, which supports PHP 7.2 and doesn't use mcrypt.
Install mcrypt on PHP 7.2, but you'll probably run into other issues as well.
Stay on Craft 2 and drop down to PHP 7.1.


Field type for selecting a section (channel / structure / single)?

You can do this with LJ DynamicFields. In the plugin docs is an example of how to create a dropdown that is a list of all sections.


Variable "entrySlug" does not exist Routing

If I'm not mistaken, I don't think setting up the route via the CP does the fancy advanced rule stuff described here. You'll therefore want to do that via the config/routes.php file with something like this:

'marketplace/<authorSlug:[^\/]+>/<entrySlug:{slug}>/edit' => ['template' => 'listings/_edit'],

Now authorSlug and entrySlug will be available for use in your listings/_edit.twig template...


Filter entries by Field value using a variable

Twig has an interpolation syntax (using #{} inside a double-quoted string) to accomplish this:

{% set location = block.locationVacancies %}
{% set entries = craft
    .entries
    .section('careers')
    .search("locationVacancies:#{location}")
    .all() %}

In addition, you can be more explicit about the values you’re searching for (and avoid any kind of sneaky search capabilities/side-effects exposed by using raw query input):

{% set location = block.locationVacancies %}
{% set entries = craft
    .entries
    .section('careers')
    .locationVacancies("*#{location}*")
    .all() %}

…or even using Twig object syntax…

{% set location = block.locationVacancies %}
{% set entries = craft.entries({
    section: 'careers',
    locationVacancies: "*#{location}*"
}).all() %}

(locationVacancies: location will also work, but disables partial matching)

  It should be noted: if you're looking to associate multiple explicit entries, you can also make the field within your (presumed) Matrix Block an Entries field, which establishes actual relationships in the database—accessing such a field (myBlock.myLocationEntriesField.all()) will return that list of Entries, exactly as set in the admin) If you just need a dynamic search param, what you have is a fine solution!


After migrating, I am getting this error for several of my buttons and menus on Craft 2.6

This error indicates that you don't have a matrix block, called header, setup in the CMS, but your template is expecting one.

The solution is to create a new matrix field;

settings > fields > new field.

The field type should be “matrix” and it's handle needs to be “header”.


Commerce: Remove tax adjuster from line item in plugin

There is a way to do this, obviously, it is worth noting that the code below is written to be easy to understand and could be improved. Also, it is worth noting that there are plenty of things to think about when implementing something like this.

Take careful consideration about how this will affect all parts of the e-commerce experience, whether that is carts, orders, adding to cart in the front end and cart management in the control panel.

The following code will remove a tax adjustment based on the SKU of the line item and the name of the tax adjustment, your criteria may obviously vary.

use craft\commerce\elements\Order;
use craft\commerce\Plugin;
use craft\events\ModelEvent;
// ...

Event::on(Order::class,
    Order::EVENT_AFTER_SAVE,
    function(ModelEvent $event) {
        $lineItems = $event->sender->getLineItems();
        $adjustments = $event->sender->getAdjustments();

        // No need to do anything if this is an order or there aren't any line items or adjustments
        if (empty($lineItems) || empty($adjustments) || $event->sender->isCompleted) {
            return;
        }

        // Figure out which line items we want to remove tax from
        $removeTaxFromLineItemIds = [];
        foreach ($lineItems as $lineItem) {
            if ($lineItem->getSku() == 'MY-EXAMPLE-SKU') {
                $removeTaxFromLineItemIds[] = $lineItem->id;
            }
        }

        if (empty($removeTaxFromLineItemIds) ) {
            return;
        }

        // Loop through adjustments and remove the tax adjustments for the line items we determined above
        $taxNameToRemove = 'My Tax';
        foreach ($adjustments as $key => $adjustment) {
            if (in_array($adjustment->lineItemId, $removeTaxFromLineItemIds) && $adjustment->type === Tax::ADJUSTMENT_TYPE && $adjustment->name == $taxNameToRemove) {
                unset($adjustments[$key]);
                Plugin::getInstance()->getOrderAdjustments()->deleteOrderAdjustmentByAdjustmentId($adjustment->id);
            }
        }

        $event->sender->setAdjustments($adjustments);
    }
);

This code can be used inside a custom plugin or module.

Hope this helps.


Live Preview is jumping to top of page on edit

I have also noticed this happening, but the Craft Stack Exchange is not the best place to post about potential bugs/issues.

It might be worth submitting a bug report to support@pixelandtonic.com as they are best suited to take things from here!


I have fixed that problem. I have changed timezone settings on the Control Panel. Actually I have to use europe/ist but this timezone give that problem. So I changed to europe/kirov and my problem was fixed.


Output postDate in a different language than CP

It looks like you need Craft Pro and even then it's not possible
to have the CP in a language that is not installed as a front-end locale.

The (new) defaultCpLanguage setting doesn't change this. See Brad's
answers here:
Change system language +
German locale & English CP language resulting in disappeared entries

But to help you with your date problem. It is possible to access most data from
craft/app/framework/i18n/data/ via craft.i18n methods.

{% macro dateFormat(date, locale) %}
    {% set localeData = craft.i18n.getLocaleData(locale|default('de')) %}
    {{
        localeData.getWeekdayName(date|date('w')) ~ ', ' ~
        date|date('j ') ~
        localeData.getMonthName(date|date('m')) ~
        date|date(' Y')
    }}
{% endmacro %}
{% import _self as macros %}

{% for locale in ['en', 'es', 'fr', 'de', 'ru', 'nl', 'no'] %}
    <li>{{ macros.dateFormat(now, locale) }}</li>
{% endfor %}


How can I extend admincp to show all related category not only the first one on the AdminCP list view?

You can use the getTableAttributesForSource event

Event::on(
    Entry::class,
    Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,
    function(SetElementTableAttributeHtmlEvent $event) {
    // field: + your field id, you can as well grab all Fields of type
    // BaseRelationField and collect those ids in an array to get all
    if ($event->attribute === 'field:2') {
        /** @var Entry $entry */
        $entry = $event->sender;

        // just a quick example to fetch the titles for all related fields
        $event->html = implode(', ', $entry->getFieldValue('relation')->select('title')->column());

        // Prevent other event listeners from getting invoked
        $event->handled = true;
    }
});

This is the function that renders the usual table html

public function getTableAttributeHtml($value, ElementInterface $element): string
{
    if ($value instanceof ElementQueryInterface) {
        $element = $this->_all($value)->one();
    } else {
        $element = $value[0] ?? null;
    }

    if ($element) {
        return Craft::$app->getView()->renderTemplate('_elements/element', [
            'element' => $element
        ]);
    }

    return '';
}


Adding description and other information to channels

I have a channel of index pages, where each entry in the index page channel serves as the index page for some channel. I use ljdynamic fields and have a 'chanel' field which is a dropdown to select the channel. Description and etc. could be other fields in this index page channel.


what's the steps can i follow to develop module for send notification from CMS OP to windows phone application?

An incredibly broad question deserves an incredibly broad answer... You'll need to build a plugin:

  http://buildwithcraft.com/docs/plugins/introduction

(Apologies for the snarkiness)


Plugin development: how can I check if user has the permissions to delete only his own assets?

Thanks to @RobinSchambach advices, I was able to find a safe solution to handle this permission problematic.

This is possible using two main addings:

Register a new custom permission from the plugin

This prevents user from be able to access other users assets

Add a custom User field on the assets to assign ownership ;

Using this we can verify that it was uploaded from user requesting the file deletion

In the plugin Service:

public function linkUserToAssets($assets = [])
{
    $currentUser = Craft::$app->getUser()->getIdentity();
    if ($currentUser && Craft::$app->request->getIsSiteRequest()
        && Craft::$app->request->getIsPost()) {
        foreach ($assets->all() as $asset) {
            if (isset($asset->id) && !empty($asset->id)) {
                $asset = Craft::$app->assets->getAssetById($asset->id);
                if (isset($asset->assetsOwner)) {
                    $asset->assetsOwner = [$currentUser->id];
                    Craft::$app->elements->saveElement($asset);
                }
            }
        }
    }
}

This adds a function to call before each entry is saved, to assign the user's ownership on entry's assets using the assetsOwner custom field.

In the plugin Module:

Event::on(
    UserPermissions::class,
    UserPermissions::EVENT_REGISTER_PERMISSIONS,
    function(RegisterUserPermissionsEvent $event) {
        $event->permissions['User'] = [
            'deleteOwnAssets' => [
                'label' => 'Delete Own Assets'
            ],
        ];
    }
);

This adds a custom permission in the CP which should be added to group of users who will perform this action.

In the plugin Controller:

public function actionDeleteAsset()
{
    $currentUser = Craft::$app->getUser()->getIdentity();
    if ($currentUser) {
        $request = Craft::$app->getRequest();
        $assetId = $request->getBodyParam('assetId');
        $asset = Craft::$app->getAssets()->getAssetById($assetId);

        if ($asset->assetsOwner[0]->id !== $currentUser->id || !Craft::$app->user->checkPermission('deleteOwnAssets')) {
            return $this->asErrorJson(Craft::t('app', self::TEXT_PERMISSION_REQUIRED));
        }
    }
}

This deletes requested assets if the current user was the owner of the asset (using assetsOwner custom field) and has the required custom permission (in this case, deleteOwnAssets).


I would use macros. A Twig macro is basically a function, that can take arguments and render HTML.

Macros can be defined inline (i.e. in the same template where it's used) or in a separate file (better if you're writing a generic macro that'll possibly be used in several different templates).

Here's how your template could look, using macros:

{% macro courseName(entry) %}
    {{ entry.deptCode ~ ' ' ~ entry.courseNumber ~ ': ' ~ entry.title }}
{% endmacro %}

{% macro msuLink(entry) %}
    {{ 'https://reg.msu.edu/Courses/Request.aspx?SubjectCode=' ~
entry.deptCode ~ '&CourseNumber=' ~ entry.courseNumber ~ '#Results' }}
{% endmacro %}

{% import _self as helpers %}

Required Courses

    {% for entry in craft.entries.section('courses').type('safsCourse') %}

{{ helpers.courseName(entry) }}

    {% endfor %}

Elective Courses

At least one agricultural science course

    {% for entry in craft.entries.relatedTo(65) %}

{{ helpers.courseName(entry) }}

    {% endfor %}

...

If you're wondering about the {% import _self as helpers %} directive below the actual macros, the {% import %} tag is neccessary to actually expose your macros to your template (even if the macros are declared in the same file), and the "helpers" part is just a contextual variable that could be named anything you want (as semantic as possible is always a good thing).


The first step to diagnose would be to determine where the bottleneck is.

If you enable devMode, you'll see database profiling information in your browser's console, including the SQL executed for each query along with the total number of queries executed.

Those queries will be ordered by the slowest performing ones at the top.  If there are multiple, slow performing queries that are taking up the majority of the time it takes to load the page, then there is likely something we could do in Craft to optimize performance in your scenario and you should contact us at support@buildwithcraft.com and send along a database dump so we can try to reproduce.

If the database queries look like they are not the issue, then the next likely culprit is disc access times.  If these folders/files are in the cloud (S3, Rackspace, etc.), or you're using NFS for your file system, then those could be slowing down the request as well.


How to handle payments on a multicurrency website using Mollie gateway?

We found a quickfix by editing the Commerce_PaymentsService.php file in craft/plugins/services/.

We changed to following:

$request = [
    'amount'               => $transaction->paymentAmount,
    'currency'             => $transaction->paymentCurrency,
    'transactionId'        => $transaction->id,
    'description'          => Craft::t('Order').' #'.$transaction->orderId,
    'clientIp'             => craft()->request->getIpAddress(),
    'transactionReference' => $transaction->hash,
    'returnUrl'            => UrlHelper::getActionUrl('commerce/payments/completePayment', ['commerceTransactionId' => $transaction->id, 'commerceTransactionHash' => $transaction->hash]),
    'cancelUrl'            => UrlHelper::getSiteUrl($transaction->order->cancelUrl),
];

To:

$request = [
    'amount'               => $transaction->amount,
    'currency'             => $transaction->currency,
    'transactionId'        => $transaction->id,
    'description'          => Craft::t('Order').' #'.$transaction->orderId,
    'clientIp'             => craft()->request->getIpAddress(),
    'transactionReference' => $transaction->hash,
    'returnUrl'            => UrlHelper::getActionUrl('commerce/payments/completePayment', ['commerceTransactionId' => $transaction->id, 'commerceTransactionHash' => $transaction->hash]),
    'cancelUrl'            => UrlHelper::getSiteUrl($transaction->order->cancelUrl),
];

This way the request sends the amount based on the base currency (in our case EUR) to Mollie.

This seems a bit hacky to us so maybe an exception for the Mollie gateway can be added to future updates to Craft Commerce.


After some searching, I decided to move my src/ folder into the web/ folder, since Craft seems to be looking only there and not at anything above that directory. Then, my CSS links were updated to relative paths like this: src/css/typeplate.css. And that worked.


Is it possible to translate the name of a field in the CP?

Static text on the front-end and Craft CP translations are handled through your translation files.

All you need to do is name your fields without the translate filter and make sure they have suitable translation arrays in your translation files.

It's also worth mentioning you will need Craft Pro to take advantage of localisation and translation features.

Here is an example to get you started, this will be added to the translation file for your German locale:

<?php

return array(
    'Surname' => 'Nachname',
);


Check if a table field’s row has a value

Something like this should do what you're looking for and will work for any number of rows:

{% set reallyEmpty = true %}

{% if entry.tableField | length %}
    {# Since you've got a default row set, we're guaranteed that [0] will be set #}
    {% for column in entry.tableField[0] %}
        {% if column|length %}
            {% set reallyEmpty = false %}
        {% endif %}
    {% endfor %}
{% endif %}

{% if reallyEmpty %}
    It's really empty.
{% else %}
    It's not empty.
{% endif %}


Authorize.net not connecting in Craft Commerce?

That error is from the cart service when trying to set the payment method ID on the cart during payment.

There are 2 possible reasons the error would appear:

1) The payment ID you are submitting is wrong

<input type="hidden" name="paymentMethodId" value="theIDhere"/>

2) In the settings (for a correctly submitted payment ID), the "Enabled to select on front-end" setting has been turned off. Screenshot: http://jmp.sh/AxoM1tI You need this on, to allow customers to use the method on checkout.

Hope that helps.


Plugin not updating in the plugin store from changelog updates

The reason the Plugin Store hasn't picked up the 2.0.1 release is that you've got 3 different 2.0.1 tags in the repo.

Usually, that's not a problem as it will just pick the first one by date.

In this case, if you browse the first "V2.0.1" tag, you'll see that its composer.json file has a listed version of 2.0.0, which is a version mismatch, so the Plugin Store will ignore it. https://github.com/hillholliday/Craft-User-Manual/blob/00e2808e328e5bfe793fd343a59b5d2445d84d27/composer.json#L5

The reasons 2.0.2 never got picked up is because there is no 2.0.2 tag in the repo.


This is down to lacking documentation. Before/after are supposed to take  "DateTime|string" as a parameter in the ElementQuery. The format is not documented.

Use "Y-m-d H:i:s"

{% set start = "2 months ago"|date("Y-m-d H:i:s") %}

Behind the scenes in building the query the CMS was replacing any dates I sent through with "2017-12-31 11:00:00" (no idea where this came from). After realising this I spelled out the before/after in format "Y-m-d H:i:s" and the dates started working.

Pixel and Tonic - Can you please update the docs to include the available date formats - or at least throw an error if it's not valid.


How to query an entry by a custom field in Craft 3

Your where clause is actually a query based where so you have to select the database fields instead of the field handles. When you want to do it with where you have to make it like that

$country  = Entry::find()->section('countries')->where([
    'content.field_code'    => ['like', 'CA']
])->all();

This is the correct documentation right now.

Edit: you might want to call the getRawSql() function in order to see the query and all selected rows. When you use your code you'll see why your sql throws an exception

Edit2:
You don't need to read the following part, these are just some explanations to the content.field_codepart - if you are interested in Craft go ahead if not skip it.

Not sure if you know that but Craft adds the prefix field_ to every fieldhandle in the content table (the table where Craft stores your entire content). So for every field you create the database includes a column field_+$field->handle that's why you have to include the field_ in before your handle in the query above.

However if you are going to change that prefix for any reasons you could use Craft::$app->getContent()->fieldColumnPrefix in order to fetch the current column prefix. I doubt many people will do this but I wanted to make sure you know it.

And the ElementQuery (the class you actually call when you do Entry::find() contains the following code

/**
 * @var string|null The content table that will be joined by this query.
 */
public $contentTable = '{{%content}}';

This is hard coded so only the developers from craft can make really deep changes here (unless you overwrite the structure in Craft)

So in the end: craft left joins the content table and selects all columns. That's why you have to use content.field_+$fieldHandle


You will need to change the version in your composer.json file to the version you want (guessing 4.3.2 if you want the last version) then run composer update on the command line.


Plugin UXD is intended to help you "design" one or more control panel pages in Craft. It is not a complete style guide but provides a set of typography, field and table elements that enables you to quickly design and develop your plugin control panel pages.

As the developer, I'll gladly accept pull requests to make it more complete.