Why is the summary and body returning an empty object using the Element API?

Try this:

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


Silly me, this has nothing to do with charge.js, one simply can't have a button with an id="submit" as weird things will happen - see this thread

<input type="button" id="otherThanSubmit">

this works fine


Why am I getting "Variable "entry" does not exist"

You can provide some fallbacks for pages that don't have en entry like this

{{entry.title|default('here is your fallback')}}

You can do this multiple times, chaining fallbacks. Inside the fallback you can provide a global or maybe set a page at the top of your template like this:

{% set entryFallback = craft.entries.id(1).first() %}
{{entryFallback.title}}

Edit

In your specific case where you just want to return the url from the page you are on to create a twitter share button, you can just get the current Url:


If found the issue.

I didn't specify define('CRAFT_LOCALE', 'de'); in the root index.php.

It doesnt suffice to create en fr folders and specify define('CRAFT_LOCALE', 'xx'); there.


I'm assuming mod_headers is installed & active? Otherwhise I can't say why the .htaccess rules are not applied (devOps is not my forte) but you could set them through the twig template.

See here for the tag to use. Basically it comes down to something like this (untested):

{% header 'X-Xss-Protection "1; mode=block"' %}
{% header 'X-Content-Type-Options "nosniff' %}
{% header 'X-Frame-Options ALLOWALL' %}
{% header 'Strict-Transport-Security "max-age=31536000"' %}
{% header 'Referrer-Policy no-referrer' %}

You can make those in a block and just include the block on all the relevant pages.


Craft license: what is considered a "dev-sounding subdomain"?

http://staging-subdomain.mysite.com would be considered a dev domain because we look for any of those keywords in the subdomain part of the URL.
http://www-next.mysite.com would be considered a public domain because it does not meet any of the criteria.


Looping through an assets field type within a matrix field that's eager loaded

Eager loading an Assets field simply means that instead of block.sectionBlockImages returning an ElementCriteriaModel, it'll return an array. This means that you can't do stuff like block.sectionBlockImages.first(), but have to use brackets notation – i.e. block.sectionBlockImages[0] to access the first Asset.

Looping over the field would look exactly the same, though. So you'll need to change this

{% for images in block.sectionBlockImages %}
    {% set image = block.sectionBlockImages[0] ?? null %}

{% endfor %}

to this

{% for image in block.sectionBlockImages %}

{% endfor %}

...and you should be good.


If you only want to style how the link looks visually, and need a work-around, you could use my Redactor Styles for Craft plugin. If you add an inline style to the plugins Styles JSON object like this:

[
  {
    "btnName":"Action button",
    "className":"btn-action",
    "spanClass":"btn-action"
  }
]

Depending on which order the user creates the link and marks the text/link and select style, you now can get the following markup from your rich text field:

A link
A link

If this works for you or not depends on your design. Unless there are some styles on the  that can't be removed, you could style it so that it looks the same by using:

.btn-action > a,
a > .btn-action { ... }

You could also instruct your users to always create the link, then select the style, or the other way around. But, it's of course a very fragile solution.

Thinking of making a new plugin just for creating more advanced links, the built in one doesn't really cut it.


I suggest to refactor again and use dropdown fields for the path to your partials instead of the channel entries with asset fields you currently have. This also keeps your twig files more secure (your asset folder is above the web root!).

Set up three dropdown fields ('pathSideBar', 'pathPrimary' and 'pathFullPage') to do
the grouping and one Matrix Block for each of them.

{% if block.type == 'widgetSideBar' %}

    {% set widgetPath = '_includes/sidebar/' ~ block.pathSideBar ~ '.html' %}
    {% include widgetPath only %}

{% elseif block.type == 'widgetPrimary' %}

    {# ... #}

{% endif %}


Error: Call to undefined function Craft\mb_convertOcase() after updating to 2.6.3017

I performed a manual upgrade as documented at https://docs.craftcms.com/v2/updating.html#manually-updating and the error automagically disappeared. Therefore, it looks like there was a glitch in the One-click Updating in this particular case.


You left off the .first().

{% set notFound = craft.entries.section('page404').first() %}

Without that, the Element Criteria Model will default to .find().

first - Returns a single Entry Model.
find - Returns an array of Entry Models.

It doesn't matter this this is a Single section! All Element Criteria Models have the same behavior, whether they're fetching data from a Single, Channel, or Structure.


String interpolation in Twig only works with double-quoted strings.
Change the .startDate line to .startDate(['and', ">= #{start}", "< #{end}"]) and it should work.


How to merge SEOmatic object in Craft 3?

Based on the SEOmatic docs, something like this should do the trick nicely:

{% do seomatic.meta.seoTitle("my title") %}


Why does Bootup.php run with PHP 5.4.16 from with Craft script but PHP 7.4.10 from the terminal command line?

Where did you define your aliases? If you haven't already, you could start by adding directives for both php and composer in your .bash_profile.
The file should contain something like (alter paths as appropriate):
# Include the location of the PHP 7.4 binary in your path
export PATH=/opt/plesk/php/7.4/bin:$PATH
# Ensure that any calls to composer are run with the PHP 7.4 binary
alias composer='/opt/plesk/php/7.4/bin/php /usr/lib64/plesk-9.0/composer.phar'

Log out/in (or source .bash_profile) and run php -v to check it's picking up the correct binary, then have another go.


You can create new template files for your second locale and simply use Twig include to only maintain one template for all of your locales.

projekte.html:

{% include 'projects.html' %}

Use a locale specific subfolder (craft/templates/de/) to separate the german templates from your main / first locale templates (see the Template Localization article in the Docs on how this works).

Another way to handle localized URIs is to not use "URI to template matching" (pt. 6 in the Routing article) but configure an entry that loads your template instead (pt. 4).

Create a single section with "projects.html" for the template that should get loaded if the single's URL is requested. The template's filename is irrelevant for the URI matching and you can set the entry's slug to whatever you want in both of your locales.

Before creating many single sections now, also consider using a "Pages" structure section instead.


Running into permission issues using Vagrant on Ubuntu

The article Local Development with Vagrant / Homestead I wrote is about Homestead (which is great), but much of it applies to Vagrant in general as well.

Included in it are some performance tips, as well as how to solve the filesystem permissions with vagrant-bindfs


You could achieve this by using a Matrix field for complex content or the awesome Super Table field for something a little more basic

Depending on how complicated the content is you are putting in the tabs would determine if you would use either the Matrix or Super Table fields respectively.

Take a look at the Super Table plugin if you aren't already using it.

https://github.com/engram-design/SuperTable


Autogenerated PDF Thumbnail using PDFThumb in a Matrix Field

You mixed in some code from the documentation resulting in a wrong variable name..
{% set pdfBlocks = entry.inhaltMatrix.all() %}
    {% if pdfBlocks|length %}
        {% for block in pdfBlocks %}
            {% if block.type == "pdf" %}
                {% if block.pdfFile %}
                    {% set rel = block.pdfFile.one() %}
                    {% if rel %}
                        {{ rel.title }}

                    {% endif %}
                {% endif %}
            {% endif %}
       {% endfor %}
{% endif %}

Also be sure to go to the plugins settings and set the appropriate assets paths.


“Service Unavailable” message when not logged as admin

Make sure your site is enabled under Settings ➞ General ➞ System Status.

Also, check your craft.log files under /craft/storage/runtime/logs/craft.log.


Go in to the structured section's settings (Settings->Sections->Structure Name)) and set the "Max Levels" property.


Can't install Craft on a GoDaddy shared hosting server

Thanks for the advice guys. It's helped me rule out the directories being an issue (sort of). Turns out that I was able to access the files in the craft directory all along. My issue related to the database settings.

Typically, the 'server' setting in the 'craft/config/db.php' folder is set to 'localhost'. But for GoDaddy you need to use your hostname. Get that by following these instructions.

You will also need to amend your 'craft/config/general.php' settings to include:

'omitScriptNameInUrls' => false,

At this time, I am unable to get clean-urls working on my Craft install. When 'omitScriptNameInUrls' is set to true, and I try to access any page (besides the homepage), I get that Internal Server Error again. I may open an new question for this as it seems to be slightly unrelated now.


Yup! Just turn on devMode in your general config:

return array(
    'devMode' => true,
);

And then just open up a console (Firebug, Chrome, etc) and look in the profiling summary report.


Eager load commerce order data in custom ElementExporter for Users

Your code looks like it actually has a further problem that you're only fetching the first order for a given user. Rather than eager loading (which is basically creating joins so that the relevant data is fetched in one go), why not use a hash map to look up each customer's set of orders? So, outside your users loop, create a separate query to fetch all orders and use GROUP BY to group them by user id. You can then reference each sub-array by its user id inside the users loop.


How to connect to a Remote DB using CraftCMS 3.1+

Probably the database doesn't listen for connections from the outside world. So yeah you'd need some kind of an ssh tunnel to connect to it. I think you may find, though, that doing development via a remote db can be pretty slow; check out Database & Asset Syncing Between Environments in Craft CMS


Multiple Service/Variable/Controller plugin files

When calling services, you should not include "service" in method name.

Try return craft()->myPlugin_other->testing();


Contact Form Extensions - Checkbox Templating

You're pretty close. In your input you have name="message[type][]". The little [] at the end there means means the data will be stored in an array, something like:

submission: {
  message: {
    type: ['New', 'Used']
  }
}

You have two options here:

Option one

You can change your inputs to be name="message[type]" instead of [type][]. This should result in a data structure more like you're expecting

submission: {
  message: {
    type: 'New'
  }
}

Then your conditional check can be kind of like you have it, but this won't allow multiple values (not sure if you want those or not).

Option Two

Update your conditional check and output to properly output the array values. This would mean something more like:

{% for type in submission.message.type %}
  <p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">
    Type of Quote: {{ submission.message.type }}
  </p>
{% endfor %}


Only execute twig block if a Matrix radio has a certain value

You can filter Matrix blocks on field values – in your case, the field "grouping":

{% for sponsor in sponsors.sponsors.grouping( 'Left column' ) %}

To conditonally output the whole wrapping div and section heading for the left and right aligned sponsors respectively, you can sort the sponsors into two arrays (left and right) beforehand, and then check the length property of those arrays before outputting the relevant markup.

Full example:

{# Pull all sponsors from the Matrix field #}
{% set sponsors = entry.sponsors.type( 'sponsors' ) %}

{# Filter sponsors into two arrays by "grouping" field value #}
{% set sponsorsLeft = sponsors.grouping( 'Left column' ) %}
{% set sponsorsRight = sponsors.grouping( 'Right column' ) %}

{# I can haz sponsors in the left column? #}
{% if sponsorsLeft | length %}

LEFT COLUMN TITLE

    {% for sponsor in sponsorsLeft %}

            {{ sponsor.sponsorName }}

    {% endfor %}

{% endif %}
...
{# I can haz sponsors in the right column? #}
{% if sponsorsRight | length %}

RIGHT COLUMN TITLE

    {% for sponsor in sponsorsRight %}

            {{ sponsor.sponsorName }}

    {% endfor %}

{% endif %}


Getting line items + shipping and their tax rates in a plugin

Currently there is a limitation on the adjuster system, in that there is no history of every adjustment made to the order for most adjusters. This is a limitation of the current architecture. I will walk through the current architecture and explain the changes that we plan to release in Craft Commerce 2:

Let's start with an order that looks like this:

itemA price        10
      shippingCost 0
      discount     0
      tax          0
      total        10

itemA price        20
      shippingCost 0
      discount     0
      tax          0
      total        20

baseShippingCost   0
baseTax            0
baseDiscount       0

order total        30

In the above order, there has been no adjustments run "over" the order yet. Lets think of this as the state of the order at the beginning of a recalculation.

When the adjuster recalculation starts it clears all the adjustable values (shippingCost, discount, tax) from the line items, and also clears the 'base' values on the order (baseShippingCost, baseDiscount, baseTax). It also resets the totals.

The first adjuster to run is the discount adjuster. It will apply any matching discounts by modifying the amount of discount on each line item as well as the baseDiscount amount for order level discounts.

Let's say that 2 discounts were applied to the order. One that takes $1 off each line item and $10 of the total order, and the second discount taking $5 off the total order and $2 off each line item. Since there are 2 discounts, the discount adjuster is deciding to return 2 adjustments to the order, one totaling $12 and the other totaling $9. The order will then look like this:

itemA price        10
      shippingCost 0
      discount     -3
      tax          0
      total        7

itemA price        20
      shippingCost 0
      discount     -3
      tax          0
      total        17

Adjustment1 (discount) -12
Adjustment2 (discount) -9

baseShippingCost   0
baseTax            0
baseDiscount       -15

order total        9

The total of the order is now $9. Currently, there are 2 ways to get to this total:

1)

all line item totals (which include each line item's `shippingCost`, `tax`, `discount`)
+
`baseShippingCost`, `baseDiscount`, `baseTax`

2)

adjustments
+
all line item price

Both of these methods get to the same total, but the problem with this is that BOTH methods still do not contain all the information. For example, the line itemA's discount is -3 but it is made up of 2 discount adjustments, -1 and -2. There currently is no way to fully know how that value came to be. The same goes for the total adjustment amount, it only stored a total adjustment made to the order, with no breakdown.

This is not ideal, but we tried to combat it with an attribute on the adjustment model:

OrderAdjustmentModel::optionsJson

This column stores an array of line item IDs (in array key lineItemsAffected) that the adjustment modified, and it also stores information about the modification rules used like the discount's attributes.

For example, in AdjustmentA all of the attributes (pricing rules) of the discount are serialized into a json array and stored in the optionsJson.

Unfortunately the 2 ideas above do not help in understanding all adjustments made to order without a lot of work.

Solution in Craft Commerce 2:

We have been working on Commerce 2 with a solution to the above issues.

1) All adjustments made to the line items are now stored as seperate adjustments on the order. For example, in the above order AdjustmentA would
create 3 adjustments, 1 to each line item for the discount, and one to the order.

All adjustments will be for single amount, not combined amounts. This means adjusters will no longer do this: $order->baseShippingCost += 10. They will not mutate the value, only add a new adjustment of 10.

2) All line item fields that an adjuster modifies are removed. This means shippingCost, tax, discounts are no longer stored on the line item. The attributes will be replaced with magic getters that add up all adjustments made to the line item for a particular adjustment type. We will probably still store them in the database but in a column called 'adjustment totals' as json (so you can still do DB queries on them).

3) All order level baseShipping, baseTax, baseDiscount attributes will be removed and replaced with order level adjustments.

This means adjusters now will return more adjustment models (with more lines added to the order), but the developer can still use the magic methods to show the total amount of shipping, discounts, tax at the line item or order level.

Let me know if you have any questions, and I will update the answer.

Note1: The migration to the new order calculation system will turn each of the line item's adjustable amounts (shippingCost, tax, discount) and baseX amounts into line item adjustments. We will archive the old adjustment totals (or zero them out so they can still show the data). This will not lose any order information, nor add any, but will be compatible with the new order recalculation adjustment system.

Note2: The issue with supplying information to 3rd parties ONLY as line items is that there can be order level adjustments that live outside of the line items. You would need to figure out how to send that additional pricing information yourself.


How to use checkboxes to filter categories on the front end?

Here is how I did it at my end for the templating side of things:

Set the queries you need and merge them into arrays like below. Please be aware this was done for craft commerce 2 products but the same can be applied to entries too as it is the same logic.

        {% set types = craft.categories.group('flowerTypes') %}
        {% set sizes = craft.categories.group('size') %}
        {% set prices = craft.categories.group('priceRanges') %}

        {% set flowersQuery = craft.app.request.getParam('flowers') | join(',') %}
        {% set sizeQuery = craft.app.request.getParam('size') | join(',') %}
        {% set priceQuery = craft.app.request.getParam('price') | join(',') %}

        {% set relationParam = [] %}
        {% set sizeParam = [] %}
        {% set flowersValues = [] %}
        {% set collectionValues = [] %}
        {% set sizeValues = [] %}
        {% set priceValues = [] %}

        {% set relationParam = ['and',{targetElement: category}] %}

        {% if flowersQuery != '' %}

            {% for queryFlower in flowersQuery|split(',') %}
              {% set flowerCategory = craft.categories.slug(queryFlower).one() %}
              {% set relationParam = relationParam|merge([{targetElement: flowerCategory}]) %}
              {% set flowersValues = flowersValues|merge([flowerCategory.title]) %}
            {% endfor %}
        {% endif %}

        {% if sizeQuery != '' %}

            {% for querySize in sizeQuery|split(',') %}
              {% set sizeCategory = craft.categories.slug(querySize).one() %}
              {% set sizeParam = sizeParam|merge([{targetElement: sizeCategory}]) %}
              {% set sizeValues = sizeValues|merge([sizeCategory.title]) %}
            {% endfor %}
        {% endif %}

        {% if priceQuery != '' %}

            {% for queryPrice in priceQuery|split(',') %}
              {% set priceCategory = craft.categories.slug(queryPrice).one() %}
              {% set relationParam = relationParam|merge([{targetElement: priceCategory}]) %}
            {% endfor %}
        {% endif %}

## this is where we set the query to grab the relational values

        {% set products = craft.products({
            relatedTo: relationParam,
            hasVariant: {
                relatedTo: sizeParam
            }
        }).status('live') %}

Set the markup for the filters, replace with whatever you use to do the front-end stuff

All {{category.title}} Flowers

                    {% include "_partials/buttons/filter" %}
                    {% include "_partials/buttons/clear_filters" %}

                <form id="formTest" class="productFilter w-100 flex-ns flex-wrap flex-row justify-between items-start">

Filter by Price

                                <svg width="14" height="14" class="svg-blue v-mid db h-100">
                                    <use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"></use>
                                </svg>

                            <fieldset class="pa0 ma0 bw0">

<input value="all-prices" class="input-reset checked-filters" type="checkbox" name="collections[]">All prices

                                {% for p in prices.all() %}

                                        <input value="{{ p.slug }}" data-value="{{p.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="price[]" {% if p.slug in priceQuery %}checked{% endif %}>{{p.title}}

                                {% endfor %}
                            </fieldset>

Filter by Size

                                <svg width="14" height="14" class="svg-blue v-mid db h-100">
                                    <use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"></use>
                                </svg>

                            <fieldset class="pa0 ma0 bw0">

<input value="all-sizes" class="input-reset checked-filters" type="checkbox" name="collections[]">All sizes

                                {% for s in sizes.all() %}

                                        <input value="{{ s.slug }}" data-value="{{s.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="size[]" {% if s.slug in sizeQuery %}checked{% endif %}>{{s.title}}

                                {% endfor %}
                            </fieldset>

Filter by Flower type

                                <svg width="14" height="14" class="svg-blue v-mid db h-100">
                                    <use class="no-barba" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/icons.svg#arrow_down"></use>
                                </svg>

                                    <input value="all-types" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="flowers[]">
                                    All flowers

                                {% for t in types.all() %}

                                        <input value="{{ t.slug }}" data-value="{{t.title}}" class="absolute left-0 top-0 h-100 w-100 input-reset checked-filters ttc z-2" type="checkbox" name="flowers[]" {% if t.slug in flowersQuery %}checked{% endif %}>{{t.title}}

                                {% endfor %}

                </form>

Then with this it builds the url query for you to grab the products/entries you need from the url.

I then use a bit of js to manipulate the url to append the checked values to the url and do Ajax to get the entries:

site.getProducts = function(url) {

            const requestUrl = url;

                const productWrapper = document.getElementById('productWrapper')
                addClass(productWrapper, 'loading')

                $.ajax({
                    type: 'get',
                    url: requestUrl
                })
                  .fail(function( jqXHR, response ) {

                    const errorMsg = jqXHR.responseText

                  })
                  .done(function( response ) {

                    var parsedResponse = $.parseHTML(response);
                    var result = $(parsedResponse).find("#productWrapper .product-container"),
                        amount = $(parsedResponse).find("#filtered-area").data('product-count');

                    removeClass(productWrapper, 'loading')

                    loadedProductCount = amount;

                    if(!loadedProductCount > 0){
                        $('.product-count').parent().html('No products match your filters.');
                        $('#filtered-area').addClass('vh-100');
                    } else {
                        $('#open-filter').html('See '+loadedProductCount+' results');
                        $('#open-filter').css({
                            'borderColor': '',
                            'borderWidth': '',
                            'borderStyle': '',
                            'color': ''
                        });
                        $('#filtered-area').removeClass('vh-100');
                    }

                    $('#productWrapper').html(result);

                  });

};

site.addUrlQuery = function(event) {

        var collections = '',
            flowers = '',
            size = '',
            price = '',
            tempArray = [],
            mergedArray = [];

        var checkedFlowers, checkedSize, checkedCollections, checkedPrice;
        const node = document;
        checkedCollections = node.querySelectorAll('input[name="collections[]"]:checked');
        checkedFlowers = node.querySelectorAll('input[name="flowers[]"]:checked');
        checkedSize = node.querySelectorAll('input[name="size[]"]:checked');
        checkedPrice = node.querySelectorAll('input[name="price[]"]:checked');

        const arrCollections = Array.prototype.map.call(checkedCollections, function (e) {return e.value;}),
              arrFlowers = Array.prototype.map.call(checkedFlowers, function (e) {return e.value;}),
              arrPrice = Array.prototype.map.call(checkedPrice, function (e) {return e.value;}),
              arrSize = Array.prototype.map.call(checkedSize, function (e) {return e.value;});

        mergedArray.push(arrCollections+arrFlowers);

        tempArray.push(arrCollections);

        if(tempArray.length !== 0){
         collections+='collections='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrFlowers);

        if(tempArray.length !== 0){
         flowers+='flowers='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrPrice);

        if(tempArray.length !== 0){
         price+='price='+tempArray.toString();
         tempArray = [];
        }

        tempArray.push(arrSize);

        if(tempArray.length !== 0){
         size+='size='+tempArray.toString();
         tempArray = [];
        }

        // const url = '?'+collections+'&'+flowers,
        //    requestUrl = url;

        const url = '?'+collections+'&'+flowers+'&'+price+'&'+size,
                requestUrl = url;

        window.history.pushState('', '', url);

        if(url.indexOf('?') != -1){

            site.getProducts(url);

        }

};

var cboxArray = [];
let checkItems = '';

  function itemExistsChecker(cboxValue) {

    var len = cboxArray.length;

    if (len > 0) {
      for (var i = 0; i < len; i++) {
        if (cboxArray[i] == cboxValue) {
          return true;
        }
      }
    }

    cboxArray.push(cboxValue);

  }

  $(".checked-filters").each(function() {

    var cboxValue = $(this).data('value');
    if(window.location.href.indexOf('?') != -1){
        var cboxChecked = null;
    } else {
        var cboxChecked = localStorage.getItem(cboxValue) == 'true' ? true : false;
    }

   //On page load check if any of the checkboxes has previously been selected and mark it as "checked"
    if (cboxChecked) {

      $(this).prop('checked', true);
      itemExistsChecker(cboxValue);

    }

    // On checkbox change add/remove the value from the array based on the choice
    $(this).change(function() {

        site.addUrlQuery();

        localStorage.setItem(cboxValue, $(this).is(':checked'));

        if ($(this).is(':checked')) {

            itemExistsChecker(cboxValue);

        } else {

            // Delete the vehicle value from the array if its checkbox is unchecked
            var cboxValueIndex = cboxArray.indexOf(cboxValue);

            if (cboxValueIndex >= 0) {
              cboxArray.splice( cboxValueIndex, 1 );
            }

        }

        if(cboxArray.length > 1){
            checkItems = cboxArray.length +' filters selected'
        } else {
            checkItems = cboxArray.length +' filters selected'
        }

        $('.filtered p').html(cboxArray.join(", "));
        $('.filtered-amount').html( checkItems );

    });

  });

    if(cboxArray.length > 1){
        checkItems = cboxArray.length +' filters selected'
    } else {
        checkItems = cboxArray.length +' filters selected'
    }

    $('.filtered p').html(cboxArray.join(", "));
    $('.filtered-amount').html( checkItems );

    $('.product-count').html(loadedProductCount);

I really hope this gets you on your way here.

Any q's please mention me and ask.


How would I create a select element with the 14 days from today as options

You're close! If there's one thing I've learned about Twig, it's easy to overthink it...

Create an array with the first date, then merge the rest of dates into the same array with a for loop. Just increment the day in the range:

 {% set rangeOfDates = [ now|date("l dS F Y") ] %}

 {% for i in range (1,13) %}

     {% set rangeOfDates = rangeOfDates|merge( [ now|date_modify("+" ~ i ~ " day")|date("l dS F Y") ]) %}

{%endfor%}

Then in your forms macro:

{{ forms.select({
    options: rangeOfDates
}) }}


Searching Multiple Categories in Craft CMS

I might be missing something, but your code is missing a {% for entry in entries %} loop wrapped around your <div>.


Javascript event on save for custom field

Attach a submit event to the #entry-form element:

$('#entry-form').submit(function(e) {
    // code run on submit here
});


How to check if on a channel/category index?

That would require some sort of convention on your end which identifies what makes up a category/channel index page, as channels and categories don’t actually have an “index URL”.

For example you could decide that all sections’ index pages should have a URI that matches the section’s handle (not necessarily a good idea though, in the event that you want a URI that includes dashes). In that case you could do something like:

{% set segments = craft.request.getSegments() %}
{% if segments|length == 1 %}
    {% set section = craft.sections.getSectionByHandle(segments[0]) %}
    {% if section %}
        We’re on a section index!
    {% endif %}
{% endif %}

There is no corresponding function for getting a category group by its handle at this time, however.

A better approach might be to just leave it up to the templates to define whether they are supposed to be an index template. So in news/index.html, the template that you want to treat as the News index template, for example, you could put this:

{% set isIndex = true %}

Any layout templates that the index template extends will then have access to that isIndex variable.


Unless absolutely everything has been moved to /uploads/ (which is unlikely), the easiest way to do it is with 3 regex's:

/hero/(.*) -> /uploads/hero/$1

/books/(.*) -> /uploads/books/$1

/slider/(.*) -> /uploads/slider/$1

vide: regexr.com


Commerce & PayPal - What does "Solution Type" mean?

Ignore the terminology, it really makes no sense. What it should say is this...

Require customers to use a PayPal account?

[Sole] No, a PayPal account is optional. Customers can still choose to pay with a credit card instead.
[Mark] Yes, a PayPal account will be required to complete a purchase.

Here's a screenshot of the documentation...

So why did PayPal decide to call this particular choice "Solution Type"?

And what do "Sole" and "Mark" actually mean?

The world may never know.


Looks like PHP is running out of memory.  You can edit your php.ini file's memory_limit setting to something higher than 32M, which is probably what it's set to right now.  Bump it up to 64M or 128M and restart Apache and you should be set.


front end date field format doesn't work? fields[dateField][date]

I suspect it might be your values. Try testing with this hard coded in and see if it works:

<input type="hidden" id="endDate" name="fields[endDate][date]" value="12/30/2017" />
<input type="hidden" id="endTime" name="fields[endDate][time]" value="2:15 AM" />

I always reference what's on this StraightUpCraft guide, and I try to be as exact as possible to the examples. You can also just inspect date fields inside a saved entry in the CMS to see what the values look like and mimic that on the front end.


Redirect IE7 or below users to a new page

I agree with Bryan, personally I like to use the Browser-Update.org notification.

Nevertheless, if you want to use .htaccess just make sure you put your redirect code before Crafts routing:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Redirect old Browsers
    RewriteCond %{HTTP_USER_AGENT} "MSIE [1-7]" [NC]
    RewriteRule ^(.*)$ http://something.com/else [R=301,L]

    # Crafts routing
    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]
</IfModule>


Redactor won't allow simple styling in heading tags

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

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

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


Add items to user's cart in Craft Commerce 2

In Commerce, a User (or guest with an email address for that matter) can have multiple carts (or unfinished orders).
So we need to get the most recently active one. Something like this should work:
$query = Order::find();
$query->id($whateverId); // you could also use $query->email
$query->isCompleted(false);
$query->orderBy('dateCreated DESC');
$cart =  $query->one();

... // rest of your code


Output two date languages on the same page without localization

The Craft/Twig dateFilter that you're using will currently only translate the string into the current locale the site is set to.

You could probably write a plugin that added its own Twig Extension that added its own filter... let's call it |translatedDate and you could pass in the target locale code as a parameter |translatedDate('en_us').

That filter would do something like:

$currentLanguage = craft()->getLanguage();
craft()->setLanguage('en_us');
...
// Do logic similar to Craft's existing date filter
...
craft()->setLanguage($currentLanguage);


How do I create a well formed CSV or XML to succesfully import entries with assets and categories?

I used FeedMe successfully and this is what I used. The images have to be already present as assets in Craft(ftp and then update asset indexes). Having the full url in the images part stumped me too. In this example I pulled the images twice because in my EE build I was using the first image of many to create a preview image and in craft I actually created a preview image field.

<entry>
    <entry_date>{entry_date format="{DATE_ATOM}"}</entry_date>
    <title>{title}</title>
    <slug>{url_title}</slug>
    <price>{product_price}</price>
    <dimensions>{product_dimensions}</dimensions>
    <description>{product_description}</description>
    <notes>{private_notes}</notes>
    <location>{product_location:title}</location>
    <number>{product_number}</number>
    <message><![CDATA[{product_message}{option}, {/product_message}]]></message>
    <status>{status}</status>
    <category><![CDATA[{categories}{category_name}, {/categories}]]></category>

    <images><![CDATA[
    {finalproductimages}
        {filename}.{extension},
    {/finalproductimages}]]></images>

    <preview><![CDATA[
    {finalproductimages limit="1"}
        {filename}.{extension},
    {/finalproductimages}]]></preview>

</entry>


Selecting a random entry based on conditional

I Think this should work:

{% for entry in craft.entries.section('team').limit(1).order('RAND()').schedulerBio(':notempty:') %}
   ...stuff
{% endfor %}


So something is definitely wrong; you should be seeing response times of around 300-500ms or so. What I'd suggest doing is profiling things on the Craft side as per the Profiling your Website with Craft CMS 3’s Debug Toolbar article.

You'll at least be able to see exactly what the bottlenecks are from a Craft perspective, and then see how much overhead is being added by the webserver.

If you find that it's slow on the Craft end of things, you may consider making sure that you are properly utilizing the cache tag


Display entries related to a category (only bottom level)

You can loop through your top level categories and check if descendants are available. Then collect the relevant category IDs that you can later use to filter the ElementCriteriaModel.

{# Define array before loop #}
{% set bottomLevelCatIds = [] %}

{# Get top level categories only #}
{% set topLevelCats = craft.categories.group('compositions').level(1) %}

{# Loop through categories and collect relevant IDs #}
{% for topLevelCat in topLevelCats %}

    {# Check for child categories #}
    {% if craft.categories.descendantOf(topLevelCat).descendantDist('1')|length %}

        {# Merge child category IDs #}
        {% set 2ndLevelCatIds = craft.categories.descendantOf(topLevelCat).descendantDist('1').ids() %}
        {% set bottomLevelCatIds = bottomLevelCatIds|merge(2ndLevelCatIds) %}

    {% else %}

        {# Merge to level category ID #}
        {% set bottomLevelCatIds = bottomLevelCatIds|merge([topLevelCat.id]) %}

    {% endif %}

{% endfor %}

{# Get the bottom level category models #}
{% set categories = craft.categories.id(bottomLevelCatIds) %}


Having a plugin trigger on entries.onSaveEntry if a Lightswitch is turned on

Yes, it's available in $event->params['entry'].

$entry = $event->params['entry'];
if ($entry->myLightswitch) {
    // do things
}


Craft 3 Field Plugin not firing $view->registerJs in entry versions

This is by design. Revisions are not meant to be editable.


How can I update a checkbox from a plugin?

If I understand correctly you're talking about a Checkboxes field type. Because you can have multiple checkboxes within such a field, Craft stores an array to the database.

Try if this works:

$entry->setContentFromPost(array(
    'agreeToTerms' => array(
        craft()->request->getPost('fields.agreeToTerms'),
    )
));


Translating Craft form error message labels

You can't translate that field. I've tried it too once but it can't be done right now without effort because craft\elements\Userhas no attributeLabels() function in it in order to translate the attribute so all Yii2 does is to change newPassword to New Password but it doesn't translate anything.

You can either submit a feature request for it or do some hacky stuff.

I submitted a feature request in their git

Edit 13.08.2018 This commit changed it, you'll be able to translate those messages now


Entries from matrix should not appear in loop

You are on the right track, to “collect” the entry IDs you have to use the merge filter in your Matrix loop though.

{% set highlightProfileSingleIds = [] %}

{% for profile in highlightProfiles %}
    {% set ids = profile.hightlightProfileTeaser.ids() %}
    {% set highlightProfileSingleIds = highlightProfileSingleIds|merge(ids) %}
{% endfor %}


How can I append a structure entry and set its order?

If you're adding them all as new entries anyway, why not just sort the records before you create the entries?

usort($records, array($this, 'sortCategoriesByPosition'));

Add that before your foreach loop, then...

private function sortCategoriesByPosition($a, $b)
{
    if ($a->position == $b->position)
        return 0;

    return ($a->position < $b->position) ? -1 : 1;
}

Stop trying to make things harder than they should be.


Apparently I am "to close to the painting" here and completely missed a simple answer. In my case, I was going to the wrong URL completely.

Bad: http://192.168.10.95/public/index.php/admin/dashboard

Good: http://192.168.10.95/admin

As you can see, USER error here. Thank you for the assistance everyone!


The original composer file that caused the error above looked like this:

{  "name": "craftcms/craft",
"description": "Craft CMS",
"keywords": [
"craft",
"cms",
"craftcms",
"project"
],
"license": "MIT",
"homepage": "https://craftcms.com/",
"type": "project",
"support": {
"email": "support@craftcms.com",
"issues": "https://github.com/craftcms/cms/issues",
"forum": "https://craftcms.stackexchange.com/",
"source": "https://github.com/craftcms/cms",
"docs": "https://craftcms.com/docs",
"rss": "https://craftcms.com/changelog.rss"
},
"require": {
"craftcms/cms": "3.0.13.1",
"vlucas/phpdotenv": "v2.4.0",
"craftcms/ckeditor": "1.0.0-beta.2",
"craftcms/redactor": "2.1.5",
"cebe/markdown": "1.1.2",
"composer/ca-bundle": "1.1.1",
"composer/composer": "1.6.3",
"composer/semver": "1.4.2",
"composer/spdx-licenses": "1.3.0",
"craftcms/oauth2-craftid": "1.0.0.1",
"craftcms/plugin-installer": "1.5.2",
"craftcms/server-check": "1.1.1",
"creocoder/yii2-nested-sets": "0.9.0",
"danielstjules/stringy": "3.1.0",
"doctrine/lexer": "v1.0.1",
"egulias/email-validator": "2.1.4",
"elvanto/litemoji": "1.3.1",
"enshrined/svg-sanitize": "0.8.2",
"ezyang/htmlpurifier": "v4.10.0",
"guzzlehttp/guzzle": "6.3.3",
"guzzlehttp/promises": "v1.3.1",
"guzzlehttp/psr7": "1.4.2",
"justinrainbow/json-schema": "5.2.7",
"league/flysystem": "1.0.44",
"league/oauth2-client": "2.2.1",
"mikehaertl/php-shellcommand": "1.2.5",
"paragonie/random_compat": "v2.0.12",
"pixelandtonic/imagine": "v0.7.1.3",
"psr/http-message": "1.0.1",
"psr/log": "1.0.2",
"seld/cli-prompt": "1.0.3",
"seld/jsonlint": "1.7.1",
"seld/phar-utils": "1.0.1",
"swiftmailer/swiftmailer": "v6.0.2",
"symfony/console": "v3.3.6",
"symfony/debug": "v3.3.6",
"symfony/filesystem": "v3.3.6",
"symfony/finder": "v3.3.6",
"symfony/polyfill-mbstring": "v1.8.0",
"symfony/process": "v3.3.6",
"twig/twig": "v2.4.8",
"yiisoft/yii2": "2.0.15.1",
"yiisoft/yii2-bootstrap": "2.0.8",
"yiisoft/yii2-composer": "2.0.6",
"yiisoft/yii2-debug": "2.0.13",
"yiisoft/yii2-queue": "2.0.2",
"yiisoft/yii2-swiftmailer": "2.1.1",
"zendframework/zend-escaper": "2.6.0",
"zendframework/zend-feed": "2.8.0",
"zendframework/zend-stdlib": "3.2.0",
"solspace/craft3-freeform": "2.2.1"
},
"autoload": {
"psr-4": {
  "modules\\": "modules/"
}
},
"config": {
"optimize-autoloader": true,
"platform": {
"php": "7.0"
}
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@composer dump-autoload -o",
"@php craft setup/welcome"
]
}
}

So I removed "enshrined/svg-sanitize": "0.8.2", from the list in the compser file, and ran the update. The next error was given for Twig. So I deleted ""twig/twig": "v2.4.8" from the file, and ran the update again. This time it was successful, and the composer file now looks like this:

{
"name": "craftcms/craft",
"description": "Craft CMS",
"keywords": [
"craft",
"cms",
"craftcms",
"project"
],
"license": "MIT",
"homepage": "https://craftcms.com/",
"type": "project",
"support": {
"email": "support@craftcms.com",
"issues": "https://github.com/craftcms/cms/issues",
"forum": "https://craftcms.stackexchange.com/",
"source": "https://github.com/craftcms/cms",
"docs": "https://craftcms.com/docs",
"rss": "https://craftcms.com/changelog.rss"
},
"require": {
"craftcms/cms": "3.0.20",
"vlucas/phpdotenv": "^2.4.0",
"craftcms/redactor": "2.1.5"
},
"autoload": {
"psr-4": {
"modules\\": "modules/"
}
},
"config": {
"optimize-autoloader": true,
"platform": {
"php": "7.0"
}
},
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@composer dump-autoload -o",
"@php craft setup/welcome"
]
}
}

So the update seems to remove a lot of the required references in the composer file. I tried doing this on a backup install first before doing the same on the live install.


The site was on amazon AWS (without load balancing), so I set an appId in the config/general.php file to keep the session "sticky", even if the filepaths were "inconsistent" on a single server instance. The autogenerated appId based on filepath must have been interacting weird with Amazon's cloud setup.

return array(
    '*' => array(
    'appId' => 'myAppId',
),


Order entries based on date field in the Control Panel

The CpSortableCustomColumns plugin lets you sort your element index tables on custom fields. Sounds like it does exactly what you want.


Looking for a good explanation on Craft login and if it is using persistent cookies or session cookies, etc...?

You're probably looking for the userSessionDuration config setting where you can adjust the length of time an authenticated Craft session should have (or just have it session/browser based).

Other related session config settings you might be interested in:

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

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


How can i check an entry author's user group?

As Fabio pointed out, i'd managed to miss the isInGroup method. Slightly embarrassing!

So for anyone else looking to do what i asked, i changed my code to the following:

{% if entry.author.isInGroup('authors') %}

and it works perfectly now.


Craft CMS 3 uses Yii2 Asset Bundles for AdminCP resources. This lets it handle dependencies such as certain scripts not loading before jQuery, for example.

Remember that many Craft CMS 3 components need to publish JS/CSS resources to work, as do third party plugins. Some system needs to manage these things, and their dependencies.

Combining it all into one isn’t practical, since different pages require different resources, and plugins may add resources in arbitrarily. If you really did combine everything needed for the AdminCP backend, it’d be slow to build (and that build would have to be done dynamically as other components add/remove resources), and not very useful, especially with http/2 and multiple streams.

Note that the way it works now is a vast improvement over Craft 2.x, where every AdminCP static resource request went through the index.php, and this was slow to load, and could not be cached.

Just ignore the cpresources/ directory; consider it a cache that you don't need to worry about.


Start a Loop at the nth Entry in a Structure and Loop to the End?

Using the offset parameter you can achieve this:

{% for entry in craft.entries.section('structureSection').offset(8) %}


Craft model and populateModels() performance issue?

Avoid calling block.entry multiple time per block since you only need to do that database query once. Alternatively you can use function memoization to cache the entry like this:

class FruitGrid_BlockModel extends BaseModel
{
    private $_entry;

    protected function defineAttributes()
    {
        return array(
            'row' => array(AttributeType::Number),
            'col' => array(AttributeType::Number),
            'sizex' => array(AttributeType::Number),
            'sizey' => array(AttributeType::Number),
            'entryid' => array(AttributeType::Number),
            'rules' => array(AttributeType::Mixed),
        );
    }

    public function getRuleClasses()
    {
        //...
    }

    public function getEntry()
    {
        if(!$this->_entry){
            $criteria = craft()->elements->getCriteria(ElementType::Entry);
            $criteria->id = $this->entryid;
            $this->_entry = $criteria->first();
        }

        return $this->_entry;

    }
}

This will only get the entry from the database once.

Also recommend renaming the rules attribute on the model to something like blockRules.

When you loop over the rules to create the ruleClasses string you may be looping over every rule created by the AttributeType declarations in your defineAttributes method.


Cache Records Being Stored for Invalid Paths

I had a {% cache %} tag around my global header template, which is pulled in by every template, including the 404 template. Apparently Craft doesn't care if the 404 template is being called or not, if it sees a {% cache %} tag it's caching that content.

The Wordpress and file extension paths are all from bots pinging the site trying to find a vulnerability, and every time those URLs threw a 404 a new cache record was created for the header.

So I set a variable in my 404 template and checked if it was set in my header template before caching:

404.html

{% extends 'layouts/_global' %}

{% set fourohfour = true %}

{% block pageBody %}

404, yo.

{% endblock %}

header.html (included in layouts/_global)

{% cache if fourohfour is not defined %}

        {% for page in craft.entries.section('Pages').level(1).all %}
            {{ page.title }}
        {% endfor %}

{% endcache %}


Can't login after restoring production DB locally

The id primary key column in the sessions table (and nearly all Craft tables) is set to be auto-incrementing (if you're on MySQL).  It should look something like:

CREATE TABLE `sessions`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) NOT NULL,
  `token` char(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `dateCreated` datetime(0) NOT NULL,
  `dateUpdated` datetime(0) NOT NULL,
  `uid` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `sessions_uid_idx`(`uid`) USING BTREE,
  INDEX `sessions_token_idx`(`token`) USING BTREE,
  INDEX `sessions_dateUpdated_idx`(`dateUpdated`) USING BTREE,
  INDEX `sessions_userId_idx`(`userId`) USING BTREE,
  CONSTRAINT `sessions_userId_fk` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

It sounds to me like that table is missing it's AUTO_INCREMENT on the id column.  Craft assumes it's there and that the database will automatically insert it.


Easy way to copy sections to a new install

Depends on your definition of "easy". :)

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

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


I don't think there is a way to do this from the back end data entry point of view currently - that is, right now, the price field is required, and indeed is required to be a number.  You can't use e.g. the value of another field in there (in which case you could have used e.g. a global or something to store a single record of the price elsewhere).

The other solution would be to deal with it via a plugin - you could listen to https://craftcommerce.com/docs/events-reference#commerce_lineitems.onpopulatelineitem and intercept this product, setting the price for the lineItem in there.  You could make a setting field in your plugin to store the actual price so there was a UI based way of changing it globally easily.  However, you'd still have to enter some price in the product when entering the product, something token like 0.01 perhaps.  Not perfect from a UI point of view and easily  misunderstood by anyone coming new to the back end.

Ideally, and it might we worth making a feature request to P & T for this - a price field that can parse twig and pulls values from elsewhere - this could certainly be very handy.

Another option would be to write a product importer and deal with the data entry that way - so that the price is set at the time of import of the data.  There's a gist that would get you started with here - https://gist.github.com/lukeholder/bbff8caef82078fc76e4

All said and done, though, this might be just one of those instances where you have to just deal with the data entry (at the moment) - it all depends of course whether the extra work/maintenance of an importer or plugin is worth doing (which all depends on how many products you're talking about and perhaps how often the price would change).


There might be a way to do this with CBaseController::renderFile(), but I'd just use craft()->request->sendFile().

The 3rd parameter is an optional $options array and you can pass a 'forceDownload' => true as one of the key => value pairs to force it to download to the browser.

Instead of hardcoding the the path to your public assets folder, you can do something like:

$path = IOHelper::getFolderName(craft()->request->getScriptFile());

That should get you the path to the folder your public index.php file is executing in and you can tack on your public asset path from there.


Is it possible to use images as variant selectors when choosing products?

I am sure you've worked this out by now, but in general terms, how you build this is entirely up to you, in front end terms.  You can make it as fancy or as simple as you like, in terms of the UI.  From simple checkboxes to some totally flash JS based UI, it's entirely up to you, as long as the form then submits the right values.  You can display any fields you wish (including images and prices) - from both the product and the specific variant(s) you're showing.

The only thing Commerce actually cares about is the purchasableId and quantity (qty) that you pass when you POST the updateCart form.

Again, when it comes to display of the basket, you will get a lineItem with the chosen purchasableId and from there can get back to the product and all its fields easily enough.  But how you choose to actually display this is again entirely up to you - you can, for example, create a basket that allows the customer to change the variant on the fly (you'd perhaps send an ajax remove item followed by an ajax add of the newly chosen purchasableId and qty).


If the entry is not already published, just set the Post Date to a date in the future.

That will set the entry to what Craft calls Pending. On the entry's index, the status indicator will be orange (instead of green).

If the entry is already currently published, no. That'd be a feature request. I agree, it would be great to be able to "publish over" the current edition (say for a contest or what not). If you set a draft's entry to a future date, Craft will un-publish the entry and set the status to pending.

You could work around this in Twig though. Say you want to have the entry change on 11/10. Set up a new Draft, name it Will Go Live on 11/10 (or whatever). Then in your template:

{% if now|date('U') > "2015-11-10"|date('U') %}

{% set theDrafts = craft.entryRevisions.getDraftsByEntryId(entry.id) %}

{# keep the "old" entry around just in case #}
{% set oldEntry = entry %}

        {%for i in theDrafts %}

            {# look for the specific draft and set if it exists #}

            {% if i.name == "Will Go Live on 11/10" %}
                {% set entry = i %}
            {% endif %}

        {% endfor %}

{% endif %}

{# template as normal #}
 ...


Can't get past the install on local MAMP Pro install... "Oops screen"

See this answer for how to work around the MAMP incomplete headers bug: https://craftcms.stackexchange.com/a/6573/57

The [warning] [application] Skipping record... log entry isn't an error at all and is completely normal to see during installation.


How to make a separate RSS feed for each entry type of a section?

Rey - depending on how you've setup your enries and folder structure you could create feed.rss as a template in both of those folders.

Inside the template you can setup the entry loop to output whatever information you need the RSS feed to include. It's not automated but completely within your control.


Display related entries on entry page using ElementAPI

If you want to show all ingredients related to the current entry you'd use the Single Entry Endpoint to pass the entry into the relatedTo param.

'ingredients/<entryId:\d+>.json' => function($entryId) {
  return [
    'elementType' => 'Entry',
    'criteria' => [
        'section' => 'ingredients',
        'relatedTo' => $entryId
    ],
    'transformer' => function(EntryModel $entry) {
      return [
        'title' => $entry->title,
        'url' => $entry->url
      ];
    },
  ];
},


Is there a way to check if entry is selected in relationship?

You should read the docs about relations

relatedEntries = craft.entries.relatedTo({targetElement: currentUser, field: 'docsApprovedBy'}).all()


What files do you have to be aware of when migrating (i.e config files)?

Most craft installs will require moving the database and asset folders, since these are typically not checked into version control. If the site is in version control, it should be a simple clone to install in a new domain.


You have twig syntax ({{...}}) inside twig syntax ({%...%}), which is never right. Does this work?

{% if entry.hasDescendants() %}
  {% redirect entry.getChildren().first().url %}
{% endif %}


Sprout SEO best practice - single or multiple field types?

tldr; Use as many Element Metadata fields as you need unique mappings between your Elements and your metadata. You can replace an existing Element Metadata field with a new one without losing data, but it will depend on the field settings of the old and new field.

A single Element Metadata field as a starting point

A single Element Metadata field across all sections is a good place to start. It reduces project overhead for getting things setup and provides a starting point with more comprehensive metadata than most sites. I typically recommend creating two custom fields: Summary and Feature Image and then mapping the single Element Metadata field to those common fields: Title, Summary, and Feature Image across all sections.

As you describe, in some cases you begin to need more specific metadata. This is a good signal for when to start considering multiple Element Metadata fields. Often, a section may have custom fields that are better suited for its metadata, and creating an Element Metadata field specific to that section will give you the flexibility to customize that sections metadata in a unique way.

Updating Element Metadata fields

If you're transitioning from an existing Element Metadata field to a new one, it's good to think about it like a migration and any SEO implications that may be affected if your metadata changes. Depending on how you set things up initially, and on what you are trying to achieve, there are a few considerations.

Dynamic Metadata

The easiest way to manage metadata is to have it dynamically generated from other content fields already present in your element field layout. If you take this approach, admins are not manually entering any metadata and all metadata is being generated based on the pattern that you set it up with.

If you update the patterns of your dynamic metadata in the Element Metadata field or add a new Element Metadata field to a channel to replace an old one, you don't need to migrate any metadata because the new field will generate the metadata dynamically for you. When you change the settings in an Element Metadata field or resave a Field Layout, Sprout SEO triggers a ResaveElements task (just like Craft does when you change a URL Format in your Section settings) and resaves all Elements that are related to that field which also resaves all the metadata based on the pattern you have in the field settings.

While you don't have to take any action on your website, note that in this scenario, if you change the metadata pattern, you are potentially changing the metadata on all of your pages. Make sure the changes are what you want and test and monitor those changes accordingly for your needs.

Custom Metadata

If you've enabled admins to edit metadata directly via Editable Meta Fields or the Meta Details overrides, the data should persist if you change to a new Element Metadata field. Sprout SEO only supports one Element Metadata field per Field Layout. When you update a field layout and replace an old Element Metadata field with a new one, as far as your Element is concerned, the only thing that changed is the Element Metadata field settings.

Again, be sure to test any changes you make and confirm the data is still there. It is possible to change the settings in a way that would overwrite some metadata when elements are resaved. But, if you keep the same custom metadata Editable Fields or Meta Details fields enabled, the existing data should persist.


Any workarounds for image resizing in Craft 2.5 Redactor II?

The only really workable solution I've found is to downgrade Redactor. Fortunately Pixel & Tonic have made this fairly painless with a plugin:

https://github.com/pixelandtonic/RedactorI


How to insert widgets in Rich Text field

Have you considered using the Matrix field type? You could create a block for rich text, then a block for a contact form (or whatever widget).

You could probably achieve what you're asking with a plugin but in my experience doing things like this in Redacter are prone to weirdness/bugginess (especially when in the hands of a client).


"Unknown package has no name defined" composer error on upgrade

Very similar to Devin's answer.
I came up against this on Friday and I had to follow these steps to resolve this issue.

Nuke the vendor folder within the project. rm -rf vendor/
Nuke the composer.lock file within the project. rm composer.lock
Clear the composer cache composer clearcache within the project.
Rollback to composer v1 composer self-update --1
Update composer globally to smooth it out composer global update
Then reinstall composer install within the project.
Finally, I was able to run ./craft update all

Hope this helps anyone else who comes up against this. It took several hours to resolve and figure out the necessary steps.


Reverse relationships with entries and users

{% set people = craft.users.group('family').ids() %}
{% set relatedPlaces = craft.entries.section('locations').relatedTo({
    targetElement: person,
    field: 'relatedPeople'
}) %}

Grab all the ids from your users, then find all locations related to those. This way you don't need multiple loops and get each location once and not multiple times


“Reactivate” is the button you are looking for. Try checking for updates so Craft gets updated license info – the Trial badge sholud go away once Craft realizes that it’s licensed to run Pro. (If not, please contact support@craftcms.com and send in your config/license.key file, and we’ll sort it out.)


How to separate a parent and it's children when looping through a category?

If you have a 2-level category, and you select one of the nested categories (Los Angeles), what you get in your entry is Los Angeles and its parent (California). There is no way to have Los Angeles without also California, though you can have California without Los Angeles. Anyway, that for loop {% for place in entry.location %} will loop over both of them.

One way to be more explicit about the cities and the states is to loop over just the cities using level to fetch only the categories at a specific level in the category, and then for each city, fetch its ancestors with ancestorOf. Your code would look like this:

{% for city in entry.location.level(2) %}
  {{city.title}},
  {% for state in craft.categories.ancestorOf(city) %}
    {{ state.title }}
  {% endfor %}
{% endfor %}


How can I hide entries depending on which category they are associated with?

The search parameter will help you do this really elegantly.

In the code below I've called the category field categoryField, but you'll have to swap that to suit your site.

{# Get current students (students who aren't also in the alumni category) #}
{% set currentStudents = craft.entries.section('people').search('categoryField:student -categoryField:alumni') %}

{% for student in currentStudents %}
    {# Output your students here #}
{% endfor %}

This is basically asking Craft to respond with the entries that have the categoryField including student but not (indicated by the - before) including alumni.

You could probably also streamline the other bits of your code using this method.

I've tested this as working on Craft 2.5.2757

Hope that helps!


If you have devMode enabled, then you have access to Twig's dump method that lets you inspect variables.

{{ dump(article_id) }}

Or, if you're feeling more adventurous, there is a debugging library called Kint that there is a Craft plugin for to help debug templates.


Craft CMS Shows 404 Error on Admin Pages

Goodness, I figured out what was going on here. The cpTrigger had been changed from admin to a different name in the craft/config/general file. [Facepalm]


Something like this should work:

public function add($user)
{
    $existingUser = craft()->users->getUserByUsernameOrEmail($user->username);

    if ($existingUser)
    {
        // They exist... log them in.
        craft()->userSession->loginByUserId($existingUser->id);
    }
    else
    {
        // They don't exist... create them.
        craft()->users->saveUser($user);
    }
}


User group discount not applied when user has existing cart

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

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

I'll report it.

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


Craft CMS FeedMe plugin - Process Instagram JSON Feed

Check out the cleanAssetUrls configuration added just for you!

http://sgroup.com.au/plugins/feedme/getting-started/configuration


Inserting data into a table fieldtype via plugin?

The thing to keep in mind here is that a table field contains a simple JSON string. So you can (and should) use PHP's native json_encode function to prepare your data...

// Your data will be an array of arrays:
$tableData = array(
    array(
        "col1" => "data",
        "col2" => "data",
    )
);

// Then simply encode it when you set your field value:
$entry->getContent()->setAttributes(array(
    'tableFieldHandle' => json_encode($tableData)
));

This will also solve any string escaping concerns for you!


Here is the method we are including libraries in our plugin.

namespace Craft
require_once(CRAFT_PLUGINS_PATH.'parse/parsequery/xx.php');


Your product element criteria is using a condition param: hasVariants, but it should be hasVariant as per the docs: https://craftcommerce.com/docs/craft-commerce-products#hasvariant

That correctly only returns products (where a variant that belongs to that product) is in stock.


Please make sure the tag settings in CraftImportService.php are set properly.


How to find the block type of Super Table field that is inside a Matrix field

That's more complicated, because fields in a Matrix are scoped to the Matrix field, which is why you can't just go:

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

You'll need to loop through the Matrix's fields to find the Super Table field, then carry on as normal.

{% set matrixField = craft.fields.getFieldByHandle('myMatrixField') %}

{% for field in matrixField.getBlockTypeFields() %}
    {% if field.handle == 'mySuperTableField' %}
        {% set blocktype = craft.superTable.getSuperTableBlocks(field.id)[0] %}


How to bootstrap / connect to another Craft instance from inside a plugin?

I don't see why you wouldn't be able to load it up from your plugin.

public function init()
{
    $otherCraftApp = require '/path/to/other/bootstrap.php';
    $otherCraftHttpRequestService = $otherCraftApp->request;
}


No, you would not check these files into Git.

I have a .gitignore rule to just ignore everything in storage/ and so I treat it as a cache directory.

Which it is... except for the unfortunate fact that any rebrand (logo, icon) files are stored in storage/ as well. But I just manually add them in via git add -f


Okay, so I found the answer. And the reason it wasn't working is because I've been using another .htaccess (a hybrid of h5bp and Craft) than the default that comes with the Craft download. And this .htaccess included a RewriteBase, which was set to /. So when one tried to access /no/{slug} the RewriteBase would send it up one folder, basically. So I had to go into each of the locales .htaccess and set their RewriteBase to /no and so on.

I'm just gonna leave it here, and I'm pretty sure I'm gonna find this post again the next time I'm making a multi-lingual site and don't understand why all of my links are broken...


How to set field values for the table field type in Craft 3

I figured this out. The table field is expecting JSON:

$entry = new Entry();
$entry->sectionId = 1;
$entry->typeId = 1;
$entry->title = $title;
$entry->setFieldValues([
  "field_handle" => '[{"col1":"hello","col2":"world"},{"col1":"more","col2":"stuff"}]'
]);


Stop image upload if moderation fails using EVENT_BEFORE_HANDLE_FILE

From investigating, the issue could not be resolved at the time of writing this answer. Even though the EVENT_BEFORE_HANDLE_FILE on the Asset class extends the cancelable event, there was not actually a way to cancel.
To answer the question, there is currently no nice way of being able to cancel this event.
I raised a ticket to add this feature, you can follow its progress here https://github.com/craftcms/cms/issues/6875
This would allow you to use $event->isValid = false; in the scenario any tests fail and you didn't want the image to continue being handled by Craft.


Is this a basic error, or do I misunderstand how Craft queries the database?

You're not misunderstanding anything, and your concerns are perfectly valid. I feel like many developers using Craft do not realise that .one() and .all() are in fact database calls, and pretty expensive ones at that. Do it your way, watch the number of DB queries go down in the debug toolbar and feel all warm and fuzzy. (Also, you don't need parentheses in conditionals unless you're doing some complex grouping - {% if prodDim and prodSpc %}).


My live preview for blog entries is not working on my computer, but is working for my account on other computers

Are you all using the same browser / operating system? Try testing in a recent release of Chrome, Safari, or Internet Explorer.


Something like this should work just for selecting a "day".

'criteria' => [
    'section' => 'news',
    'customDateFieldHandle' => ['and', '>='.DateTime::createFromString(craft()->request->getPost('date'))->format("Y-m-d").' 00:00:00', '<='.$DateTime::createFromString(craft()->request->getPost('date'))->format("Y-m-d").' 23:59:59')];
],


{% if '4' not in navigation.navi.ids() %}
    {% exit 404 %}
{% endif %}


Live Preview Not Updating - No errors found

Okay, so I figured this out and its a very stupid twig template noob mistake on my part.

The mistake is this:

I had a section called 'demo' with a field called 'demoField' and created a template folder called 'demo' with an index.html file inside. The mistake is that my template had this:

{% for entry in craft.entries.section('demo').find() %}
    {{ entry.demoField }}
{% endfor %}

Looking at it now, this won't work, but simply {{ entry.demoField }} will work.

It threw me off because it was still showing the content in the template and saving it to the database, but the live preview would simply not work.

Quite a silly mistake, but just starting out I completely missed this. Hopefully this will help someone in the future.


Creating a custom, "multiple dates picker" field

Instead of creating a custom field could you do it with a Matrix with each date going into a matrix row?
I've done something similar in the past for scheduling delivery dates for a Commerce order. Each order has a matrix field for delivery dates and each date (along with some other data) is added as a separate row.


Can only submit my Sprout Form form if I'm logged into my site

This might not help but I've had a similar problem with a couple of my own modules and then with LInkVault that I went around in circles with. It suddenly stopped allowing non logged in users from downloading files. I contacted support who spotted the issue and fixed it in minutes. They gave this message:

Link Vault’s FrontEndController class has the allowAnonymous property set to true so that can’t be part of the problem

then a few minutes later:

Apparently, a recent Craft update added some logic in the craft\web\Controller::init() method that converts boolean allowAnonymous values to an integer which was part of the check that determines whether guests should be able to access a controller action. Link Vault’s front end controller had its own init() method but it wasn’t calling the parent’s init() method. So that is fixed now.

I leave this here in case it's any help either to this specific problem or anyone else with modules that run in to this issue.


You can use a Relation Field for each of your element types and include a custom js rule so if one of them has a value, the other one can't be selected.

The more difficult way would be to extend the field and the ElementSelectModal and the ElementIndex to select multiple element types but this is going to be a little bit more tricky since you'll need a custom controller to fetch all elements and can't rely on the ElementsController


What is the difference between dateModified, dateCreated and dateUpdated?

dateCreated and dateUpdated are pretty standard columns that you can find in pretty much every Craft database table. They store the date in which the row was created and last updated, respectively.

dateModified is an assets-specific thing, and that stores the time that the file was last modified, according to the file system.


Site url is not generated correctly when using environment variables

Cache poisoning would only happen if you don't hard-set your @web alias manually and it is auto-determined.
Set it in your config/general.php with:
'aliases' => [
    'web' => getenv('SITE_BASE_URL'),
],

Then you'll be able to revert to using it in your Control Panel.
In terms of why this happened; you can't add to an environment variable the way you can with an alias so http://$SITE_BASE_URL/en will become a string and the variable aspect of it will disappear.
When you define $SITE_BASE_URL, it can only be used as is in the CP so if you wanted to use variables for you site, you would need to define one for each site/language.


Adding all the Matrix Block field types of the same kind to get a total

Twig allows you to add variables just as they were integers. You'll want to setup your totalHours variable before your loop begins so that the totalHours variable is available in the scope outside of the loop itself.

Something like this should work for you:

{# Create a variable to track your total hours #}
{% set totalHours = 0 %}

{% for block in entry.matrixFieldHandle %}

    {% if block.type == 'hoursBlock' %}
        {# Increment your total hours by adding the value
           of your hours block to the current totalHours #}
        {% set totalHours = totalHours + block.hoursFieldHandle %}
    {% endif %}

{% endfor %}

{# Output the result #}
Total Hours: {{ totalHours }}

While I can't test your specific code, here's a generic example that is doing the same thing that will work if you copy and paste it to your template:

{% set totalHours = 0 %}

{% for hours in 0..3 %}
    {% set totalHours = totalHours + hours %}
{% endfor %}

Total Hours: {{ totalHours }}


Prevent Redactor from adding site identifier to entry links

I solved this by creating a Redactor plugin that listens for the link.inserted event and strips out the site identifer:

craft/config/redactor/plugins/myplugin.js:

(function($R)
{
    $R.add('plugin', 'myplugin', {
        onlink: {
            inserted: function(link) {
                link.nodes.forEach(node => node.href = node.href.replace(/@\d+/, ''))
             },
        },
    });
})(Redactor);

craft/config/redactor/redactorFieldConfig.json:

{
    "plugins": ["myplugin"]
}


Solution:

I have this line inside my config.
define('BASEPATH', realpath(dirname(__FILE__) . '/../') . '/');

And inside the imager config file imager.php I have:
'.dev' => array('imagerSystemPath' => str_replace('craft/','images/', BASEPATH),

So, make sure the paths are all set according to your environment / directory structure.


.htaccess for Craft CMS - removing segment from URL

I might be way off here, but if you are wanting to run Craft as your main front-end, could you not place the Craft index.php in the root of the site and then you CRM in a sub-folder of its own?

If you have all you CRM stuff in its own sub-folder, Craft should just ignore that folder as it physically exists. If you've got specific things you need to have in your .htaccess file for you CRM, you could have that .htaccess in the sub-folder, rather than the root. That way you can just have the standard Craft .htaccess file in the root of the site.


Working with Structure & Multiple Pagetypes

Assuming that those pages are working off of different entry types, you should check out this great help article...

  How can I give each Entry Type its own template?

Basically, you let a parent template decide which child template to load, based on the current entry type.


Is there a way to speed up the CMS on UNIX server?

First of, check your web server error log wether or not php is dying because of memory exhaustion.

Second, working with many Craft objects/models tend to be slow, you can speed this up by using { cache } blocks cleverly, but be wary that using them wrong can severely impact your performance in a negative way.
Check this blog post for some insight into the topic: https://nystudio107.com/blog/the-craft-cache-tag-in-depth

Third, the biggest improvement you can implement is caching before the application server (php), some alternatives are fastcgi cache (if using nginx), varnish, saas solutions like fastly/keycdn and probably many other I don't know about.

Implementing caching can be a big job depending on the site and should be thoroughly tested.

Fourth, you can add some sort of APM or tracer to investigate what part(s) of your solution is using the most time.

You don't mention the timings of your site, could you elaborate a bit about how slow it is?

In my experience it is hard to get a craft2 site with a lot of content down under 500ms ttfb without heavy caching, but ymmw.


Folders required to download when moving a Craft 3 installation to another server?

You'll need to take:

/config
/modules (if there are any custom modules, but no harm in taking it anyway)
/web
/storage/rebrand (if you have rebranded the control panel)
/templates
/translations (if you have added any static translations)
/vendor (unless you plan to run composer install on the new server)
composer.json
composer.lock
craft (CLI)

You can generally discard the whole contents of storage and cpresources as they'll get automatically recreated, unless you have put anything in storage/rebrand. However, you'll still need a storage directory, even if it's empty.


How to tell whether a SuperTable column has data or is empty?

I forget who solved this for me! I think it was Michael van Dorth.

      {# Caption #}
      {% if block.caption %}

{{ block.caption }}

      {% endif %}

      {# Setup #}
      {% set rows = block.contactTable.all() %}
      {% set phoneRows = 0 %}
      {% set emailRows = 0 %}
      {% set websiteRows = 0 %}

      {% for row in rows %}
        {% if row.phone != '' %}
          {% set phoneRows = phoneRows + 1 %}
        {% endif %}
        {% if row.email != '' %}
          {% set emailRows = emailRows + 1 %}
        {% endif %}
        {% if row.website != '' %}
          {% set websiteRows = websiteRows + 1 %}
        {% endif %}
      {% endfor %}

      {# Headings #}

          Name
          {% if phoneRows > 0 %}Phone	{% endif %}
          {% if emailRows > 0 %}Email	{% endif %}
          {% if websiteRows > 0 %}Website	{% endif %}

      {# Body #}

        {% for row in block.contactTable.all() %}

            {{ row.contactName }}

            {% if phoneRows > 0 %}
              {% if row.phone|length %}{{ row.phone.link }}{% endif %}
            {% endif %}

            {% if emailRows > 0 %}
              {% if row.email|length %}
                Email
              {% endif %}
            {% endif %}

            {% if websiteRows > 0 %}
              {% if row.website|length %}
                Website
              {% endif %}
            {% endif %}

        {% endfor %}


Run a localized site using one Craft install on 2 servers

Craft has exceptional locale functionality, which would cater for your different languages.

See here for relevant answer...

Besides the above, I understand that:

Multi-location/domain installation is not possible at the moment.
the licence for Craft applies to a domain. So for your example, each domain would require a separate Craft licence.


It works the same way related entries, (and all other elements) work.

So assuming you are on the products page, and have the product variable this should work:

{% set relatedTestimonials = craft.entries.section('testimonials').relatedTo(product) %}

{% for testimonial in relatedTestimonials %}
  {{ testimonial.title }}
{% endfor %}


How would I pass and entry's field value to an include?

You'll never need to put Twig tags within other Twig tags... Try it like this:

{% include "partials/includes/page-header" with { 'title' : entry.heading } %}


Assuming you're on the latest 3.5.x release, then my guess is you need to set the "Title Translation Method" setting for whatever Entry Type you're saving to to "Translate for each site".


I'd probably try is something like this:

    {# Grab all (8) stories in a random order #}
    {% set allStories = craft.entries.section('work').type('projects').order('RAND()').find() %}

    {# Now loop through only the first two items in the array #}
    {% for entry in allStories|slice(0, 2) %}
        <— stuff —>
    {% endfor %}

    {# Now loop through items 3-8 in the array. #}
    {% for entry in allStories|slice(2, 6) %}
        <— stuff —>
    {% endfor %}

Documentation for the Twig slice() method can be found here: https://twig.sensiolabs.org/doc/2.x/filters/slice.html


How do you create a custom button field type (with js includes) for customizing the CP?

I thought I would report back with the good, the bad, and the ugly.

The good It is very possible (and quite easy) to create a field type button element, and include your own custom javascript as is explained in the fieldtype plugin documentation. Setting the defineContentAttributes to return false will prevent columns from being created in the database. And name, value variables are not even needed in this case in templates->render array. Here is the basic MyPlugin_CustomButtonFieldType.php:

class MyPlugin_CustomButtonFieldType extends BaseFieldType
{
    public function getName()
    {
        return Craft::t('Custom Button');
    }
    public function defineContentAttribute()
    {
        return false;
    }
    public function getInputHtml($name, $value)
    {
        craft()->templates->includeJsResource('myplugin/js/custombutton.js');
        return craft()->templates->render('muplugin/fieldtypes/CustomButton/input', array(
        ));
    }
}

And in the fieldtype template file (for a default CP craft looking button):

<input id="custombtn" type="submit" class="btn submit" value="{{ 'Do Something'|t }}" >

So far so good. Imagine the possibilities!

The Bad It is basically impossible (as far as I can tell) to over-write the default actions (i.e. action/saveEntry) via javascript as it is often dynamically inserted into the DOM via javascript depending on if you're using the command+s save shortcut or the save button sub-nav, etc. So replacing the default controller action, doesn't look like an option.

Update: It does look like you can prevent the default form submission, though. And then perhaps write your own .click() listener.

$('#entry-form').submit(function(event) {
    event.preventDefault();
    return false;
}
$('input.save').click(function()){...}

The Ugly It is possible to prevent fields from getting saved to the database (i.e. credit cards, and cvc codes) by simply removing the 'name' attributes from the fields, using something like:

jQuery(function($) {
     // prevent the form from saving credit card and cvc codes
     $('input[name*="creditCardNumber"]').removeAttr('name');
     $('input[name*="cvc"]').removeAttr('name');
}

But it's pretty much a hack job and not very pretty.

So, custom field types with buttons and javascript look like a very easy and very powerful way to customize the CMS. And so far it seems pretty easy to send data via javascript to remote services, retrieve tokens, forward the token via ajax to a custom controller to get processed, saved and result returned.

Messing with the default actions on the other hand, not such a good idea.


Can't update from v2.6.2789 via manual update

Are you 100% sure you are updating the right website/folder and not looking at the wrong one? Are you sure you are using the newest version of craft to install and not your old download?

If this is not the case. You could save your templates folder, All the folders you made yourself in the public folder and the plugins folder if you have any installed and make a backup of your current database and install a new fresh version of craft.

Then implement your saved files / database. Your database should be imported via the program or client you made your database in as this is not possible yet to do via the Craft admin panel. This is basically the same as a manual update.


You could loop all regions and select their corresponding stores

{# you can as well include eager loading here #}
{% for region in craft.entries.section('regions').storesRegion(':notempty:').all() %}
    {% set storesForRegion = craft.entries.section('stores').relatedTo({
        targetElement: region,
        field: 'storesRegion'
    }).all() %}
    {{ region.title }}
    {% for store in storesForRegion %}
        {{ store.title }}
    {% endfor %}
{% endfor %}

If you want to increase your performance you can use eager loading at this point and include with(['storesRegion']) to your region Query


Trying to access 'title' attribute via getEntryTableAttributeHtml. Any idea how?

If you wanna change the title one way is override the __toString() method on your model.

/**
 * @return string
 */
public function __toString()
{
    return (string)$this->name;
}

If you wanna chage the status icon next to the title you can override the getElementQueryStatusCondition function on your ElementType class

public function getElementQueryStatusCondition(DbCommand $query, $status)
{}

Regards


You can override the control panel's CSS with a plugin. Use the popular "Control Panel CSS plugin" by Lindsey DiLoreto or make your own little one.

Make use of the includeCssResource() function and include a CSS file with your custom redactor styles:

myRedactorCssPlugin.php:

public function init()
{
    if (craft()->request->isCpRequest())
    {
        craft()->templates->includeCssResource('myRedactorCss/redactor.css');
    }
}

resources/redactor.css:

.redactor_editor h1 {
  font-weight: normal !important;
}
.redactor_editor p {
  background-color: #eee;
}


You can do this in a single query using the search parameter:

{% set uncategorized = craft.entries.section('news').search('-categories:*') %}

More on searching here.


Triggering the start of a task from a CRON job

Everything you need to manage tasks is in the TasksService, so you should be able to just use that in your controller action to kick off any pending tasks, using something along the lines of:

if (!craft()->tasks->isTaskRunning())
{
    $task = craft()->tasks->getNextPendingTask();

    if ($task)
    {
        craft()->tasks->runPendingTasks();
    }
}

If you have a look around craft/app/services/TasksService.php you'll see you can also grab and run tasks by type which might be useful in this situation.


Incorrectly setting module template variable

Was running into the same problem today. I was able to access the controller and the service, but none of the variables. Looks like Brad was able to fix the problem but didn't add a final solution.

I wasn't registering any variables on the init() function. Adding the last line of code registered the variable but did not load it onto every request.

    // Register our variables
    Event::on(
        CraftVariable::class,
        CraftVariable::EVENT_INIT,
        function (Event $event) {
            /** @var CraftVariable $variable */
            $variable = $event->sender;
            $variable->set('formSenderModule', FormSenderModuleVariable::class);
        }
    );

To add it onto every request, I had to add form-sender-module into my bootstrap array in app.php.

'bootstrap' => ['form-sender-module']


Error uploading .bmp file format - gets rejected

You're probably using GD, which doesn't support BMP files.

If you install  Imagick on your server, Craft will use it automatically and it supports a much wider range of file types, including BMP files.


Removing the LivePreview and Share Buttons?

If you add a blank or invalid template path in your Section's settings (Settings > Sections > Edit Section) then both live preview and the share button will be disabled.


Is there a way to allow users to control alignment of images in the Redactor plugin using Craft 3

It looks like the right way to do this is to tweak the redactor settings:

https://github.com/craftcms/redactor#redactor-configs

and

https://imperavi.com/redactor/docs/settings/image/#s-imageposition

All you have to do is add this key to your redactor config:

"imagePosition": true,

and clear your control panel cache.

The option for image position shows up on the 'edit image' screen.

If you want to use classes to control your image alignment and you want the redactor fields to continue to be WYSIWYG, you need to share those CSS classes between the CP and your front end. This answer will probably help: Where do I add custom css for the Redactor editor in the Craft control panel?


You need to get the parent entry model before requesting its children with the getChildren method. craft.entries.id(4) only creates a criteria model prepared to query for entries matching your criteria. You now have to use the first method to query for an entry model.

{% set parent = craft.entries.id(4).first() %}

{# Check if it indead returned an entry model, could also return nothing #}
{% if parent %}
    {% set children = parent.children %}
{% endif %}


That plugin doesnt append any file extensions to the routes. Try either changing the route in elementapi.php to news.json or try to visit http://yoursite.dev/news


How to setup conditionals within a matrix?

If you have an image, you want to display it, and if there is also a linkedDocument, you want the image to link to that document. This should handle both cases, without too much code duplication.

{% if block.type == "image" %}

  {% set image = block.image.first %}

  {% if image %}
    {# set the imgTag, which we will display regardless #}
    {% set imgTag %}
       alt="{{ image.title }}">
    {% endset %}

    {% set linkedDocument = block.linkedDocument.first %}

    {# we may or may not have a linkedDocument. Display the image in either case #}
    {% if linkedDocument %}
      {{imgTag}}
    {% else %}
      {{imgTag}}
    {% endif %}
  {% endif %}

{% endif %}


You would need to pass the current pagination page number with your entry links and than make Craft
respond to URLs in a format like this: example.com/my-section/p2/my-entry-slug.

I guess this is more complicated than you'd think, as this is probably not possible to do with
the default paginate tag and its preset routes. And I also don't know of a way to combine the paginate
tag's page token with custom routes.

So I believe there's no other choice left than replacing paginate with a custom solution replicating its
functionality.

This is possible with dynamic routes and some logic in your templates. So you'd first have to set up a route
with a [page] and a [slug] token, which you can then access in your template.

my-section/p[page]/[slug] and
my-section/p[page]

I'll give some example code (untested and incomplete), to help you get started with the template.

All the pagination links build upon the route's page variable used in craft.entries's offset and limit parameters. With custom routes you also have to query for your entry entry model manually, I set it up to get the page's first entry
if there's no slug variable set from your route.

{# Set params #}
{% set params = {section: 'orchard'} %}
{% set entriesPerPage = 5 %}

{% if page is defined %}
    {% set offsetParam = (page - 1) * entriesPerPage %}
    {% set pageSegment = '/p' ~ page %}
{% else %}
    {% set offsetParam = 0 %}
    {% set pageSegment = '' %}
{% endif %}

{# Get the entry model #}
{% if slug is defined %}
    {% set entry = craft.entries.slug(slug).first() %}
{% else %}
    {% set entry = craft.entries(params).offset(offsetParam).first() %}
{% endif %}

{# Get pagination params #}
{% if page is defined %}
    {% set entriesOnNextPage = craft.entries(params).offset(offsetParam + 1) %}

    {% if entriesOnNextPage|length %}
        {% set nextPageSegment = '/p' ~ page + 1 %}
    {% endif %}

    {% if page == 1 %}
        {% set prevPageSegment = '' %}
    {% else %}
        {% set prevPageSegment = '/p' ~ page - 1 %}
    {% endif %}
{% else %}
    {% set entriesOnNextPage = craft.entries(params).offset(entriesPerPage) %}

    {% if entriesOnNextPage|length %}
        {% set nextPageSegment = '/p2' %}
    {% endif %}
{% endif %}

{{ entry.title }}

    {% set entriesOnPage = craft.entries(params).offset(offsetParam).limit(entriesPerPage) %}

    {% for entry in entriesOnPage %}
        {% set image = entry.mediaThumb.first() %}

    {% endfor %}

    {% if prevPageSegment is defined %}
        Previous Page
    {% endif %}

    {% if nextPageSegment is defined %}
        Next Page
    {% endif %}


Impossible to invoke a method ("limit") on an array

craft.entries now returns an ElementQuery. When you add the .all() you're telling Craft to execute the query, which returns an array of Elements.

That means that solutions is now a simple array, and won't have methods like .limit(1) that can be executed on it. It looks like you just want to use the first item in the solutions array, so try changing this:

      {% nav solution in solutions.limit(1) %}
           solutions(current)
      {% endnav %}

To this:

       solutions(current)

More here: {% nav %} Tags


Performance basics? BlogPost+Comments vs. One ever-expanding Matrix Field?

Regarding performance:
If you look at the database structure of Craft, you'll see that Matrix content is stored across multiple tables, with each block having its own record, just like entries do. I've never compared calculations, but I'd bet there's no significant difference in the DB performance between your two ideas. Using eager loading you could retrieve a BlogPost entry and all Comment entries related to it in three DB queries.
If you want to run a quick exercise to test your theory of performance, model out both options. Create one entry that has 10 "comment" Matrix blocks, and one entry that has 10 related "comment" entries. Don't even worry about a front end, just create two empty templates—one for each approach—that get the respective entry and its comments. Use the Yii front-end profiler (activated under your user account's Preferences tab) to check out the performance difference. This will suggest what kind of performance difference there might be.
Also keep in mind that once you layer on your page caching strategy, performance differences might be a moot point.
Regarding usability:
From a management standpoint, idea 1 sounds much easier to work with, as you're utilizing Craft's content structure in a natural way (as you said, idea 1 is a well-tested and proven approach to this use case). Craft already exposes a very streamlined API for creating, editing, deleting, and querying entries. Doing the same for a Matrix field on an entry is certainly possible, but you'll probably end up writing your own interface if you plan on doing that at scale.
Also consider the interface within Craft for you to manage things. A Comment entry type already has a dedicated admin section for you to browse, search, sort, and manage comments. Trying to do any sort of query across Matrix blocks distributed among BlogPost entries is not built in to Craft's interface; you'd have to write a whole plugin to add that functionality yourself.
I'd go with idea 1 for sure.


Commerce 2: View all orders of a specific product?

Yes it is possible but I don't think there is currently a plugin that will do it for you. There are a couple of reporting plugins in the store though I'm not sure whether they work with Commerce elements. Either way, I imagine you would need to write your own query.

There is a Commerce reporting plugin in the works from Foster Commerce but it appears to have been delayed. Going by the previous version that one should include the sort of report you want.

You could also roll your own plugin to generate the report or even, to be honest, create a Twig template which will output the data you want as a csv (or whatever).


Craft Commerce: Frontend Validation on Address Fields

Would removing required via JS be an option?