How to use Sprig to filter categories using a dropdown I'm having an issue where I'm adding a dropdown to my search to filter through the first parent attribute in a category (Winter 2020, Spring 2021, and so on). The search field works, but nothing happens if I select from the dropdown (Winter 2020).
What am I missing?
{% set search = search ?? ''%}
{% set category = category ?? ''%}

{% set entryQuery = craft.entries ({
    search: search,
    section: 'articles',
    limit: 2,
    }) %}

{% set myCategoryQuery = craft.categories ({
    group: 'edition',
    level: 1,
    }) %}

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

<form>
    <input sprig s-trigger="keyup changed delay:200ms" id="search" name="search" value="{{ search }}" type="text" placeholder="Search" autocomplete="off">
    <select sprig name="category" id="category" value="{{ category }}" class="form-control">
      <option value="">Any</option>
        {% for category in categories %}
          <option value="{{ category }}">{{ category }}</option>
        {% endfor %}
    </select>
  </form>

        {% for entry in entries %}

          {% for category in entry.edition.all()%}
             {{ category }}
          {% endfor %}

{{entry.title}}

          {% for category in entry.authors.all() %}
          {{ category.title }},
          {% endfor %}

        {% endfor %}
        {% if entries|length == 0 %}

No entries found

        {% endif %}

You need to apply the category filter to the entry query.
{% set categoryId = categoryId ?? '' %}

{% set entryQuery = craft.entries ({
    search: search,
    section: 'articles',
    limit: 2,
    relatedTo: categoryId,
}) %}

And also update the select field to match.
    <select sprig name="categoryId" id="category" value="{{ categoryId }}" class="form-control">
      <option value="">Any</option>
        {% for category in categories %}
          <option value="{{ category.id }}">{{ category }}</option>
        {% endfor %}
    </select>

See the Sprig filters video for an explanation of how to output and use categories as filters:
https://putyourlightson.com/sprig/videos#sprig-filters


How do you filter matrix blocks by type? Is there a way to filter a matrix by block type, or get a count of how many items there are of a certain type? Can't find a syntax example.

I created a matrix with two blocks. In pseudo code, basically what I want to do is this:

{% set typeOneBlocks = theMatrix blocks where type == "typeOne" %}

{% if typeOneBlocks != null %}

        {% for block in typeOneBlocks %}

{# do stuff #}

        {% endfor %}

{% endif %}

Same with typeTwo blocks. If there are no items of one type or the other, I don't want to create that container and have it sitting empty.

If there is not a way to filter or get a count, I'd have to use for loops to increment vars for how many of each block type there are and then act based on those counts. Seems there should be a simpler way.

You can grab a specific block type in Matrix by doing this:

{% for block in entry.myMatrixField.type('typeOne') %}
    {{ block.text | markdown }}
{% endfor %}

If you wanted to know the number of blocks of a certain type, you can do:

{% set blocks = entry.myMatrixField.type('typeOne') %}
{{ blocks | length }}

If you want to search for multiple block types, you can do this:

{% set blocks = entry.myMatrixField.type('typeOne, typeTwo') %}

For your specific example, it would look like this:

{% set typeOneBlocks = entry.myMatrixField.type('typeOne') %}

{% if typeOneBlocks | length %}

        {% for block in typeOneBlocks %}

{# do stuff #}

        {% endfor %}

{% endif %}


Output Matrix in relation to category I'm setting up an FAQ page using a matrix. Each Matrix block contains a question and an answer field. Each Q+A needs to be outputted within a section on the same page such as General, Payments...

I've figured the best way to do this is using categories to assign the Q+As section, limiting each Q+A to one category. I'd then need to output all Q+As for each section with it's category as a header.

Desired Output:

General

Question field output

Answer field output

Question field output

Answer field output

Payments

Question field output

Answer field output

....

I'm fairly new to craft so perhaps I'm overcomplicating it by assigning it to a category, it seems like it's the easiest way to add new Q+As and for them to appear within the right section.

How would I go about outputting this? I've set up a Category Group called 'faqCategories'

Here's my matrix setup:

It's tempting to use the Matrix block for things that might actually be better as a a channel or a structure.  I thing this might be the case here.

The way you've set it up is fine, relating each FAQ to a category is a good approach.

In any event, the plugin groupBy should help you:

https://github.com/timkelty/groupby-craft

Or you can look at this example:

http://craftcookbook.net/recipes/279


How does Craft handle uploading assets to AWS? When users upload assets to a Craft CMS site setup to use AWS, do the assets go directly to AWS or are they uploaded to the Craft server first?

The reason I ask is I'm building an area where users upload potentially large files from the frontend, and it's quite likely a lot of users will choose to do it at the same time.

If the files are uploaded to the Craft server first, I might have to spec-up the server a bit more and would welcome any tips for helping Craft handle the multiple large uploads as efficiently as possible.

If the files are simply uploaded to AWS, I take it that means there will be little impact on the Craft server and I won't need to worry about any of this. Is that right?

They are uploaded to Craft first to a temporary file, then Assets uses the Asset Source to work out where to send them next - either the local file system or a remote one.

For handling large uploads in general you could look at this plugin: https://superbig.co/plugins/large-upload


which Sources of asset field are checked I have an asset field (craft\fields\Asset), how do I figure out which Sources it can use? (Which of the Sources boxes are checked)?

This is for Craft 3, and I'd like to do it in twig (I have the asset field in twig)

You can get all available sources with

field.getSourceOptions()

Which returns you an array of all sources, no matter if they are selected or not (just to get the ids and such)

and with

field.sources

you'll receive an array if you selected several sources or a string (*) if all are selected.


Display entries including all locales for XML sitemap I’m trying to build an XML sitemap that contains all entries including those in a different locale. I thought the localeEnabled(false) would allow entries for all locales to be displayed, however, the following doesn’t seem to work:

{% set pages = craft.entries.section('pages').status('live').localeEnabled(false) %}

If is assign a locale:

{% set pages = craft.entries.section('pages').status('live').locale('de') %}

then the entry is displayed.

I have tried using .locale(null) and .localeEnabled(null) without success.

Any ideas?

Not sure, but I think the only way is to query for each locale and merge.

{% set siteLocales = craft.i18n.getSiteLocales %}
{% set pages = [] %}
{% for locale in siteLocales %}
    {% set localePages = craft.entries.section('pages').locale(locale.getId).find() %}
    {% set pages = pages|merge(localePages) %}
{% endfor %}

{% for page in pages %}
    {{ page.title}}
{% endfor %}


How can I extend admincp to show all related category not only the first one on the AdminCP list view? I would like to extend the adminCP via plugin to not only show the first related item, but every related item in the list (like categories, or tags etc...) Right now the adminCP is showing only 1 item in the table view

You can use the getTableAttributesForSource event

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

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

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

This is the function that renders the usual table html

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

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

    return '';
}


Redactor field doesn't display Redactor fields are failing to display for my client and I'm stumped as to what might be happening.

They work fine for me and I haven't heard reports from any of the other 10+ CMS users.

It seems OS/browser specific, because the person that reached out is on a brand new computer running the latest version of Windows 10 and Chrome. When I asked them to test in Firefox everything worked fine.

Some more technical details:

The site is running Craft 2.6.3017
Chrome 67.0.3396.87
Windows NT 10.0; Win64; x64
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36

It sounds like it could be related to this question, but it's not quite the same. Has anyone else heard reports of this?

Turns out the issue was caused by a js error being thrown by an ad blocking plugin the user had installed on his browser.


How to optimize nested reverse relations? I have the following situation:

A section called "membership" and a section called "member".
Within the "member" section I can choose one or more memberships.
Now I'd like to display all memberships with the reverse related members.

The output would look something like this:

membership 1
    member 1, member 2, member 3

membership 2
    member 2, member 4

membership 3
    member 1, member 5

How would I do this?

I have the following code, but it's very slow:

{#

    Get all membership entries

#}
{% set entries = craft.entries({
    section: 'membership',
    order: 'cf_membershipShorthand',
}) %}

{% for entry in entries %}

{% if entry.cf_membershipShorthand %}{{ entry.cf_membershipShorthand }} – {% endif %}{{ entry.title }}

    {#

        Get the related members entries

    #}
    {% set members = craft.entries({
            section: 'member',
            relatedTo: entry,
        })
    %}
    {% if members|length %}
        {% for member in members %}
            {% set image = member.cf_ma_asset[0] ?? null %}
            {% if image|length %}
                {% set imageParams = { width: 30, height: 30 } %}

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

I even tried to eager load the related members entries, but, to my surprise, that even added queries.

I must be on the wrong path. Could anyone enlighten me?

Thanks

Update to my question:
I know how to eager load the related entries:

{% set member = craft.entries({
        section: 'member',
        relatedTo: entry,
        with: [
            ['cf_ma_asset', { withTransforms: [{ width: 30, height: 30 }] }],
        ]
    })
%}

To my surprise that adds queries, but is much faster...

There’s a lot going on here. Let’s first work out the outline of your algorithm, and therefore where things could be improved.

Query and iterate memberships

Query and iterate members

Query first asset

Get asset transform

Note: Every time a transform is used, Craft first has to check whether the transform has been generated (from the docs)

As you can see, there are multiple levels of nested relations going on. You’ve mentioned using eager-loading already, but it is definitely beneficial here. One of the cool things Craft can do is eager-load nested relations.

Have you tried something like this?

{% set memberships = craft.entries({
    section: 'membership',
    order: 'cf_membershipShorthand',
    with: [
        '{relatedMembersField}.cf_ma_asset'
    ]
}) %}

{% for membership in memberships %}
    {% for member in membership.{relatedMembersField} %}
        {% set image = member.cf_ma_asset[0] ?? null %}
        {% set imageParams = { width: 30, height: 30 } %}

        {% if image %}
            {# Output image with transform #}
        {% endif %}
    {% endfor %}
{% endfor %}

Where {relatedMembersField} is the handle of your entries field.


Entry next sibling return a deactivated entry I got an entry template from a structured section.
With prev / next nav links at entry bottom.
But the next sibling is deactivated.
So the page return is 404 not found !

{% set prev = entry.prevSibling %}
{% set next = entry.nextSibling %}

{% if prev %}
    <&nbsp;{{ prev.title }}
{% endif %}
{% if next %}
    {{ next.title }}&nbsp;>
{% endif %}

Should it be status=live by default no?

The getNextSibling documentation says:

  getNextSibling() will return the next sibling whether or not it’s enabled. If you want to get the closest enabled sibling, you can do this instead:

{% set next = craft.entries.positionedAfter(entry).order('lft asc').first() %}

Similarly for getPrevSibling to get the previous enabled sibling you can do:

{% set prev = craft.entries.positionedBefore(entry).order('lft desc').first() %}


When adding a new Entry, I'm having an error I'm new at Craft and I want to add new Entry into a jobs section. But I'm always receiving en error message.

{% extends '_layouts/site' %}

{% block body %}

    {% set company = entry.company %}
    {% set jobDescription = entry.jobdescription %}
    {% set jobRequirements = entry.jobrequirements %}
    {% set location = entry.location %}
    {% set salary = entry.salary %}
    {% set email = entry.email %}
    {{ company }} &nbsp; - &nbsp;{{ entry.postDate.rfc1123 }}

    Description
{{ jobDescription }}
    Requirements
{{ jobRequirements }}
    Location
{{ location }}

    Contact us at
 {{ email }}

Salary
{{ salary }}

{% endblock %}

Just based on your screenshot, my guess is the settings for your entry type for your "Jobs" section has "Show the Title field" unchecked and you've set the "Title Format" setting to be "jobs".

I'm not sure if you unchecked that box on purpose, but if you re-check it, you can manually set the Title (which the slug is auto-generated from on new entries) on a per-entry basis.


Is it possible to change the default search result order (CP)? Craft version: 3.3.19

Is it possible to set default order for CP entry search results? The default is search score but for instance for blog entries, news, etc. the date of the entry is usually more important than the relevance. I need to overwrite the default behaviour somehow.

Thx

Maybe?  Pretty hacky I think, but there is an EVENT_AFTER_SEARCH you can listen to that has the results already scored.

You could probably take those results, then resort by whatever other attributes you want and pass them along back to the CP.


Translation files on load balanced multiple instance site We have quite a large Craft based site that requires load balancing so there are often multiple instances of the site.

The problem we are having is with the translation files. Because these are stored as files when you update them through the admin they are only updated on the site instance you are currently on. Obviously this isn't scalable.

What would be the best solution to make these static translations scalable in this sort of environment? Move the translation files to an S3 bucket? (this would be ideal but have don't think this is possible) or move all translation fields to the database somehow? (what would be the best field type to store them as and where?) or is there some other solution?

Why not just check your site into a git or subversion repository, and when the translation files are updated, push them to the repo, and have the other servers pull the changes down?

You could even automate it with the various git hooks.


For loop through custom field in JavaScript I'm using a script to animate four sets of numbers on a page.  I would like the numbers to be editable from within the admin (a SuperTable field).

Currently I have this:

   {% for stats in entry.statsPanels %}

0{{ stats.statDescription }}

   {% endfor %}

Which is working fine for looping through and pulling back the 'Stat Descriptions'.

Somehow I also need to loop through the 'Stats Number' column and embed this into the JavaScript that animates the numbers...  at the moment they're hard coded '400, 60, 1800, 40'.

     $(document).ready(function(){
      function numberWithCommas(n) {
       var parts=n.toString().split(".");
       return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
      }

      var endingCounterVar = [400, 60, 1800, 40];

      for (let i = 0; i <= 3; i++) {

      let counter = { var: 0 };
      let tal = document.getElementById("tal-"+i);

      TweenMax.to(counter, 5, {
       var: endingCounterVar[i],
       onUpdate: function () {
        let nwc = numberWithCommas(counter.var);
        tal.innerHTML = nwc;
       },
       ease:Circ.easeOut
     });
    }
   });

Any help is very much appreciated.

Thank you

Martin

You could output the numbers in a data attribute on a wrapping HTML element:

{% set numbers = '' %}

{% for stats in entry.statsPanels %}
    {% set numbers = numbers ~ stats.statsNumber %}
    {% if not loop.last %}
        {% set numbers = numbers ~ ',' %}
    {% endif %}
{% endfor %}

<div class="myComponent" data-numbers="{{ numbers }}">
...
</div>

Then you can read them in your JavaScript file:

var endCounterVar = $('.myComponent').data('numbers');

if (endCounterVar.length) {
    endCounterVar = endCounterVar.split(',');
}

This might not be the cleanest/shortest way to achieve this in Twig, mind you!


Cloudinary thumbnail creation for assets I realized Craft 3 generates its own thumbnails and does not use Cloudinary to do this on the CP. My question is, how and where should I modify the JavaScript code, or what is the best practice to use external generator.

What I would like to do is really just utilize the query string of Cloudinary instead of doing this on Craft side...?

So somehow I would like to overwrite this call, and change it:

SITE/cpresources/4c875891/thumb-30x30.jpg?v=1522966431

And I also would like to avoid the generate thumbnail:

http://tr3nds.test/index.php?p=admin/actions/assets/generate-thumb&uid=7b78d4ed-9c3d-4193-89c0-f20e0d3c35be&width=30&height=30&v=1523244927

You can catch the EVENT_GET_ASSET_THUMB_URL event in your plugin and return the $event->url:

   Event::on(Assets::class, Assets::EVENT_GET_ASSET_THUMB_URL, function(GetAssetThumbUrlEvent $event) {
            $event->url = $this->thumbUrl($event);
        });

   protected function thumbUrl($event)
      {
           return "{$this->cloudinary_ulr}/image/upload/w_{$event->width},h_{$event->height}/{$event->asset->filename}";
      }


How to get the author of an entry? I have one user group created, several users in it excludes admin.
I've tested it includes admin to that user group, but with no effect.

If you create an entry in channel as admin and check at front end for author of the entry, you'll see not admin, but actually the data of a first user created in Craft.

Is it done on purpose? If so, What is it, so I understand that.

You get the author's username of an entry via it's entry model like so:

{{ entry.author }}


How would I trigger updateElements for BaseElementIndex from a plugin's JavaScript? If I wanted to update the Elements listing based on an action taken from a plugin, would it be possible to do this?

Setup:

We're on an Elements listing page.
We filter the results with a search query.
We then click an Element's name to move to its individual editing page

The Problem:

Currently in my tests with Google Chrome if I:

Filter a list by a search query (say lastName::T* on the Users listing page),
Click on one of the usernames
Hit "Back"

My search is not saved, i.e., I'm returned to a non-filtered list.

My workaround to this is to write a simple JS plugin that stores your search query - if populated - when you navigate away from the page. I then re-populate the search query when you re-enter the page but I have to tell Craft to execute it, IE to fire updateElements.

My current workaround for this is to fire a change event on the search box if the search query is stored and it's not an Ajax request. It works, it just feels kind of hacky.

So I'm wondering if there's a more native, less hacky solution.

The cleanest way to do this would be to provide your own Javascript class that overrides Craft.BaseElementIndex, which stores the latest search value in localStorage:

MyElementTypeIndex = Craft.BaseElementIndex.extend(
{
    onAfterHtmlInit: function()
    {
        // Do we have a stored search value?
        if (this.instanceState.searchVal)
        {
            this.$search.val(this.instanceState.searchVal);
        }

        this.base();
    },

    updateElements: function()
    {
        // Store the current search val in localStorage
        this.setInstanceState('searchVal', this.$search.val());

        this.base();
    }
});

// Register this as the official index class for this element type!
Craft.registerElementIndexClass('MyElementType', MyElementTypeIndex);

Save that file somewhere in your plugin’s resources/ folder (let’s say it’s craft/plugins/myplugin/resources/js/index.js), and then include it from your plugin’s init() function:

class MyPlugin extends BasePlugin
{
    // ...

    public function init()
    {
        if (craft()->request->isCpRequest())
        {
            craft()->templates->includeJsResource('myplugin/js/index.js');
        }
    }
}


Get category children I would like to select just the children of any given main category (eg. Accessories, Stomps in the picture), regardless of segments in my URL.

I've been trying to understand why the code below won't work.

This just won't work. Why?

{% set categoryGroup = craft.categories.group('productTypes').descendantOf('accessories') %}

    {% for category in categoryGroup %}

{{ category.title }}

    {% endfor %}

Because the descendantOf function expects a parameter of type ElementInterface or an integer

 /**
 * Sets the [[descendantOf]] property.
 *
 * @param int|ElementInterface|null $value The property value
 *
 * @return static self reference
 */
public function descendantOf($value);

You'll have to insert the ID of your accessories element or the element itself

{% accessories = craft.categories.title('accessories').first() %}
{% set categoryGroup = craft.categories.group('productTypes').descendantOf(accessories) %}


Search form returning all pages My search form is returning all of the sites pages, regardless of the search term used.

Even if I search for a load of random letters (dfbdsufbsf) all pages are returned.

This is my search form code.  I've tried changing the button to and  but no joy

      <form class='form form--search' role='search' action="{{ url('search/results') }}">
        <fieldset>

            Search
            <input class='form__input form__input--search' placeholder="Search" name='q' id="q" tabindex='1' type='search'>
            <button class='form--search__button' type="submit"></button>

        </fieldset>
      </form>

And here is my search results page (search/results.html) (markup removed)

{#
 # Search template
 # ---------------
#}

{% extends "_layout" %}
{% block content %}
  {% set query = craft.request.getParam('q') %}
  {% set entries = craft.entries.search(query).order('score') %}

Search Results

    {% if entries|length %}

{{ entries|length }} results:

    {% else %}

Your search for “{{ query }}” didn’t return any results.

    {% endif %}

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

{% endblock %}

Any ideas why this is happening.  I'm using the latest version of Craft.  This is happening locally and on production.

Sorted.

It was a .htaccess issue

One of my redirects had a typo in it

RewriteRule ^old-page$ /new-page [R=301,L#]

should be

RewriteRule ^old-page$ /new-page [R=301,L]


How to add tags in craft CMS 3 This is my first template that im working on in craft cms3, i've managed to make the most of the homepage and other tabs of website dynamic using the CMS, but I can't figure out how do I make tags and categories dynamic on the homepage and sidebars of all the related pages.

The bottom of homepage which I want to make dynamic

The sidebar of the page that I want to make dynamic

if you want to have a look at the website im working on heres the server link http://52.65.202.173/

Will be really grateful for the help, thanks!

Here are some basics:

First, tags and categories are two different things. As a first step, think long and hard about how you want to organize your content. Keep in mind that Categories can be hierarchical, whereas Tags are not.

To start using Categories, you must first create a Category set, say, "Blog", then specify categories within that set, e.g. Beauty, Health, etc. Note that you can assign fields to a category set, so you can associate things like icons or brief description for each one!

To use your Categories in entries, first create a Category field(s) and then add it to one or more of your channel entry types. then, when you create a new entry, you can assign a category to it.

To access entries by category in your templates, refer to this section of Craft Docs


Twig create link with variable I would like to create a link to another page in my plugin and send a specific ID with it but I don't really know how to do it in craft and twig.. I spend too much time on that little task and searched in the internet but could not really find something.

In my template I have

//loop through all database entries
{% for val in entries %}
    .....
    Edit
    .....
{% endfor %}

But it does not really work. How can I pass a specific id in my url and how can I receive this parameter in my php backend?
I didn't find something like craft()->request->getGetVar()and my $_GET is always empty. Of course I could just take the URL and use subtring and explode to get the correct value but I'm not sure if this is the intended way

Use the ~ symbol to concat strings.

//loop through all database entries
{% for val in entries %}
    .....
    Edit
    .....
{% endfor %}


Is it possible to define optional route segments? Is it possible to have optional route segments/variables with getCpRoutes() and getSiteRoutes()?

I'd like the following route to work, even if the URI only contains one segment ("myplugin") rather than two ("myplugin/somevalue"):

"myplugin/(?P<myVariable>[-\w]+)" => array( "action" => "myPlugin/myAction" )

How would the regexp look? Is it even possible, or do I need another route pointing to the same action, but omitting the myVariable segment?

This question is kind of a follow up to Route that should be matching numbers not matching a zero?

You can make a capturing group optional, simply append ? to it. In this case you'd need to add an additional group that includes the backslash and make it optional.

"myplugin(/(?P<myVariable>[-\w]+))?" => array("action" => "myPlugin/myAction")


Resaving Entries hitting a mysterious memory limit I renamed a channel section and Craft (2.6.3012) is trying to resave all the entries therein (about 500 entries, many with up to 10 localized versions). I'm constantly getting this error (in /craft/storage/runtime/logs/phperrors.log):

[26-Mar-2018 15:53:40 UTC] PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 43 bytes) in C:\server\project_x\craft\app\helpers\ModelHelper.php on line 95

Here's the thing... in php.ini, the memory_limit setting is set to 512M. Not the 256M one would expect from the error. In Craft's admin/utils/phpinfo page, it shows that PHP does indeed have a limit of 512Mb, but the process still hits a mysterious memory limit at 256MB.

I'm running locally on XAMPP, PHP 5.6.24 (switching to PHP 7 prevents me from being able to login for some reason), and this is just part of setting up a site, so I don't care about performance or advisable settings with this issue.

What am I missing?

Most likely you'll need to add this line to the Craft config file (craft/config/general.php)...

'phpMaxMemoryLimit' => '512M',

Craft 2 docs
Craft 3 docs


'Could not find your craft/ folder' error despite following installation instructions Thanks in advance for any help - I'm starting to feel like a fool for coming up against errors so often. But here goes.

I have confirmed with my hosting provider that Craft CMS is compatible.

I have put /craft/ folder and the contents of the /public/ folder next to each other in the htdocs directory on my hosting server.

I've updated the location of the /craft/ folder in index.php (to $craftPath = './craft';)

When I navigate to mysite.com/admin I get Could not find your craft/ folder. Please ensure that $craftPath is set correctly in /var/www/virtual/mysite/htdocs/index.php

I've checked that the root folder is performing correctly - I can successfuly navigate to an image at mysite.com/pic.jpg.

I have a similar set up for one particular installation and have the $craftPath set as follows:

$craftPath = 'craft';

Which works fine.


Search products and entries with pagination Is there any way of searching both entries and products at the same time? Wanting a single search on the site which will return all entries and products containing the searched for phrase.

Looked at combining the results from craft.entries.search() and craft.products.search() but this stops us from using pagination which we would like to have. Anybody got a solution or suggestions?

Would prefer not to split into 2 search pages if possible. Thank you.

Unfortunately you would need to do 2 element query searches and combine the results on the front end.

Most developers tend to go for https://algolia.com when they want fast advanced search, including searching across elements.

Probably easiest to get started by searching for an Algolia plugin in the plugin store. I only know https://github.com/Rias500/craft-scout for Craft 3 at the moment.


Site set up with mutiple sub domains I will build a group site in craft which will have the main domain and multiple sub domains.
e.g.
domain.com
property.domain.com
connect.domain.com

The news feed on each sub domain will be different but it will all display on the main domain news feed. The site build etc for each will be similar but content will be different.

What is the best way to set this up in Craft?

Is the following something which can be done.

Use Multi Environment Config to set the SiteURL for each domain.
Point all the domain/sub domains to the 1 public folder.

Within my main _layout.html template file detect what the siteurl is and based on that include different header and footer files for each sub domain?

The same news template files can then be used.
And just use a different structure for the nav on each sub domain.

Is that workable and the best way to do it or should I be having different root folders for each sub domain?

The approach you described is interesting and should actually work. Separate root folders would allow you to define the template folders individually (→ see Ben's answer on how to set this up), but it looks like that's not what you need and your subdomains are more part of one and the same site.

Even with multiple root and template folders you could still include shared template partials, but sharing CSS, JS and assets would be troublesome. But, then again, more easy to have these individually for each subdomain.


Edit the create new section page When creating sections, I need a way to toggle all of them off or on. I have 188 sites and you can imagine how big of a pain it is to untoggle one by one.

Am I able to do this somehow? Create a module?

Edit: I've been told creating this many sites isn't a good idea, so perhaps this is a foolish question

Javascript 'hack' in browser console:

$lightswitches.each(function(){
    var lightswitch = $(this).data('lightswitch');
    lightswitch.turnOff();
});


Matrix Fields translation not working I have the following problem:
My Craft site was setted up normally. I made entries with matrix structure and build one after another.

Then after i built a lot of entries i wanted to set up a second locale for the site.

So i used the craft manual on your site and i told the fields that i want to have in the second language as well that its translateable.

But now if i want to translate my matrix fields in the entry, THE HOLE matrix structure is gone :O but of course i do not want to create them new.

If i do ne entries now after setting up the second language, matrix fields are translateable, but not my entries that were exist before... How can i now fix it?
I read on different blogs that is a bug..

Please help me :)

Best Regards

My guess is that you've got xDebug installed and you're running into this: Why are some entry detail views empty in the control panel?

Or your php.ini file's memory_limit is set to something low and you're running out of memory and it needs to be bumped up.


How to create modals I just want to create a modal and play with it, but can't find a way to do so. I already checked other questions on the subject, but I still can't figure why my modal isn't showing correctly.

Here is my code :

            some text I'd like to be shown...

var $modal = new Garnish.Modal($('#my-modal'));

$('#show-modal-btn').click(function() {
    $modal.show();
});

When I load the page, the big shader appears instantly, and my modal is nowhere to be found, and it moved in the dom tree. Clicking the button doesnt make it appear again.

Foud the answer after digging a bit, in fact I missed a little detail.

The base javascript code was correct :

$modal = new Garnish.Modal($('#my-modal')); //create a new modal
$modal.show(); //shows the modal
$modal.hide(); //hides the modal

Everything is in the HTML code, you need to declare something like this :

Modal header

Go check the modal sources for api methods.


This page isn’t working // I think it's my .env? Been struggling for hours to solve this with no solution and I'm under a deadline for a client. Any help would be so amazing.

Here's what happened:

I set up the initial craft project with craft create
This got pushed to Github and other devs have been continuing work
We were collaborating just fine on the project back and fourth with changes.
In my development I somehow deleted my .env file.
Now - I can't get my /admin/dashboard to show up or the craft site at all.
I've been playing with the settings in the .env I've been going back and fourth with the /phpMyAdmin/?lang=en page trying to set up and link a database.
It seems: the project is fine, the database is fine, but I can't seem to link my database and the craft project and get craft to run at all.

Any tips? Any direction? I am just seeing this in the browser:

This page isn’t working localhost is currently unable to handle this request.
HTTP ERROR 500

Help please! Thanks.

FYI - I am on MacOS running MAMP (From my applications folder) and I have PHP 7.2.11 all installed and running.

Thanks!

Yes, the .env file holds the environmental-specific settings/"secrets" that Craft needs to run. So you'll need to recreate it; here's a template:

https://github.com/craftcms/craft/blob/master/.env.example

More information can be found here: Environmental Configuration


Hosting Craft Site on Github Pages with Paid Domain I'm planning to move from an outside free hosting site to Github Pages free hosting, my site is a small portfolio, but I make changes every now and then so I want to take advantage to have my changes live right when I push to my repository, not having to copy those files to my hosting server and etc. Also I currently have a paid domain, the process would be, host on Github Pages, and redirect to custom domain, in this case I use Hostinger.

If possible:

I currently have on my Repo the templates folder, and my the public_html folder, do I need to include the whole craft folder and structure?

Please any step by step procedure would be appreciated, thanks.

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

Closing.


Database Connection Error after updating from Craft 2 to 3 Good evening all,
I am updating a small site from Craft 2 to 3, and after following the instructions in the documents, I loaded up the backend of my site and was greeted with the install screen.
I know that this typically means that the DB_TABLE_PREFIX is improperly set, but I triple-checked and I'm 99% certain that it's correct. I double-checked with my Craft 2, which looks like
// The prefix to use when naming tables. This can be no more than 5 characters.
    'tablePrefix' => 'craft',

And matched it to my .env file:
# The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)
DB_TABLE_PREFIX=craft

I also checked for a craft_info table, and that is present. The version listed in the version column is 2.9.2, if that makes a difference.
I am unable to login to my admin panel, or view my website now. I get the following when viewing my website:
Database Connection Error – craft\errors\DbConnectException
Craft CMS can’t connect to the database with the credentials in config/db.php.
↵
Caused by: Database Exception – yii\db\Exception

Any help is greatly appreciated!
-Shad

Does the table prefix value in you .env file need to be in quotes? eg
DB_TABLE_PREFIX="craft"


Craft as an API provider & authenticaton I'm building an API provider using Craft and need to implement some kind of client authentication. I don't need to worry about individual users, but I'd like to require that clients authenticate in some way. My current thinking is the client can pass an authorization header header of some kind, or just use basic authentication to access the content on the Craft CMS site, I'm just not sure how to consume the header on the Craft side & validate it before serving the content. Can anyone offer up some tips on how to implement something like this using Craft?

It sounds like you're not necessarily interested in authenticating against Craft's current users, but you just want some type of header authentication in place.

If you set those header (via whatever means) in the API request, you can have a plugin's controller read those via HeaderHelper::getHelper($headerName) and perform whatever authentication logic that you require.

If authentication passes, let the request go through, if not, you can throw new HttpException(503);.


How do you handle SEO on your site? How do you guys handle SEO? Do you just make your own meta fields and add them in the template manually or am I missing something? I did notice there are some plugins being developed but there are sites in the wild now so it's been handled some how. Thanks!

Without having to use a separate Plugin this is a good basic practice on setting up basic SEO for your site.

First create three new fields called "seoTitle", "seoDescription" and "seoKeywords". Put these three fields in a Global group called "globalSeo".

In your layout template "layouts/_layout.html"

    {% set seoTitle = globalSeo.seoTitle %}
    {% set seoDescription = globalSeo.seoDescription %}
    {% set seoKeywords = globalSeo.seoKeywords %}
    <!DOCTYPE html>
    <html>
        <head>
            <title>{% if title is defined %}{{ title }}{% else %}{{ seoTitle }}{% endif %}</title>
            <meta name="description" content="{% if description is defined %}{{ description }}{% else %}{{ seoDescription }}{% endif %}"/>
            <meta name="keywords" content="{{ seoKeywords }}"/>

            {# You can then use the same fields for Facebook tags etc.. or create separate fields. #}
            <meta property="og:title" content="{% if title is defined %}{{ title }}{% else %}{{ seoTitle }}{% endif %}"/>
            <meta property="og:description" content="{% if description is defined %}{{ description }}{% else %}{{ seoDescription }}{% endif %}"/>
        </head>
    <body>

You can now per template override these standard variables with your own for that particular page and/or template.

For a template:

    {% extends "layouts/_layout" %}
    {% set title = "This is a my custom Page Title" %}
    {% set description = "This is a my custom Page Description" %}

For a entry:

    {% extends "layouts/_layout" %}
    {% set title = entry.title %}
    {% set description = entry.descriptionField %}

.. or if you want to user to have custom control over the entry SEO as well you can always add the same "seoTitle" fields to the entry's Channel/Structure/Single and do:

    {% extends "layouts/_layout" %}
    {% set title = entry.seoTitle %}
    {% set description = entry.seoDescription %}


Cache until expiryDate Caching is hard.

I want to delete the cache when a news entry hits it's expiryDate. So I wrote

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

{% cache until newsExpiration.expiryDate  %}
   Bla
{% endcache %}

Now the news entry has expired and no news is present so there is an error:

  Impossible to access an attribute ("expiryDate") on a null variable

I then wanted to write a conditional to see if newsExpiration is defined.

{% if newsExpiration is defined %}
   {% cache until newsExpiration.expiryDate  %}
{% else %}
   {% cache %}
{% endif %}

But that also throws an error because Twig is expecting a closing tag to the cache.

  Unexpected "else" tag (expecting closing tag for the "cache" tag
  defined near line xy).

I there a proper way to define the cache tag including both present and absent entries without query conditionals?

Caching is hard.

https://twitter.com/codinghorror/status/506010907021828096

Something like this should work.

{% if newsExpiration is defined %}
    {% cache until newsExpiration.expiryDate  %}
        ...
    {% endcache %}
{% else %}
    {% cache %}
        ...
    {% endcache %}
{% endif %}

You'd probably want to use an include for the body of the two cache tags to keep things DRY.


Entry Group Empty State I have entries that are getting grouped, but I've noticed that it will return nothing if there's nothing within a group. I'm looking to see if there's a possibility of showing an empty state to a user?

{% set loopCount = 0 %}
{% for status, proposals in proposalsByGroup %}
  {% if proposals|length %}
  {% set loopCount = loopCount + 1 %}

    {{ status }}
      {% for proposal in proposals %}

                {% include 'proposal/_proposalInfluencer.html' %}

      {% endfor %}

  {% else %}
    There's nothing here!
  {% endif %}
{% endfor %}

Unfortunately, the above does nothing as no group actually exists so it won't run the code?

To achieve an empty state for my group (When there's no entries existing within that group). I re-assembled the array and outputted them in a certain order - allowing for an if to come alive when there actually wasn't any status available.

{% set proposals = craft.entries.section('proposals').authorId(currentUser.id) %}
{% set proposalsByGroup = proposals|group('proposalStatus') %}

{% for status in ['pending','accepted','delivered'] %}

  {% if proposalsByGroup[status] is defined %}
    {% set entriesInStatus = proposalsByGroup[status] %}
          {{ status }}
          {% for proposal in entriesInStatus %}
             Hello.
          {% endfor %}
  {% else %}
          {{ status }}
          Nothing here, but still gives a status that you've set above.
  {% endif %}
{% endfor %}


How to add custom options or fields to an Order Adjuster? How do you add options or custom fields to an OrderAdjuster in Commerce 2?
I'm migrating a website from Craft2 to Craft3 and need this, this is how I do it in Commerce 2:
$promotionsAdjuster->optionsJson = [
    'lineItemsAffected' => [$lineItem->id],
    'affectedDiscountId' => $adjustment->id,
    'removeAffectedDiscountAmount' => $adjustment->amount - ($lineItem->total*$adjustment->optionsJson['percentDiscount']),
    'percentageDiscount' => true
];

Found it, you just need to use:
// `sourceSnapshot` can contain information to explain the adjustment
$adjustment->sourceSnapshot = [ 'data' => 'value' ];


Replacing content a specific URL/page already reserved in Structured Data Entries I have a site that I've created a 'Generic Page' type for that is a Structured type with URL Format of {slug}.

This is great for the client as they can create an entry for 'toplevelpage' and then children e.g. 'toplevelpage/firstchild' and the URL structure works as desired.

In a few places, they have custom pages that are not Structured type 'Generic Page' entries but need to sit in that same site URL structure. For example, toplevelpage/fistchild is a 'Generic Page' but they need a toplevelpage/customchild but the parent URL is now owned by the Structured type.

Can I get Craft or Twig to look for Singles or even Twig magic at that level and then just have a stub structured Generic Page that has is content overwritten?

First off, for communication reasons, let's refer to the "Structure" as a section, not a page type. Anytime you create either a Channel or Structure section, you have the ability to create what are called "entry types".  You will see them listed on the far right of Settings > Sections in Craft.

The Solution in a nutshell

In your case, you will want to create a new Entry Type in your Structure to accommodate this custom deviant page, which will allow you to choose different fields for that type and its own template for its own custom code.

What is an "Entry Type"?

Ok, so what is an Entry Type?  You know when you go to post a status on facebook and you have the ability to just write text, or you could choose to upload an image, or you might want to check in?  All of these different types of status posts may share the same fields (like the text field to post your status), but some have additional or completely different fields (like uploading an image), but they are all "Status Posts" to Facebook, just different types of status posts.  This is a very over-simplified example, I know, but it's kind of what Entry Types in Craft are for a Channel or Structure.  They're like an inherent built-in category group that allow you to design different custom field layouts for different types of entries within that one Channel or Structure.

So if you make a Structure called "Generic Pages", you could then create different entry types in that Structure like "Single Column", "With Sidebar", "Top Banner", etc, and they can all get their own custom field setup with their own templates.  Or you could just use one template for them all. I've created Events channels before using things like "Event", "Concert", "Party", "Meetup", etc as the different types.  When I create a new entry in the "Events" channel, I then choose which type of event it is, and by doing so, I'm able to customize which type gets which fields.  They all have a "Start Date" field, but maybe the "Concert" type has a "Door Price" field, whereas "Meetup" doesn't. This way you don't have a confusing "Door Price" field for "Meetup" events that shouldn't be or don't need to be filled in.

Templating

Ok, so how do we handle this in the templates? When you create the section in Craft, you'll point to whatever template you want for the section as a whole (let's say /generic-pages/_entry for example).  In that _entry template, add just this line:

{% include "generic-pages/" ~ entry.type %}

Then inside the /generic-pages/ directory, you create a different template for each entry type you made in Craft.  Name that template exactly how the handle looks like.  So if you made a "Single Column" entry type and the handle is singleColumn, then "singleColumn.html" is the name of your template.  Customize that template all you want.

Here's a proper article on Craft's site talking about this method:
https://craftcms.com/support/entry-type-templates

Even if you're using one template for all entries in this Structure/Channel regardless of entry type, you can still be selective with how you grab your entries like:

{% set entries = craft.entries.section('genericPages').type('singleColumn') %}

Or be conditional based on type:

{% if entry.type == 'concert' %}
    // do something
{% endif %}

Read more about Entry Types in the Craft Docs: https://craftcms.com/docs/sections-and-entries#entry-types


What is the best way to handle HTTP requests within a plugin using Yii or Craft? I have a custom module which is moderating content before entry save, I am looking to use a Microsoft Azure API to handle the moderation, in their documentation they use a HTTP library to make the request.
Is there something which Yii or Craft already offers which I could utilise, if so, how would I perform the same function which is below.
The example provided by MS Azure is below. {body} would be content which I pass in.
<?php
// This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
require_once 'HTTP/Request2.php';

$request = new Http_Request2('https://westus.api.cognitive.microsoft.com/contentmoderator/moderate/v1.0/ProcessText/Screen');
$url = $request->getUrl();

$headers = array(
    // Request headers
    'Content-Type' => 'text/plain',
    'Ocp-Apim-Subscription-Key' => '{subscription key}',
);

$request->setHeader($headers);

$parameters = array(
    // Request parameters
    'autocorrect' => '{boolean}',
    'PII' => '{boolean}',
    'listId' => '{string}',
    'classify' => 'True',
    'language' => '{string}',
);

$url->setQueryVariables($parameters);

$request->setMethod(HTTP_Request2::METHOD_POST);

// Request body
$request->setBody("{body}");

try
{
    $response = $request->send();
    echo $response->getBody();
}
catch (HttpException $ex)
{
    echo $ex;
}

Thanks

Craft includes Guzzle which is very full-featured... I'd use that.
Sorry I don't have time for converting your example but here's a simplified version of how to use it in a Craft plugin:
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://www.example.com/api',
    'http_errors' => false,
    'timeout' => 10
]);

$data = ['some' => 'stuff'];
$uri = 'post-a-thing'

$response = $client->request(
    'POST',
    $uri, [
        'body' => json_encode($data),
        'headers' => [
            'User-Agent' => 'CraftCMS',
            'Content-type' => 'application/json'
        ]
    ]
);

(I usually set http_errors to false so that I can handle http error responses in my own code and fail more gracefully than Guzzle).


Image asset not being displayed This is my second website I am building with craft cms and I have no prior experience with Twig.

I have had a particular issue with echoing image assets from a singles entry.

The line I copied from my previous website with craft was;

Field handles were updated correctly and yet on the template page the image is not displayed.

After looking into this I found the following;

{% set asset = entry.teamImage1.first() %}

{% if asset %}
    {{ asset.url }}
{% endif %}

This had no effect either.

Assuming you have an assets field with the fieldHandle teamImage1 then the following should work.

{% if entry.teamImage1|length %}
    {% set asset = entry.teamImage1.first() %}
    {{ asset.url }}
{% endif %}


How does the Craft Grid System work? Plugins are able to extend Craft and embrace the existing UI nicely. While I'm comfortable extending it in many ways, I don't feel like I could clearly explain to somebody else how the grid system works on the back end and have recently seen a few CP UIs rendered on larger screens (2400px+) that suggest that I may not fully understand how it behaves between devices.

After you extend the CP layout:

{% extends "_layouts/cp" %}

You can build a grid using grid, item, and pane classes and various attributes. Here is an example with likely too many attributes just to put several of them out there into the discussion:

      ...

      ...

Here are a few of the questions I wonder about while working with the grid:

How many columns does the grid support?
Are there any considerations to keep in mind as our plugin's UI adjusts to mobile layouts or big screens with high resolutions?
How do data-position="left" and data-position="right" work? When do we need to use them?
How do the data-colspan attributes work? Are there defaults in place for data-colspan, data-min-colspan, data-max-colspan?
Are there any other features of the grid I'm overlooking or leaving out?

This is somewhat of a guess, but is based on what I could find. It might not answer everything but it might be a start :)

From what I can work out the grid work is worked out around the values you provide yourself, if you look at app/resources/js/craft.js on line 10244 this seems to be where the grid starts.

On line 10339 is the refreshCols function which seems to be responsible of figuring out how wide items are are where they should be placed.

It looks like Craft will take the values you supply data-max-cols="3" data-min-colspan="2" etc and try to work out the best possible layout (This is where data-position gets dealt with aswell) ...

line 10466
// Figure out all of the possible colspans for each item,
// as well as all the possible positions for each item at each of its colspans
...

line 10532
// Now find the layout that looks the best.
// First find the layouts with the highest number of used columns
....

etc etc, so it looks like there aren't really any set defaults, you just gotta play around with the numbers and see what works best for the layout you are trying to achieve.

Lastly, on line 10775 is:

defaults: {
    itemSelector: '.item',
    cols: null,
    maxCols: null,
    minColWidth: 320,
    mode: 'pct',
    fillMode: 'top',
    colClass: 'col',
    snapToGrid: null,
    onRefreshCols: $.noop
}

I realise I could be looking in the wrong direction and apologies if this doesn't completely answer your question, but hopefully it will provide an insight.


if isAjax not working or not detecting ajax request in template I can't stand this and have to ask for help again.. Still working on my buddy's website.

I want to increase a entry's counter (using Entry Count plugin)
So for my _entry.html I added an if statement to see if the request is for Ajax or not. If not, show the entire page. If it is only run the counter twig line.

_entry.html

{% if not craft.request.isAjax and not craft.request.isLivePreview %}
    {% extends "_layout" %}
    {% set title = entry.title|t %}

{% block content %}
 {# CONTENT GOES HERE #}
{% endblock %}

{% else %}
    {# ONLY INCREASE THE VIEWS/COUNT #}
    {% do craft.entryCount.increment(entry.id) %}
{% endif %}

Javascript on main page

$.get($(this).attr('data-url-item'), function(data) {
console.log(data);
});

Now I don't need to actually pickup any data or show it, so I'm using $.get() currently have the console.log() there so I can see which version of the page I'm getting.

Any help is appreciated.

You're bumping into a Twig gotcha: you can't conditionally extend a template. Either a template extends another template (i.e. it has an {% extends %} tag in it) or it doesn't. It doesn't matter if the {% extends %} statement is inside an {% if %} statement.

The solution is to create an additional layout template – e.g. _ajax.html – and use a ternary operator to have your entry template extend one or the other, before putting the conditional that loads either the content or the call to entryCount.increment inside the {% block content %}. Note that for your purposes, the _ajax.html template can be completely blank, except of course for the {% block content %}{% endblock %}). Also note that since we now need to test if the request is an Ajax request twice, it makes sense to cache the test to a variable isAjax:

{% set isAjax = craft.request.isAjax and not craft.request.isLivePreview %}
{% extends not isAjax ? '_layout' : '_ajax' %}
{% block content %}
    {% if not isAjax %}
        {# CONTENT GOES HERE #}
    {% else %}
        {% do craft.entryCount.increment(entry.id) %}
    {% endif %}
{% endblock %}

Not very elegant, is it? A better option might be to create a different endpoint for incrementing the counter entirely, negating the need to create an additional layout template and to wrap most of your content in a conditional. To create a dedicated endpoint for incrementing the counter, you can create a dynamic route. Make sure the route contains a <number> token, which will hold your entry ID (the route could just be count/<number>, for instance). Have the route point to a new template called _count.html or the like, and put the following in that template:

{% do craft.entryCount.increment(number) %}

You'll have to expose the current entry's ID to your JavaScript somehow, but that's easily done by setting a data attribute somewhere in your markup – e.g.

<body data-entryid="{{ entry.id }}">

Then, you just need to use jQuery or the like to issue a request to http://yourwebsite.com/count:

$.ajax('/count/'+$('body').data('entryid'));

Closing thought: So long as you "don't need to actually pickup any data or show it", I'm curious why you couldn't just request the basic template as-is. As long as the template contains the call to entryCount.increment somewhere inside the {% block content %} block, does it really matter if it loads the full layout behind the scenes? Sure, there's a little overhead, but it's way less work and probably doesn't matter that much in the scheme of things.


Get a related entries author in a plugin Very new to plugin stuff and taking baby steps so forgive me if this is obvious.

I have a simple notification service set up to send an email to the author of an entry (front end submitted) when it is saved.

This simply sends the email to $entry->author

The entry that gets submitted also has a related entry field and I'd like to send the author of that entry an email as well, but I'm not sure how I'd get access to them? Any pointers?

Something like this should do it:

// Grab an entry.
$entry = craft()->entries->getEntryById(4);

// The current entry's author.
$originalAuthor = $entry->getAuthor();

// This is assuming your Entries field is called "relatedEntry"
$relatedEntry = $entry->relatedEntry->first();

// Make sure one was selected.
if ($relatedEntry)
{
    // The related entry's author.
    $relatedEntryAuthor = $relatedEntry->getAuthor();
}


Plugin settings page in CP styling I'm having issues finding out what all the classes are Craft uses to style its control panel.

I have extended the layout but is there any place with more information about what classed there are and how to use them?

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

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


Sprout SEO: How to access meta fields assigned to globals? In the Sprout SEO docs you can pass for entries:

{% do craft.sproutSeo.meta({
    id: entry.id
})

And it is smart enough to grab the data. How would could I do similar for meta fields assigned to a global set?

To manage global meta data settings, we recommend using the Meta Defaults. They have all the supported fields and can be accessed by admins in the Control Panel.

The Sprout SEO Meta fields only work with Entries right now, so unfortunately, the data they store will not be usable if they are added to a Global Set.

While I understand these following items aren't exactly what you are looking to do, here are a few steps that could help customize the user experience:

Sprout SEO allows you to rename how the plugin is named in the interface. So you could update the plugin name to just use 'SEO' to help a client associate the SEO tab more specifically with the role of updating SEO meta data.
If you'd have various things setup in Globals and feel that you'd like to somehow tie in the Meta Defaults to that area of your Control Panel, the Sprout Fields plugin has a Notes Field that allows you to add a field that allows you to add more detailed documentation or links to a Global Set.


Bootstrapping Craft gives fatal error I'm using Craft Pro 2.3.2625

I'm trying to write a command-line called script which can call Craft's functions (to create new entries with assets).

Based on Brandon's updated answer here:

Bootstrap Craft from another app

Using:

$craft = require 'craft/app/bootstrap.php';

in a standalone script should just work after Craft 2.2 - but doing so gives me the following errors (paths tweaked to remove project name):

PHP Notice:  Undefined index: SERVER_NAME in craft/app/bootstrap.php on line 105

Notice: Undefined index: SERVER_NAME in craft/app/bootstrap.php on line 105

Notice: Undefined property: Craft\WebApp::$request in craft/app/controllers/TemplatesController.php on line 156

Fatal error: Call to a member function isSiteRequest() on a non-object in craft/app/controllers/TemplatesController.php on line 156

That bootstrap file is only meant to be used by web applications. Even if you got past this error, the file is still going to give you a WebApp instance, when what you really want to be working with in that environment is a ConsoleApp.

If you want to load Craft from the command line, use craft/app/etc/console/yiic instead (make sure it has executable permissions), or if you already have a PHP script running, load yiic.php.

Unfortunately those files don’t work like bootstrap.php though - they will not only instantiate a ConsoleApp instance, they’ll run it as well. So you would need to provide your own functionality through a plugin that adds custom console commands. You would do that by creating a consolecommands folder in your plugin folder, with files inside it that end with Command.php (e.g. MyPlugin_UtilsCommand.php) and a matching class name, which extends BaseCommand.

More details about how to write the class are available from BaseCommand’s class reference.


Optimizing pagespeed I'm not sure what is the cause for this page rendering so slow.
I thought it was the image transforms but I've removed them and still it's really slow to render.

Page in question: http://dharmaavenue.net/e-drops

From the profiling report:

Time:   64.61081s

Memory: 461,289Kb

Total Queries: 52

As you can see it's just a simple nav menu.
Here is the code:

{% block content %}

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

            {% nav entry in eDrops %}

                    {% if entry.slides|length %}
{#
                        {% set image = entry.slides.first() %}
#}
                         {{ entry.title }} >

{#

#}

                    {% else %}
                        {{ entry.title }}
                    {% endif %}

                    {% ifchildren %}

                            {% children %}

                    {% endifchildren %}

            {% endnav %}

{% endblock %}

The entries are basically individual gallerys with many images in the slides field. I'm guessing that all the details of these are being fetched unecessarily, and that stopping this from happenign will solve my problem.

If anyone can help me with this it would be most greatful :)

Not sure how you implemented the cache tags, but I would recommend to cache each "eDrops" entry individually.

I also took out {% if entry.slides|length %}. Testing if entry.slides.first() returns anything is all you need. In order to make the length filter work, Craft internally applys find() to the criteria model behind entry.slides. This means you (unintentionally) added an additional database query (besides first(), which you need anyways).

Keep in mind, that assets are elements in Craft and relationship queries take their time (→ also explained in the Matrix field example here: What are the most common template performance gotchas to avoid?).

{% nav entry in eDrops %}

    {% cache globally using key 'eDrops-' ~ entry.id %}
        {% set image = entry.slides.first() %}

        {% if image %}
            <img src="{{ image.getUrl('fitThumb') }}">
        {% else %}
            {{ entry.title }}
        {% endif %}
    {% endcache %}

    {% ifchildren %}
        {% children %}
    {% endifchildren %}

{% endnav %}


If Entry is related to Category-A, then print xyz I have succussfully been able to list entries within the 'brandx' category slug, but I can't figure out a way to print specific content only if the current 'product' listing is related to the 'brandx' category.

I have tried quite a few things and have come up empty, so I feel like I'm either missing something basic, or there's a trick I can't find in the docs or here.

{% paginate craft.entries.section('shopDetails').level(1).limit(24) as postsOnPage %}
      {% for product in postsOnPage %}
           …
            <h5>
              {% set cat = craft.categories.slug('brandx').first() %}
              {% set catGroup = craft.entries.relatedTo( cat ) %}
              {% if product {# is within the catGroup #}  %}
              Brand X
              {% endif %}
              {{ product.title }}
            </h5>
{% endpaginate %}

All you need to do is this in the product for Loop

{% if product.category.first.slug == 'brandx' %}
    Brand X
{% endif %}

Or Shorthand

{{ product.category.first.slug == 'brandx' ? 'Brand X' }}

Not tested but thats the gist of it.

--Edited


What is the best way to handle errors in plugins and templates? What's the best way to prevent exceptions in my plugin from blowing up my entire page? try/catch and return null, and then check for null in the template?

For example: my plugin fetches data from a remote REST API. If that request fails for any reason I get an error page. I understand why, but I'm looking for the best way to handle it. I'd appreciate any input, even if it seems glaringly obvious to you.

Yep, Craft makes pretty liberal use of try/catch blocks. Wrap your HTTP request in that, and return whatever makes sense in the context – null, false, or maybe an empty array.

Probably also worth logging the error, so the developer can investigate why it’s not working, using Craft::log().

Remember when catching exceptions, that there’s a good chance the exception class won’t be in Craft’s namespace. So you’ll probably need to prepend the exception class(es) with \.

So to put it all together:

try
{
    // Make the HTTP request
    // ...
}
catch (\Exception $e)
{
    Craft::log('The request to domain.com failed: '.$e->getMessage(),
               LogLevel::Warning, false, 'mypluginhandle');

    return false;
}


After upgrading to 2.5: Table 'alpineductless-craft.craft_elementindexsettings' doesn't exist A client upgraded their site to 2.5, and I believe the update didn't finish.

At first there was a 500 error. I tried rolling the app back (code only) and it  gave an error that the database version didn't support rolling back. Replacing the craft/app directory with a fresh version of 2.5 fixed the 500 error.

The site and some of the admin area work, but in the control panel I cannot access Assets or Entries, I get this error:

CDbCommand failed to execute the SQL statement: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mysite.craft_elementindexsettings' doesn't exist

So it seems like something with the migration failed. Except must have not been fully failed, because of the error I got about the database version.

The catch is that the client didn't do a database backup before initiating the update, so there isn't a good rollback point.

Could I manually add this table? Any other potentially fixes for this? Is there a way to tell Craft to re-run the migration to 2.5?

As Lindsey D pointed out in the comment, the answer was to restore the database backup from the automatic backup located in /craft/storage/backups that is generated when the update was initiated.

When this backup is put into place it will re-run the database migration when you visit the Admin area.

So my full solution was 2 steps:

Replace /craft/app with a fresh copy
Restore the automatically backed up database in /craft/storage/backups


Alphabetical index for a list of entries I would like to build an alphabetical list of craft entries, but group them by the initials of one field of each entry. Thus, getting some kind of alphabetical index, like

A

Apples
Ananas

B

Beer

How do I do that?

First, sort all entries by multiple criteria:

{# get our entries and order by firstname, lastname #}
{% set allEntries = craft.entries.section('entries').orderBy('lastname asc, firstname asc').all() %}

Then use craft's custom "group" filter (lastname[:1] picks the first letter):

{# group them by the first letter of the last name https://docs.craftcms.com/v3/dev/filters.html#group #}
{% set allEntriesByGroup = allEntries | group('lastname[:1]') %}

Then loop through that multidimensional array (firstletter, entriesInGroup) is key -> value in twig:

{% for firstletter, entriesInGroup in allEntriesByGroup %}

{{firstletter}}

    {% for entry in entriesInGroup %}

{{entry.lastname}}, {{entry.firstname}}

    {% endfor %}

{% endfor %}


How can I order search results by the post date? I want to order my search results by the post date (not the created on date).  And, this did not work...

{% if entries|length %}
    {% for post in entries.groupBy('postDate') %}
        {% include 'partials/card-standard-4' %}
    {% endfor %}
{% else %}

Your search for “{{ query }}” didn’t return any results.

{% endif %}

{% set entries = craft.entries.orderBy('foo').all() %}

There is an orderBy property you can use on the query


Craft 3: Struggling with CRAFT_BASE_PATH and CRAFT_VENDOR_PATH I am struggling with the definition of CRAFT_BASE_PATH and CRAFT_VENDOR_PATH in web/index.php:

My absolute URLs are as follows:

/home/xxx/public_html/craft/ (not publicly accessible)

and

home/xxx/public_html/web/ (publicly accessible)

Thank you very much for your help!

You should almost never have to change these from the default settings.

All you need to do is make sure your webserver points to your server root properly (in your case, /home/xxx/public_html/web/)

The default Craft 3 install has web/ as the server root, with Craft and all of it's files/folders in the root directory. If you don't change anything, the index.php that ships with Craft will "just work" once you've pointed the webserver at the web root.

In your case, it sounds like you're saying that you've moved all of Craft into a craft/ directory that sits alongside the web/ directory. Assuming you've moved everything into that folder, you'd do something like this in your index.php:

// Project root path
$root = dirname(__DIR__).'/craft';


How to do an ajax submission to Craft Contact Form with attachments using FormData? JS

.on('submit', '#application-form', function(e) {
    e.preventDefault();

    var form = $(this),
        formData = new FormData(form[0]),
        msgBox = form.find('.msg-box'),
        submitBtn = form.find('.submit'),
        loader = submitBtn.find('.fa');

    submitBtn.prop('disabled', true);
    loader.css('display', 'inline-block');

    formData.append('attachment[]', form.find('#resume')[0].files[0]);
    formData.append('attachment[]', form.find('#portfolio')[0].files[0]);

    $.ajax({
        url: '/',
        type: 'post',
        data: formData,
        dataType: 'json',
        contentType: false,
        processData: false,
        success: function(data) {
            msgBox.fadeOut(function() {
                if(data.success) {
                    $(this).text( 'Your application has been submitted!').removeClass('error');
                    form[0].reset();
                } else {
                    $(this).text('An error occurred. Please try again.').addClass('error');
                }

                submitBtn.removeAttr('disabled');
                loader.removeAttr('style');

                msgBox.fadeIn();
            });
        }
    });
})

HTML

<form id="application-form" class="content-block-lg" method="post" action="" accept-charset="utf-8" enctype="multipart/form-data">

            {{ getCsrfInput() }}
            <input type="hidden" name="action" value="contactForm/sendMessage">
            <input type="hidden" name="fromEmail" value="no-reply@example.com">
            <input type="hidden" name="subject" value="Application Form">

            <input type="text" id="address" name="address">

                <input type="text" name="message[Name]" placeholder="Name">

                <input type="text" name="message[EmailOrPhone]" placeholder="Email or Phone">

                <textarea name="message[body]" rows="3" placeholder="Tell us about you"></textarea>

                <input type="text" name="message[LinkToOnlinePortfolio]" placeholder="link to online portfolio">

                Upload a pdf of...
                <input id="resume" type="file" placeholder="resume">
                <input id="portfolio" type="file" placeholder="portfolio">

                    resume
                    portfolio

                <button class="submit" type="submit">send </button>

</form>

The problem I am getting is that, with the code above, submitting the form, I get a response of the entire Homepage html.  I've tried using the url set in the action hidden input, but that just gives me a 404 response.  It's like it can't see the "Action" being passed in because it's in FormData?

I have it working now using this:

$('#Form').submit(function(ev) {
// Prevent the form from actually submitting
ev.preventDefault();

var formData = new FormData($(this)[0]);

// Send it to the server
$.ajax('/', {
  url:  '/',
  data: formData,
  type: 'POST',
  async: false,
  cache: false,
  contentType: false,
  processData: false,
  success: function(response) {
    if (response.success) {
      alert('Thank You. Your message has been sent');
    } else {
            // response.error will be an object containing any validation errors that occurred, indexed by field name
            // e.g. response.error.fromName => ['From Name is required']
            alert('An error occurred. Please try again.');
          }
        }
      });
});


Why is my custom console command throwing Calling unknown method: ...getAcceptsJson? I have a module with a console controller (ScriptsController):

namespace modules\vetscripts\console\controllers;

use yii\console\Controller;
use yii\console\ExitCode;
use modules\vetscripts\VetScripts;

class ScriptsController extends Controller
{
    public function actionExpiring()
    {
        VetScripts::$instance->scripts->expiringScripts();

        return ExitCode::OK;
    }
}

When I run it using $ ./craft vetscripts/scripts/expiring I get the following error and stack trace:

2019-08-05 11:35:24 [-][-][-][error][yii\base\UnknownMethodException] yii\base\UnknownMethodException: Calling unknown method: craft\console\Request::getAcceptsJson() in /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Component.php:300
Stack trace:
#0 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/web/Controller.php(189): yii\base\Component->__call('getAcceptsJson', Array)
#1 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('expiring', Array)
#2 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('vetscripts/scri...', Array)
#3 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/console/Application.php(93): yii\console\Application->runAction('vetscripts/scri...', Array)
#4 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/console/Application.php(147): craft\console\Application->runAction('vetscripts/scri...', Array)
#5 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Application.php(386): yii\console\Application->handleRequest(Object(craft\console\Request))
#6 /Users/steven/Code/vetscripts/craft(22): yii\base\Application->run()
#7 {main}

This is my first time attempting a custom console command, which I need to get a cron job up and running. Is there something I'm missing here?

Thanks!

I had a hunch that a web controller with a similar name was getting called, and indeed that is what was happening. In my module's init method I was setting the controller namespace like this:

$this->controllerNamespace = 'modules\vetscripts\controllers';`

By default, then, the console was going to the web controller, I'm assuming. @Selvin pointed me in the right direction with this:

use craft\console\Application as Console

...

public function init()
{
    ...
    if (Craft::$app instanceof Console) {
        $this->controllerNamespace = 'modules\vetscripts\console\controllers';
    }
    ...
}

Now I can see my module's custom console actions when running ./craft from the console.


Update failed, restoring from app.bak? Running Craft version 2.3, build 2644, schema version 2.3.4... we clicked "update" and got an error screen that looks like the install screen that simply says "oops".

How can I restore my site from the files that are in the (automatically generated) folder "app.bak"?

You can restore your database from your pre-update attempt database backup that you (hopefully) made.  Assuming you've got the the backupDbOnUpdate config setting set to true, Craft made one for you in craft/storage/runtime/backups as well.

You can also download any previous version of Craft's files via: Where can I download previous versions of Craft?

Just replace the existing craft/app folder with the fresh one you downloaded and delete app.bak.  I wouldn't recommend restoring directly from app.bak because depending on where your update failed, it could be in an inconsistent state.

I'd recommend doing a manual update when you're ready to update again as you probably ran into your server's max execution time or memory limit (which tends to happen on these larger updates).