Equivalent of EE admin info code Just wondering: Is there a equivalent for this piece of code written in EE:

{if logged_in}
    <div id=“admin”>
        Page render time: {elapsed_time} sec |
        Queries: {total_queries} |
        Gzip: {gzip_mode}  |
        EE version: {app_version} build {app_build}
    </div>
{/if}

Source: http://www.blue-dreamer.co.uk/blog/entry/expressionengine-measuring-performance-during-development

Not exactly. But if you're looking for stats, devMode does some query profiling right in the console:

I'm not sure if you're looking for a 1-1 correlation but you can obtain whether or not the server supports gzip with the Server variable HTTP_ACCEPT_ENCODING (kind of useless IMO). Craft also will display its version number at the bottom of the CP when you're logged in, so I don't really see value there either but you can get it via your templates (see below).

If you need more than that, you could always make a simple plugin (I like to start with Lindsey D's Business Logic  boilerplate variable class) and then just grab the data you need.

To only display the data to admins when they're logged in, you can do so like:

{% if currentUser and currentUser.admin %}
  Craft {{ craft.app.getEditionName()}} {{ craft.app.getVersion() }}.{{ craft.app.getBuild() }}
    ... do other stuff
{% endif %}


Fetch the three entries before, and after, a given Structure entry, with wrapping For a given structure entry, I need to return the previous three, and the next three entries as one array. But if the given entry is the last in the structure, I need the "next three" to wrap around and select the first three entries, if that makes sense.

The given structure entry should not be included the results.

Does anyone know how I can achive this: all my efforts so far have failed or are far too complex.

Assuming that when you are on the first page, you don't show the last 3 entries of your structure and the single array you need is an array of entries, this should do it for you:

{# Set how many entries to have around current entry #}
{% set surroundingEntries = 3 %}

{# Fetch prev 3 entries - reverse order because of limit() #}
{% set prevEntries = craft.entries.positionedBefore(entry).orderBy('lft desc').limit(surroundingEntries).all() %}

{# Fetch next 3 entries #}
{% set nextEntries = craft.entries.positionedAfter(entry).limit(surroundingEntries).all() %}

{# if there aren't enough nextEntries, add some #}
{% if nextEntries|length < surroundingEntries %}
    {% set limit = surroundingEntries - nextEntries|length %}
    {% set extraEntries = craft.entries.section('sectionName').limit(limit).all() %}
    {% set nextEntries = nextEntries|merge(extraEntries) %}
{% endif %}

{# Put prevEntries back in order and merge nextEntries to it #}
{% set results = prevEntries | reverse | merge(nextEntries) %}

If you need an array of ids, replace .all() with .ids() and if I misunderstood you and  you need two separate arrays, simply don't merge them as results and use nextEntries / prevEntries but don't forget to |reverse your prevEntries to get them back in order :)


How I add security header on the front-end on Craft CMS I have Mod_headers installed and active on my server, I know that Craft adds some headers from PHP but only for Control Panel requests. How can I add security headers to the front-end?
Thank you

Since you mentioned mod_headers, you can add headers at the web-server level using .htaccess and Apache's header set command: https://httpd.apache.org/docs/2.4/mod/mod_headers.html


404 issues and redirect/.htaccess When I type mydomain.dev/blahwrongurl - for some reason .htaccess doesn't redirect to the 404.html file, but just write the blahwrong url out on the page and nothing else?

I get the feeling that I messed up routes somewhere, but I deactivated all of my plugins but nothing changed.

Does anyone know why?

Probably what you're seeing the the generic webserver 404 error page... which means there's something wrong with your server config, as its not sending 404's to Craft to handle.


Setting a conditional for username in URL? Similarly to how Craft knows that a category is defined when a category slug is used, is there a way to detect a user in the same way?

{% if category is defined %}
...
{% endif %}

Something along the lines of (which only returns true if a user is logged in):

{% if user is defined %}
...
{% endif %}

If a username is in the URL, would/should above code return true similarly to how {% if category is defined %} returns true if a category slug is in the URL? (i.e. .com/news/sherlock_holmes)

I'm able to return author posts using method listed in this question, I'm just trying to simplify even further and have one template list all these views.

If you're looking for the current (logged in) user, you should use the global variable currentUser.

{% if currentUser %}
    {# currentUser returns a User Model if there is one, so do with it whatever you like #}
{% endif %}

However, if you want to find a user through a URL segment, you might want to get into using routes. If you use advanced routing, you can get what (I think) you want by adding following to your craft/config/routes.php:

return array(
    '(?P<category>[^/\]+)/(?P<user>[^/\]+)/' => 'path/to/template',
)

In your template, you can then use the variables {{ category }} and {{ user }}. Don't hang me on the RegExp-pattern, this is not tested but should get you further.


Searching entries by title's first initial only We're looking to pull entries from a channel that starts with a specific letter. We've tried using Craft's search option, with 'C*', to pull any title with a word that starts with C. However, it's pulling entries whose second or third words begin with C as well. Is there another route we should consider to achieve this result?

{% set myQuery = craft.entries.section('channelName').limit(null).search('title:C*').order('title') | group('title|first') %}

You're close! According to the entry on searching in the Craft docs, this should work:

{% set myQuery = craft.entries.section('channelName').limit(null).search('title::C*').order('title') | group('title|first') %}

Note the format of the search string with a double colon: title::C*.


Craft queue not being processed, listen not running I built a site on a dev server and the Craft queue worked in that with no extra setup needed. In fact I installed Async Queue Manager because Crafts way was too slow. They both worked fine.

I moved the site to its live server, and the queue is not running. It runs if I manually enter ./craft queue/listen on the command line. When I stop that process it wont process the queue anymore.

Does anyone know why it would not work on this other server? Do I need to do anything special to make it work? I suppose I could run ./craft queue/listen and leave it, but I would need to set it to run on boot. I never did this on the old server.

Thanks

You will need to investigate the log files to determine the source of the problem. There should be a storage/logs/queue.log file. This article might be helpful https://nystudio107.com/blog/zen-and-the-art-of-craft-cms-log-file-reading


Site will not load. Asking me to save "login" as a file What would make a site want me to download the index.php when viewed?  I downloaded the database and all files from a staging server where site was fine.  When I go to any site URL on local machine it prompts me to save "login".  The contents of the saved file are the public index.php.  Is there some setting or cache I need to clear?  I have 10 other sites working local with no issue.

Running latest version of Craft 2.6.2789 on cPanel EasyApache4 server running the new PHP Handler with PHP7 selected for the site..

It actually is asking me to save the file using whatever the last segment is.  Here are contents from my htaccess file:

    RewriteEngine On

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

# php -- BEGIN cPanel-generated handler, do not edit
# Set the “ea-php70” package as the default “PHP” programming language.

  AddType application/x-httpd-ea-php70 .php .php7 .phtml

# php -- END cPanel-generated handler, do not edit

You need to remove this when running local.  The following piece of code is added on servers running the EasyApache4 PHP Handler.

# php -- BEGIN cPanel-generated handler, do not edit
# Set the "ea-php70" package as the default "PHP" programming language.

  AddType application/x-httpd-ea-php70 .php .php7 .phtml

# php -- END cPanel-generated handler, do not edit


Matrix Field Integration I'm just looking for a little guidance here. I have a decent grasp of the matrix field but the functionality I want exactly is causing me some issues.

Im trying to setup a matrix field with the following:

Category name: Football (need the ability to set the category is in panel)

 -> PDFs

  -> PDF Title (Title of PDF)
  -> PDF Asset (Upload PDF Here)

  -> PDF Title (Title of PDF)
  -> PDF Asset (Upload PDF Here)

Category name: Rugby (need the ability to set the category is in panel)

 -> PDFs

  -> PDF Title (Title of PDF)
  -> PDF Asset (Upload PDF Here)

  -> PDF Title (Title of PDF)
  -> PDF Asset (Upload PDF Here)

  etc.

So looking at the matrix field it look like I need someway to create a matrix field within a matrixfield? I see i can use some plugins for this, But i want to make sure im not missing something first.

Thank you very much.

UPDATE

I've setup my matrix field like this, is this correct for what I want?

For a Matrix field inside a matrix field I recommend using Supertables.

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

It doesn't look exactly the same as a matrix block but works the exact same way. With supertables you can go as deep as you want.
Super table is a field you can add into your matrix block which is able to use all the fields you want so you dont have any limitations.

My first impression on your Matrix field looks alright to me but, I might misunderstand it.


Image Transforms not stretching image i´m implementing a image gallery and want to show the thumbnails ( no problem here ) with a transform applied, and i want to implement a image transform on the large image that opens on a lightbox. Why? because it´s a responsive website, and the load speed is crucial, and don´t want to slow things down loading the full image uploaded directly from the client camera ( 6mp or more ), i want to load a large image with a max width of 1000px and jpg quality of 70. I applied the transform and works fine, but the images below 1000px are streted to fit 1000px.

So, my question is: how to set max width of an image to 1000px BUT not forcing it if it´s smaller than the required size?

Crop Fit and Scales don´t do the job.

Any help is welcome! Thanks.

Before you run your transform, you can check the width of the asset file and adjust your transform as needed.

{% set thumb = {
    mode: 'scale',
    width: 1000,
    quality: 70,
} %}

{% if asset.width < 1000 %}

    {% set thumb = {
        mode: 'scale',
        width: asset.width,
        quality: 70,
    } %}

{% endif %}


Craft CMS plugin with AJAX gives 404 error I have created a small craft cms plugin to pull some information from the DB, and everytime I execute the plugin I get a 404.

Here is the controller

namespace Craft;

class UserExists_UserControllerController extends BaseController
{
    public function actionGetUser()
    {
        $this->returnJson($response);
    }
}

And this is the jquery:

$.ajax({
    url: "{{ url("actions/userexists/usercontroller/getUser") }}",
    dataType: "json",
    success: function(data){
        console.log(data)
    }
});

If you aren't currently logged in, you're apt to be running up against the "anonymous access" limitation.

This section of the Controller documentation should help:

  By default, controller actions are only accessible to logged-in users. You can override that by changing the protected $allowAnonymous property on your controller class. To allow anonymous access to all of your controller’s actions, set it to true:

<?php
namespace Craft;

class CocktailRecipes_IngredientsController extends BaseController
{
  protected $allowAnonymous = true;

  // Your action methods
}


Element-api - filter Draft entries by the draft author (not original author) I have a remote app that enables preview based on your editor craft account. I want to retrieve draft entries that they are working on, but i cant find a way to do this. 'authorId' seems to always be the original author of the entry, rather than the draft.

Here is the important bit of my code ->

$user = Craft::$app->users->getUserByUsernameOrEmail($userp);

           return [
          'elementType' => Entry::class,
          'paginate' => false,
          'pretty' => true,
          'criteria' => ['draftId' => $entryId, 'section' => 'cashwrap', 'drafts' => true, 'orderBy'   => 'dateUpdated desc', 'authorId' => $user->id, 'limit' => 10 ],

I cant find any ref for retrieving, or filtering by the draft author id? The above will only show drafts for original author id not draft author.

I think i have found the answer after digging in Element docs... looks like this works! in criteria

'draftCreator' => $user->id


SQLSTATE[HY000] errors Sometimes my clients site is down and it shows one of the following errors (black text on white screen):

[error] [system.db.CDbCommand] CDbCommand::fetchAll() fout: SQLSTATE[HY000]: General error: 1 Can't create/write to file '/tmp/#sql_135b_0.MYI'

CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'krycer_be_craft.t' doesn't exist

They are the same errors that are shown in the log files (with a bunch of other stuff).
The wierd thing is, it doesn't happen all the time. Nothing changed on the site scince a few weeks also. A few weeks ago I restored a database back-up, but everything worked fine untill now.

Does anyone has an idea? I updated to the latest version and cleared the cache, maybe it'll help but I would like to know the reason behind these errors.

If I had to guess, MySQL has ran out of disk space on the volume that it's trying to write to.  Either that, or your host applies some artificial limit to the size of your MySQL databases that you're bumping up against.


Getting error in template: Impossible to access an attribute ("getUrl") on a NULL variable ("") This was working fine previously and not sure what triggered the error. Any idea how to resolve issue?

{% for block in entry.servicesItems.type('images') %}

        {# grab the first image #}
        {% set image = block.image.first() %}

        {# link to the full sized version #}

        {# generated the transformed thumbnail version #}

{{ block.imageTitle }}

{{ block.imageContent }}

{% endfor %}

You can just test if image is defined first using:

{% set image = block.image.first() %}
{% if image %}
    ...
{% endif %}


Are there any tradeoffs if you use the null-coalescing operator in place of first()? With the addition of the null-coalescing operator (??) in Twig, it now appears that the following two examples both provide a way to retrieve the first entry and fallback to null if no entry exists:

{# Get the first entry using the `first` method on the ElementCriteriaModel #}
{% set entry = craft.entries.section('news').first() %}

{# Get the first entry by accessing it in the result array directly #}
{% set entry = craft.entries.section('news').limit(1)[0] ?? null %}

It seems, with the addition of eager-loading and the alternative results syntax required for accessing eager-loaded elements in our templates, that the latter option may provide a consistent syntax to use throughout our templates vs. swapping between the former and the latter depending on which type of query you are performing.

Aside from the uglier syntax in the option that uses the null-coalescing operator, are there any other tradeoffs to consider in choosing the first method vs. the null-coalescing method when retrieving a single entry?

My gut says the first option (.first()) is going to be slightly faster, but in real world performance my guess is that it's negligible.

Personally, I think I'd prefer the cleaner, more explicit, syntax of the first.


Access global field content What could be the reason for this error when I’m targeting a global field?:

Impossible to access an attribute ("footer") on a boolean variable ("").

I created a global set Footer with a matrix field also named Footer, I'm trying to get its content via:

{% for block in footer.footer %}
  {% if block.type == "column" %}

{{ block.headline }}

{{ block.columnContent }}

  {% endif %}
{% endfor %}

I do not see anything obviously wrong with your code, but something that has caught me out many times is a misspelling of field names, so be sure your twig code matches your field names exactly. One thing that is a bit odd is the error message references "footerContent", but that does not appear in your code.


Test for empty RichText field I have a rich text field which contains:

This is what is left when you delete all content of a redactor field.
This can't be deleted without the HTML view of Redactor.

Is it possible to write a conditional that checks for an empty field ignoring HTML markup?

{% if entry.poorText is not empty %}
   {{ entry.poorText }}
{% endif %}

Does not work in this case.

You can use the striptags filter to remove all HTML tags from your string. With the trim filter you can strip all whitespace from the beginning and the end of it:

{% if entry.poorText|striptags|trim %}
    {{ entry.poorText }}
{% else %}
    Here could be a nicely formatted text!
{% endif %}


Redactor clips plugin removes DIV tags from inserted HTML? I'm trying to insert a clip
my text
. But when I insert the clip, the DIV tags are removed.

I have this setting in my Redactor config json: replaceDivs: false

Edit:

There's other problems / bugs with the Redactor API going on that lead to unexpected behavior on formatting the inserted HTML. The solution provided below does allow to insert HTML with DIV tags only if inserted in a new paragraph, otherwise it strips the tags. Another issue I came across is that I get empty SPAN tags added and I don't know where these come from?!

--

The plugin uses Redactor API's insert.html function. Which by default cleans the HTML before inserting it. But there's a parameter to prevent it from doing so.

You can hack / fork the plugin and set the parameter in redactorclips/resources/clips.js (line 63):

this.insert.html(html, false);

I will create a Github issue for this, because it definitely makes sense to have HTML cleaning disabled by default or at least have a setting for it. (Edit: makes no sense as long as there's all the other issues with the API!)


IDing every descendent of a matrixfield Medium has a feature (that's likely the groundwork for their paragraph commenting, among other things) that adds an id to every tag inside of an article. Like so

I'm interested in replicating the behavior with Craft, in such a way that I can then write queries like element = craft.entries.find(2).element.find(120)

Each block within your Matrix field already has an ID, which you can access via block.id within a for-loop on your Matrix field:

{% for block in entry.myMatrixField %}
    ID: {{ block.id }}
{% endfor %}

If you want to be able to query directly for a specific Matrix block, you can use the Low Blocks plugin, which provides a craft.lowBlocks.id() function for accessing a block by its ID:

{% block = craft.lowBlocks.id(123) %}


Craft CMS plugin action debugging with IntelliJ I have xDebug and IntelliJ setup to debug Craft and can run a debug profile where it stops on a breakpoint in index.php and interprets all the variables, etc. in IntelliJ console. However, it never gets to the plugin action when running host/plugin/someaction which has in that action a breakpoint.

Any suggestions?

Right! setting the mapping to the specific file, in this case the controller of plugin made it all work.

Thanks again for taking the time!


Find structure entries which parents relate to other entries I want to select all children of all entries that fulfil specified relation parameter.

I have tried this, but I think .isDescendantOf only supports single entry. Is this even possible?

{% set parents = craft.entries.section('training').level('1').relatedTo(relationParam) %}
{% set children= craft.entries.section('training').isDescendantOf(parents).eventDate('>= ' ~ now).order('startDate DESC') %}

I thought giving more background to this might help, as possibly an entirely new approach will be necessary. Consider this setup in Craft CMS

I have a 2 level structure, where top level is a big matrix describing an event and has quite a big classification section where multiple categories are selected. Then it's children are specific instances of that event with their own date and location.

I don't want to force my client to repeat categorization on each of the lvl2 entries since they've already done it on lvl1.

Can I select all lvl2 entries that have parents fulfilling specific relation param?

Yes, it looks like the descendantOf param doesn’t accept an array of element models or array of element IDs. Here’s what you can do in Twig to work around the problem.

This solution does trigger an additional query for every parent entry matching your relatedTo criteria. But as it’s only fetching the ids column, it might not perform too bad actually, depends on the amount of matching parent entries though.

{% set idsParam = [] %}
{% for parent in parents %}
    {% set idsParam = idsParam|merge(parent.getDescendants().ids()) %}
{% endfor %}

{% set children = craft.entries({
    section: 'training',
    ids: idsParam,
    eventDate: '>= ' ~ now|date('U'),
    order: 'startDate DESC',
}) %}


Get matrix entries related to an image asset via specific field I have a Matrix field that has an Entries field. I want to get those entries, in the selected order, removing entries that don’t have an image asset assigned to the pageImage field.
Attempt 1
Gets correct entries but doesn’t maintain the selection order.

block.entries.relatedTo('and', {
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
})

Attempt 2
Same result as above. Correct entries but wrong order.
craft.entries.relatedTo('and', {
  sourceElement: block
}, {
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
})

Setting the field value in the first statement results in an empty result set.
Attempt 3
Seems to work but generates extra queries.
{% set ids = block.entries.ids() %}
{% set entries = craft.entries.id(ids).fixedOrder(ids).relatedTo({
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
}) %}

While you said that Attempt 1 was giving you the correct entries, just in the wrong order, if you have two blocks, you will probably find that you’re getting all blocks’ related entries each time. Because when you set that relatedTo param on block.entries, you’re actually overriding the existing relatedTo param that the Entries field type set, which limits entries to just those that are related to the current block. So with a little more testing you’ll find that’s more than just an ordering problem.

Attempt 2 is the right way to go - finding entries that are explicitly related to both the current block and some number of assets. If you want those entries to show up in the order they were related within the current block, you just need to set the order param. In this case you’ll want to set that to sources1.sortOrder, as sources1 is the alias that the craft_relations will get when it’s joined into the query to aid in a sourceElement relation param for the first time.

craft.entries({
    relatedTo: [
        'and',
        { sourceElement: block },
        { targetElement: craft.assets.kind('image'), field: 'pageImage' }
    ],
    order: 'sources1.sortOrder'
})

One thing I would recommend is, if you are going to be running this same query on multiple Matrix blocks on the same page, you should define that craft.assets ElementCriteriaModel outside of the main for-loop. That will save Craft a DB query for each block.

{% set allImages = craft.assets.kind('image').limit(null) %}

{% for block in entry.myMatrixField %}

    {% set entries = craft.entries({
        relatedTo: [
            'and',
            { sourceElement: block },
            { targetElement: allImages, field: 'pageImage' }
        ],
        order: 'sources1.sortOrder'
    }) %}

    ...

{% endfor %}


Filtering/searching for entries by category in the control panel Is there any way of filtering by category in the control panel entries list?

Likewise, is there for an "entries" field (like how Playa lets you filter by channel, category)?

You can via the search box:

myCategoriesField:"some category title"

See http://buildwithcraft.com/docs/searching for details on the syntax.

We do plan on making it possible to add category/tag filters to the element indexes though, including the modal selection windows.

Update: You can add a list of categories to the Entries page sidebar using the Category Sources plugin.


Images not showing on the site Our website has been live for more than a year with no issues, but today it seems the images have disappeared and are showing as a '?'

Any ideas why this might be?

It is hard to answer without additional information, but here are some things you can check:

Did you try it in other browsers/on other computers/in a different network?
Is there enough free disk space on your server?
Did you check the server logs?
Did you ensure the "Assets in this source have public urls" option is on for your volume(s)?
Did you try to clear the cms caches?


Live Preview Not Updating - No errors found Okay, first I know this question has been asked - specifically here: Live preview not automatically updating

But that suggestion did not help. I have no console errors, no network errors. In fact, when I view the network tab in Chrome I can see it successfully POSTing the changes as I type in live preview mode. I have this set up on MAMP using craft.dev as the hostname.

I tried this in both Chrome and FireFox with no luck, as well as trying a fresh install of Craft with no success.

Any thoughts are greatly appreciated on what the issue might be.

Thanks.

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.


order and limit the occurrences of related categories I'm generating a list of all related categories of the entries listed on the page.

{% for entry in entries %}
    {% set categories = craft.categories.group('functieGroep').level(2).relatedTo(entry).all() %}
    {% nav category in categories %}
        <option value="{{ category.title }}">{{ category.title }}</option>
    {% endnav %}
{% endfor %}

This produces the list of categories. However, I want this list sorted by category.title and only show one occurrence of similar listed categories?

As is mentioned in multiple places, Twig is for viewing, not manipulating data. However, this should work.

We create an empty array, then loop through each entry's categories and if they aren't in the array, add them. Then finish up with a sort by title

{% set categories = [] %}
{% for entry in entries %}
  {% set entryCategories = craft.categories.group...all() %}
   {# notice the IF to combat duplicates #}
   {% for category in entryCategories if category not in categories %}
     {% set categories = categories|merge([category]) %}
   {% endif %}
{% endfor %}
{% nav category in categories|sort((a,b) => { a.title <=> b.title } %} {# reverse to b.title <=> a.title to change sort #}
...
{% endnav %}


Limit a field to entries by entry type Is it possible to have an "entries" field but only allow selection to entries of a specific "entry type" within craft?

I'm trying to use entry types as a sort of way to enable interfaces with chunks of content. Requiring specific fields for one type of content and different fields for another type of content.

I realize I could create many channels and accomplish the same thing, but these data structures are similar in a lot of respects with only minor differences (which are important depending on the context they are going to be rendered). So I would prefer to have an overarching channel with several types.

Probably too late for you, OP, but the Entries Subset plugin for Craft 3 lets you do this and more.


Dynamic navigation using a global Hi guys does anyone know how I might go about creating a dynamic navigation using a global with the navigation items as fields, is this even possible?

Global is not really the best option for dynamic navigation, because by definition it is designed to contain just one of something — and while it supports multiple fields, it only supports one instance of each field. Technically you could use a field within the global that supports multiple items (i.e. table fieldtype or matrix fieldtype), but none of the fieldTypes support hierarchical structures natively, so I don't see the advantage. Or you could simply paste static HTML into a text field, but I wouldn't really classify that as dynamic. Overall, not a particularly good option.

You should probably be looking into using a 'structure' (or to a lesser extent 'categoryGroup'), where each entry would represent a page or nav item, organized hierarchically. In this way you can reuse the same field within each entry (i.e. 'title') and loop through the entries to dynamically generate the nav, with the added benefit of being able to reorganize the nav easily using drag-and-drop.

For more information, see:

Documentation on using the nav tag.
Documentation on giving each Entry Type it's own template.
Answers from previous questions, such as here and here.
Check out some of the dedicated nav building plugins, such as a&m navigation or craft nav.


Solspace select options not being stored I am populating a select drop down with custom options in the template, but those options are not being displayed in the individual Form submission page.

Example code below:

{% if field.handle == "country" %}

      <select name="{{ field.handle }}" id="form-input-{{ field.handle }}" required>
          <option value="">Country *</option>
          <option value="AF">Afghanistan</option>
          <option value="xx">another country...</option>

{% endif %}

The Country field handle is country

Outputted html is:

        <select name="country" id="form-input-country" required>
            <option value="">Country *</option>
            <option value="AF">Afghanistan</option>
            <option value="xx">Another country...</option>
        </select>

When I view the individual submission in admin I see the below:

But in the submission list page the value does appear:

Thanks

Unfortunately this is currently a limitation of Freeform. It expects that the option values are predefined for the field, and not dynamically loaded at template level.

It's on our feature requests list to come up with a way to let users override this functionality. :)


Is there a way to limit the Asset upload directory in Redactor? I am looking to control what asset directories are available from the image upload button in a rich text field. Is this possible?

Also, does anyone know the Redactor setting to set the default size of the editor? I can't seem to track it down.

Thanks!

Is there a way to limit the Asset upload directory in Redactor?

No. You'll want to use a Matrix Field with an image block.

That said, it's possible you could create a Redactor button that does this via a plugin, but it'd probably be a bit of work.

Does anyone know the Redactor setting to set the default size of the editor?

The setting your looking for is minHeight.  Here's an example:

{
    buttons: ['html','formatting','bold','italic','unorderedlist','orderedlist','link','image','video'],
    plugins: ['fullscreen', 'pagebreak'],
    minHeight: 200
}

A longer discussion on custom Redactor toolbars and a few more examples can be found in this article: Custom Redactor Toolbars for the Rich Text Field in Craft CMS


proc_open error with the Contact Form I get the following error upon submit of the contact form (Pixel and Tonic's version).

  proc_open() has been disabled for security reasons

Using Craft 3.0.5 and Contact Form 2.1.1. Email is being sent by Sendmail

Client's website host are not willing to enable proc_open. Is anyone aware of a simple way around this?

Here's the Stack Trace:

yii\base\ErrorException: proc_open() has been disabled for security reasons in /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:296
Stack trace:
#0 /home/blahblah/vendor/craftcms/cms/src/web/ErrorHandler.php(84): yii\base\ErrorHandler->handleError(2, 'proc_open() has...', '/home/blahblah/...', 296)
#1 [internal function]: craft\web\ErrorHandler->handleError(2, 'proc_open() has...', '/home/blahblah/...', 296, Array)
#2 /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php(296): proc_open('/usr/sbin/sendm...', Array, Array)
#3 /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php(58): Swift_Transport_StreamBuffer->establishProcessConnection()
#4 /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php(126): Swift_Transport_StreamBuffer->initialize(Array)
#5 /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php(52): Swift_Transport_AbstractSmtpTransport->start()
#6 /home/blahblah/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php(67): Swift_Transport_SendmailTransport->start()
#7 /home/blahblah/vendor/yiisoft/yii2-swiftmailer/src/Mailer.php(151): Swift_Mailer->send(Object(Swift_Message))
#8 /home/blahblah/vendor/yiisoft/yii2/mail/BaseMailer.php(263): yii\swiftmailer\Mailer->sendMessage(Object(craft\mail\Message))
#9 /home/blahblah/vendor/craftcms/cms/src/mail/Mailer.php(159): yii\mail\BaseMailer->send(Object(craft\mail\Message))
#10 /home/blahblah/vendor/craftcms/contact-form/src/Mailer.php(100): craft\mail\Mailer->send(Object(craft\mail\Message))
#11 /home/blahblah/vendor/craftcms/contact-form/src/controllers/SendController.php(51): craft\contactform\Mailer->send(Object(craft\contactform\models\Submission))
#12 [internal function]: craft\contactform\controllers\SendController->actionIndex()
#13 /home/blahblah/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#14 /home/blahblah/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#15 /home/blahblah/vendor/craftcms/cms/src/web/Controller.php(76): yii\base\Controller->runAction('', Array)
#16 /home/blahblah/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction('', Array)
#17 /home/blahblah/vendor/craftcms/cms/src/web/Application.php(272): yii\base\Module->runAction('contact-form/se...', Array)
#18 /home/blahblah/vendor/craftcms/cms/src/web/Application.php(520): craft\web\Application->runAction('contact-form/se...', Array)
#19 /home/blahblah/vendor/craftcms/cms/src/web/Application.php(256): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#20 /home/blahblah/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest(Object(craft\web\Request))
#21 /home/blahblah/web/index.php(21): yii\base\Application->run()
#22 {main}

I'm about 99% sure that if you swap from using sendmail to SMTP, or almost any of the other mail transports in the "Mail Adaptors" category in the Craft 3 Plugin Store (SES, Postmark, Mandrill), they won't end up going through proc_open.


Session related question - opening browser with multiple tabs We are having a situation wherein the users are trying to open URLs in the same browser with multiple tabs, while doing that the session variables which store unique identifiers are overwritten.

Is there some setting which can help in overcoming this problem?

Per default, there is no way to have different sessions in the same browser window. The sessions are always shared trough all tabs. If two different Sessions are enough, you could use a privat/incognito browser window.

A other solution could be to use HTML 5 SessionStorage for your variables. But this works only for your own variables: Craft CMS use normal sessions/cookies. You can find further informations about your topic here: https://stackoverflow.com/questions/368653/how-to-differ-sessions-in-browser-tabs.


Unable to delete some entries It is weird that I can delete some entires in the app but some I can't. When selecting specific entry to delete, I don't see the option to delete it. I only have "edit entry" and "view entry". In some other entries I have the "delete..." option as well.
Why is that?

You can define different permissions in Craft CMS, if you are not admin its likely someone restricts your access.

Furthermore you can't delete entries in a section of type single - those entries will always exist


What's the best way to degrade gracefully when using a Plugin Variable? When providing plugin users with variable containing arguments like {{ craft.pluginname.variable(arg1, arg2) }} what's the best practice for returning something that doesn't throw an Internal Server Error exception for Missing argument 1 or argument 2?

Should this be done as part of the /services/PluginService.php or somewhere else? Is it better to return a nicer Javascript console error (or Craft error log) vs. crashing the page?

I think the best way to do this would be in your PluginHandleVariable file's method, just have it accept one, optional parameter and expect it to be an array.

public function variableMethod($options = null)
{
    if (!$options || !is_array($options))
    {
        return "No options set";
    }

    // Now you can check for individual options on the array
    if (isset($options['option1'])
    {
        ....
    }

}

Then both of these would work:

if craft.pluginname.variable()
if craft.pluginname.variable(options)


How do I prevent a runPendingTask script being included in returned HTML via ajax? I have created a route to retrieve some categories via AJAX. When the AJAX call returns the HTML a runPendingTask script is also returned with the HTML. How do I prevent this?

/*<![CDATA[*/
(function() {
    var XMLHttpFactories = [
        function() {
            return new XMLHttpRequest()
        },
        function() {
            return new ActiveXObject("Msxml2.XMLHTTP")
        },
        function() {
            return new ActiveXObject("Msxml3.XMLHTTP")
        },
        function() {
            return new ActiveXObject("Microsoft.XMLHTTP")
        }
    ];
    var req = false;
    for (var i = 0; i < XMLHttpFactories.length; i++) {
        try {
            req = XMLHttpFactories[i]();
        } catch (e) {
            continue;
        }
        break;
    }
    if (!req) return;
    req.open('GET',
        "http:\/\/tfc.dev\/hollywood-road\/index.php\/actions\/tasks\/runPendingTasks",
        true);
    if (req.readyState == 4) return;
    req.send();
})(); /*]]>*/

The next (post 2.5.2767 release) will no longer inject that code on AJAX requests.


Loop through entries in a Matrix block type I have a Matrix field with 4 Block types. I loop through them like this

{% for block in entry.MatrixFieldHandle %}
    {% set type = block.type.handle %}

    {% switch type %}
        {% case 'BlockType1' %}
            {{ block.fieldHandle }}

        {% case 'BlockType2' %}
            {{ block.fieldHandle }}

within one of these cases, I need to loop through the entries:

{% case 'BlockType3' %}
    {% for row in block|batch(2) %}

        {% for block in row %}

{{ block.fieldHandle }}

        {% endfor %}

{% endfor %}

The html output is close, but I do not get any content displayed. What is wrong?

I'm assuming you are talking about your block type having a Entries field within.

You simply loop through it like this:

{% case 'BlockType3' %}

{% for entry in block.entriesFieldHandle %}

{{ entry.title }}

{% endfor %}


Looking to use a tag slug/URI and loop through entries of that tag It doesn't appear that tags are handled the same way as categories in the sense that categories have a slug (which results to a URI). I'd like to use tags to link to a "tag" page, similar to a category page, but "Really Cool Tag Name" doesn't work/look right as part of a URL. I've used the Slugify plugin to turn the tag in to a slug, however, I'm not sure the best approach to return the relationship of that tag as that slug is not related to the tag at all. Would the best practice be to add an additional slug field to the tag group? Then I'd be able to make that relationship. Thoughts?

Here's a really DRY way to do it.

Setup a route, something like "news/tags/(tag)" to load the "news/index" template (the same one used for listing all entries).

In the "news/index" template:

{# If there is a tag token in the URL, set a filtered variable. #}
{% if tag is defined %}

Tag: {{ tag }}

    {% set tag = craft.tags.name(tag).first() %}

    {% set entriesToShow = craft.entries.section('news').relatedTo(tag) %}

{% else %} {# No tag token in URL, assume unfiltered overview page. #}

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

{% endif %}

{# the entry loop for both filtered and unfiltered entries #}
{% for entry in entriesToShow %}
    {# display entry #}
{% endfor %}

When templating tag links to this system use:

{{ siteUrl }}news/tag/{{ tag.name|url_encode }}

This method allows you to reuse your entry loop and you don't even need a "tags" template. I can also be expanded to filter by categories as well without needing another template.


Show only top level categories assigned to an entry Having a bit of a brainfart here...
If hotspotCategory is my entry's categoryfield and that category group has nested categories, how do I return only the top level categories?

{% set entryCats = entry.hotspotCategory %}
{% if entryCats | length %}
    <span class="filter_cat">
       {% for cat in entryCats %}
          {{ cat.title }} {% if not loop.last %}, {% endif %}
       {% endfor %}
     </span>
 {% endif %}

this works but if I do something like

{% set entryCats = entry.hotspotCategory.level(1).all() %}

I get an

Impossible to invoke a method ("level") on an array.

error.

What am I missing here?

To clarify: my entry has the following categories attached (slow & fast food are subcategories):

- food & dining
--- slow food
--- fast food

Now, on the entry page I only want to display the top level category, not the subcategories.

You might want the siblings of the selected Category via siblingOf - I think you'll need to do this with two steps.


How to cache content per user? Is there a way to cache content with the (% cache %} tag on a per-user base?

If user A is logged in, his content gets cached. User B logs in, but his content should not interfere with that of User A.

In the upcoming Craft 2.2 release, we've added a using key parameter to the {% cache %} tag for for situations like this.

So you'd be able to do something like this for per user caching:

{% cache using key "myImportantUserCache" ~ currentUser.id %}


RSS caching removes items from feed I am pulling in a feed I know that has two items. When I add caching to craft.feeds.getFeedItems(feedurl, limit, cache) the first items is not pulled in.  However if I remove caching or add "0" that item is pulled in. Would this have something to do with the feed or craft?

The 3rd parameter passed into getFeedItems is for an offset, not caching.  The caching parameter is in the 4th place and accepts any valid PHP time format.


Implementing Revolution Slider The slider requires an unique ID per slide, wrapped in
 tags, so I am trying this:

    {% for testimonials in craft.entries.section('testimonials').limit(3) %}

            {{ testimonials.body_testimonial }}

            {{ testimonials.title }}

    {% endfor %}

This results in the first slide entry with both Title & Body, but the second and third slides only parse the Title not the Body.

Could someone verify the craft code is correct? The entries are made in a Channel section with a handle; testimonials.

Yes, your code looks fine.

It's possible that the second and third entries just don't have content in the body_testimonial field.

(Unrelated — I recommend using testimonial as your loop variable, since it represents a single Testimonial entry. This is a good practice in general: Variables that represent a list should have a plural name, and variables that represent a single object should have a singular name.)


Why would Craft Commerce only be using the dummy gateway? This maybe an obvious one but I thought I should document it here. After purchasing Craft Commerce and enabling your payment gateway of choice after disabling the dummy gateway, payments are still being processed using the dummy gateway only.

If you are in development mode then Craft Commerce will still use the dummy gateway. You need to disable dev mode to allow your payment gateway to be used.


How can I use slim templates with Craft? Coming from ruby and rails, I’ve been using slim (https://slim-lang.org) for years. It’s brevity and clarity have become the norm to me and writing and reading  full html feels a bit exhausting.

I am wondering, is there a way to use slim with twig templates in Craft? Does anyone here use this combination? Would you be willing to share your setup?

Thank you!

To answer your question: I think you CAN, but it will not be easy.

Craft is built on top of the Yii framework. It lets you override things (settings, classes) in the config/app.php file that gets installed by default. So, you should be able to change the view renderer to anything you want:

<?php

return [
    'components' => [
        'view' => [
            'class' => 'craft\web\View',
            'renderers' => [
                'slim' => [
                    'class' => 'path\to\your\slim\ViewRenderer',
                ],
            ],
        ],
    ],
];

Of course, this would require a Yii ViewRenderer based on Slim, which I don't think is  available (yet). You could build it yourself, based on the Twig ViewRenderer used by Craft.

The reason I would not do it, is that Craft has several Twig filters en functions that make your templating life easier. You'd have to create wrappers for those, to be able to use them. I don't think the added complexity of all this weighs up to the advantage of using Slim.


Using Yiic for plugin migration I've been trying to follow the docs for creating a plugin migration (https://craftcms.com/docs/plugins/migrations) but any attempts to run yiic seem to die with:

CDbConnection failed to open the DB connection.

My Google-fu has not come up with any relevant answers. This is with Craft setup in a Vagrant box, if that makes a difference.

If you're using 'localhost' for the 'server' in craft/config/db.php, try '127.0.0.1' and visa-versa.

For some reason, some environments are picky about that when connecting to MySQL from the CLI.


Entry Form: Populate checkbox list from another entry and save options in entry I am trying to load some options in to a checkbox list from another entry so that a user and save select them form a checkbox list but I am unable to save the Entry Form with their selection.

I have created the registeredOccurances checkbox field in the Section, it has no options set as I want to set them on the entry form.

<input type="hidden" name="fields[registeredOccurances]" value="">
    {# Load rows from SuperTable in to checkbox list #}
    {% for block in entry[dateFieldHandle] %}
        <input type="checkbox" value="{{ loop.index }}" name="fields[registeredOccurances][]"> {{ block.date }}
    {% endfor %}

    {% if entry is defined %}

{{ dump(entry.getErrors()) }}

    {% endif %}

The dump is outputting the below, can someone help to interpret it?

array(1) { ["registeredOccurances"]=> array(1) { [0]=> string(33) "Registered Occurances is invalid." } }

Thanks for your help :)

Could this be a reserved word? Generally I access fields using entry.registeredOccurances is there a reason you are using fields[registeredOccurances] and entry[dateFieldHandle]?


Using ImageOptimize plugin with Matrix fields With the ImageOptimize plugin for Craft 3, you create an OptimizedImages field type and then assign that to the Field Layout of your chosen Asset Volume. As far as I can tell (I'm very new to Craft), this means that it won't work to add an Assets field inside a Matrix because it doesn't have the OptimizedImages field associated with it. (I've tried, and received Calling unknown method: craft\elements\Asset::optimizedImages())

Is anyone aware of a possible workaround? I'm guessing that something like Craft Neo, which allows you use existing fields in a Matrix, would be a solution, but at this early stage, there is no version of the plugin for Craft 3.

Thanks for any insight!

I'm also using ImageOptimize and yes, it does work within Matrix.
Your image has to have the call to the plugin code as specified in the plugin docs. Additionally, your image calls must match the image size you've setup within the plugin preferences panel. Within Matrix, you are calling the assets Field Type.

Here's a sample:

{% if block.type == "graphicCalloutBlock" %}
        {# Full Width Image #}
        {% set image = block.graphicCalloutImage.one() %}

                 {% if image | length %}

                {% endif %}

{% endif %}


"Call to undefined method Calendar\Library\Carbon::setWeekStartsAt()" Solspace Calendar I've got Solspace Calendar installed to the best of my knowledge. I have repurposed the 'calendar_demo' files to 'calendar'. Both /calendar and /calendar_demo just show:

  "Call to undefined method Calendar\Library\Carbon::setWeekStartsAt()" in DateHelper.php.

/calendar/week does the same. A path like calendar/2016/11 just give a Twig error.

I can't understand why this is happening. I'll give more details if you ask me, I don't know what else to give.

The issue has to do with another third party plugin (Postmaster) installed and also using Carbon. The Postmaster plugin appears to be using an older copy of Carbon and Calendar is loading Postmaster's Carbon library, causing issues.

Manually updating the vendors directory to use latest versions may resolve this issue. We will try to reach out to the developer of Postmaster and see if they can resolve this on their end. :)

Customers effected with this issue can contact Solspace support for an updated vendors folder for Postmaster that may resolve the issue.


Write into Sprout Forms from another plugin I'd like to be able to create a Sprout Forms entry from another plugin I'm working on. Is this possible?

I had a bit of a look at the SproutForms_EntriesController->actionSaveEntry() action but it's kind of all bundled up.

This other plugin is a self contained booking system that I don't want to use an actual Sprout Forms form for - but to keep it consistent for the client I'd like to write (for reference) these entries into a pre-existing form I've set up.

Thanks!

When leveraging another plugin programmatically, you will typically want to use the service layer. In your case, the SproutForms_EntriesService.php is where the saveEntry action gets processed. The saveEntry service method expects a SproutForms_EntryModel:

craft()->sproutForms->saveEntry($entry);

Here is a longer example:

// Create a new instance of a SproutForms_EntryModel
$entry = new SproutForms_EntryModel();

// Set some SproutForms_EntryModel attributes
$entry->formId    = 4051;
$entry->ipAddress = '127.0.0.1';
$entry->userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36';

// Set the custom fields
$entry->setContentFromPost(array(
    'fullName' => 'Test Name',
    'message' => 'Test message'
));

// Save the entry
craft()->sproutForms_entries->saveEntry($entry);

Sprout Forms should dynamically set the title value for you, based on the value you have in the Advanced->Title Format setting.

In the case it doesn't seem to work, a quick way to see if there are any errors is to kill your script after you tried to save the entry and view the full list of errors (or use a more advanced PHP debugging workflow with a tool like XDebug):

Craft::dd($entry->getErrors());

See the answer from Brandon Kelly on this post for more information on how to set custom fields on an Element.


What it "Assets in this source have public URLs" good for? just a short question - what is "Assets in this source have public URLs" good for? Oh course, I can't use getUrl() in the templates, yes, but I can still get the filename etc. So I don't see the use of this parameter?

Another question: when I upload assets to craft, sometimes they are put in the folder I expect, sometimes craft creates a subfolder (named like the asset-id I guess) and puts the file inside that folder. In which case a subfolder is created?

It let's you define "private" asset sources that you don't want publicly exposed on the web.

  Another question: when I upload assets to craft, sometimes they are put in the folder I expect, sometimes craft creates a subfolder (named like the asset-id I guess) and puts the file inside that folder.

If you're uploading these files through an Assets field, then that field's setting can define a dynamic subfolder path where the upload will be saved based on the contents of the entry/user/tag/category/etc. that it is being saved in.  Sounds like that's what you've got defined.


How do I keep the 2nd  styled inside a  in my Rich Text (Redactor) editor? I think this is some kind of a Redactor bug. This used to work just fine but within the last couple of Craft updates all of my words styled with the  within a paragraph tag ends up unstyled with a "" before the words that were styled with with this tag when saved, when loading a saved Entry Redactor loads it this way. It seems to happen only to the second styled  instances. I've contacted support but they didn't have an answer. I'm quite desperate to fix this as it's messing up our style guide Craft based site.

Here is an example shot.

Looks like a Redactor bug to me as I can reproduce it on their demo site: http://imperavi.com/redactor/

I've created a support ticket with them reporting the issue.


Installing the Charge plugin breaks plugin page I am attempting to install the Charge plugin on a Craft site.  When I upload the plugin folder I get an error when opening the plugin page that says that the page cannot be loaded.  It works locally.  If I remove the plugin folder that page loads.  There is not a Craft error, I get an error that the page is "unable to handle the request", or just a total white screen. Anyone aware of an issue with the plugin?  I could not find anything here or online about it.

The folder is in the correct place and all the files are there, nothing has been tampered with or altered that would cause an issue.

So the answer at the bottom of the page here ended up solving my issue.

The plugin was using php short array syntax " [ ] " which is available in 5.4 + and the server was set at 5.3.29.  When I changed that it worked perfectly.


Searching multiple queries using CraftCMS search function As you can see in the code below I'm currently searching for the keyword but how can I make it so it picks up on entries that have a matching keyword, location & salary or if they don't fill out one of the fields then just search using the remaining fields.

{% set keywordQuery = craft.request.getParam('keyword') %}
{% set locationQuery = craft.request.getParam('location') %}
{% set salaryQuery = craft.categories.getParam('salary') %}

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

<form action="{{ url('jobs/list') }}" class="submit-this">

             <input type="text" name="keyword" placeholder="Keyword">

             <input type="text" name="location" placeholder="Town, City, Postcode">

              <select name="salary">
                   {% for category in craft.categories.group('salary') %}
                         <option value="{{ category.slug }}">{{ category.title }}</option>
                   {% endfor %}
              </select>

              <input type="submit" name="search" value="Search" class="form-submit">

</form>

{% for entry in entries %}

                {{ entry.title }}

            {{ entry.jobsExcerpt }}

                    {% for block in entry.location %}

                                {% for category in block.category.limit(1) %}
                                    {{ category.title }}
                                {% endfor %}

                    {% endfor %}
                    {% for block in entry.salary %}

                                {% for category in block.category.limit(1) %}
                                    {{ category.title }}
                                {% endfor %}

                    {% endfor %}
                    {% for block in entry.keyword %}

                                {% for category in block.category.limit(1) %}
                                    {{ category.title }}
                                {% endfor %}

                    {% endfor %}

                Apply

{% endfor %}

I just can't seem to figure it out, any help would be much appreciated.

Thanks.

You'd have to set up an ElementCriteriaModel with parameters adapted to your entry type and the values you're getting from the query string.

I'd recommend to read the official docs on that topic

https://craftcms.com/docs/templating/elementcriteriamodel
https://craftcms.com/docs/templating/craft.entries

After that you shouldn't miss Combined searches and filters using Craft on Webstoemp's blog, a great introduction to setting up search forms and "filtering" the results with the ElementCriteriaModel.


Redirect to url based on current year/month I've got a calendar template set up and would like to have http://domain.com/calendar redirect to http://domain.com/calendar/current_year/current_month but am having trouble getting this to work.

My current code is:

{% if craft.request.segment(2) == "" %}
  {% redirect "calendar/{{ now.year }}/{{ now.month }}" %}
{% endif %}

But this ends up going to a 404 with this url:
http://domain.com/calendar/%7B%7B%20now.year%20%7D%7D/%7B%20now.month%20%7D/

You never use {{ echo tags within other Twig tags. What you have to do instead is to use string concatenation.
{% redirect "calendar/" ~ now.year ~ "/" ~ now.month %}


SuperSort - Sort by multiple variables Is there a way with SuperSort to sort an array by multiple variables? For example, let's I have the following data and I want to sort by count and then alphabetically:

pineapples (2)
grapefruits (4)
apples (2)
bananas (3)

Ideally, I would want that to be sorted as:

grapefruits (4)
bananas (3)
apples (2)
pineapples (2)

I was able to accomplish this by just adding both variables to my SuperSort tag. In essence, what I did was this:

{% set fruits = fruits | supersort('natsortas', '{count} {title}') %}

It seems to be working in my situation, but if there's a better way to do it, I'm open to suggestions.


Only allow one Lightswitch to be active at a time I am working on a news section. There is a single featured news story so the lightswitch marked with ('1') displays the latest entry as the featured story.

Below this the rest of the entries are displayed so here I then display all other latest entries with the lightswitch marked with ('0') or in this case ('not 1').

My problem is that if two or three entries are all marked as the featured story (or a user creates an entry and marks it as featured then repeats a few days later and doesn't uncheck the previous one) then they will not display in the below section. Is there anyway to only allow one lightswitch to be checked as ('1') at any one time.

Featured entry:

  {% for entry in craft.entries.section('news').featured('1').limit(1) %}

All other news entries:

  {% for entry in craft.entries.section('news').limit(4).featured('not 1') %}

You'd have to write a custom plugin that added an event listener for the  entries.saveEntry event.

Inside the event listener, you could check if the entry being saved has a true value for the featured Lightswitch field, and if so – pull all other entries with a true value for that same field (in the same section), setting their featured attribute to false before re-saving them.

Something like the below would go into your plugin's primary class:

public function init()
{
    parent::init();

    craft()->on('entries.saveEntry', function (Event $event) {

        $entry = $event->params['entry'];

        if ($entry->section->handle !== 'news' || !$entry->featured) {
            return false;
        }

        // Get all entries from the same section with a `true` value for the Lightswitch field
        $entries = craft()->elements->getCriteria(ElementType::Entry, array(
            'section' => 'news',
            'featured' => true,
            'id' => 'not ' . $entry->id,
            'limit' => null,
        ))->findAll();

        // Update all other entries' Lightswitch field value to `false`
        foreach ($entries as $entry) {
            $entry->getContent()->setAttribute('featured', false);
            craft()->entries->saveEntry($entry);
        }

    });

}

If you're new to plugin development in Craft, I'd suggest looking at the Business Logic plugin template or the pluginfactory.io app – also it'd be a good idea to read the official docs on the subject.

If you don't want to write a plugin, you could also solve this by foregoing the featured field for the entries. If you added a featuredNewsStory Entries field to a Global Set instead (and limited the Entries field to 1 entry), you'd make sure that there was only ever one featured news story in the system. The editiorial workflow would suffer, though – publishing a new, featured news story in this manner would mean that the editor would first have to create the story, then pop into the Global Set after saving the entry to actually mark it as "featured".

Anyway, here's how you could pull the featured news story from a global, as well as the other news stories that aren't featured:

{% set featuredNewsStory = yourGlobalSetHandle.featuredNewsStory.first() %}
{% set otherNewsStories = craft.entries.section('news').id(featuredNewsStory ? 'not ' ~ featuredNewsStory.id : null) %}

Of course, there is another possible "workaround" here: continue with your current solution, but add another clause; making sure that the featured news story pulled is the newest one only:

{% set featuredNewsStory = craft.entries.section('news').featured(1).order('postDate desc').limit(1).first() %}
{% set otherNewsStories = craft.entries.section('news').id(featuredNewsStory ? 'not ' ~ featuredNewsStory.id : null) %}

With the above in place, you could just communicate to your client that "if you set more than one entry to be featured, only the newest one will actually display as featured" or the like.


Retrieving entry just after saving it returns null I'm having this issue where when I save an Entry and try to fetch right away I get a null.
Example:
$entry = new Entry([stuff here]);
$entry->title = 'foo';

if (!Craft::$app->elements->saveElement($entry)) {
    dd($entry->getErrors());
}

$existingEntry = Entry::find()
            ->noCache()
            ->section('handle')
            ->title('foo')
            ->one();

//null

This is just to simplify the issue I'm having.
My use case is actually a loop that checks if the entry already exists (according to the title), if so it adds data to it, if not, creates it and adds the data. What is happening is that I get multiple entries created with the same title because when I check if it exists, I get a null.
I thought it could be cache, hence the noCache() but nope.
And I can also confirm that the entry is saved/created. If I go to the dashboard I can see it there.
Clarification:
The snippet above is just to explain it in a simple way what the problem is. It's not actual code I'm using. I am aware that I do have the entry object and it doesn't make sense to fetch it right after saving it.
My question is solely about why I cannot get an entry that was previously saved. I find this behaviour weird and was not expecting it.

Searching for an Element by Title, as you describe, is potentially problematic as the Title is not required to be unique. But may not even be necessary in your case.
The $entry object that you pass to the craft\services\elements::saveElement() method will get updated in the same scope that you are running the saveElement code. It appears that you are already accessing that same $entry object when you are using it to throw errors.
See the Objects and References page in the PHP docs for a discussion of the behavior.
Here's a rough update of your code per that expectation:
$entry = new Entry([stuff here]);
$entry->title = 'foo';

if (!Craft::$app->elements->saveElement($entry)) {
  dd($entry->getErrors());
}

// No need to query, you can already access the Entry you just saved
$entry->title

// If you need to query, you could do so via the ID
// from the Entry Element object you just saved:
$entry = Craft::$app->elements->getElementById($entry->id);
$entry->title

Is there a reason you need to query the Element again right after you save it?


How to install plugin in Craft 3 I've tried installing a plugin to my Craft 3 local installation. I ran this from the command line in my project root:

composer require boboldehampsink/import but, this error was returned

craft/plugins/import/ does not exist and could not be created.

Thanks if anyone can help.

You are trying to install a Craft 2.x plugin, which you can see, among other things, by looking at its composer.json. Craft 3 plugins will always have a "extra property with a "handle" defined.

"extra": {
    "handle": "plugin-handle",
}

The currently latest release of the Import plugin is v0.8.33, and is not compatible with Craft 3:
https://github.com/boboldehampsink/import/blob/0.8.33/composer.json

Until the plugin store goes live, most plugin developers note their compatible plugins in this list:
https://github.com/craftcms/plugins


Is this the correct and safest way to update / save a new record? public function saveGoal(Logic_GoalModel &$model)
{
    // New goal
    $isNewGoal = !$model->id;

    // Populate record
    $record = $this->getGoalRecordById($model->id);
    $record->userId = $model->userId;
    $record->goal = $model->goal;
    $record->complete = $model->complete;

    // Save record
    if($record->save(false))
    {
        // Populate id
        if($isNewGoal)
        {
            $model->id = $record->id;
        }

        return true;
    }
    else
    {
        return false;
    }
}

private function getGoalRecordById($id = null)
{
    if($id)
    {
        $record = Logic_GoalRecord::model()->findById($id);

        if (!$record)
        {
            throw new Exception(Craft::t('No record exists with the ID “{id}”', array('id' => $id)));
        }
    }
    else
    {
        $record = new Logic_GoalRecord();
    }

    return $record;
}

It is definitely a way to save record. :)

You might want to be more explicit with validation, though.  i.e.

if ($record->validate())
{
    // Save record
    if ($record->save(false))
    {
        // Populate id
        if($isNewGoal)
        {
            $model->id = $record->id;
        }

        return true;
    }
    else
    {
        return false;
    }
}
else
{
    $model->addErrors($record->getErrors());
}


Channgel entry to disabled Is it possible that when my user adds a new entry in a channel on the English site, it gets copied to the channel of my Belgian site, but this entry is set automatically to disabled?

So my English user adds a blog item and enables them, they are copied to my Belgian website but they are disabled?

Thanks!

Under Settings > Sections > [section] > Site Settings, you can set the Default Status per-site for new entries in that section.

For copying the actual content, set the appropriate "Propagation Method" setting underneath. Note that the propagation only happens on the first save. If you need to overwrite/sync content across sites after the first save, there's the Sync Sites plugin: https://github.com/timkelty/craftcms-site-sync


Can we hide version number in control panel for certain user groups? Usecase: the site I'm building has public registration, the publicly registered users have access to only their own specific entry in the back-end (which makes use of many complex fields, such as Matrix, which is why I'm not trying to put this form on the front-end for them to manage).

While everything else is hidden from them already, it'd be nice to hide the Craft version just to hinder any neer-do-wells from easy bug-hunting and hacking shenanigans.

It'd still be useful to have that info displayed for other admin groups though.

Is that possible?

You would need to write a plugin that hides it with Javascript. We don’t have any plans to make it customizable.


{% if loop.first %} and {{ loop.index0 }} not working with Matrix I have a problem with {% if loop.first %} and {{ loop.index0 }} with the following snippet:

{% for block in entry.locationSlideshow %}
  {% switch block.type %}
    {% case 'upload' %}
      {% for image in block.image %}
        <button {% if loop.first %}class="is-active" {% endif %}data-slide="{{ loop.index0 }}">{{ image.title }}</button>
      {% endfor %}
  {% endswitch %}
{% endfor %}

The problem is that all buttons get the class is-active and 0 instead of 0, 1, 2, 3...

This is working fine outside of a Matrix field. Any ideas what I am doing wrong here?

Regards
Ben

At the moment loop.first and loop.index0 are relative to your block.image loop.

If you want them to be set based on your entry.locationSlideshow loop (the parent loop) you can use {{ loop.parent.loop.index0 }} and {{ loop.parent.loop.first }}

For more information see the Twig documentation.


Impossible to invoke a method ("getUrl") on a string variable ("60") I'm a beginner and don't understand this error, and how to correct it:

Template error
Impossible to invoke a method ("getUrl") on a string variable ("60")

I'm trying to display only the first entry of one loop. In my case,
'selectedArtwork' has an Entries type and 'pictures' an Assets type.

Here is my code:

{% if entry.selectedArtwork | length %}
    {% for artwork in entry.selectedArtwork %}

        {% set assets = artwork.pictures.first() %}
        {% if assets | length %}
            {% for asset in assets %}

                {% set artworkPicture = { width: 475 } %}
                {% set artworkPictureRetina = { width: 930 } %}

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

And the part of code highlighted in Craft's debug mode are:

This code is working well as an entry template of another page of my website to display all entries, but not here for my homepage to only display the first entry.

I think your problem is here:

{% set assets = artwork.pictures.first() %}
{% if assets | length %}
  {% for asset in assets %}

This sets assets to the first artwork.pictures, not to a list of assets, and then you try to loop over that single asset.

If you want a figure for every pictures of every selectedArtwork of your entry, try this:

{% set artworkPicture = { width: 475 } %}
{% set artworkPictureRetina = { width: 930 } %}

{% for artwork in entry.selectedArtwork %}
  {% for asset in artwork.pictures %}

  {% endfor %}
{% endfor %}

set artworkPicture and artworkPictureRetina once, outside your loop.
no need to use {% if ...|length %}. If the length is 0, the for loop will run 0 times.

If you want a figure for the first picture of every selectedArtwork, try this:

{% set artworkPicture = { width: 475 } %}
{% set artworkPictureRetina = { width: 930 } %}

{% for artwork in entry.selectedArtwork %}
  {% set asset = artwork.pictures.first %}
  {% if asset %}

  {% endif %}
{% endfor %}

If you want a figure for the first picture of the first selectedArtwork, try this:

{% set artworkPicture = { width: 475 } %}
{% set artworkPictureRetina = { width: 930 } %}

{% set artwork = entry.selectedArtwork.first %}
{% if artwork %}
  {% set asset = artwork.pictures.first %}
  {% if asset %}

  {% endif %}
{% endif %}


Oauth Facebook Issue with redirect URI I am getting an error with oauth (1.0.79) when using Facebook:

  Required option not passed: access_token Array (
  [{"error":{"message":"Error_validating_verification_code__Please_make_sure_your_redirect_uri_is_identical_to_the_one_you_used_in_the_OAuth_dialog_request","type":"OAuthException","code":100,"fbtrace_id":"A2ThFvRVsAZ"}}]
  => )

Facebook is changing the url entered and replacing the /'s in the p=actions/oauth/connect part of the redirect URI with ASCII characters %2F p=actions%2Foauth%2Fconnect which I assume is then not matching the 2 uri's causing the above error.

Is this the issue? Is there a workaround? Or is this a tweak that needs to be made to oauth?

Cheers

You can set usePathInfo = true in your Craft general settings to force Craft to use PATH_INFO to generate URLs.

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

Dukt OAuth should now show you a redirect URI without a query string (Facebook doesn’t like slashes in the query string and automatically encodes them) and you should be able to make the URIs match exactly.


Safely calling other plugin code from a different plugin I have a Craft Plugin that is a logging library I want to use in other plugins I develop, but I don't want it to be a dependancy in these other plugins. Is there a nice, space efficient way in Craft to do something like below? I don't want to have to wrap every call in an if statement:

# If WatchTower isn't installed... don't explode please!!!
@craft()->watchTowerDB->log($params)

My plugin seems to stop processing and redirect to the current page if it isn't installed. Thanks!

You could write a wrapper log method that's abstracts the check away so you only have to do it once.  The update your code to use the wrapper.

That method could just use craft()->plugins->getPlugin('pluginHandle') to see if the target plugin is installed and enabled.  Craft will auto-load the plugin's services, so you don't need to check specifically for them.


How do I add Entry Types to URL? In the Sections settings ("Entry URL Format") I would like to add an entry property tag for Entry Type.

discography/{slug}

Sure just do this

discography/{type}/{slug}


How to get specific single with status live How can I get a specific single (careers) with status live in twig?

This should work:

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

{% if not careers|length %}
    {% exit 404 %}
{% endif %}


PNG 500 error - Save operation failed I have just discovered that all Craft sites on our server no longer let users upload PNG files and I'm struggling to find the issue / fix.

The craft.log simply says 'Save operation failed' and the JS console mentions 500 internal server error.

I've tried various PNG formats, and weirdly other systems on our server using Imagemagick are running fine.

Anyone had a similar issue / suggestions for debugging?

If other image formats are working fine, then maybe check that you have Imagick installed and enabled on the server.

Eg.

sudo apt-get install imagemagick php5-imagick
sudo service apache2 reload

If you're on a shared host then either consult their knowledge base or contact support to check for Imagick availability.

Some servers/hosts only have the GD library installed by default, which isn't so good with PNG files.


Is it possible to translate the name of a field in the CP? I have content editors that speaks different languages. Is there a way to translate the name and introduction of a field in the control panel? A simple {{ "value"|t }} seams not to work.

Example: English content editors should see "surname" as field name and german speaking editors should see "Nachname".

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

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

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

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

<?php

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


Foreign Key column pointing to `craft_relations` table I am writing a plugin with a Record. I want the primary key of the table to also be a foreign key relating to the craft_relations table. Ordinarily, I would add something like this...

public function defineRelations()
{
    return array(
        'element' => array(static::BELONGS_TO, 'ElementRecord', 'id', 'required' => true, 'onDelete' => static::CASCADE),
    );
}

However, it seems like the craft_relations table does not have a matching Record.

How can I add a primary key column which is also a foreign key?

I might be wrong, but I don't believe you'll be able to do that within the defineRelations() method – Craft needs a record class for the table you want to create a relation with.

A workaround is to override the createTable() method in your record class and add the foreign key constraint manually using DbCommand:

public function createTable()
{
    parent::createTable();
    craft()->db->createCommand()->addForeignKey($this->getTableName(), 'id', 'relations', 'id', 'CASCADE', 'CASCADE');
}

To be perfectly honest the above feels quite hacky and there might be a better way – but it seems to work :)


Using values from one entry as default values in another? Is it possible to do the following in Craft?

I want to set up course information as follows:

1) have a courseType which contains default values for that type of course - name (i.e. 3 hour skills, full day masterclass etc), price, capacity, trainers etc

2) have a course which has a courseType entry filed among other details such as details of the course, equipment used, etc. The course will also have fields for price, trainers & capacity.

Is it possible to have the course price, trainers & capacity fields filled with the value of the courseType selected when it is chosen in the CP new course page? These course fields should then be able to be overridden if required on a course by course basis.

Any suggestions would be very welcome - I'm new to craft and can find any examples like this.

Thanks in advance.

First of all I would like to leave a few links for you.

Pluginfactory.io is a page where you can create your "starting" files. It creates an empty Plugin, with all the required files/functions with example codes for routing and services....
The Docs about Craft Plugin developement

Then to the code: you'll need to insert a function like this in your Plugin's primary class

craft()->templates->hook('cp.entries.edit', function(&$context) {
    if ($context['sectionHandle'] === 'course') {
        // you can get these from a config file or you could create
        // plugin settings, I'll just insert an array here, it's faster
        $config = [
            'entryTypeOne'     => [
                'title'         => 'A title',
                'body'          => 'some information',
                'relationField' => [1, 2, 4] //<-- array of element ids
            ],
            'anotherEntryType' => [
                'title'         => 'Another title',
                'body'          => 'some more information',
                'relationField' => [] //<-- array of element ids
            ]
        ];

        /** @var \Craft\EntryModel $entry */
        $entry = $context['entry'];
        $entry->getContent()->setAttributes($config[$entry->getType()->handle]);
    }
}

However: unfortunately you can't set default values when the user changes the entry type with this method, thus we'll need another "hack".
As you can see in the Relabel Plugin Craft provides ways to change default functions. You can insert this javascript

Craft.EntryTypeSwitcher.prototype.onTypeChange =  function(ev)
{
    this.$spinner.removeClass('hidden');

    Craft.postActionRequest('entries/switchEntryType', Craft.cp.$container.serialize(), $.proxy(function(response, textStatus) {
        this.$spinner.addClass('hidden');

        if (textStatus == 'success')
        {
            var fieldsPane = this.$fields.data('pane');
            fieldsPane.deselectTab();
            this.$fields.html(response.paneHtml);
            fieldsPane.destroy();
            this.$fields.pane();
            Craft.initUiElements(this.$fields);

            Craft.appendHeadHtml(response.headHtml);
            Craft.appendFootHtml(response.footHtml);

            // Update the slug generator with the new title input
            if (typeof slugGenerator != "undefined")
            {
                slugGenerator.setNewSource('#title');
            }
        }
    }, this));
}

To change the default behavior when someone changes the entry type. All you have to do is to change the destination of the script
from

Craft.postActionRequest('entries/switchEntryType'

to something like

Craft.postActionRequest('yourpluginhandle/controllername/switchEntryType'

Then you'll take the default EntriesController function

public function actionSwitchEntryType()
{
    $this->requirePostRequest();
    $this->requireAjaxRequest();

    $entry = $this->_getEntryModel();
    $this->enforceEditEntryPermissions($entry);
    $this->_populateEntryModel($entry);

    $variables['sectionId'] = $entry->sectionId;
    $variables['entry'] = $entry;
    $variables['showEntryTypes'] = true;

    $this->_prepEditEntryVariables($variables);

    $paneHtml = craft()->templates->render('_includes/tabs', $variables) .
        craft()->templates->render('entries/_fields', $variables);

    $this->returnJson(array(
        'paneHtml' => $paneHtml,
        'headHtml' => craft()->templates->getHeadHtml(),
        'footHtml' => craft()->templates->getFootHtml(),
    ));
}

And do exactly the same like in the first function

$entry->getContent()->setAttributes($config[$entry->getType()->handle]);

Unfortunately if you want to take care of all use cases you have to overwrite another function. When someone is trying to create an entry via an ElementEditor(the thing that pops up when you click on "new entry") in a relation field. It works exactly the same like my first method and it's the same like Here


Interne Serverfout after one click update Hello and good evening,

After the one click update the message 'Interne Serverfout' appears on the screen. One can no longer connect to either the fron or backend of the installation ?

What is the correct procedure to roll back to a working website here ?

-Ruud

Interne Serverfout (Internal Server Error) is a fatal error that has happened and your web server killed the request.

Usually, fatal errors like this are either because PHP times out, or runs out of memory... the underlying error message will be either in your web server's error logs or Craft error logs.

Try editing your php.ini file and increasing the memory_limit setting to at least 256M, and the max_execution_time setting to at least 120.

If you’re not sure where your php.ini file is located, create a PHP file called ini.php alongside your index.php file with this:

php
echo 'Loaded php.ini: ' . php_ini_loaded_file();

Then access that file in your web browser by going to http://your-project.test/ini.php.

Once you’ve made your changes, restart your web server, restore your database from a pre-update attempt database backup and then try again.


What is the future for the Craft rich text editor? I can (almost) appreciate the recent impositions of Redactor 2, but when it comes to handing off the site to a client, Redactor 2 is virtually unusable for anything more than paragraph text.

Are there any other rich text editors being considered as core replacements in the future? If so, +1 for an implementation of Froala into Craft. I see there is already a Yii2 implementation available.

Eventually, if a Craft CKEditor plugin doesn't come to life, then we might consider developing a 1st party (Pixel & Tonic) CKEditor plugin, although it would likely not replace the native Redactor Rich Tech Field implementation.

And of course, 3rd party plugins can implement whatever WYSIWYG they want to use.


Craft 3: Front End Entry Form I am following the documentation for Craft 2 here to create an entry form on the front end of my website. The form appears correctly on the front end but when I submit it, I get the following error:
"Page not found.
Caused by: Invalid Route – yii\base\InvalidRouteException
Unable to resolve the request: entries/saveEntry"

Here's my form:

<form method="post" accept-charset="UTF-8">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="redirect" value="news/{slug}">
    <input type="hidden" name="sectionId" value="1">

    Title
    <input id="title" type="text" name="title" value="">

    Body
    <textarea id="body" name="fields[body]" rows="20"></textarea>

    <input type="submit" value="Submit">
</form>

Does anyone know where I am going wrong here? The user I am currently using to submit the form is an admin. I realize that the docs I'm following are for Craft 2 but I could not find this form in the Craft 3 docs.

Any help would be appreciated and thanks in advance!

Craft 3 uses snake-case paths instead of camelCase paths
Your action parameter must be entries/save-entry

Its all stated in the docs

Edit: generally a good idea is to inspect the html in your cp form and copy it to your frontend. You'll be able to solve 90% of your issues that way


Is it possible to have different plugin settings per locale? I'm looking into the possibility of using Foxycart for a multilingual, multi currency site. Currently it is not possible to have multiple currencies in Foxycart so it would require having separate Foxycart accounts for each currency. I would therefore need to store the cart url and api keys for each Foxycart account within the foxycart plugin.

What would be the best way of going about this? Is it possible to store different plugin setting based on locale?

The other idea I had was to store the api key etc in the config file but not sure if that is best practice or not.

I haven't used foxycart plugin, but looking at the '_settings.html' file, it looks like it stores both the 'storedomain' and 'apikey' as part of the plugin settings. I would suspect that you would need to fork the plugin and modify it.

You could possibly add additional settings to the plugin for the different domains (i.e. storedomain-en, storedomain-es, apikey-en, apikey-es), and then add some logic in the plugins main 'init' method to pick up the different settings based on the current locale.

$settings = craft()->plugins->getPlugin('foxycart')->getSettings();
\FoxyCart_Helper::setSecret($settings['apikey-'.craft()->language]);
\FoxyCart_Helper::setCartUrl("https://" . $settings['storedomain-'.craft()->language] . "/cart");

Or, you could set the 'storedomain' and 'apikey' in your multi-environment config array:

return array(
    '*' => array(
        'storedomain' => array(
            'en' => cart.en.domain.com,
            'es' => cart.es.domain.com',
        ),
        'apikey' => array(
            'en' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
            'es' => 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY',
        ),
    ),
    ...
);

and then retrieve them using something like:

$settings = craft()->plugins->getPlugin('foxycart')->getSettings();
$storedomain = craft()->config->get('storedomain');
$apikey = craft()->config->get('apikey');
\FoxyCart_Helper::setSecret($apikey[craft()->language]);
\FoxyCart_Helper::setCartUrl("https://" . $storedomain[craft()->language] . "/cart");

You would probably also need to go and modify some the variable methods to return the localized versions, so that when you asked for 'storedomain', it returned the correct value. I.e. :

<form action="https://{{ craft.foxyCart.storedomain }}/cart" method="post" accept-charset="utf-8">

I have no idea what other integration points the foxycart plugin has with craft however. If it attempts to sync data in any way with foxycart, it might not like switching accounts like that.

Overall this sounds pretty messy. I would proceed with caution.


Sum with a group by Author I am trying to build a leaderboard page, and I'm having difficulties finding a way to group the entries by Author.

I was able to create a plugin to get the sql sum function in there, but I now need to add a group by Author and order by Score DESC to that.

First steps were taken from here: Ability to SUM() or GROUP BY from the template or ElementCriteriaModel

What I ultimately want is a query that would look like this (very simplified of course):

SELECT author, SUM(content.score) as score FROM content Group By Author Order By score DESC

Is there a way to do this "natively" or do I need to write my own query?

Not sure if this is the best way to do it, but I created this little function in a Variable class.  I get all the necessary info (username and score) in an array.  Works fine for what I needed.

public function leaderboard(ElementCriteriaModel $criteria)
   {
       $query = craft()->elements->buildElementsQuery($criteria);

   if ($query)
   {
      $query
          ->select("authorId, SUM(field_score) as score, users.username as username")
          ->join("users", "users.id = authorId" )
          ->group("authorId")
          ->order("score DESC");

               return $query->queryAll();
       }
   }


Recommended Structure - One Site with Pages With Totally Different Layouts? I've got a site with one base URL that is run on one Craft instance. The site is for a yearly event and each year the header / footer / body page elements / design are different. However, we want to keep all previous years pages in existence with the look and feel of that year so people can look at that page exactly as it existed in that year. URL structure would be something like example.com (current year), example.com/2017, example.com/2018, etc.

However, there are some of consistent codebase elements that I would like to have as easily editable for each unique year. For example, SEO elements like meta descriptions and social media descriptions should be unique for each year, while still being easily updatable using the same field across individual year entries.

What I'm debating is the best way to set this up in Craft to balance site speed and overall manageability. A few options I'm thinking about:

Do a different entry and layout for each year and then reuse the individual fields that need to be editable across all pages in the different templates.
Do one base template and then use conditional logic that swaps in the CSS, header structure, footer structure, etc. for each year. Would also somehow need to have multiple matrix fields available in this to add unique content structure for each year. Concerned about lots of database queries for this one and impact on site speed.
Some sort of hybrid approach leveraging different entry types across template(s) but not exactly sure what that would look like.

Other suggestions on approach or thoughts about which option is better? Thanks!

Option 1 is a safe bet. This allows you to have completely separate, editable templates for each chosen year. You can then change the page slug to match the year of that page. You can reuse fields year over year if you'd like or create new fields for each year. Plugins like seomatic will help you create individual SEO content on a per template basis.


Creating and saving a GlobalSet element type in Craft 3 The following code is in a migration. It runs fine and there are no errors and prints SAVED, but nothing is saved in the globalsets database table.

All my other content migrations run fine so it is not a DB issue.

    $globalConfig = [
      "type" => \craft\elements\GlobalSet::class,
      "settings" => [
        "name" => "Meta",
        "handle" => "meta"
      ],
    ];

    $element = Craft::$app->getElements()->createElement($globalConfig);

    if (Craft::$app->getElements()->saveElement($element)) {
        print "SAVED";
    }

Why is this not saving ?

Answer:

So I looked in the craft core to see how the CP does it. Turns out we have to use this

$gs = new \craft\elements\GlobalSet();
$gs->name = "Meta";
$gs->handle = "meta";

Craft::$app->getGlobals()->saveSet($gs);

Hope this helps someone.

Craft core reference

https://github.com/craftcms/cms/blob/develop/src/controllers/GlobalsController.php#L55-L96


White blank page when accessing website and Craft login page I'm getting white blank page when trying to access my website and Craft login page. I haven't updated the website for few months. So I assume no files has been changed.

I checked with the hosting provider, and they say everything is okay on their part.

So I turned on the Dev Mode. And it came back with this error :
Fatal error: Class 'Craft\HttpRequestService' not found in /home/alpw7814/craft/app/framework/YiiBase.php on line 213

What could possibly cause this? Is there anything I need to check?
Thank you in advance.

That error indicates that Craft is missing some files (or they are corrupted) in its craft/app folder.  You can download a fresh copy of Craft from https://craftcms.com and replace your existing craft/app folder with the new one and that should resolve it.


"Field Limit is too big for your chosen Column Type" error on already existing fields when updating matrix I'm getting the following error when I'm trying to update a matrix:

"Field Limit is too big for your chosen Column Type.""

I'm trying to add a new block type but this error keeps getting up on fields that already exist in other block types.
The problem seems to related to the plain text field type. I've read somewhere about the field limit exceeding the mysql varchar length but 80 or 100 shouldn't be a problem, no?

Does anyone have an idea what might be the problem?

I'm running on:

PHP version 7.2.15
OS version  Linux 4.19.76-linuxkit
Database driver & version   MySQL 5.7.26
Image driver & version  Imagick 3.4.3 (ImageMagick 6.9.7-4)
Craft edition & version Craft Pro 3.4.19
Yii version 2.0.35
Twig version 2.12.5
Guzzle version  6.5.3
Imagine version 1.2.3-dev

If you scroll down a little bit from your screenshot, you'll see an "advanced" toggle for the Plain Text field settings.

In there is a "Column Type", which I'm guessing is set to varchar(255B) for you.

Set that to Text and that should solve it for you.


Latest update to Craft 3.1.27 crashed server I updated the site locally to 3.1.27  (it is working fine) and moved the vendor files, composer.lock and composer.json to the server.

After the update, I went to the admin and clicked on the "finish up" button. On reload the server crashed with the following errors:

18-May-2019 18:42:16 America/Los_Angeles] PHP Warning:  require(C:\home\site\vendor\composer/../symfony/polyfill-intl-idn/bootstrap.php): failed to open stream: No such file or directory in C:\home\site\vendor\composer\autoload_real.php on line 66

The File "C:\home\site\vendor\composer/../symfony/polyfill-intl-idn/bootstrap.php" is on the server.

I've reuploaded the vendor files as well as the composer.json and composer.lock. Not sure what else to do. Any ideas?

https://www.untye.com/Before-The-Wall/Liner-Notes

Thanks,

Rick

Got it working by using the local database to restore to production. "Finishing up" must have failed to update the db correctly. Fortunately, the local and production databases had been synced before the install failed.


Disabling individual sites on a Craft 3 multisite Is there a way to disable non-primary sites on a multisite setup so that users are redirected to a 503 template?

I can't see any configurations that allow me to to this. All sites are either disabled or live.

Seems like this is something you'd do from your .htaccess file or public index.php files for each of the non-primary sites you define.

For example if you have a public_html/index.php for your English primary site and a public_html/de/index.php for your German site, your German one would just header("Location: http://mysite.com/503"); to redirect.