Display a user's selected checkbox options for a category field type in a front-end Edit Profile form

Try something like this (completely untested):

{# Grab all categories in the group and set variable. #}
{% set categories = craft.categories.group('designCategories') %}

{# Grab the categories Ids that the user already selected #}
{% set userOptionIds = user.designOptions.limit(null).ids() %}

{# Display all category checkboxes in the form, with the logged in user's saved selections already checked.#}
{% for category in categories %}
    <input type="checkbox" id="designOptions" name="fields[designsOptions][]" {% if category.id in userOptionIds %}checked{% endif %} value=" {{ category.id }}">
        {{ category.title }}
    </input>
{% endfor %}


You can see the changes made to static translations in Craft 3 in the Craft 3 upgrade docs here:

https://docs.craftcms.com/v3/changes-in-craft-3.html#static-translation-files

In your case, craft/translations/en_gb.php would need to change to craft/translations/en-GB/site.php.


Redactor pagebreak plugin and linking to pages

The example is the docs you're referring to will simple output the first "page" of the Rich Text field and if there are more pages show a "Continue Reading" link that loads the full entry.

For the functionality you're looking for you'd have to do something like this (completely untested):

{% set totalPages = entry.body.getTotalPages() %}

{% for i in 1..totalPages %}
    {{ i }}
{% endfor %}

Then your template would grab the page from the querystring and display it  using entry.body.getPage(page).


Craft's relatedTo takes a model, an ID, or an array of either of these. So if you're passing '171,172,179' It's probably coming through as a string and only reading the first ID.

Try making it an array and looping through the values:

{% set catPars = craft.request.getParam('cats')|split(',') %}
{% set related = ['and'] %}
{% for catPar in catPars %}
    {% set related = related|merge([{targetElement: catPar}]) %}
{% endfor %}

{% set swatches = craft.entries({ section: 'swatches', relatedTo: related }) %}

Without knowing your setup I don't know if it's actually targetElement or sourceElement. You can also pass in the field name as well if you want to get more specific. See the documentation linked above for the definitions of all of those.


While not a direct answer to your question, as of the next (post 2.4.2702) Craft release, Craft will now return a validation error on the UserModel if a non-image is uploaded for the user's profile photo.


See below for some twig code to get you started, I omitted the actual HTML output for the individual items to better keep the overview.

Whats happening is, you get all (or a reasonable big amount amount) of your entries, and start looping over them.

The first time, you open a div that will contain 6 items. Afterwards, each time the loop index can be divised by 6 (aka, 6 more items have been looped over) you close the container div & open a new one.

Than finally after the last iteration, you close the container div again.

Making the 6 items hide or display you can do with Javascript. Let me know if you need extra pointers on that.

{% for entry in craft.entries.section('alumni').order('RAND()')}
    {% if loop.first %}

    {% endif %}

    {# Build item output here #}

    {% if loop.index is divisible by(6) %}

    {% endif %}

    {% if loop.last %}

    {% endif %}
{% endfor %}

Info on divisible by


Elements API - How to order / limit the output with an asset field of an entry

You could use the relatedTo parameter (docs) to query recipes related to the entry that has your Entries field on. Something like:

return [
    'elementType' => Entry::class,
    'criteria' => [
        'section' => 'recipes',
        'relatedTo' => ['sourceElement' => $entryWithEntriesField]
],

Where $entryWithEntriesField is the entry (or id of the entry) that contains the entry selection field would return the list of recipes attached to that entry.


I would construct an array of the category slugs outside of your childCategories loop (using twig's merge filter:

{% set queryCatSlugs = [] %}
{% for category in query %}
  {% set queryCatSlugs = queryCatSlugs|merge([category.slug]) %}
{% endfor %}

Then your childCategories loop can use twig's containment operator (in) for the test:

{% for childCategory in childCategories %}
  {% if childCategory.slug in queryCatSlugs %}
    ... matches ...
  {% endif %}
{% endfor %}


A section can't have a handle that starts with a number, but there is nothing stopping you from using fiveminutes for the section's handle and setting the section's URL Format to 5minutes/{slug}.


Bad Request: Post Request Required when saving hyperlink in specific redactor field

From 'p' => '500.shtml' it looks like your server is configured to redirect to a 500.shtml file whenever it encounters an error, which is probably confusing Craft routing and obscuring the real error message.

I'd check to see if you have Suhosin or ModSecurity installed on the server as it's possible the link you're trying to add it tripping up one of their rules.


Open the php.ini file in your favorite text editor.
Search for max_execution_time. It'll probably be set to something like 30 or 60.
Change it to 120 and save the file.
You'll likely need to restart your web server before the change takes affect.


GraphQL: Prevent users seeing entries authored by other users

You can do this using a custom module that adds an authorId condition to element queries, for graphql/api requests.

use Craft;
use craft\elements\db\EntryQuery;
use yii\base\Event;
use yii\web\ForbiddenHttpException;

// ...

// Is this a GraphQL request?
if (Craft::$app->request->getActionSegments() == ['graphql', 'api']) {
    Event::on(EntryQuery::class, EntryQuery::EVENT_BEFORE_PREPARE, function(Event $event) {
        // Get the current user
        $user = Craft::$app->user->identity;

        // If no one is logged in, return a 403 error
        if (!$user) {
            throw new ForbiddenHttpException();
        }

        // Only Editors are allowed to see everything
        if (!$user->isInGroup('editors')) {
            /** @var EntryQuery $query */
            $query = $event->sender;
            $query->subQuery->andWhere(['authorId' => $user->id]);
        }
    });
}

Note: Since the results will start changing for the same element query depending on who is logged in, you’ll also need to disable the enableGraphQlCaching config setting.


Craft 3 Upload To Bluehost - Index.php outside root issue

Without getting too much into it, i feel you need to look at a symbolic link for public_html to the web folder (if you have linux server):

https://www.shellhacks.com/symlink-create-symbolic-link-linux/

Or change .htaccess file:

https://www.expression-web-tutorials.com/bluehost-main-domain-sub-folder.html


Use alias for site url based on root url defined as env var?

Good practice imo, it's what I do as well. Values come from the .env vars, and for things that are URLs or paths, I make aliases out of them to take advantage of what you're showing above.

This cannot cause any kind of issue like @web -- the only thing wrong with @web is that the host name is computed dynamically, potentially from untrusted browser data.

You're not doing that here, you are explicitly providing the host name, so it's totally fine. You could even do:

'aliases' => [
        '@web' => getenv('ROOT_URL'),
    ],

...to redefine the dynamically generated @web alias to something that is from a static value for the URL.


Latency issues on local development server

In the end I resolved my problem - which was unfortunately not related to craft at all. For unknown reasons there it was just quite evident visible.

Facts:
I'm running MAMP on a local OSX (Yosemite) setup. My craft website is running on a virtual domain pointing to localhost.
PHP 5.4
Mysql 5.x
Craft 2.3.26 Pro version

Issue:
Long latency (~10s) when editing an entry/adding stuff.

Solution:
In the end it was related to OSX issues with resolving a vhost address and resulting in loopbacks. A detailed description of the issue und how to resolve it can be found on stackoverflow.


How can I pass variables to email's template onBeforeSendEmail

I don't know if this is the same kind of thing you are looking for, but I think it's close.

I created a plugin that handles a contact form submission. When the user fills out the form, an email is sent to me & the person who filled out the form. I'm not listening to onBeforeSendEmail, but rather listening for a save event that I call via controller.

I told Craft that I needed a settings area in my plugin, then I created a textarea where I could manage the email that was sent to the user(s). This is what that looks like:

Hi {{firstName}} &mdash; thank you for reaching out to us!
We wanted to drop you a quick note that we've received your information and we'll be in touch very soon!

Regards,
The friendly folks at this website

To get {{firstName}} to use the value that were entered in the form, I used this in my plugin's service file.

That way it would read "Hi Steve - thank you for..."

MyPluginService.php

...
$email = new EmailModel();
$email->fromEmail = $emailSettings['emailAddress']; // set in CP
$email->replyTo = $emailSettings['emailAddress'];   // set in CP
$email->sender = $emailSettings['emailAddress'];    // set in CP
$email->fromName = $emailSettings['senderName'];    // set in CP
$email->toEmail = $contact->email;
$email->subject = $settings->guestSubject;
$email->body = craft()->templates->renderString($settings->welcomeEmailMessage, array('firstName' => $contact->firstName));

if (craft()->email->sendEmail($email)) {
    return true;
}
....

It's the craft()->templates->renderString() part that lets me hook into my plugin to set the variable values.

Hope this helps!


I'd say that due to the level of nested that you have going on, this is probably as compact of code as you can get out of the box. From an efficiency standpoint, you are only looping through the loop once, so I can't imagine there being anything more efficient.

If you're wanting to minimize the amount of logic in your template, then you can create a plugin and utilize template variables that would accept the matrix content as a parameter. Logic would be handled with PHP and could return an associative array of properties (specialWin, specialNominations, normalWin, normalNominations). So you'd end up with something like this:

{% set matrixData = craft.myPlugin.myPluginVariableMethod( entry.matrixloop ) %}
{# Debug Information #}
{#
<p> Special win: {{ matrixData.specialWin }} </p>
<p> Special Nominations: {{ matrixData.specialNominations }} </p>

<p> Normal Win: {{ matrixData.normalWin }} </p>
<p> Normal Nomination: {{ matrixData.normalNominations }} </p>

{{ entry.matrixloop | length }}

Personally, I'd go with the plugin route just to keep heavy logic out of the templates. It's nice that you can do that type of logic via twig if you want, but it also muddles things up a bit.


CraftCMS > UserSessionService should be compatible with CWebUser

It's a known issue you can safely ignore on Craft 2, that's been resolved for Craft 3.

PHP 7.0 (or maybe it was 7.1) changed the way that particular error was reported from E_STRICT (which Craft 2 is suppressing) to E_WARNING, which Craft 2 isn't suppressing, so now it pops up on latter versions of PHP.


How do you password protect a site in progress?

Front-end user features are only available in the Pro edition of Craft.

Seems like the easiest thing to do would be to use .htaccess password protection for the site.


I'm assuming you're using a multi-environment config.  From wherever your plugin is bootstrapping yiic, you need to manually set the CRAFT_ENVIRONMENT PHP constant to the environment you want yiic to load in the config files.


"Custom" validation for plugin settings page

It sounds like you're on the right track. You could create a custom validator, as detailed here.

<?php namespace Craft;

use Carbon\Carbon;

class MyPlugin_ExampleModel extends BaseModel
{
    protected function defineAttributes()
    {
        return [
            'startDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '<= endDate',
            ],
            'endDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '>= startDate',
            ],
        ];
    }

    public function rules()
    {
        $rules = parent::rules();

        $rules[] = ['startDate', 'validateFutureDate'];
        $rules[] = ['endDate', 'validateFutureDate'];

        return $rules;
    }

    public function validateFutureDate($attribute)
    {
        $value = $this->$attribute;

        if ($value && Carbon::now()->gte($value)) {
            $message = Craft::t("Date must be in the future");
            $this->addError($attribute, $message);
        }
    }
}

You can also extract the validation into a separate class, which would make it easier to test (details are in the aforementioned article).

Caveats and disclaimers

This code is completely untested. In particular, I'm not sure whether the date comparison will work with the attribute value as-is. You'll probably also want to check what happens to the custom validation if the value contains an invalid date-time string.


Apart from reading the docs on plugin development, I would suggest checking out a plugin called Business Logic, which provides a plugin template for creating project specific business logic, with a basic controller, service, and variables file already set up, and doc blocks which explain what the various components do.

For just printing a string I would look into creating a custom variable in your plugins 'variable' file. If the method is more complicated then you can use your variable as a wrapper to call one your service methods defined in your plugin's 'service' file. Here is an example variables file, with a call to a service method:

<?php namespace Craft;

class MypluginVariable
{
    // return the result directly
    public function exampleVariable()
    {
        return 'Anything you want!';
    }
    // call a service method and return the result
    public function exampleServiceMethodWrapper($value)
    {
        return craft()->myPlugin->myServiceMethod($value);
    }

}

You could call these from your template using {{ craft.myplugin.exampleVariable }} and {{ craft.myplugin.exampleServiceMethodWrapper('customValue') }}. These are assuming you want to just print the result of course.

The contactForm plugin that you are looking at is interacting with the plugin through the hidden form field <input type="hidden" name="action" value="contactForm/sendMessage"> which directs craft to submit the form to the contactForm's actionSendMessage() method defined in the plugin's 'controller' file. See controller docs for more info.

Fyi {{ getCsrfInput() }} is a native craft method so won't be in the plugin.


You can select elements by class and give your html elements custom data attributes.

When this is your clickable html element with the corresponding div

<button data-id="dimsTarget4" class="myButton">

Your jquery could be

$('.myButton').click(function(){
    var containerId = $(this).data('id');
    $('.myContainer').removeClass( "is-active" );
    $('#'+containerId).addClass( "is-active" );
})

And that's basically it. You'll remove the class from all your divs and add it to the one specified in your data-id attribute.

You won't need any twig elements in your JavaScript (which is much better) and define everything in your twig template. That way your Javascript will behave independently. When you change your html you won't need to change your Javascript that much and you can reuse the code

Note: I just used the button as an example. You can insert whatever class name or html element you like. Since you didn't mention the structure of your html I decided to use a button


How to loop through category group and identify those related to entry

Your solution looks like it's almost there, but it would be making a lot of DB queries as Craft will be querying the database for each category. You can give Craft all the help you can with something like this.

{# First, retrieve all of your events categories #}
{% set cats = craft.categories.group('events').find() %}

{# Get the IDs of all categories related to this entry #}
{% set relatedCats = craft.categories.group('events').relatedTo({sourceElement: entry}).ids() %}

{# Test if the current category ID is in the array of related category IDs #}
{% for cat in cats %}
    {{ cat.title }}
{% endfor %}


Do structures exist without any page behind it?

No, you have to design a template for it. To make that template available under mysite.dev/lunch-menu you have multiple options.

The easiest way to do it is to simply save the template as /lunch-menu/index.html.

Another pretty common option is to use a Single section for your menu's Structure section index page. This is not very complicate to set up and because your "Lunch menu" now got it's own entry type, you can add custom fields to it. That's a good thing to have if you need other content on that lunch menu's index page besides the actual lists.

You could also create another structure (e.g. named "Pages") and make you Lunch menu structure's index page an entry of that other structure. Besides index pages, like the "Lunch menu" index or a "News" index for example, you could also add entries like "About" or "Contact" to that structure. One advantage of this approach is that you have all your pages (indexes and single content) in one structure and you can create your site navigation out of it.


Figured it out by debugging getSiteUrl in UrlHelper.

Setting siteUrl like 'siteUrl' => strtolower((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https://' : 'http://') . $_SERVER['SERVER_NAME']) is fine for browser requests, but $_SERVER['SERVER_NAME'] isn't available when running a console command.

The scheme is set correctly and since we have addTrailingSlashesToUrls set to false, the result became http:/.

Fixed for now by hard-coding siteUrl in our general.php for each environment.


AFAIK, there’s no current first-party policy enforcements, but there is this plugin we’ve used in the past to make sure passwords aren’t easily guessed or previously pwned. I would give it a go in the meantime.


Is it possible to execute a custom function on the entry crud methods?

You'd have to create a plugin but you could listen for the entries.saveEntry event that is noted here: http://buildwithcraft.com/docs/plugins/hooks-and-events

Then lookup the value, run validation and even return a custom error message if things were not saved correctly.

Hope this helps.


Try this:

$queryAllUsers_email = User::find()
    ->email($new_email)
    ->anyStatus()
    ->all();

It's likely the email address you're searching for is for a user that isn't activated yet or suspended, etc.

Using anyStatus will search for the user regardless of their status.


Can I get the value of an environment variable in routes.php (or other config files)?

I think you'll just need to do something like this in your routes.php file:

$general = require __DIR__.'/general.php';

return array(
    'foo' => $general['environmentVariables']['bar'],
);


Adding Code Mirror to a Redactor field is a bad idea.

The entire point of a WYSIWYG field is to allow a content editor to easily format text to be displayed on the front-end. Conversely, the entire point of Code Mirror is to colorize a snippet of code. It's hard to imagine a use-case where you'd want to colorize the value of your WYSIWYG.

Instead, I'd recommend using a plugin like Ace Freely to store code snippets. This will allow you to easily view your code snippet in the control panel, without giving it unnecessary paragraph tags and awkward spacing.

You can then apply Code Mirror on the front-end to render a colorized version of that code snippet.


Twig replace filter - use part of regex match

Craft's replace filter will just use PHP's preg_replace method behind the scenes if it detects that a regular expression has been passed in.

It sounds like you're looking for the PHP preg_match method, which isn't available natively.

There was a plugin that added support for this in Craft 2, but I don't think it's been ported to Craft 3. You might be able to use that as a starting point if you'd like to port it, though.


How can I add headings using the Rich Text field

You can modify Craft's default Redactor configs stored in craft/config/redactor or add custom config files to this directory. Then select the config of choice for each rich text field individually in the field settings.

To use "block styles" in the editor, add the formatting button to the toolbar with this config:

{
    buttons: ['formatting', 'bold', 'italic']
}

You can also modify the formatting dropdown, if you want to restrict the block styles available to your client:

{
    formattingTags: ['p', 'h2', 'h3', 'h4']
}

.

Edit:

Just noticed that you already have the button in your toolbar, it's the second one from the left :D


Making multiple pages different with the same template

You could try creating a different entry type for your "hello" section.

For example, I am building a site for a restaurant. The "food" section is a structure. Each entree is the same template, each "category" uses the same section, but a different entry type. That way the admin only has to click "new entry", then choose either "entree" or "category" as the entry type.

Each category gives me the titles, "sandwiches" "burgers" etc, then my entree type is the actual food item.

Depending on what they pick, input fields will be different, however the markup on the page remains the same.


Yes, you can do something like that. I built something very similar a few months ago where I checked for a query parameter in the URL when the page loaded, created a cookie with it using the Cookies plugin so I could access it in twig, then appended that query parameter to a donation button on other pages.

Cookies: https://plugins.craftcms.com/cookies

You also need to check if the parameter has changed or disappeared, and update or replace your cookie value accordingly. Some of the code I used is below.

_layout.twig:

{# User Tracking #}
    {% if craft.app.request.getParam('s_src')|length %}
        {# If a user lands on the site with s_src in the URL, set a variable to track them throughout the site #}
        {% set s_src = craft.app.request.getParam('s_src') %}

        {# Use that variable to set a cookie, which will track them between pages #}

    {% else %}
        {# If there isn't an s_src param in the URL, clear the variable, but still define it so Craft doesn't crash #}
        {% set s_src = '' %}
    {% endif %}

content block:

{# If there's an s_src param in the URL, use that. If there isn't, check for the cookie and use that. If there isn't one, use the defaultSessionVariable #}
{{ block.button.text }}

If you're in the UK, Europe or California, you'll need to comply with the GDPR / CCPA legislation on cookies.


Paginate search results after combining sections in Craft 3

I doubt this is possible in Twig by default because you have two different Element types, thus you'll need to different instances of the ElementQuery to populate all models correctly. I think you'll need to create your own pagination. That being said Element::find()->all() will throw an error

  Cannot instantiate abstract class craft\base\Element

Thus you'll have to Query for your elements in your own

// get all possible element ids
$sectionId = X;
$query = (new Query())
    ->select('elements.id')
    ->from('{{%elements}}')
    ->leftJoin('{{%elements_sites}}', 'elements_sites.elementId = elements.id')
    ->leftJoin('{{%entries}}', 'entries.id = elements.id')
    ->where(new OrCondition([
        ['=', 'entries.sectionId', $sectionId], <-- your section Id
        ['is', 'entries.sectionId', null],
    ]))
    ->andWhere(new OrCondition([
        ['=', 'elements.type', \craft\elements\Entry::class],
        ['=', 'elements.type', YourCalenderClassComesHere],
    ]))
    ->andWhere(['elements_sites.siteId' => 1])
    ->limit(10)
    ->offset(0)
    ->column();

// populate entry by Id
foreach ($query as $elementId){
    $element = Craft::$app->getElements()->getElementById($elementId);
}


Setting up routes for AMP template with category-based urls

You don't strictly need to change the AMP template for each entry type; you can just load the entry in your AMP template via the slug in the URL.

Check out how I did it here: Implementing AMP in Craft CMS


Array from matrix fields without quotations

You would need to join the array into a string, like so:

// Begin defining the response data for this entry
$data = [
    'title' => $entry->title,
    'slug' => $entry->url,
    'status' => $entry->status,
    'textArea' => implode(' ',$bodyBlocks)
];


You seem to have discrepancies in your naming. There is craft-project-name and craftprojectname in there. Could it be that?

Fix the naming and try to delete the plugin row in the database, composer remove it then re install..?


Is there a way integrate redactor with your assets fields?

A better way to tackle something like this would be to use a matrix instead of just a rich text area.

With a matrix you can have an image block and then in your template you can pull any info you want from the images custom fields.

We normally have at least three block types with a normal matrix, text, image, and gallery.

Text is just a refactor text block.  Image is an image with a "position" field to control alignment (float left/right/center) the a gallery block which lets you select a series of images which display in a slideshow


How can I output a specific field in Sprout Forms email notifications?

Turns out, there's an element twig variable that I can use (it contains the Sprout Form entry), so I can output:

{{ element.first_name }}

for instance.


Blank white pages after moving index.php

Not sure the underlying cause, but clearing the craft/storage/runtime/cache folder that both sites shared caused both sites to start working as expected.


I'm a beginner myself but have used assets plenty of times. It should be something like this:

{% set entry = craft.entries.section('gallery').first() %}
{% set assets = entry.gallery %}
{% if assets | length %}
    {% for asset in assets %}
        <img src="{{ asset.getUrl('imgTransform') }}" width="{{ asset.getWidth('imgTransform') }}" height="{{ asset.getHeight('imgTransform') }}" alt="{{ entry.title }}">
    {% endfor %}
{% endif %}

I use a set entry instead of a for loop because I'm assuming you only have one entry (one gallery). Maybe use a single section instead of a channel than? If you have multiple galleries, a channel is perfect, than you can use a for loop.

The imgTransform can be set in your assets page in the Control Panel. More info: http://buildwithcraft.com/docs/image-transforms


I find the answer. The config is in "Additional nginx directives"


The contents of the "public" folder are supposed to be in your web root. So you're probably better off with a separate virtual host instead of accessing your Craft site in a sub folder for that reason. You can also move the contents of the public folder to the web root for localhost. Just change the path to the craft folder in index.php in that case.

I created an instruction on how to install Craft's demo site on Wampserver some time ago. Although that's not exactly the same as installing Craft, you should be good to go after following "WampServer setup" and "Virtual host setup".

If you're still having trouble after that, then it's probably worth taking a look in either the server logs or the logs at craft/storage/runtime/logs to see what's wrong.


How to create multisite in Craft CMS v3?

This is a very general question. Take a look at the following resources as a starting point:

Managing Multiple Sites in Craft 3 – Sites and Localization - Straight Up Craft
Using Craft CMS Multi-Site - Mijingo


One structure vs a structure per section?

TL;DR: Let the content dictate how you model and architect it.

If the site is sufficiently small or sufficiently simple, I think either approach is ok. My team has used both approaches, and it really depends on the Client's needs.
An incomplete list of reasons to use separate channels and structures are:

Tagging/Categorizing things like Products is probably easier to manage when they are in their own channel
Your client has multiple divisions and they are managing their content separately, and thus need to control permissions
You want to reference content pieces in multiple places

An incomplete list of reasons to use a Site Pages approach are:

The content isn't highly relatable, or doesn't rely much on relationships/categories/tags
The site is small enough
The client has demonstrated an ignorance or apathy for understanding content and "just needs a site"
Project management constraints: fast timeline, cheap budget, or pain-in-the-ass-go-away clients.

If you're familiar with ExpressionEngine and channels, then you probably know that things don't have to be pages to be in a channel or structure. You can combine the two approaches for a slightly sophisticated site.
Here's an example we have done that uses both approaches:

We used structures for things like Executive Team Bios that appear on one page. The landing page is in the Site Pages structure, which supports 3 levels max, while the bios themselves are managed in a separate structure (a channel would have been fine here, but the structure allows us to order by rank without an "order" field). We put a Management Widget blockType in a Matrix/Neo field so the user can put that content where they need to. That block allows them to select "Management" or "Board of Directors", so the block is reusable on multiple pages.
This block could have easily been a nested block using Neo/SuperTable fields, but the categorization (Management/Board) is what led us to make it it's own structure. Some members belong to both groups, and without the relationship it would have required inputting and managing duplicate content.

If navigation is your concern, you can use plugins like Navee or A & M Navigation to allow content managers to build navigations. Or on smaller sites, we just have a "Navigation" global field group with entries fields, and users can build out header and footer navigation as they deem appropriate.
My advice is let the content dictate how you model and architect it. If you have complex content requirements, don't try to shoehorn them into a one-structure architecture. Craft's CP allows you to group channels and structures, and the Expanded Singles plugin allows you to put singles in the entry sidebar. This can help content managers know what they are editing while allowing for more complex models. See below:


Best way to re-populate input field with Model data on front-end?

The way the Craft docs do it is basically how you are already:

<label for="userLastName">Last Name *</label>
<input id="userLastName" type="text" name="fields[userLastName]" {%- if entry is defined %} value="{{ entry.userLastName }}"{% endif -%}>


Is there a way to use the includeCssFile tag to include a css file for print media?

You can use the {% includeCssFile %}, you just need to make sure and wrap all of the styles in the print stylesheet with @media only print { } or @media print { }

@media only print {
   nav {
       display:none;
   }
   p {
       color:#000000;
   }
   .etc {
   }
}


Update fields structure from local to production

There are lots of similar questions with good discussion on this:

What's the best practice for handling data migration and organization across development environments?

Recommended workflow when developing new websites

What's the best practice for upgrading a versioned Craft site?

Ultimately, we want to building something in core to help manage this and the upcoming Craft 3 has taken a step in that direction with Content Migrations.


Use a plugin from another plugin in Craft 3

You can call the main plugin class directly

MobileDetect::$plugin->mobileDetectService

I don't know this plugin, maybe the class is wrong but that's the syntax you can use


How to loop through a table and set variables based on the existence (or not) of data in those tables?

Well. It's not pretty but it works. That improvements could be made on this is both certain and welcome.

{# Check to see if we've for got prices set, Set them if we do... #}

{% set priceDKK = entry.price[0].DKK ? entry.price[0].DKK : false %}
{% set priceEUR = entry.price[0].EUR ? entry.price[0].EUR : false %}
{% set priceUSD = entry.price[0].USD ? entry.price[0].USD : false %}

{# Figure out which price and rate we have to calc with... #}
{# Create our var before the loop (because scope)... #}

{% set basePrice = "" %}

{# We work down the list looking for our first set price #}
{# We will set it as our base price #}
{# We are going to convert all prices to DKK first #}

{% for price in entry.price %}
  {% if priceDKK %}
    {% set basePrice = priceDKK / rateDKK %}
  {% elseif priceEUR %}
    {% set basePrice = priceEUR / rateEUR %}
  {% elseif priceUSD %}
    {% set basePrice = priceUSD / rateUSD %}
  {% endif %}
{% endfor %}

{# Calculate prices if they don't exist... #}
{# We do not calc prices that were manually set... #}

{% for price in entry.price %}
  {% if not priceDKK %}
    {% set priceDKK = basePrice * rateDKK | round(-3,'ceil') %}
  {% endif %}

  {% if not priceEUR %}
    {% set priceEUR = (basePrice * rateEUR) | round(-3,'ceil') %}
  {% endif %}

  {% if not priceUSD %}
    {% set priceUSD = (basePrice * rateUSD) | round(-3,'ceil') %}
  {% endif %}
{% endfor %}

{# end #}


I just tried this and it works with Craft 2.3.2636. The only difference is this isn't using ContentModel::setAttributes(), but I wouldn't have thought that would affect it.

$entry = new EntryModel();
$entry->sectionId   = 2;
$entry->typeId      = 2;
$entry->authorId    = 1;
$entry->enabled     = true;
$entry->locale      = "en";

$entry->getContent()->title       = "English Title";
$entry->getContent()->description = "English description.";

if (craft()->entries->saveEntry($entry))
{
    $entryEs = craft()->entries->getEntryById($entry->id, "es");

    $entryEs->getContent()->title       = "Spanish Title";
    $entryEs->getContent()->description = "Spanish description.";

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


Issues using the elements service in console commands

There was a bug in Craft where custom fields weren't being loaded when using the ElementsService in the context of a console command.

Just fixed it for the next (post 2.2.2598) release.

Am I'm not sure I'm following the locale issue.  Can you post that as a separate question with some more clarification?


Setting channel url format to include value of entries fieldtype URL

It needs to be:

{destination.first().slug}

Or if this is for Craft 3:

{destination.one().slug}


I have never tried it on a table field, but you could try:

{% for row in block.example.limit('1').order('RAND()') %}
    {{ row.examplerow }}
{% endfor %}

OK, above will not work. I went back on my theory and actually tried it on a table field I had laying around. This worked for me:

{% set rows = shuffle(block.example) %}

{% for row in rows | slice(0, 1) %}
   {{ row.examplerow }}
{% endfor %}


Sorting Entries field results by category

It’s not totally clear from your question where you’re building the relation to the categories,
but I have a feeling that this is the solution you’re looking for.

{% set groupParam = '{ object.categoriesFieldHandle.first() ? object.categoriesFieldHandle.first().title : "No categories" }' %}
{% for groupTitle, entriesInGroup in entry.entriesFieldHandle|group(groupParam) %}
    {{ groupTitle }}

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


Modify an ElementCriteriaModel to compare against numeric field

Here's what's actually happening with this line of code...

$criteria->creditsUsed > 0;

You are actually generating the boolean value of "is creditsUsed more than zero". Granted, you aren't setting it to an actual variable, but nonetheless you are generating a boolean value. For example:

$moreThanZeroCreditsUsed = ($criteria->creditsUsed > 0);

Even though you're not assigning that new boolean value to a variable, it's still valid PHP (and therefore no error is thrown).

What it looks like you are trying to do instead is to actually set the value of creditsUsed, which you'd need to use an equals sign to do:

$criteria->creditsUsed = "whatever";

If my memory serves me correctly, the way to denote a comparison on an ElementCriteriaModel is to simply pass the comparison as a string:

$criteria->creditsUsed = "> 0";

See the last example in this subsection... Granted, it's being applied via Twig syntax, but it's still modifying the ElementCriteriaModel in the same way:

craft.entries.width('>= 100')


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

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

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

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

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

{{ entry.title }}

        ...

{% endfor %}

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

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

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

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

                {% children %}

        {% endifchildren %}

{% endnav %}


Get a defined image-transform's width and height in front-end template

Craft does not provide the assetTransformService in the craft.variable but you can include it by yourself.
Create a function in your PluginVariable.php that does

public function getTransformationByHandle($handle){
    return craft()->assetTransforms->getTransformByHandle($handle);
}

and in your twig template
{% set transformation = craft.pluginHandle.getTransformationByHandle('yourHandle') %}

Edit: if you don't have a custom plugin then visit this page Pluginfactory fill out the inputs and select the lightswitch for "variable" paste my function into the /variables/pluginHandleVariable.php file and create a folder with the same name as your pluginhandle (the one you inserted in the input at the page) in /app/plugins/ then go to the control panel, install the plugin.


I found any relative link should not lead with a slash.


Filtering a list of entries is quite simple. Here's an example from one of our sites:

{% for job in craft.entries({
    section: 'jobs',
    applicationsClose: ">= " ~ (now|date('Y-m-d')),
    internalExternal: 'external',
}) %}

    ...

{% endfor %}

Here we define the section we're looking in and then filter by two custom fields: applicationsClose and internalExternal.


Image transforms not working on front-end

The fix (for my project) was to enable the PHP output_buffering directive.

I added this to the account specific php.ini file for the hosting account.

output_buffering = On

This from the web hosts docs to explain why this fix worked:

*"Doing a header redirect requires outputting an HTTP header with the response. The problem is, if PHP has already begun outputting the body of the document, it cannot then output a header because the headers ended when the body started.

Output buffering prevents PHP from outputting any part of the body of the document until the output buffer is flushed (or PHP exits). This allows you to output headers at any time."*
http://kb.site5.com/php/how-to-repair-headers-already-sent-php-errors/

Another thing to try is add 'imageDriver' => 'gd, to your config file. This helped me with issues on a different server.
https://docs.craftcms.com/v2/config-settings.html#assets


I restored the database backup that came with your ticket locally and created an article.html template in craft/templates and was able to load the route on the front-end of the site as well as get it to display in Live Preview.

My guess is that either 1) there's something wacky with the permissions on that file that Craft/PHP can't read it or 2) there's a .htaccess rewrite rule in your setup that's interfering with that request.


Display entries by category (multiple categories)

You can use .relatedTo(category)

{% for category in craft.categories.group('categoryName') %}

{{category.title}}

  {% for entry in craft.entries.section('news').relatedTo(category) %}
    {{entry.title}}

  {% endfor %}
{% endfor %}

You can check for length if you don't want to show categories which aren't related to any entry.

See the relations documentation


What is the value of hosting assets on Amazon S3? Best practices question

S3 is not itself a CDN, no.  However, you can use Cloudflare as a free and very easy to set up CDN service in front of it.

For me the main advantages of S3 are that it's a centralised repository of assets I can point all my environments to (so dev, staging, production all point to the same S3 and thus have identical assets available to them with no need to sync anything).  I trust Amazon to runs servers more than I do individual other companies, simply by virtue of their size and experience (and I know some of the engineers as well - they're smart people!).

With Cloudflare in front of S3, you get CDN and static asset caching benefits, and images are served very quickly.


Craft CMS 3 admin panel returns 404 with SSL

tl;dr: In my case, adding AllowOverride All back in to httpd.conf fixed the issue.

I was having the same issue on my staging server. I noticed that, in addition to /admin throwing a 404, all of my site's subpages were 404-ing. This cause me to try the unrouted index.php url for a subpage (mysite.com/index.php?p=subpage) and it worked! Note, this wasn't working for /index.php?p=admin because it was properly routing to /admin/login. Plugging in /index.php?p=admin/login worked.

I ran through the Craft guide for removing index.php from urls. Everything was set up properly, but my server admin found that AllowOverride All had been commented out of httpd.conf during a server update and was never un-commented. Adding AllowOverride All back in to httpd.conf fixed the issue.


Can Matrix fields be added/shown on the entries listing of the control panel?

That's not possible, Matrix blocks (and also Tags) don't have an element index view in the CP.

You could write a plugin that adds such a page to the CP. It would list all the Matrix blocks that meet your requirements (owner ID, owner entry, ...).

Another idea would be to just use an Entries field instead; the entries section you'd set up for the field comes with an index view for free.


In Craft 3 the csrf token validation in the general.php config is set to true by default. In order to request your controller with post requests you have to turn it off or include the token

https://docs.craftcms.com/v3/changes-in-craft-3.html#csrf-token-params

{% set csrfTokenName = craft.app.config.general.csrfTokenName %}
{% set csrfToken = craft.app.request.csrfToken %}
<input type="hidden" name="{{ csrfTokenName }}" value="{{ csrfToken }}">


When you added the type param to your {% paginate %} tag, you removed the as entries bit, which is required. (That tells the tag what variable name it should give to the current page’s entries.)

{% paginate craft.entries.section('woods').type('mahogony').limit(5) as entries %}


After trial and error I figured out you can escape characters using double backslash.

{{ article.postDate.format('j\\<\\s\\u\\p\\>S\\<\\/\\s\\u\\p\\> F Y') | raw }}

Outputs: 14th January 2016

In search of documentation I found a mention of double-escaping regular expressions due to Twig auto-escaping \. At this point I'm guessing this works for most Craft-Twig functions.


Loop through all sites in multisite installation

Nikolay,

As I responded in the slack, I will respond here in case anyone else has this question.

In the template you can access this information like so:

SiteUrl: {{ siteUrl }}
Langauge: {{ craft.app.language }}
Handle: {{ craft.app.sites.currentSite.handle }}

I'm not entirely positive how to loop the sites in the template but you can get a sites object in PHP by running the following in a controller somewhere or in the init() method of any plugin that is installed:

$sites = Craft::$app->getSites();
var_dump($sites);
exit;

This will output the structure of the sites object. Baring this you can look through the craft source / docs to find the details on the site object that returns. There should be a method for getting sites by id or by handle; $sites->getSitesByID() or $sites->getSitesByHandle() but I have not double checked this so you'll have to try it or look it up. If there is not a method then it should be accessible via an array property like $sites->sitesByHandle or $sites->byHandle. Again you'll have to double check on this.

By the way, that functionality should translate to the template version of the sites object craft.app.sites so you should be able to do:

{% set sites = craft.app.sites.getSitesByHandle() %}

Or something like that anyway.

Once you figure it out feel free to update this to reflect the proper methods / properties :)


All of the HTML that Craft uses to render your site lives in your craft/templates folder.

In one of the files in that folder, you're presumably defining your <head></head> tags.

You'd want to find where that is and insert your JavaScript analytics tracking code before the closing head as per the Head Analytics installation docs.

Probably worth a read through the Craft does to familiarize yourself with Craft concepts as well.


As of Craft 2.3, overridePhpSessionLocation is set to false by default.  Meaning that wherever Apache (or whatever web server you're using) and PHP is configured to save the PHP session files, that's where they will go.

If you set overridePhpSessionLocation to true, then the session files will be saved in craft/storage/runtime/session. Just be aware there is a bug in PHP that will prevent session garbage collection from running if you override the default session save path (which is what that config setting does). So you'll want to provide your own external method of session file garbage collection.

So, your options are to 1) enable sticky session as the load balancer level to ensure that a user will always get sent back to the same server that their session was created on or 2) provide an external shared storage drive that all of your web servers can write the PHP session files and point each web server to use that.

Personally, I'd just enable stick sessions.


How to move Craft from a subdirectory to public_html

Without having seen your setup, I'd say this is what you need to do:

Move all files and folders (don't forget the hidden ones) to the correct location
Edit your web/index.php file, to make it look for Craft in the right location (it's looking 2 folders up now, it should only be one folder up.
Change your site's base url, in your config/general.php, .env, or wherever you've set it.
Change the paths and urls for the asset folders
Just to be sure, clear your cache (removing the contents of storage/runtime should do the trick)

Again, depending on your setup there's a thousand things that could prevent this from working, but it should get you going!


The timezone could not be found in the database

Is this a custom template global from a plugin or is it a field on a Craft global set, because those you usually access with {{ myGlobalSet.endDate }}.


Is it possible to break out of a loop in twig?

Currently there is no special build-in command to do it (unless you want to use a plugin, as stated by Brandon Kelly). There is a workaround, however. The workaround is to check for additional condition.

{% set break = 0 %}

{# this variable we will set to 1 when we do not want code in our loop to run anymore #}

{% for i in 20..100 if break == 0 %}
    ...
    {# on some condition we will set break to 1 to prevent running of further code #}
    {% set break = 1 %}
    ...
{% endfor %}


Live Preview only works for Entry variable?

We just changed this behavior in Craft 2.3.2616:

  Live Preview and Share links will now show the unpublished entry/category changes wherever the entry/category are being referenced in the templates (even areas where the entry/category was fetched from the database).

So now Live Preview (and Share links) should work as expected for you.


Passing optional variable values into an include template

So in this case with ctaUrl, the issue is that you are checking if ctaUrl is defined.

As long as a field exists, is defined will return true as in reality, the variable block.ctaUrl exists, it's just empty. To check for content in your case, you should test for NULL. So if ctaUrl is not NULL show your link.

In terms of organisation of your code, it's up to you. Like Roi said, you don't need the with. Your matrixBlocks will be available within the component.

Whether you set stuff up in the main template is up to you. Personally, I would do my logic in the component rather than the main templates.

You will need to be consistant with your naming but the component is where you need this logic so if it's is in there, you don't need to dig around to understand what is going on. If you remove a component, the logic goes with it as suppose to have a bloated main template and also, you don't do a lot of stuff before you need to. No need in checking if you have a ctaUrl if your _components/imageRight isn't requested...

One reason for doing the logic in the main template would be that you would have less duplication (maybe) but from experience, I'm not sure it's worth it. So In your case:

{% set matrixBlocks = entry.fullContentMatrix.all() %}

{% for block in matrixBlocks %}
    {% if block.type == 'imageRight' %}
        {% include '_components/imageRight' %}
    {% elseif block.type == 'imageLeft' %}
        {% include '_components/imageLeft' %}
    {% elseif block.type == 'someOtherBlock' %}
        ....
    {% endif %}
{% endfor %}

Then do your work in your components:

{{ block.heading }}

{{ block.bodyContent }}
{% if ctaUrl is not NULL %}
  Click
{% endif %}

Doing this, you will have a lean and clear main template and the component level logic will live in the component where it belongs. My opinion only though... Plenty of ways to do this :)

So to your question:

  What is the best way to write this so that variables are only passed to the include if they are defined?

In your case, don't worry about that, check if they are defined when you need to use them, at component level.


'Unknown error' caused by redirect in htaccess

It might be down to the order you have the code in your htaccess file? Did you try putting your code above the Craft rewrite code?

# redirect PHP or HTM to no extension
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.(php|htm?)
RewriteRule ^ /%1 [L,R=301]

# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]

Also I tend to exclude certain directories when I don't want rewrites to apply. One way to do this would be;

# ------------------------------------------------------------------------------
# | Exclude directories from the rewrite rules                                 |
# ------------------------------------------------------------------------------
RewriteRule ^craft - [L]


Is there no way to have separate templates for text and html emails in craft?

Correct.  That's something we're going to try to address in Craft 3.

Regarding the ampersand encoding, I can't reproduce that locally.  Maybe your email client is encoding it or there is an overly aggressive mod_security / Suhosin / Apache setting that's doing it?


So for Craft 2.x, what I'd suggest is just doing this via Twig. This is discussed here: https://github.com/nystudio107/seomatic/wiki/10.-Dynamic-Twig-SEO-Meta


Craft not generating language links correctly

In a multilingual site, your siteUrl config setting in /craft/config/general.php needs to be an array where the keys correspond to your installed locales:

return array(
    // ...
    'siteUrl' => array(
        'no' => 'http://example.com/',
        'en_us' => 'http://example.com/en/',
    ),
);


Is it possible to populate admin form with data supplied by an external API?

Short answer: yes it is

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

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

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


I've figured this out (the solution is not in the docs). Follow these steps:

1) In the amforms plugin's settings, create a custom text field called 'notificationRecipients'.

2) Add that field to your form's list of fields in the form's settings.

3) Under the notifications tab of your form, add this to your "Email Recipients" field:

defaultAddress@domain.com,{notificationRecipients}

4) Now in your template, add a hidden input in the <form> like so:

<input type="hidden" name="fields[notificationRecipients]" value="{{ entry.yourCustomFieldEmailAddress }}">

Keep in mind that multiple emails should be separated by commas like example1@gmail.com,example2@gmail.com,example3@gmail.com

That's it!

If you don't want the list of email recipients to appear in your notification email, then you need to edit line 24 of craft/plugins/amforms/templates/_display/templates/email.twig to look like this:

{% for field in fields if field.getField().handle != 'notificationRecipients' -%}

Additional examples and info can be found on these closed issues of the developer's git page:

#72
#86
#99


Your code isn't working because you set the related game(s) to a variable entries (i.e. {% set entries = craft.entries...%}), but you're not actually doing anything with that variable. Then you try to render the link to the related game(s), but you're simply re-using the entry variable – which refers to the review entry, not the related game entry.

If you change

{% set entries = craft.entries.section('games').relatedTo(entry) %}

Game link:

...

to something like

{% set relatedGames = craft.entries.section('games').relatedTo(entry) %}
{% if relatedGames|length %}

Game Link:

        {% for game in relatedGames %}

{{ game.title }}

        {% endfor %}

{% endif %}

...it should work.

Note that in some cases, its a good idea to be as specific as possible when you're dealing with relations. Simply doing relatedTo(entry) will work, but you can also let Craft know where the relation was created (i.e. in which field), and whether the related elements you're looking for is the source or the target elements for the relation. In this case, then Entries field is on the game entry, which means that the review entry is the target element (i.e. the entry that has been selected in an Entries field), and the game entry is the source element (i.e. the entry that actually has the Entries field in its field layout).

Assuming your Entries field on the game entry has a handle relatedReviews, a more specific relatedTo query for your use case could look like this:

{% set relatedGames = craft.entries.section('games').relatedTo({
    field: 'relatedReviews',
    targetElement: entry
}) %}
...

Being specific about relations can be more performant, and helps avoid issues where you might have multiple relations involving the same elements (e.g. if your review and game entries where also related via a different Entries field).

Another detail to note is that whenever you're dealing with the source element (e.g. if this was the template for the game entry, and you wanted to list the related review entries), you rarely need relatedTo – you can just do this (of course, replace relatedReviews with the real handle for your Entries field):

{% set relatedReviews = entry.relatedReviews %}
{% for review in relatedReviews %}
    {{ review.title }}
{% endfor %}


Get entries with related to selected categories and then group by category

I may not understand fully, but it sounds like you could just loop over the attached Department Categories, then query for Staff related to that category:

{# Load the Departments Categories: #}
{% set departments = entry.allDepartments.all() %}

{% for department in departments %}
  {# Find all the Staff Members associated with the department: #}
  {% set staff = craft.entries({
    section: 'staffMembers',
    relatedTo: department,
    with: ['staffPhoto']
  }).all() %}

{{ department.title }}

    {# Loop over the Staff Members: #}
    {% for person in staff %}

{{ person.title }}

    {% endfor %}

{% endfor %}

  There is a (very slight) performance penalty for performing queries like this in a loop, but it sounds like each of these focused sub-pages won't have too many Departments listed anyway.


Saving a variant with new stock from plugin

I haven't done this, but as a rule I try an mimic what Commerce actually does itself.  In this area I would be inclined to follow the code Commerce uses in it's own completed order handling, found in public function orderCompleteHandler in commerce/services/Commerce_VariantsService.php around line 290:

        $purchasable = $lineItem->getPurchasable();

        // Only reduce variant stock if the variant exists in db
        if (!$purchasable)
        {
            continue;
        }

        $clearCacheOfElementIds = [];
        if ($purchasable instanceof Commerce_VariantModel && !$purchasable->unlimitedStock)
        {

            // Update the qty in the db
            craft()->db->createCommand()->update('commerce_variants',
                ['stock' => new \CDbExpression('stock - :qty', [':qty' => $lineItem->qty])],
                'id = :variantId',
                [':variantId' => $purchasable->id]);

            // Update the stock
            $purchasable->stock = craft()->db->createCommand()
                ->select('stock')
                ->from('commerce_variants')
                ->where('id = :variantId', [':variantId' => $purchasable->id])
                ->queryScalar();

            // Clear the cache since the stock changed
            $clearCacheOfElementIds[] = $purchasable->id;
            $clearCacheOfElementIds[] = $purchasable->product->id;
        }

        $clearCacheOfElementIds = array_unique($clearCacheOfElementIds);
        craft()->templateCache->deleteCachesByElementId($clearCacheOfElementIds);


You can use the date method for creating a date object.
e.g.:
{% set tweetDate = date("Fri Sep 02 14:42:42 +0000 2016") %}


Two domains with two different templates

Multi-environment-configs: don't think so.

Maybe a solution is to use json template files on website1.com that you read (without craft) on website2.com?


Set a user's group on a registration form using a hidden field

There's a couple of problems you're probably running into.

By default, assigning user permissions (either directly or via groups) requires the the currently logged in user to have the assignUserPermissions permission. It sounds like you're doing this from a front-end request, where I'm guessing there is no authenticated session in place.
User groups and permissions are applied in Craft after the user has already been saved, so even if you got by #1, your changes would probably be overwritten.  The events you should be listening for are probably onBeforeAssignUserToGroups and onAssignUserToGroups.

Of course, you can always write a custom plugin that has a controller action, point your form to it, and do whatever custom user saving logic your situation requires as well.


Depends on how you want to determine "most popular"...

If you want to calculate based on page views, then check out Ben Croker's Entry Count plugin (as Brad mentioned in his answer).

If you want your users to vote on most popular, then check out my Upvote plugin, designed to emulate Stack Exchange or Facebook "likes".


My bad. Total n00b error. Made the content a global so it can exist outside of specific template and solved it


A plugin that has config settings can provide the default values for those settings in plugins/pluginHandle/config.php.

Since you've defined CRAFT_PLUGINS_PATH as craftdevplugins, that would be craftdevplugins\pluginHandle\config.php.

End users can set can set custom values in config/pluginHandle.php.  Since you've defined CRAFT_CONFIG_PATH as craftdevconfig, that would be craftdevconfig\pluginHandle.php.


As far as I know (please correct me if I missed something) you can only search for the entire matrix by matrixField:value and not certain fields within your matrix since the table searchindexes only contains the id of the matrix field itself, not the id of the field inside the matrix.

However: you could create a Query from your ElementCriteriaModel in PHP via

$command = craft()->elements->buildElementsQuery($criteria);

Join your matrixblock table as well as your matrixblock content table

$command->join("your matrixTable", "matrixTable.ownerId = elements.id");
$command->join("your matrixContentTable", "matrixContentTable.elementId = matrixTable.id");

And search for your field with a where

$command->andWhere('MyAwesomeField LIKE %whatever%');


Use twig's {% spaceless %} tag only under certain conditions

You could do it by buffering your output, i.e.

{% set output %}
{# Your code here #}
{% endset %}

{% if isDev %}
     {{ output }}
{% else %}
    {% spaceless %}
        {{ output }}
    {% endspaceless %}
{% endif %}


Are you experiencing performance issues? If not, is this overhead really an issue?

If it is, how about caching the global menu for a really long time? https://craftcms.com/docs/templating/cache


Upgrade failed - what needs to be restored?

That should do it!

Auto-updating to 2.5 is causing a few people headaches, mainly because people are bumping up against their php.ini setting limitations. It's a pretty significant update, requiring pretty significant server resources to handle the transition.

Once you've successfully rolled back, I'd recommend performing a manual update. This takes a lot of pressure off of your server, and only leans on your server resources to run the database migrations (which definitely shouldn't cause any overloads).


Output a Twig tag within another Twig tag

You are hashing the string '{{item.mailto}}'. There shouldn't be any need for the quotes or second set of curly braces.

Twig does not permit curly braces inside curly braces.

Try {{ item.mailto|hash }} instead.


How do you reset a cart under Craft Commerce 2?

The commerce/cart/remove-all-line-items action (or in Craft 2 terms, commerce/cart/removeAllLineItems) was deprecated (and subsequently removed in Commerce 3), so it's up to you to build a form to explicitly delete all line items:
<form method="post">
    {{ csrfInput() }}
    {{ actionInput('commerce/cart/update-cart') }}

    {% for lineItem in craft.commerce.carts.cart.lineItems %}
        <input type="hidden" name="lineItems[{{ lineItem.id }}][remove]" value="✓">
    {% endfor %}

    <button type="submit">Empty Cart</button>
</form>

This snippet just loops over the current line items, and outputs a hidden input element, which sends the proper POST value to the update-cart action.
It's also possible to give your customer control over which line items are to be removed by changing the input to a check-box (and providing adequate labeling).


This is how I did it:

In my custom plugin, in its init function, I use the following statement to hook into the before delete event:

craft()->on('elements.onBeforeDeleteElements', array($this, 'beforeDeleteElements'));

In the same custom plugin, in the beforeDeleteElements function mentioned in step 1, I examine the passed in event, and determine if the entry type being deleted is the entry type I am interested in, if so, I use the following function to find the related assets and then delete them:

protected function deleteRelatedImages(EntryModel $entry)
{
    $criteria            = craft()->elements->getCriteria(ElementType::Asset);
    $criteria->relatedTo = $entry;
    $assets              = $criteria->find();

    if (!$assets) {
        return;
    }

    foreach ($assets as $asset) {
        $sourceType = $asset->getSource()->getSourceType();
        $sourceType->deleteFile($asset);
    }
}


Delete Stale Template Caches tasks much larger in Production than Staging

First, this is perfectly normal. :)

Have a look at Brandons explanation here on how the cache tag works.

  If the element was added or modified, it queues up a new “Delete Stale
  Template Caches” task, which cycles through the templatecachecriteria
  table to see if there are any cached element queries which (if not
  cached) would have started showing the just-saved element. If the
  query returns the element, its corresponding cache will be deleted.

So, the number of steps corresponds to the number of rows in the templatecachecriteria table in the database.

Why would this be different between staging and production? Probably because you're getting different kind of traffic on the production site than the staging site.

It's important to understand that the cache is tied to the url, so mydomain.com/news and mydomain.com/news?id=212 will result in two different caches being created in the database, and a number of rows in the templatecachecriteria table being created based on the number of criterias created inside the cached code (which can be alot).

The example given above is an example that we encounter a lot, where when an old site is replaced by a new one, there will still be a lot of links pointing to the new one. If these aren't handled correctly by either rewriting them to new url's, or returning 404's, this could result in many old urls generating new caches for the same page.

The recommended way to avoid this is to use the globally keyword, and using the request path as the key, see the example in the "using key" section of the docs for {% cache %}.

Another common caveat is that there are caches on the 404 page that is not declared as globally, for instance a menu that needs a selected state or something. Then all urls that results in a 404 not found page, will create new caches with new criterias in templatecachecriteria. I've seen examples where this will eventually just kill the server because of the number of criterias that are rerun when an entry is saved.

If I were you I'd have a look in the templatecaches table, and look at the path column to identify the paths of the created caches. This will often reveal groups of urls which generates more caches than they ideally should, and you could work from there to reduce the number.


How do I print the name of the Section on an index page


Display entries by Category (Category in Super Table)

Not sure if you're still looking for an answer, but relation support has just been added to Super Table 0.3.7. Previously, relations wouldn't work with Super Table, as its a little bit of a special field, having sub-queries to perform for relations (each row).

You can now query fields just like Matrix:

{% set reverseRelatedElements = craft.supertable.getRelatedElements({
 relatedTo : {
   targetElement: entry,
   field: 'superTableFieldHandle.columnHandle'
 },
 elementType : 'Entry',
 criteria: {
   section: 'someSection'
 }
}) %}


How can I work with related entries within a Matrix in a plug in?

It’s an entries field, so $skill->skillName returns just the ElementCriteriaModel prepared to query for one or more elements matching the criteria.

You need to do something like this:

$entry = $skill->skillName->first();
$skillName = $entry ? $entry->title : null;


Using ElementType as field type for plugin in what way do I provide my own data to the modal?

Ah, in that case you'll need to make your own ElementType. You should probably check out https://github.com/pixelandtonic/Events - that's meant to be a simple ElementType to serve as an entry point while we get some documentation together.

Also, there are some videos to watch over here: http://buildwithcraft.com/docs/plugins/working-with-elements#creating-new-element-types


How do I create a structure side navigation that will show active parent list-item and active child list-item

After a long search and lots of trial and error, I've found the perfect solution!
This is how I created a dynamic structure navigation : parent/child (2 levels deep) with class="active" on the parent and the child
.

{# Get top-level entries in structure section 'features' #}
{% set parentFeatures = craft.entries.section('features').level(1) %}

{# Loop through top-level entries #}
{% for parentFeature in parentFeatures %}

    {# Check if entry has descendants/children #}
    {% if not parentFeature.hasDescendants %}

        {# List navigation item if entry has NO child entries #}

            {{ parentFeature.title }}

    {% else %}

        {# List navigation item if entry does have child entries #}
        {# Show an active class if it is active or if it contains a child that is active #}

            {{ parentFeature.title }}

                {# Get child entries of current iteration's top-level entry #}
                {% set subPages = parentFeature.getChildren() %}

                {# Loop through those 2nd-level entries #}
                {% for subPage in subPages %}

                    {# This is the place where you'd nest the next menu hierarchy !! #}

                    {# List sub-menu navigation item #}

                        {{ subPage.title }}

                {% endfor %}

    {% endif %}
{% endfor %}

Thanks to Carlcs's old answer about this found here: https://craftcms.stackexchange.com/a/1847/6586


Automatically subscribe users to MailChimp list?

Install the MailChimp Subscribe plugin and add the following users.onActivateUser event listener to your site’s Business Logic plugin.

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

    if (!$user->admin) {
        $result = craft()->mailchimpSubscribe->subscribe($user->email, '');

        if (!$result['success']) {
            Craft::log('Couldn’d subscribe to MailChimp list: '.print_r([
                'errorCode' => $result['errorCode'],
                'message' => $result['message'],
            ], true), LogLevel::Error);
        }
    }
});


Override max-length on the Title format field

See reply from brandonkelly on GitHub for an alternative to adress this issue.

https://github.com/craftcms/cms/issues/5132#issuecomment-544507473


How can I get all entries that are equal to, but not after a date?

I think the only issue is that you're adding "today" to the query as a string, not the variable you've created. try:

{% set today = now %}
{% set events = craft.commerce.products.type('event').eventEndDate('>=' ~ today) %}

The code in the answer you referred to had the same error, I've fixed it.


How can I sum value across entries assigned to a category for a given year across multiple years?

{% amount = craft.entries
   .postDate(['and', '>=' someDate, '<=' ~ someOtherTime])
   .select('dollar')
   .relatedTo(category)
   .sum()
%}

Loop through all years and sum the value


Is it safe to make the 'app' folder writeable by the web server?

Security is not off or on, it's layers of an onion.  Anything you do has to factor into the bigger picture.

My layers include:

What user does the web server run as? What user is your content?
Your web server should never be the same as the user who owns the files, typically www-data, www, apache, etc. Also, don't run apache as the user nobody.
Are you using PHP-FPM, su-PHP, fastcgi, or Apache w/ mod_PHP baked in? I prefer fpm since you can run every website as a separate pool and separate PHP ini / open_basedir configs, increasing security. If a site gets hacked, only that pool is affected.
What are the permissions of the folders/files? Shouldn't ever be 777, ideally 750 for directories and 640 for files. The web server should be added to the user's group and given read permissions (so it can only access static files).
Who else has access to the server? Deploy users via SSH, (s)FTP, MySQL replication users, etc. Limit access to need-to-know.

Just to play devil's advocate, if you do disable the one-click updates in production, that also makes it harder to simply update, which could be worse than not updating at all. I've seen well-meaning WP Devs tend to fall into this trap, keeping their client's sites in a sort-of cryogenic state. While Craft is not as widely used, the same security precautions apply.

I'm reminded of Brad's post about security here:

  Perhaps the biggest thing Craft has going for it, in the event a security related bug is that we can get the fix deployed quickly to our users with Craft's one-click auto-updating. In addition to that, we can mark a release as "critical", which gets special attention in the control panel.

Craft probably needs to eventually write files to the server anyway, including cache files, and assets, so unless you're shutting off access there as well, I'd wager it's the same risk—maybe even more so—because asset files/uploads tend to be in the web root unless you do some file aliasing.

And without question, if you're not backing up your database and filesystem regularly, you're asking for trouble. Let's assume you are hacked. If you don't have good back-ups, whether auto-update is on or off is not going to help you.


Craft does not offer this functionality natively. Luckily there's a few plugins out there that will help your users navigate around a bit easier:

In the CP Nav
https://github.com/engram-design/CPNav (This should accomplish your need)
https://github.com/picdorsey/craft-sidebarenhancer

In the Entries index
https://github.com/james1238/EntryTypeSources
https://github.com/engram-design/ExpandedSingles


Adding alt tag to image in a rich text field via its Edit button, within a matrix - breaks code link to the image

Make sure you're on the latest release.  In 2.4.2670, we updated Redactor to the latest so that might have fixed some bugs.
I can't reproduce what you're seeing. The modal that comes up from the Redactor edit image button doesn't have an "alt" field, so I'm not sure where you're seeing that.
If view source and manually add the alt tag, it behaves as expected no matter how many times I save/edit the entry.
Bug reports are better off here. :)


You should be able to check for this like so:

if($params['isNewEntry'])
{
 // The entry is new
{
else
{
 // The entry is being updated
{

See here in the docs: http://buildwithcraft.com/docs/plugins/events-reference#entries-onBeforeSaveEntry


Module: EVENT_AFTER_SAVE_ELEMENT won't detect changed user group

That's because groups are not attached to the user directly. At the moment Craft stores the user it hasn't handled the permissions not the user groups.

The workflow is

Handling all kinds of variables and data
Fetch/Create a user
Populate the new field values for the user
Store the user
Handle verifications such as sending them an email
Assign the user to groups and grant them permissions

At the moment your event triggers the user wasn't assigned to the groups.

If you want to change users depending on their groups you should use the  Users::EVENT_AFTER_ASSIGN_USER_TO_GROUPS event


What have you tried so far?

The documentation seems to be missing, but looking at /craft/plugins/commerce/models/Commerce_DiscountModel.php you can find the properties purchaseQty and perItemDiscount that you need for the calculations.

{% for prod in product.variants %}
   {% for discount in craft.commerce.discounts %}
      {% set totalPrice = (discount.purchaseQty * prod.price) %}
      {% set totalDiscountPrice = (discount.purchaseQty * (prod.price + discount.perItemDiscount)) %}
      {% set totalDiscount = (totalPrice-totalDiscountPrice) %}
      {% set totalDiscountPercent = (totalDiscount/totalPrice)*100 %}

If you buy {{ discount.purchaseQty }} items, you only pay {{ totalDiscountPrice|currency(cart.currency) }} instead of {{ prod.price|currency(cart.currency) }} per item. So your total today is only {{ totalDiscountPrice|currency(cart.currency) }} insted of {{ totalPrice|currency(cart.currency) }}. You therefore save {{ totalDiscount|currency(cart.currency) }}. That's a discount of {{ totalDiscountPercent|round }}%.

   {% endfor %}
{% endfor %}

This will show all of the discounts for all of the products. You will need to modify it slightly if you have specified the discount for a specific product. You also need to check if the discount is enabled or not using discount.enabled


A-Z filter menu - limiting output to one when there are multiples

You can use the group filter and create a 2d array with the letter as the first index and the entries as second index.

{% set allEntriesByFirstCharacter = allEntries|group('companyName|slice(0, 1)|lower|replace("/[^a-z]/", "0-9")' ) %}

The string passed in the filter will get rendered as an object template an equal results will be grouped by the same key.


Server-side address validation in Craft Commerce 3

According to Luke, this is the preferred method for Commerce 3.

In a custom module or plugin:

Event::on(\craft\commerce\models\Address::class, \craft\base\Model::EVENT_DEFINE_RULES, static function(\craft\events\DefineRulesEvent $event) {
    $rules = $event->rules;
    $rules[] = [['firstName','lastName'], 'required'];
    $event->rules = $rules;
});

Some more details about what kind of rules you can add here, if you want something more complex than a list of required fields:
https://www.yiiframework.com/doc/guide/2.0/en/tutorial-core-validators


How do I set mime-types for Craft templates?

If you want to explicitly set the mime type from your template, you can do it with Craft's {% header %} tag:

{% header "Content-Type: application/json" %}

If it is already set via this method, Craft will go with it and not attempt to auto-detect/set the mime-type on it's own.


Does defineSearchableAttributes() work with getter methods on the model?

I have since discovered that searching on a related model is fairly easy to implement. You just define the related model as an attribute that can be searched on in defineSearchableAttributes method of the element type.

For example:

/**
 * @inheritDoc IElementType::defineSearchableAttributes()
 *
 * @return array
 */
public function defineSearchableAttributes()
{
    return ['dateCreated', 'totalPaid', 'customer'];
}

Then you just have to have a matching handler for that attribute (customer) in the modifyElementsQuery method, like so:

    if ($criteria->customer) {
        if ($criteria->customer instanceof MyPlugin_CustomerModel) {
            if ($criteria->customer->id) {
                $criteria->customerId = $criteria->customer->id;
                $criteria->customer = null;
            } else {
                return false;
            }
        }
    }

    if ($criteria->customerId) {
        $query->andWhere(DbHelper::parseParam('orders.customerId', $criteria->customerId, $query->params));
    }

Then once search indexes are rebuilt, you'll be able to search on all attributes of a customer.


Image transform with focal point - in Element API

Focal Points apply to the Asset itself; that way the same Focal Point can be used with any transform, and it'll still keep the same point of interest centered when the image is transformed.

It should use the Focal Point automatically, you shouldn't have to do anything other than set it in the image editor.


Sprout reports options can't find form fields

As Ben Parizek pointed out in the comments this was a bug that was fixed on Sprout Reports 1.2.8.

I couldn't see Sprout Reports update because my Craft CMS installation was below v3.3.7, I updated Craft CMS and then updated Sprout Forms to v1.2.8 which fixed the bug.


You made the template filename and folder match the URI (routing case 6), which is not necessary for entries. Because you probably also set a template in the section setting, this is getting loaded for http://example.com/work/ (routing case 4).

So I think you should just edit the single section's settings and point to the right template.


TemplatesController error related to webfont!

TemplateController is what all template requests in Craft get routed through.

That error just means that someone/something is trying to load a resource (in your case yoursite.com/fonts/BlissBold-webfont.ttf) and that doesn't exist on your file system and Craft has no idea how to resolve that request, so it issues a 404 Not Found in response.

It's more of an informational thing than anything and not really an error.

In the upcoming Craft 3, 404's get logged in separate files so as not to clutter up the main logs.


Craft Commerce - Different confirmation email address for different product types or category

Should be pretty doable with a small plugin.

You'd want to listen to something like the onOrderComplete event, then loop through the line items making note of which product types the line items belong to, adding email address to an array to send to.

Then at the end, you can loop through your email address sending the appropriate emails out to each of the users.


How do I add an HTML block from template extension to main layout template? (i.e. meta data)

Option A: Set individual properties in the child template

If you want to set specific meta properties instead of defining a block, you can include lines like this in _layout.html:

{% if metaDescription is defined %}<meta property="description" content="{{ metaDescription }}">{% endif %}
{% if metaKeywords is defined %}<meta property="keywords" content="{{ metaKeywords }}">{% endif %}

Then, you can simply set either value from within the child template...

{% set metaDescription = entry.summaryFieldOrWhatever %}
{% set metaKeywords = entry.tagField %}

Option B: Pack an array with properties in the child template

...or as you pointed out, that could get cumbersome if you have a whole bunch of meta data. In that case, you could take a similar approach with an object instead of a block. So in _layout.html:

{% if metaProperties is defined %}
     {% for prop in metaProperties %}
     <meta property="{{ prop.name }}" content="{{ prop.value }}">
     {% endfor %}
{% endif %}

In the child template, then, you could...

{% set metaProperties = [
    { name: "description", value: entry.summaryFieldorWhatever },
    { name: "keywords", value: entry.tagField }
] %}

This way, you could set as many items as you'd like and still avoid passing markup to the parent template.

[EDIT] Typo fix


Have a look at Iain Urquhart's plugin, Pointy: https://github.com/iainurquhart/Craft-Pointy

It's a port of his EE addon that's similar to Entry Mapper, but I'm not 100% certain if it's production ready or not.


Try doing something like:

{% set nextBlock = block.getNext() %}

https://craftcms.com/docs/templating/matrixblockmodel#getNext


Performance when loading lots of Elements but only need limited data

Not in Craft 2 without completely bypassing ElementCriteriaModel and building your own SQL query.

In Craft 3 (currently in beta) you can, though – you can override which columns get selected in your element queries, and you can choose whether you want the data returned as element models or just plain arrays.

{% set entries = craft.entries
    .section('news')
    .select('elements.id', 'content.title')
    .asArray()
    .all() %}


Hosting Craft Site on Github Pages with Paid Domain

Whoops, sorry, just found out that Github Pages only works with static content (No PHP, No database).

Closing.


Correct way to getOrderByNumber() from my Plugin in Commerce 2

All of Craft’s core services are available via the Craft::$app->getServiceName()->callServiceMethod() signature.

For example, the Elements service would be Craft::$app->getElements()->saveElement()

In the case of other plugins, most will make their Singleton “instance” available as a property on (or method of) their primary plugin class:

use craft/commerce/Plugin as Commerce;
// Maybe a class declaration, and inside your own method…
Commerce::getInstance()->getOrders()->getOrderByNumber('abc123...');


Dashboard grid layout broken after an auto update gone wrong

Try clearing your browser cache. (Your browser might be holding onto a stylesheet or something from the previous version.)


Enironment Variable being rendered literal

You can't append anything to the value if you use environment variables. You need to use aliases for this.
In you config/general.php, add this:
'*' => [
    'aliases' => [
        'assetBasePath' => getenv('ASSET_BASE_PATH'),
        'assetBaseUrl' => getenv('ASSET_BASE_URL'),
    ],
],

Then in the asset volume settings, use the aliases in the Base URL & File system path:


How can I pre-populate my billing/shipping information within Commerce?

What I gathered from the documentation, you could try this:

{% set customer = craft.commerce.getCustomer() %}

then

{{ customer.address.businessName }}

or it might be

{{ customer.addresses.businessName }}

https://craftcommerce.com/docs/customer-model


Return the contents of a template from a custom Twig function in a module?

There is no craft() function in Craft 3 and there are no Modules in Craft 2.
You probably mix the two different versions.
Craft 3
Craft::$app->getView()->renderTemplate('/path/to/template');

Of course you need to be in the correct namespace. You have to either use Craft or do \Craft
Craft 2
craft()->templates->render('path/to/template')


Instead of allowing cross site access, I'd recommend that you instead just make sure that the site is only accessible through one domain (not both www.domain.com and domain.com). This will also improve your SEO ranking, since search engines will index both these domains as separate, duplicated content. You can rewrite the domain in your .htaccess, like this:

# Remove the www from the URL
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

# Force the www
# RewriteCond %{HTTP_HOST} !^www\.
# RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

Notice that only one of these rules should be used, if you enable both you'll get a redirection loop.

Also, make sure you use the correct domain in your Craft config.


Tasks either don't start or don't run as background processes

The issue seemed to stem from the fact that Caddy serves up PHP with fastcgi, instead of Apache or Nginx, and something to do with http requests used to start the task. AJAX requests (what my other functioning task plugins were using to kickoff) were unaffected.

Following a suggestion found here: https://stackoverflow.com/questions/11758334/fastcgi-finish-request-creates-hung-connection-when-open-session-exists

I've placed

session_write_close();
fastcgi_finish_request();

at the top of the runStep($step) function in each plugin's Task class and it resolved the issue!
Though, I'm not sure if either of the lines above have other implications.

Update
I should add, that from what I can tell, the above snippet does cause issues with tasks on Apache setups. (tasks will start yet never finish). Unless you are using Caddy Server in production, (you're probably not and using Valet for development) the snippet above should only be used as a temporary hack to get through your tasks.


Custom Labels for Address Fields Craft Commerce

I think you're looking for the attribute function:

{% set field = attribute(addressFields, key) %}
{{ field.label }}


Odd behaviour when uploading .svg Assets

Half-bug, half side-effect/undesired behavior for SVG sanitization that got added in Craft 2.6.2982 for SVGs that use embedded data.

The next release of Craft (post 2.6.2983) adds a sanitizeSvgUploads config setting (true by default) that you will be able to set to false to disable SVG sanitization.


How to make next/prev links for entries circular/endless

I'm going to assume your project section is named projects, if it's not, replace it with you section name.

Try this:

{% if nextEntry %}
    {% set nextEntryUrl = nextEntry.url %}
{% else %}
    {% set firstEntry = craft.entries.section('projects').first() %}
    {% set nextEntryUrl = firstEntry.url %}
{% endif %}

{% if prevEntry %}
    {% set prevEntryUrl = prevEntry.url %}
{% else %}
    {% set lastEntry = craft.entries.section('projects').last() %}
    {% set prevEntryUrl = lastEntry.url %}
{% endif %}

Prev Project
Next Project


You don't automatically get a Craft ID account just from making a purchase.

You'd need to manually create one at https://id.craftcms.com.

If you create one with the same email address you've made purchases with, those purchases and license.key files will automatically be tied to your account so you can manage them and the domains they are associated with.

If you make purchases with different email addresses, you'll have ways of claiming those licenses via alternative email addresses from within your Craft ID account.

If you already have a Craft ID account and you don't remember the password, you can go through the "Forgot your password" link on https://id.craftcms.com by entering your existing username or email.


Craft Commerce - No closure name "Customer"

In the latest beta update a change was made to how addresses are managed. You can no longer access the customer from the address model.

So the following does not work:
{{address.customer}}

There was only one location we did this in the example templates and that was in the file: craft/templates/commerce/_includes/address.html. We removed it from the example templates, so I expect that possibly you have not updated your example templates from the latest release. You will need to manually download the latest release from http://craftcommerce.com/download to get the latest example templates, as the 'one click update' magic does not update the example templates automatically.

If you need to access the customer for the order, it is always best to do it from the order and not the order's addresses – like this:

{{order.customer}}


Enable the user to upload background Image

You can simply add it inline to your body tag like so:

<body style="background-image: url({{ myGlobal.myAssetsField.first().url }})">

If you want to only use it with selected templates, you'd better use Craft's includeCss tag:

{% set bodyCss %}
    .myBodyClass {
        background-image: url({{ myGlobal.myAssetsField.first().url }});
    }
{% endset %}

{% includeCss bodyCss %}


Restrict a users permission to only edit 'translatable' fields on a specific site?

Of course you can just remove the fields via CSS/JS but you could as well remove those fields from the visible layout from the beginning
Craft::$app->getView()->hook(
/**
 * @param array $context
 */
    'cp.entries.edit',
    function(array &$context) {
        /** @var Section $section */
        $section = $context['section'];

        /** @var \craft\models\EntryType $entryType */
        $entryType = $context['entryType'];

        /** @var Entry $entry */
        $entry = $context['entry'];
        /**
         * Array of field handles you want to remove
         */
        $fieldsYouWantToRemove = [
            'relation',
            'tag',
            'category'
        ];

        // include certain conditions you like, either by registering custom permissions and do
        // Craft::$app->getUser()->checkPermission('myFancyPermission');
        // or just search for the current users groups
        // Craft::$app->getUser()->getIdentity()->getGroups();
        if($entry->siteId === 4 && $section->handle === 'insertYourSectionHandle' && $entryType->handle === 'yourEntryTypeHandle'){
            // grab all the fields in the layout
            foreach ($entryType->getFieldLayout()->getTabs() as $tab){
                /** @var \craft\base\Field[] $fields */
                $fields = $tab->getFields();
                foreach ($fields as $key => $field){
                    // check if the fields handle is forbidden
                    if(in_array($field->handle, $fieldsYouWantToRemove, true) === true){
                        // remove the field
                        unset($fields[$key]);
                    }
                }
                // set the fields back
                $tab->setFields($fields);
            }
        }
    }
);

'cp.entries.edit' is a hook that enables you to manipulate all variables in the given context, so you check if the entry has a certain type and is in a certain section and remove all the fields from the tabs that you don't want to show.
You can register custom permissions for each field, for each site or you can even use events to check if the content has changed if you really want to make sure they didn't manipulate the HTML
edit
You can as well check for the translation setting in the field
if($field->translationMethod === Field::TRANSLATION_METHOD_SITE){
    unset($fields[$key]);
}

or
if($field->translationMethod !== Field::TRANSLATION_METHOD_NONE){
    unset($fields[$key]);
}

Whatever you need


How do I toggle list/grid view on section index page without affect category filtering

If I don't misunderstand anything from your question, you're basically looking for a way to pass data with a link, in your case the toggle state, which is responsible for the grid / list view.

There's multiple ways to do that. See Brad's short but precise answer on an related question.

You said that you're preferably looking for a way that doesn't reveal the toggle state in the URL. I can understand the thinkings behind that, but keep in mind, that this is the only way one could save the site or post a link to someone else with the information included.

Another idea: Most sites probably use Javascript for such a toggle (I've seen many Wordpress themes with such a feature). But you'd still need to save the state somehow or completely AJAXify the relevant pages.


Not natively, but there are some SMS related plugins for Craft 3 that might be useful.

https://github.com/bertoost/Craft-3-Mailjet

https://github.com/bertoost/Craft-3-Messagebird

Otherwise, you're looking at a custom developed plugin specific to your needs.


Craft chokes on rendering large amounts of entries?

You may need to up your php memory limit. Should be good through Host CP to do, or if locally, edit the php.ini file.

Also, craft will generally max out at 100 entries as default so adding .limit(null) to a request should also help...


(content) Propagation + website in multiple languages

Hopefully someone has a better answer than me, but I’ve been in the same situation recently and the way I eventually did it was to output the field for each page in Json using element api, then create a new field that does allow different blocks per locale/site and re-import the content back into that field per locale using feed me.

I left both fields on the control panel for a period of time so the client could check everything was correct, then moved the templates over to use the new field.


Craft storage dir as linked in capistrano

I've eventually tracked down this peculiar ERR_EMPTY_RESPONSE to a php error buried deep in my apache logs - zend_mm_heap corrupted. So as it turns out nothing to do with Capistrano (or Craft) at all! This zend_mm_heap error is a php memory error that I seem to have solved by upgrading my version of PHP after unsuccessfully upping my output_buffer as suggested in this stackoverflow thread. It's worth noting that there was nothing in the Craft log about this error, no mention of anything untoward. The Craft\HttpException I found above is, I believe, essentially a '404' error as my site was running in 'offline mode' so requests had to be run through _enforceSystemStatusPermissions.

I did initially have some issues with permissions with Capistrano where my server was setting new files created by craft to 644 www-data:www-data and therefore my user couldn't edit these files, despite being in the www-data group, and so Capistrano was having a hard time removing old releases. I've fixed this by adding a umask 002 to /etc/apache2/envvar.

Now that the zend_mm_heap error seems to be behaving, and my permissions are correct, deploying with Capistrano is working rather well. For future reference, my linked dirs config looks like this:

set :linked_dirs, %w{public/resources craft/config/local craft/storage}

public/resources is my (single) craft asset source, craft/config/local are my server-specific config files as suggested here which is working nicely for me. craft/storage is obviously the craft storage folder that is shared between releases.

In terms of deployment, I think Capistrano (and other tools of a similar ilk) is great. I'm hosting my repository in a private BitBucket account and push new changes onto the master branch. I have two stages set up :production and :staging which deploy to two different vhosts on my server (staging domain is test.domain.com).

My stage configuration looks like this (for staging)

set :stage, :staging

set :deploy_to, "/var/www/domain-test"

# Allow user to define which branch to push, e.g.
# BRANCH=my-new-feature cap staging deploy
set :branch, ENV['BRANCH'] || "staging"

This last line is really helpful if I want to quickly test something on the master branch without having to merge it into the staging branch and push and deploy.

I hope that helps someone who comes across a similar issue. If anyone wants more info about my Capistrano set up, let me know. I highly recommend it as a method of deployment, once you figure out your (inevitable and strange) server errors!


How can you get an entry type's name from its handle in a template?

A simpler way to do this might be:

{{ entry.type.name }}