Is there a way to get a variants stock quantity in commerce? Like the question says. I know you can check if a variant is "in stock" with v.hasStock, but is there a way to pull the current stock quantity value?
In my particular situation I would like to do something like this:
<input type="number" min="0" max="{{ variant.availableStock }} />
So as to prevent users from inputing a quantity that the store doesn't have.

You can do the following:
{{ variant.stock }}


Setting up Route for Category-based RSS Feeds I think that I need to set up a few routes to handle my category based RSS feeds. I have a current url structure as follows

http://something.com/shows/wmr/marketing pr

http://something.com/categoryGroup/parentCategory/childCategory

I need rss feeds from both the parent and child categories

http://something.com/categoryGroup/parentCategory/feed
http://something.com/categoryGroup/parentCategory/childCategory/feed

The rss template i am using is stored in

categories/_shows.rss

I have munged something together in the cp routes settings but I would prefer to have this in routes.php. Having access to the parentCategory and childCategory values without doing a segments thing would be nice.

Okay, I think that I have figured it out. Posting here for posterity. Based on the requirement above, I put these in my routes.php file.

'shows\/(?P<parentSlug>[a-zA-Z0-9\-\.]+)\/(?P<childSlug>[a-zA-Z0-9\-\.]+)\/feed' => 'categories/_shows.rss',

and

'shows\/(?P<parentSlug>[a-zA-Z0-9\-\.]+)\/feed' => 'categories/_shows.rss',

This gives me two variables. parentSlug and childSlug


Front-end searching: Automatically redirect when only 1 result When performing a search on the front-end, is it possible to have two different behaviors, depending on the number of results?

With more than one result, show the normal "results" page.
With only a single result, automatically redirect to that entry page.

Redirecting to the first result is simple...

{% if results|length == 1 %}
    {% redirect results[0].url %}
{% endif %}


Commerce 2 Stripe gateway seems to be working correctly, but order remains unpaid I am using the Stripe gateway plugin for Commerce 2.

I have done the following:

Entered the stripe API keys correctly.
Set the Webhook URL up correctly in Stripe.
Correctly disabled CSRF protection for the webhook url.
Used the example templates with the stripe.js token submitting correctly.
Since I am using 3dSecure, I am getting redirect offsite correctly.
After returning from offsite, I see the completed order successfully.

In the control panel the order is completed, but it is unpaid.

The last transaction has the status 'processing'.

Any ideas why the order isn't paid?

The processing transaction status is used when a gateway returns from offsite correctly (the user has done everything they can to make payment on the order) but since we didn't get a definitive answer from the gateway that the card has been charged, we put the transaction into a 'processing' status.

This status means we complete the order as there is nothing more for the customer to do.

We later get a response from the gateway (outside of the user checkout flow) to the webhook URL to let us know the payment charge on the card has been made. We then update the order with a successful payment transaction.

It sounds like the webhook isn't being hit with that update information.

After looking at your logs and config, I see that after the webhook request from stripe comes in, the system raises an error.

The error is caused by the fact that you have set the isSystemOn config to false in production. This means the webhook request from stripe is failing, since only logged-in admins can access the system with that config setting set to false.

My guess is you made the payment with the example templates while admin :)


ElementAPI endpoint routing syntax for multi-level structure Would like to be able to handle requests for structured requests so that it may be handled in one endpoint

    about.json
    about/the-team.json
    about/contact/london.json

Presumably a form of regex would be required for this to work?
Contemplating:

    pages/about.json
    pages/about/the-team.json
    pages/about/contact/london.json

All though how would you prepare a check for 'pages' as your first node?

Currently have this but not fees able.

   '<slug:{slug}>*.json' => function($slug) {

thanks

Quite a simple solution set the criteria to uri and you just pass the endpoint as is as a catch all.

$normal =  preg_replace('/.json/', '', craft()->request->path);
return [
        'endpoints' => [
            craft()->request->path => [
                'elementType' => 'Entry',
                'criteria' => ['uri' => $normal],
                'first' => true,
                'transformer' => new DetailTransformer(),
            ],
        ]
    ];


What causes an entry's field to be marked as "modified" when the entry is saved? When an entry is saved, what causes the entry's individual fields to be marked as "modified" in the POST request?

I'm trying to troubleshoot an issue where a modified Redactor field that is a child of a Neo field is not being saved. When I examine the POST data in the debug bar, I see that the field's updated content was posted, but the 'modified' key in the array is still set to '0'.

What's interesting is that if I modify the Redactor field by typing words in it, the field's 'modified' key is set to '1' in the POST data, as expected. However, if I try to just add a single period; highlight text and press delete; or try to copy and paste text into the Redactor field, the 'modified' key is not set to '1' when I save.

So it appears that, in order for the Redactor field to be marked as "modified", I have to type a certain amount of text into the field.

Edit: After more testing, it appears that adding or deleting a single character is not enough for the field to be marked as 'modified'. However, if you add at least two characters, with a pause between each character, the field will correctly be marked as modified. If you type a word quickly, and then save, the field is not marked as modified. If you type a word and be sure to leave at least a second's pause between typing two of the characters, the field is marked as modified.

I'm trying to troubleshoot this issue and identify the root of the problem; is this an issue with the Redactor plugin not reporting that its field has been changed? Is it an issue of the Neo plugin getting in the way of its child field's Redactor field reporting the change, or is an issue with Craft, itself, not picking up on the field being modified?

Since the issue is in the request's POST data, it appears that this is a JavaScript issue, and not a server-side one (though I could be wrong, because I don't know all the ins and outs of how Craft saves entries).

If anybody has any suggestions of where the problem might lie, I'd be very grateful!

The versions involved are:

CraftCMS: 3.4.10.1
Redactor: 2.6.1
Neo: 2.6.5.1

When an Edit Entry page is loaded, Craft takes note of all the fields’ current form values, and when the form is submitted, only field values that have changed will be posted. As far as the back-end is concerned, if a field is included in the post data, then it was changed; otherwise it wasn’t.

I suspect that the modified param you are seeing is a Neo-specific thing. Sounds like maybe they have their own change tracking going on, which is separate from how Craft does it.


Debugging Craft plugin actions I'm new to php development, so I'm probably doing something silly...

I have setup Craft running in a Vagrant VM on Windows 8. I am using XDebug and Eclipse as my IDE. It all works beautifully! However I cannot debug any of my plugin code. I can step into the Craft code but it never breaks on any plugin actions. I suspect its something to do with the way the Craft code is calling the actions, it looks like it is using some sort of reflection to call the methods of the plugin class. Can anyone help? Is there a way to debug plugin code? Or perhaps a better IDE if it is Eclipse that has this limitation?

I can confirm that Win8.1 + PHPStorm + xDebug and plugin code works fine.

Are you symlink'ing (using mklink in Windows) to your plugin code by chance? xDebug won't follow symlink's by default and at least in PHPStorm, you have to explicitly setup the path mapping in your project's settings to tell PHPStorm/xDebug where the actual paths to your symlink'ed files live.


Change entry status on front end I'm going wrong here somewhere, but I have a (edit) entry form and I'd like a 'disable' field to change status. The edit form works fine but status changes are ignored. Here's my field:

<input type="checkbox" name="enabled" id="enabled" value="{{ entry.enabled }}"{{ entry.enabled == '1' ? ' checked' }}>

Am I missing something? Thanks guys.

You need to include a hidden field with the value of 0 before the checkbox to ensure that the value is included in the form data if the checkbox is unchecked. See the docs on templating for checkbox fields.

So you'll need to have this in your form:

<input type="hidden" name="enabled" value="0">
<input type="checkbox" name="enabled" id="enabled" value="1"{{ entry.enabled == '1' ? ' checked' }}>

When the checkbox is checked, the value of 1 for enabled will override the value of the earlier hidden field.


How to write a simple navigation? After endless trial and error I figured out the right syntax for a simple one level navigation.

{% set navi = craft.entries.section('not projekteintrag' ) %}
{% for entry in navi.order('id asc') %}

{{ entry.navigationTitle }}

{% endfor %}

Is there a parameter to just trigger single pages? Right now I grabbed the singles with filtering the entries.
What is the difference between writing the upper syntax and:

-

{% for entry in craft.entries.section('not projekteintrag' ).order('id asc') %}

{{ entry.navigationTitle }}

{% endfor %}

My solution is to setup a dedicated "Menu" section and use an entries field type for the links.  This allows you to pull together entries from multiple sections into a single menu.

My normal setup is to have to custom fields

relatedEntry - Entries field allowing you to select any other entry
customURL - text field for custom url input

The idea being that you could fill in either or and have a dynamic menu with links to entries or custom links.

Then on the template side you simple would do this

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

{% nav link in menu %}

        {% if link.relatedEntry|length %}
                {{ link.title }}
        {% else %}
                {{ link.title }}
        {% endif %}

        {% ifchildren %}

                {% children %}

        {% endifchildren %}

{% endnav %}

I hope that helps


Using Commerce to pay for posting entry I'm trying to figure out how to do the following:

Person registers as new user
User creates a new entry with a front-end entry form
Entry is saved as disabled so it's not publicly visible
User has the option to make entry public by making a payment with Craft Commerce.
When the Craft order is complete it updates the entry in step 3 to enabled so that is will be publicly visible.

I think I should be able to use this event commerce_orders.onOrderComplete but I'm not sure how to pass the entry ID into this event and also how to check if the order that has just been completed is the order that applies to this event checkout.

Any thoughts on how to accomplish this?

You will need to write a plugin with three responsibilities:

Keep track of which entries have been purchased
Set an entry to enabled when it has been purchased
Ensure that entries always have the correct status (enabled/disabled) whenever they are saved

For the first one, you will need to create a new DB table that can store records of which entries have been purchased.

In your plugin, create a records/ table with a MyPlugin_EntryPurchaseRecord.php file:

<?php
namespace Craft;

class MyPlugin_EntryPurchaseRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'myplugin_entrypurchases';
    }

    public function defineRelations()
    {
        return array(
            'entry' => array(static::BELONGS_TO, 'EntryRecord'),
            'order' => array(static::BELONGS_TO, 'Commerce_OrderRecord'),
        );
    }
}

With that in place, the table will automatically get created when you install your plugin.

Next, give your primary plugin class an init() method where you can set up some event listeners:

<?php
namespace Craft;

class MyPluginPlugin extends BasePlugin
{
    // ...

    public function init()
    {
        craft()->on('commerce_orders.orderComplete', array($this, 'onOrderComplete'));
        craft()->on('entries.beforeSaveEntry', array($this, 'onBeforeSaveEntry'));
    }
}

Your onOrderComplete function will be responsible for recording the purchase in your entrypurchases table, and updating the entry’s status to enabled:

public function onOrderComplete(Event $event)
{
    /* @var Commerce_OrderModel $order */
    $order = $event->params['order'];

    // Look for a line item with an entryId option
    foreach ($order->lineItems as $lineItem)
    {
        if (!empty($lineItem->options['entryId']))
        {
            // Validate the entry ID
            $entryId = $lineItem->options['entryId'];
            $entry = craft()->entries->getEntryById($entryId);
            if (!$entry) continue;

            // Record the purchase
            $purchaseRecord = new MyPlugin_EntryPurchaseRecord();
            $purchaseRecord->entryId = $entryId;
            $purchaseRecord->orderId = $order->id;
            $purchaseRecord->save();

            // Enable the entry
            $entry->enabled = true;
            craft()->entries->saveEntry($entry);
        }
    }
}

And your onBeforeSaveEntry function will be responsible for making sure entries’ statuses are set correctly depending on whether they’ve been purchased:

public function onBeforeSaveEntry(Event $event)
{
    // Ignore for new entries
    if (!empty($event->params['isNewEntry']))
    {
        return;
    }

    /* @var EntryModel $entry */
    $entry = $event->params['entry'];

    // Ignore entries in other sections
    if ($entry->section->handle != 'mySection')
    {
        return;
    }

    // Has the entry been purchased?
    $purchaseCount = MyPlugin_EntryPurchaseRecord::model()->countByAttributes(array(
        'entryId' => $entry->id
    ));

    $entry->enabled = ($purchaseCount != 0);
}

Last but not least, you will need to update your entry purchase form to record the entry ID being purchased. We’ll do that as an option on the line item.

(If you look at the onOrderComplete function, we’re actually combing through the purchased order’s line items to look for these entryId options. This is where it gets set.)

<form method="POST">
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="redirect" value="commerce/cart">
    <input type="hidden" name="qty" value="1">
    <input type="hidden" name="purchasableId" value="{{ variant.purchasableId }}">

    <!-- Associate the line item with this entry ID -->
    <input type="hidden" name="options[entryId]" value="{{ entry.id }}">

    <input type="submit" value="Buy Now">
</form>

Baring any typos, that should do it!


Display Category Group Name in Template Having a bear of a time doing something which seems like it should be quite simple. I'm trying to display the category group name in my templates, using the handle and can't quite get it. I've explored the docs but haven't found much help there.

I've tried:

{{ caseStudiesCategories }}

Error: Variable "caseStudiesCategories" does not exist

As well as:

{%  set catName = craft.categories.group('caseStudiesCategories') %}
{{ catName }}

Error: Object of class Craft\ElementCriteriaModel could not be converted to string

Any thoughts or ideas?

Thanks.

You're close! It's slightly counterintuitive but group is a property of a category. So you need to grab the group from an actual category. This would work:

{% set catName  = craft.categories.group('caseStudiesCategories').first.group %}

Basically you're getting the first category in the group and grabbing the group name (you could also use [0] instead of .first).

If your entry has a category field, you can access the group name in a similar fashion:

{% set catName = entry.yourCategoryField.first().group %}


Excluding specific field value from search I want to find all entries that match the title field where excludeFromSearch != 1 (is false).

{% set query = 'and excludeFromSearch not 1 and ' ~ 'title:"' ~ "myValue" ~ '"' %}

    {% set results = craft.entries({
    section: querySections,
    search: query,
    orderBy: 'score',
    }).limit(50) %}

It does not work. My field excludeFromSearch is a lightswitch.

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

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

Or slightly cleaner / Craft 3:

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

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


Migrating a Craft site to a different host. I'm moving my site from one host to another, and I'm having some trouble moving my craft site over. I have all of the files moved, and in the config file I'm pointing to the new database which I've imported over already. But when I go to the site or the admin url I'm getting a 500 error. Any thoughts?

Per the OP's comment, there was a database connection error in the Craft log files. Once that was corrected it solved the 500 Internal Server Error.


Batch set entries as draft? I have 900 entries that I have imported via the excellent import plugin. I need these to be set as draft (or 'disabled' status). Is there any way I can do this programatically? I don't fancy doing it manually.

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

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


Feed Me Plugin: Can Match fields but feed not importing I can detect and match up the fields from my json file but when doing the import I get the following error in the log:

No feed items to process.   3/28/2019 2:53 PM

error   Unable to reach data/case-studies.json. Message: File path cannot be found.

For some reason, it isn't picking up the file when doing an import. How do I resolve this?

I have validated the json file and it is correct so I'm stumped!

This info may be outdated now, but just for anyone else who Googles "File path cannot be found " and ends up here (this page is the only result), it seems Feed Me is incompatible with the AsyncQueue plugin. I uninstalled Async Queue, and the import from Feed Me ran without issue.


Get first X paragraphs, then output the rest The below is code that works to only show the first paragraph, then show the rest. Is it possible to instead, show the first five or six paragraphs, then show the rest?
{# Split paragraphs using a limit of 2 #}
{% set paragraphs = block.body|split('
', 2) %}

{# Get first paragraph and add the missing closing tag  #}
{% set firstParagraph = paragraphs|first ~ '
' %}

{{ firstParagraph|raw }}

{# The rest of the text is here, due to the limit in the split filter #}
{{ paragraphs|last|raw }}

Wordsmith works for this, but I'm unable to see a way to output the rest of the paragraphs.

Seems like a huge hack to me but here's how to do it:
{# Split paragraphs using with a limit of 3 #}
{% set paragraphs = text|split('
', 3) %}

{# Get an array containing the first 2 paragraphs, and convert it back to a string, adding missing closing tags  #}
{% set firstParagraphs = paragraphs|slice(0, -1)|join('
') ~ '
' %}

{{ firstParagraphs|raw }}

{# The rest of the text is here, due to the limit in the split filter #}
{{ paragraphs|last|raw }}

To adjust the number of paragraphs in your first group, just change the limit parameter of the join twig filter (this is a bit counter intuitive, see the Twig documentation to understand the logic).


Matrix vs Multiple entry types I am building a new website using Craft CMS and I have a requirement from the design team that they want to be able to re-use templates across multiple sections. For example define how a product looks like and then be able to add a product from any sections.

I thought implementing this using a Matrix or having a channel/structure section with multiple entry types however I am bit unclear when to use entry types and when to use matrix or maybe there is better way to implement this and I am not aware?

I see this question as two parts: information architecture and templating.
If you're used to something like WordPress where the template has a one-to-one relationship with how the template gets data and how information is routed, ignore everything you've learned.
Templating
Let's get the requirement of reusing templates out of the way first. Twig, Craft's templating language,  lets your reuse templates quite easily.
Not only can you use reuse templates from any page inside Craft, you can also extend templates from other templates.
Craft then lets you define which template is going to be used for each section. You could just set it to a single one and be done with it if your content doesn't change that much from section to section. A single Matrix field could pull off quite a bit across the entire site.  Speaking of...
Matrix
Matrix fields can be used for "site builder" like functionality. Matrix lets you define block types (eg Pullquote, Featured Image with Caption, etc) and then by mixing and matching the blocks, you can "build up" a page. The blocks can also be reordered. That gives authors a lot of flexibility in how they layout the pages.
Entry Types
Entry types define what content Sections contain but unless you define the same Entry Types across multiple Sections, they're not "global" like Matrix fields would be.
Entry Types are useful if you need to define content (and layout) requirements for entries in the same section. If you curate a blog for example, you might have a "Link" Entry Type that links to other entries or even other blogs. Then you might have a "Blog Article" Entry Type for "regular" content.
In your templates, you have the ability to check which Entry Type the entry happens to be and have your template format it how it should look. The Happy Lager does this inside the News section.
Information Architecture
In my experience, there aren't any hard and fast rules for using Matrix and Entry types, it really depends on your content and requirements. You could probably pull off what you're asking for with either.

If your templates are "designed", meaning the products are always going to live in a certain spot inside a template, then you can probably use a relational field to define the relationship.

If you want your authors to be able to define multiple elements on a page and then pull in the products from anywhere, Matrix is going to be your weapon of choice

Mijingo just introduced a course you might find useful on the subject as well.


Folders required to download when moving a Craft 3 installation to another server? If I'm downloading a Craft 3 website one server in readiness to deploy onto a new server, which folders should I download aside from?:

/templates
/web

Also, do I need to redownload the 'cpresources' folder again inside the /web directory if I already have a local copy of Craft CMS installed?

You'll need to take:

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

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


Craft and AJAX page transitions - how to exclude local hash links from executing AJAX? I've got a website in development with new pages loaded via AJAX instead of traditional page loads. Most links on the site will use AJAX to load a new page, however there are some links I need to exclude from this behaviour. For example, local hash links that simply scroll you down to an anchor on the same page. Or, links to PDF files that are hosted locally but should obviously not be loaded via AJAX. I have enough control over the HTML that I can simply add a class to these links that I want to exclude, such as .local-anchor, or .pdf. The code I have effectively excludes these links if you directly load the page the first time, however any time the page is loaded via AJAX my exclusion no longer works. The .local-anchor links and any others that should be excluded are still somehow executing the AJAX functions. Example of the relevant JS code:

$(document).on("click", "a:not('.local-anchor, .pdf')", function(e) {
    var href = $(this).attr("href");

    // check that it points to this domain
    if ( href.indexOf(document.domain) > -1 || href.indexOf(':') === -1 ) {
      history.pushState({}, '', href);
      loadPage(href);
      e.stopPropagation();
      e.preventDefault();
    }
  });

You can see this live page (in development) here: http://dma.nz/practice/

The links:

Our approach to design
The architectural process
Awards + Publications
Contact

Scroll you to anchors further down the same page and should be excluded. Yet if this page is loaded via AJAX (test by navigating to one of the other main nav links on top right and then return to Practice) then these links are triggering AJAX to reload this same page which screws things up.

How do I need to amend this JS to make sure they are ALWAYS excluded?

----------- UPDATE -----------

As per August's suggestion I tried removing the single quotes around the :not, as well as adding an extra if statement to double check. Neither of these solutions work. My current JS is looking like this:

$(document).on("click", "a:not(.local-anchor, .pdf)", function(e) {
    var href = $(this).attr("href");

    if ( !$(e.target).is('.local-anchor, .pdf') ) {
      // check that it points to this domain
      if ( href.indexOf(document.domain) > -1 || href.indexOf(':') === -1 ) {
        history.pushState({}, '', href);
        loadPage(href);
        e.stopPropagation();
        e.preventDefault();
      }
    }
  });

The :not exclusion is working. If the page is first loaded directly (not via AJAX) then those local anchor links do as they should. However if the page is loaded via AJAX then the exclusion stops working. Whether it's in the form of :not on the selector and/or an if statement to catch those classes.

I'm baffled here. Can't understand why that exclusion would work in one case but not the other. Any other ideas?

The function you mention isn't the problem. It isn't being called because, as you say, the exclusion clause is working perfectly.

But you also have a hook on the window.popstate which is triggered when you change the URL (by adding #contact to it for example).

This hook, as below, subsequently fires the loadPage function you have coded:

$(window).on("popstate", function(e) {
    // -------------------------------------
    //   If there was an AJAX page transition already,
    //   then AJAX page load the requested page from the back or forwards button click.
    //   Variable initially set after the $main variable.
    // -------------------------------------
    if (changedPage) loadPage(location.href);
  });

See more on the popstate event:

https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate

As others have mentioned though, this is Javascript specific rather than Craft, so should probably be moved or archived?


How do I get model/record attributes in their proper types, and not just strings? Here's my record (model is nearly identical):

namespace Craft;

class Recurly_PlanRecord extends BaseRecord
{

  public function getTableName()
  {
    return 'recurly_plans';
  }

  protected function defineAttributes()
  {
    return array(
      'sortOrder'      => AttributeType::SortOrder,
      'code'           => AttributeType::String,
      'max'            => AttributeType::Number,
      'min'            => AttributeType::Number,
      'annual'         => AttributeType::Bool,
      'base_endpoints' => AttributeType::Number,
      'endpoint_code'  => AttributeType::String,
      'base_cost'      => array(
        'type'     => AttributeType::Number,
        'decimals' => 2,
      ),
      'endpoint_cost'  => array(
        'type'     => AttributeType::Number,
        'decimals' => 2,
      ),
    );
  }
}

In the DB, the column types seem to be set correctly based on this.
What I can't figure out how to do, is actually get data back in the specified types, not just strings.

Here's me using it in a service:

$record = Recurly_PlanRecord::model()->find();
var_dump($record->attributes); // all strings :(
var_dump($record->base_cost); // string '1402.50' (length=7)

$model  = Recurly_PlanModel::populateModel($record);
var_dump($model->attributes); // all strings :(

What I want is float 1402.50. What I get is a string.

I'm having the same problem with AttributeType::Bool.

What am I doing wrong?

Currently the only thing Craft does in BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() is some normalization when the attribute in either case happens to be AttributeType::DateTime or AttributeType::Mixed.

All other attribute types will be returned directly as the database returned them (as a string).

However, I agree with you that we probably should be doing more to return the exact type as the attribute specifies.  Since that's potentially a big breaking change, though, it'll have to wait until Craft 3.0.

The good news is, thanks to PHP's loose typing system, you can still workaround most cases.

For example a bool will come back as either the string '1' or '0'.

Using that in a PHP conditional if ($myModel->boolAttribute) will evaluate to true or false.

Using your float example: '1402.50' + 100.00, PHP will properly cast that to 1502.50.


Only display entries based on a field conditional Hey I am trying to get 4 entries, but only want 4 that have a body length > 100.

How would I accomplish this?

{% for entry in craft.entries.section('artists').order('RAND()').limit(4) %}
  // only display 4 entries with entry.body|length > 100
{% endfor %}

Thanks!

You could do something like this:

{# Grab all entries with a body > 100 %}
{% for entry in craft.entries.section('artists').order('RAND()').find() if entry.body|length > 100 %}

{# Limit output to the first 4 #}
{% if loop.index1 <= 4 %}
        {{ entry.id }}'s body field has a length greater than 100!

    {% endif %}
{% endfor %}

Keep in mind that if entry.body is a Rich Text field than any HTML markup (
, , etc.) will be included in that length count as well.

Twig doesn't have a break or continue tag natively, but if you install the MN Break and Continue plugin, you can make it a bit more efficient:

{# Grab all entries with a body > 100 %}
{% for entry in craft.entries.section('artists').order('RAND()').find() if entry.body|length > 100 %}
    {% if loop.index1 > 4 %}
        {% break %}
    {% endif %}

    {{ entry.id }}'s body field has a length greater than 100!

{% endfor %}


Get last item added to cart Does anyone know a nice way to get the last lineItem(s) added to a cart in craft commerce via twig template? Example use case, an 'added to cart' confirmation page. I know for this you could query param a product/variant id but multiple could be submitted.

I attempted {cart.lineItems | last} but they do not seem to be in date order. I also checked the class models but didn't find any helpful methods or attributes.

Perhaps some kind of db query, as sql has date fields?

Since multiple line item can be updated or added to the cart at the same time, it would be hard to point to a specific line item that is newest.

The line items have a dateUpdate column you could sort and query on.

{% set result = craft.query()
    .select('*')
    .from('{{%commerce_lineitems}}')
    .where({
        'orderId': cart.id
    })
    .orderBy('dateUpdated ASC')
    .one()
%}

We could look to added a lastUpdateLineItem() method to the order element in future version of Craft Commerce. You can submit the idea here: https://github.com/craftcms/commerce/issues


Matrix - using Limit on block types I'm using Matrix fields for blog posts. These are made up of text and image block types. I want to pull in only the first image block and a snippet of text from the first text block into the blogs index page for listing the entries.

Adding limit(1) to each block type didn't work.

{% for entry in craft.entries.section('blog').limit(3).find() %}

    {% for block in entry.blogBody %}

    {% switch block.type %}

      {% case "text" %}
      {{ block.text|hacksaw(chars='100', append='...') }}

      {% case "blogimage" %}
       {% for asset in block.image %}

      {% endfor %}

 {% endswitch %}

{% endfor %}

{% endfor %}

{% endblock %}

You can limit which blocks you want by type and only show the first of each, if they exist. Something like this might do the trick:

{% for entry in craft.entries.section('blog').limit(3).find() %}

        {% set textBlock = entry.blogBody.type('text').first() %}
        {% set imgBlock = entry.blogBody.type('blogimage').first() %}

        {% if textBlock %}
            {{ textBlock.text|hacksaw(chars='100', append='...') }}
        {% endif %}

        {% if imgBlock %}

        {% endif %}

{% endfor %}

{% endblock %}


Can anyone tell me what's wrong with the 'andWhere' part of this query? What am I doing wrong in the 'andWhere' part of this query? I've tried a variety of different ways of doing it but nothing seems to work... It just seems to be ignored. Does anyone know the proper way I should be doing it?

foreach($entryIds as $entryId) {
    $data[] = craft()->db->createCommand()
    ->select('*')
    ->from('amforms_content')
    ->where(array(
            'elementId' => $entryId
    ))
    ->andWhere('dateCreated > 2017-02-11')
    ->queryAll();
}

return array($data);

The syntax for comparing a date should be:

->andWhere('dateCreated > "2017-02-11"')


Blank entry input page I can't edit my entries. The entry page has no input fields. See attachtment

I run the latest Craft version. Cleared the cache, tried different browsers.
No errors in my console.

It looks like that no javascript file is loaded on the page.

Usually when you see this, PHP is running out of memory trying to load the page.  Bump your php.ini file's memory_limit setting to something higher and that should fix it.

Update:

Actually, this is in your phperrors.log file:

[23-Sep-2014 15:11:20 UTC] PHP Fatal error:  Maximum function nesting level of '100' reached, aborting!

See here for the fix.


Move Icon Disappears from Categories editor The move symbol -  the one that allows you to move a category in the list up or down, etc. -- is gone from one of my category groups.  It's the one that appears just after the checkbox to select a category and right before the name of a category.

How do I get it back?

I know, stupid question. But I have no clue what I did to make it disappear.  The other category groups are okay.

Ugh...never mind.  I guess I took it off structure without realizing it.


PHP eval filter for Twig If I am confident in the users of our webpage that they will never be messing with the Twig templates, then what risk is there to creating a |php filter for Twig that just does this?

{% set text = "echo 'Hello World';" %)
{{ text | php }}

Filter function:

function myPhpEvalFunction ($text = null) {
   return eval($text);
}

In Craft 3 it is actually possible.

{{ craft.app.view.evaluateDynamicContent('phpinfo();') }}

See: Can we use PHP in our templates instead of Twig?


Use query string with relatedTo() with categories inside a category group I have created a test category called test inside the what-we-do category group. There are three files at play

The first has a line of code that generates the query string on button click

{% for cat in categories %}

{{ cat.title }}

{% endfor %}

The second takes the query string formats it and passes it to the list template. The code looks like

{% if craft.request.queryStringWithoutPath %}
    {% set categoryQueryString = craft.request.QueryStringWithoutPath| replace({"category=" : ""}) %}
{% else %}
    {% set categoryQueryString = "" %}
{% endif %}

    {% include '_includes/snippets/blog/list.html.twig' with {category : categoryQueryString} %}

Then the list code looks like

{% set sections = 'blogPosts' %}
{% paginate craft.entries.section(sections).relatedTo(craft.categories.slug('what-we-do/' ~ category|default)).limit(limit) as pageInfo, pageEntries %}

{% for entry in pageEntries %}
    {% if entry['listingPageText']|default %}
        {% set content = entry.listingPageText %}
    {% endif %}

{{ content }}

{% end for %}

This section seems to be working when I dump it but I am not seeing any of my entries rendered

{% paginate craft.entries.section(sections).relatedTo(craft.categories.slug('what-we-do/' ~ category|default)).limit(limit) as pageInfo, pageEntries %}

I'm wondering if there is something simple i'm missing

If I use

{% paginate craft.entries.section(sections).relatedTo(category|default).limit(limit) as pageInfo,pageEntries %}

I can get the posts to appear but it does not filter by category it just defaults and renders all the blog posts.

I'm guessing that's because I have to pass the full category url what-we-do/test assuming the category name is test.

What I really need is it to show the blogposts that are of category test inside the category group what-we-do

craft.categories will return you an object of type ElementCriteriaModel

craft.categories.slug('what-we-do/' ~ category|default) sets an attribute of this object, but it does not fetch the elements yet.

The relatedTo parameter needs to be an element, a list of elements, an array and some other staff but it can't handle a query (which the ElementCriteriaModel is)

You have to fetch the element(s) before you pass it to the function with first(), ids(), last() or find()

craft.entries.section(sections).relatedTo(craft.categories.slug('what-we-do/' ~ category|default).first())

Btw: just as an additional note {{ cat | kebab }} will print the title in kebab case. Mostly that will be the slug but if the user changes the title or the slug or inserts something completely different from the beginning, your logic will break


Unwanted output when using Twig conditional I am displaying a series of icons and associated labels in an unordered list. Some of the icons should only be displayed when a user is in a specific set of user groups, so I am using a conditional. Without the conditional, the icon and label displays perfectly, but when I wrap it in a conditional, it seems to output an extra blank character which breaks my layout.

Entry 1

{% if currentUser.isInGroup('admin') %}

Entry 2

{% endif %}

Chrome Inspector shows two quotation marks separated by a blank line between the li.icon elements, which I think indicates one blank character. When I remove the conditional, these quotation marks and the blank line don't appear, and the layout looks correct.

If I collapse all the logic and HTML elements into one long line of characters with no spaces between them, this weird blank output still occurs. Wrapping the block in the {% spaceless %} tag doesn't seem to work either.

What might be causing this?

I pasted your HTML into TextMate with “Show Invisible Characters” enabled, and it shows that there are two “zero width no-break space” (U+FEFF) characters in there, at the end of these lines:

{% if currentUser.isInGroup('admin') %}

-- and --

{% endif %}

Here’s a screenshot:

Those characters tend to come from code that was copied from Google+, which likes to add them at the very end of each post.

Unfortunately, Sublime Text doesn’t show these types of characters; you need to use TextMate to see them.


Craft Translation Fallback I disabled translation for Spanish and it returned 404 page.

I set all my fields to translatable and By default craft translations are empty.

How can I return English by default? Using Spanish locale

Thanks! :)

By disabling a locale for an entry you are removing the automatically created route for this entry and locale (→ docs for routing).

But what you can do, is to diable the automatic routing (uncheck "Entries in this section have their own URLs" in the section settings) and add the same routes as custom dynamic routes manually.

news/{slug} →  news/_entry

Those manual routes won't 404 for disabled entries and you can have some logic in your _entry.html template.

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

{% if not entry %}
    {% set entry = craft.entries.section('news').slug(slug).locale('en').first() %}
    {% set duplicateContent = true %}
{% endif %}

{% if not entry %}
    {% exit 404 %}
{% endif %}

I would also recommend to set your meta tags accordingly and make search engines aware of the duplicated content. I updated the code with a new variable definition, test if it is defined in your _layout main template.


Can't upload assets in Craft 3 CMS When I upload an image to assets, it just shows the progress bar loading, but it won’t upload my image into assets. Originally, this had worked before, but for some reason it suddenly just stopped working. I’m using Media Temple for my production. I checked my error log and it says:

  Got error 'PHP message: PHP Warning:  File upload error - unable to
  create a temporary file in Unknown on line 0

I’ve checked my files permissions and changed /tmp to 777 and I’ve also changed my assets folder to 777 too. I even checked my disk space for the /tmp folder and it still have 25GB left so it’s not out of disk space.

I know this is a while ago but I ran in to the same issue and thought I'd share the culprit in my particular case.

I adjusted the upload_max_filesize value via a php.ini file from the default 2MB to 10MB, but I misspelled the configuration as upload_max_filesize = 10MB instead of upload_max_filesize = 10M. I was seeing the exact same error as the original poster. Once I fixed the setting, changing 10MB to 10M, the error went away.


Missing Download PDF Button in Orders for Craft Commerce I'm not sure what happened, but the "Download PDF" button that is on the orders in the CMS is missing. I thought maybe the order PDF template file or path was missing but both of those are there. Is there a true/false statement somewhere I might have erased? I can't find anything on this.

Thanks

The Download PDF button will show if the OrderModel that gets passed to the template's getPdfUrl() method returns a URL.

You can see the logic it uses in commerce/models/Commerce_OrderModel.php, function getPdfUrl().

It gets the orderPdfPath Commerce setting, then checks if that template exists on the front-end templates folder.

My guess is you've got something messed up with the path to that template somewhere.


How to save data from a form in Craft? Explain with an example? where do you handle the POST requests?
where do you write the validation rules and flash error messages?
where do you write save to db code?
(mainly i want to know how do you route a POST request to a controller and where do you write the controller?)

You'd do this wiht a Craft plugin or module.

Try giving the plugin docs a once over: https://docs.craftcms.com/v3/extend and if you have some specific questions, feel free to post back.

You can also generate Craft plugin boilerplate code at https://pluginfactory.io that already has a lot of this setup for you.


Is there any way to replace the asset programatically? In the CP, when we upload an image with a same name, craft will ask if we wanna keep both or replace.
So in plugin, is there any way to do the replace?

You need to set the scenario SCENARIO_REPLACE or SCENARIO_CREATE depending what you like to do

$asset = new \craft\elements\Asset();
$asset->tempFilePath = $tmpFilePath;

$asset->setScenario(\craft\elements\Asset::SCENARIO_REPLACE);


Custom Fieldtype with Checkboxes - Remove value and set to null when checkboxes are left blank I created a custom field type to show user groups in a checkbox layout, e.g. (http://cl.ly/image/0A1a140m031h).

I am running into one small issue. If I add content with a checkbox(s) option selected and save the entry. Then I try to edit the entry and uncheck all the options, the entry will still have the original checkbox options selected and won't return to the null state as expected. I was trying to use prepValueFromPost but that doesn't seem to run unless the value is set. How do I fix this?

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


How to add a unique number for each reiteration and render it multiple times? I am working on a testimonial slider and each slide is wrapped in an <li> tag. The JS looks for a similar id number, one for each layer of the slide, in this case I need to change the 1 in the example below.

Example:

"rs-1"
id="slide-1-layer-2"
id="slide-1-layer-3"

I loop through the entries with a normal {% for %}{% endfor %} statement and I tried rendering the required number (1) with the {{ loop.index }} but I guess you can only use this once...

Is there a method do this? Perhaps with Twig?

If I am not clear this is what the result should be:

<li>"rs-1"
        id="slide-1-layer-2"
        id="slide-1-layer-3"
</li>
<li>"rs-2"
        id="slide-2-layer-2"
        id="slide-2-layer-3"
</li>
<li>"rs-3"
        id="slide-3-layer-2"
        id="slide-3-layer-3"
</li>

etc...

Set it as a variable inside your loop and you can reuse it all you want.

 {% for entry in craft.entries.section('yourSection') %}
    {% set loopIndex = loop.index %}
    <li>"rs-{{loopIndex}}" id="slide-{{loopIndex}}-layer-2"</li>
 {% endfor %}


Live preview using Vue.js I'm building a Vue.js site with Craft as the backend, which works pretty well so far. The only thing I can't get to work yet is live preview.
Vue-Router relies on the window.location which is flawed in live preview (https://example.com/admin/entries/pages/1-homepage instead of https://example.com/homepage). Is there any way to get this right?

Update: A new issue popped up. About to test things, I noticed the content does not change because - obviously - I pull it from the Element API, which pulls it from the database. I'll update my answer below when I've found a way around this.

Craft 3.2 introduces Headless Preview which works a treat with SPA's. Essentially Craft exposes tokens which you can forward on to subsequent Element API requests and Craft will do the rest. The interesting thing to note with this release is that Live Preview isn't actually "live" rather draft entries that are saved and accessible by tokens generated to identify the entry version.

Your example outlined above is adequate in configuring Vue Router for these previews to work. But we also need to pass on these preview tokens to Element API. These tokens allow Craft to do away with obfuscating URL's loaded in the Live Preview iframe and now load the actual entry URL as you would access it on the actual website.

For example, previously Live Preview would load /admin/entries/282-project-slug in an iframe, it now loads the entry target URL /projects/project-slug?x-craft-preview=XXX&token=XXX. Fantastic!

Detecting Preview Mode

Live Preview loads the entry URL in an iframe with tokens exposed via a query string. These are x-craft-preview and token. We can extract these from the URL either client-side or server-side. The choice is entirely up to you but we just need to grant easy access to these tokens.

Client-side detection example:

let hashes = window.location.search.slice(window.location.search.indexOf('?') + 1).split('&')
let params = {}
hashes.map(hash => {
  let [key, val] = hash.split('=')
  params[key] = decodeURIComponent(val)
})

// x-craft-preview = params['x-craft-preview']
// token = params['token']

Server-side detection example (Twig):

{% if craft.app.request.isPreview %}
   token = {{ craft.app.request.getQueryParam('token') }}
   x-craft-preview = {{ craft.app.request.getQueryParam('x-craft-preview') }}
{% endif %}

  It's worth noting that Craft 3.2 also deprecates isLivePreview in
  favour of isPreview since Live Preview is no longer programatically
  live rather drafts saved on-the-go and tokenized.

Configuring Vue

For demonstration purposes we will declare the following variables and assume we now have access to the tokens.

const craftPreview = // value of 'x-craft-preview',
const craftToken = // value of 'token'

Set the router mode to mode: 'abstract', for example:

const router = new VueRouter({
  mode: craftPreview ? 'abstract' : 'history',
  ...
})

The router will resolve the preview URL so there's no need to replace the path. If you're still having trouble with this then you can try setting it to see if it resolves your problem...

router.replace({ path: window.location.pathname })

Below is an example of forwarding these params with Axios as our HTTP client.

axios.get('/api/v1/project.json', {
  params: {
    slug: 'project-slug',
    token: craftToken,
    'x-craft-preview': craftPreview
  }
})

Alternatively, you could utilise Axios interceptors and configure params before each request.

axios.interceptors.request.use(
  (config) => {
    // Forward Craft Preview tokens to API
    if (craftPreview) {
      const params = {
        token: craftToken,
        'x-craft-preview': craftPreview
      }
      if (!config.params) {
        config.params = params
      }
      else {
        Object.keys(params).map(key => config.params[key] = params[key])
      }
    }
    return config
  },
  (err) => {
    return Promise.reject(err)
  }
)

Hopefully this steers people in the right direction. As always, huge shout out to the Craft team for making this possible.


Getting Unique entries? I am querying data using the code below. In the database, there are duplicate entries for 'title', how can I get distinct values?

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'institutions';
$query = craft()->elements->buildElementsQuery($criteria);
//$query->setDistinct('title');
$query->order('title asc');

$queryResults = $query->queryAll();
$institutions = EntryModel::populateModels($queryResults);

return $institutions;

The query returned by buildElementsQuery() is already prepped to fetch unique entries. But it’s possible for two distinct entries to have the same title, which is why it may look like duplicate entries are being returned.

To only fetch entries with unique titles, do this:

$query->group('content.title');


Customize the field.html file for Sprout Forms I've set up a Spout Form, and I can customize the form.html file after copying it and moving it to my own templates/_form/formHandle folder. But when I want to customize the field.html file (I do the exact same thing as with the form.html file) nothing happens. Does anyone know what I'm doing wrong? I only want to add some custom classes, nothing fancy :-).

Thanks!

To override field.html you will also have to provide an override for tab.html and errors.html.

The field.html template is a bit more complex and the Twig code to get it to work depends on a few other files to work properly.

I've updated the documentation to better reflect this requirement: Template Overrides

If you only need to update the classes, you may also want to consider Rendering Options.

Rendering options would let you dynamically pass the class names to the underlying form code. Depending on how predictable your field names are, it could work like this:

{% set options = {
    "class": "form-class form-class-customized",
    "errorClass": "form-has-error",
    "fields": {
        "fieldHandle": {
            "class": "my-fancy-class",
            "errorClass": "field-has-error",            }
    }
} %}

{{ craft.sproutForms.displayForm("formHandle", options) }}


Getting categories in elementAPI performance issues and help required I am using elementAPI to get data from a directory.
The items listed in the directory have two categories assigned:
Category level 1 country
Category level 2 region

Below is how I am getting the data in the elementAPI plugin

'api/v2/country/<slug:{slug}>.json' => function($slug) {

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->slug = $slug;
$category = $criteria->first();
return [
    'elementType' => 'Entry',
    'criteria' => [
        'section' => 'directory',
        'relatedTo' => ['targetElement' => $category],
        'limit' => 1,
    ],
    'transformer' => function(EntryModel $entry) {

        return [
            'country' => (string)$entry->country[0],
            'port' => (string)$entry->country[1],
            'title' => $entry->title,
            'mapinfo' => $entry->mapaddress,
            'url' => $entry->url
        ];
    },
];
},

The addition of

'country' => (string)$entry->country[0],
'port' => (string)$entry->country[1],

adds 1.5 seconds to the request, compared to not putting them in which comes in at .656ms. It seems the category data is already requested outside of the transformer but i cant see how to get the category array into the transformer. I also can't see why the specifying the categories  in the transformer is so 'expensive'.

Any ideas on speeding up would be very welcome.

I'm no expert on the elementAPI, and a better answer will most likely come, but the country and port fields are relations to different elements (i.e. categories)....so Craft by default uses lazy loading to load this data only when it is called on by default, as I understand it.  And that would probably be why the execution time jumps up.

What you really want to do, I think, is eager load this data as part of your initial query.

For resource on eager  loading, see:

https://craftcms.com/docs/templating/eager-loading-elements
https://straightupcraft.com/articles/examples-of-eager-loading-elements-in-twig-and-php

...so the question is, can you eager load in the element API?  I am not sure, but I'd suggest adding the with part to your criteria and trying it! I'm just guessing on the syntax here, but it looks like:

return [
    'elementType' => 'Entry',
    'criteria' => [
        'section' => 'directory',
        'relatedTo' => ['targetElement' => $category],
        'limit' => 1,
        'with' => ['country','port'],
    ],

...would be worth trying.  My gut feeling is this will work and will distinctly lower your execution time over the lazy loading way, but I'd love to get a report back!


Commerce element query on custom field in console command I'm on Craft 3.4.30 (latest 3.4) and Commerce 2.2.25 (latest 2.2):
My product type "ticket" has a custom date field with handle productStartDate.
E.g. the following query in TWIG works:
{% set products = craft.products().type('ticket').productStartDate('>= 2021-01-01 00:00:00').all() %}

I get nice results including my custom field productStartDate
I am trying the same in a console command with PHP:
use craft\commerce\elements\Product;
$product = Product::find()
                ->type('ticket')
                ->productStartDate('>= 2021-01-01 00:00:00')
                ->all();

Gives me this Exception:
Exception 'yii\base\UnknownMethodException' with message 'Calling unknown method: craft\behaviors\CustomFieldBehavior::productStartDate()'

in /myproject/vendor/yiisoft/yii2/base/BaseObject.php:222

Stack trace:
#0 /myproject/storage/runtime/compiled_classes/CustomFieldBehavior.php(542): yii\base\BaseObject->__call('productStartDat...', Array)
#1 [internal function]: craft\behaviors\CustomFieldBehavior->__call('productStartDat...', Array)
#2 /myproject/vendor/yiisoft/yii2/base/Component.php(297): call_user_func_array(Array, Array)
#3 /myproject/vendor/craftcms/cms/src/elements/db/ElementQuery.php(548): yii\base\Component->__call('productStartDat...', Array)
#4 /myproject/modules/console/controllers/WarmProductGroupsController.php(61): craft\elements\db\ElementQuery->__call('productStartDat...', Array)
#5 [internal function]: modules\console\controllers\WarmProductGroupsController->actionIndex(false)
#6 /myproject/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#7 /myproject/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)
#8 /myproject/vendor/yiisoft/yii2/console/Controller.php(164): yii\base\Controller->runAction('', Array)
#9 /myproject/vendor/yiisoft/yii2/base/Module.php(528): yii\console\Controller->runAction('', Array)
#10 /myproject/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('theme/warm-prod...', Array)
#11 /myproject/vendor/craftcms/cms/src/console/Application.php(87): yii\console\Application->runAction('theme/warm-prod...', Array)
#12 /myproject/vendor/yiisoft/yii2/console/Application.php(147): craft\console\Application->runAction('theme/warm-prod...', Array)
#13 /myproject/vendor/yiisoft/yii2/base/Application.php(386): yii\console\Application->handleRequest(Object(craft\console\Request))
#14 /myproject/craft(22): yii\base\Application->run()
#15 {main}

Any hints why?

Found it: the reason for the Exception is, that the dynamic method productStartDate (coming from the CustomFieldBehavior) needs an Array as parameter.
I have no clue why I get this misleading Exception though...
So finally, this works:
use craft\commerce\elements\Product;
$product = Product::find()
                ->type('ticket')
                ->productStartDate(['>="2021-01-01 00:00:00"'])
                ->all();


Exclude groups from user search I have a client who needs the flexibility to add new user groups in the future to allow access to only certain sections etc.

Anyone in these user groups will appear on the website team page, so what I need to do is to exclude our admin group (and an ex employees group!)

Currently i'm chaining the groups to include as per:

{% set params = { group: 'groupB,groupC,etc,etc,etc'} %}
{% for team in craft.users(params) %}

Is there a way of telling it to just exclude groupA instead?

You can do that like so:

{% set params = { group: 'and, not groupX, not groupY' } %}


Reset shipping method on cart empty and order complete Is it possible without a plugin?

Our client desperately wants the shipping method to be reset (not selected) after an order has been placed or the empty cart button is clicked.

Edit: The shipping method does indeed reset after a completed purchase. Apologies. Regardless, reset on empty cart is still an issue.

Thanks

You're right, this does not seem to clear automatically when you remove all line items, but you could I think just set an extra post value in your form that calls removeAllLineItems to clear the shipping handle at the same time...because in this controller there is a call to $cart->setContentFromPost('fields'); I presume if you set the shipping handle to "", that set content will cause the shipping method to be dropped from the cart.

So basically add <input type="hidden" name="shippingMethod" value=""> to your form & it should work.


Output postDate in a different language than CP How to retrieve the postDate of an entry in a different language than the CP.
In the general config settings i have the following,

    'defaultCpLanguage' => 'en'

But i would like to display the dates in the frontend in a different language. As in translated month names. Is this possible?

I tried the following with no result:

    {{ entry.postDate | date("d/F/y", "Europe/Paris") }}
    {{entry.postDate.format("d F y")}} #}
    {{entry.postDate | date('d F Y')}}

The format works, but there is no translation.

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

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

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

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

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


Any way to manually generate a transform on an asset source? I imported all of the posts from a WordPress blog, using a regular expression to update the image URLs to their new location in a Craft Asset Source. However, many of the original photos are straight out of the camera - 2000x3000px or whatever. What I would like to do is use that same regex to update them to a transformed version: so /wp-content/uploads/2014/12/photo.jpg would become /media/blog/_fullWidth/photo.jpg. I already set up that replacement and it's working great.

The problem is that the "Full Width" transform hasn't been generated, and just calling the URL from a Rich Text field bypasses Craft, so it never gets generated. Short of manually re-adding every photo through Redactor with the transform, is there any way to force Craft to generate a particular transform on all the images in an asset source?

You could just make a temporary template that makes Craft generate them for you. And depending on how many these are, you better use limit and offset with your craft.assets call.

{% set images = craft.assets.source('myAssetSource').limit(50).offset(0) %}
{% for image in images %}
    <img src="{{ image.url('fullwidth') }}">
{% endfor %}


Set cookie and redirect back to referral URL I'm setting up a site for a brewery that requires age verification.  When a user visits the site, I check for the presence of a cookie (I'm using nystudio107's cookie plugin) and if it hasn't been set, it should redirect them to a verification page, which will then take them back to the page they were originally trying to view.

If I just send the user back to the homepage after verification, it works fine. But when I try to pass a variable to get them back to the page they were originally trying to view, things break.

Here is my code to check for the cookie and redirect to the verification page (it works as intended):

{% if getCookie('age') %}
    Page Content
{% else %}
    {% redirect "age" %}
{% endif %}

Here is the verification page code (setting the redirect variable isn't working).

Are you 21 or older?

{% set redirect = craft.request.getUrlReferrer() %}
No
Yes

From here they go to the template that actually sets the cookie (again, issues with the query string):

{{ setCookie('age', '21', now | date_modify("+365 days").timestamp ) }}
{% redirect siteUrl ~ craft.request.getQuery('age') %}

If I take out the redirect variable and query string, and just redirect to siteUrl, it all works fine. I'm having trouble passing the original URL along to get the user back to the page they're actually trying to go to.

Instead of relying on craft.request.getUrlReferrer() you could set a cookie containing the original URL before you redirect them to age verification page.

{% if getCookie('age') %}
    Page Content
{% else %}
    {{ setCookie('originalUrl', craft.request.url ) }}
    {% redirect "age" %}
{% endif %}

You can than use that cookie to redirect to the original link & destroy it again once you verified their age. Destroying it might not be entirely necessary as there's not duration specified so the cookie only lives for the current session.

{{ setCookie('age', '21', now | date_modify("+365 days").timestamp ) }}
{% set redirectUrl = getCookie('originalUrl') %}
{{ setCookie( 'originalUrl' ) }}
{% redirect redirectUrl %}


Craft license and develop a website locally? Is there any problem with buying a Craft Client account, working on the website locally (on my pc), and when it´s done move it to the server?

Is this permitted by the license?

Sebastian, you can always work locally "for free", using "craft.dev" as host name.

Check the FAQs here at the bottom of the pricing page https://buildwithcraft.com/pricing

MAMP PRO makes it really easy to setup custom host names, btw.


Model and its behaviors do not have a method or closure named "optgroup" I'm attempting to finish my first fieldtype plugin (how exciting!) but having an issue with displaying options in a select dropdown in an entry.

My ColumnWidth_WidthsFieldType has this:

<?php

namespace Craft;

/**
 * Widths Fieldtype
 *
 * Allows entries to select associated widths
 */
class ColumnWidth_WidthsFieldType extends BaseFieldType
{
    /**
     * Get the name of this fieldtype
     */
    public function getName()
    {
        return Craft::t('Column Widths');
    }

    /**
     * Get this fieldtype's column type.
     *
     * @return mixed
     */
    public function defineContentAttribute()
    {
        // "Mixed" represents a "text" column type, which can be used to store arrays etc.
        return AttributeType::Mixed;
    }

    /**
     * Get this fieldtype's form HTML
     *
     * @param  string $name
     * @param  mixed  $value
     * @return string
     */
    public function getInputHtml($name, $value)
    {
        // call our service layer to get a current list of widths
        $widths = craft()->columnWidth_widths->getAllWidths();

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

        // populate the $widthsOptions array with $widths
        foreach ($widthsOptions as $widths )
        {
            $widthsOptions[$widths->id] =  $widths->name;
        }

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

My columnwidth/_fieldtypes/widths has this:

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

{% set widths = craft.columnwidth.getAllWidths %}

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

But I'm getting this error:

Craft\ColumnWidth_WidthsModel and its behaviors do not have a method or closure named "optgroup".

The only post I found was here:

Displaying a list of fields in a form select

I'm sure I'm missing something and any help is appreciated!

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

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

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

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

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

Your field type template should be something like this:

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

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


Front end user profile: update password Typical scenario: users log in on the front-end and have a profile page where they can update their info, including changing their current password.

I have referenced this article from 2014 but it's not working for me; maybe it's outdated by now?

Is it possible to change a user's password in the front-end?

From that article I get:

User needs to be logged in
User needs to submit their current password (input name="password")
User needs to add a new password (input name="newPassword")

I've done all of this in my code and it does not work. For simplicity's sake, I've even copied and pasted the code from the link posted above but it does not work. I've created a fake user called "Mister Test" with a password of "purple"; if I try to change the password on the front end to something like "test123", it does not redirect to my success url and does not change the password.

I don't know what else to do. Not much coming up in google searches. My original code is below:

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="/">
    {# redirecting to homepage just for testing #}
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

    {{ "Current password"|t }}
    <input type="password" name="password" id="currentPassword">

    {{ "New password"|t }}
    <input type="password" name="newPassword" id="newPassword">

    <button class="btn" type="submit">{{ "Save"|t }}</button>
</form>

Sounds like it might be a form submission issue rather than anything related to password /profile updates. I ran into a similar issue a while ago and resolved it by disabling Suhosin on my server. May want to give that a try.


Model public method throws CMapIterator warning I have a strange problem with the following public method on a model.

public function getAttributes()
{
    return $this->getId() . $this->getStyle() . $this->getDataAttributes();
}

CMapIterator warns with the following array_keys() expects parameter 1 to be array, string given

But if I alter it to

public function getAttributes()
{
    return array($this->getId() . $this->getStyle() . $this->getDataAttributes())[0];
}

Everybody is happy. It's late and I'm probably shouldn't be coding but any thoughts on the issue would be much appreciated.

Here is the complete model for reference...

namespace Craft;

class Core_CodeModel extends BaseModel
{
    /**
     * @return array
     */
    protected function defineAttributes()
    {
        return array_merge(parent::defineAttributes(), array(
            'cssId' => array(AttributeType::String),
            'cssClass' => array(AttributeType::String),
            'style' => array(AttributeType::String),
            'dataAttributes' => array(AttributeType::Mixed),
        ));
    }

    public function getDataAttributes()
    {
        return is_array($this->dataAttributes) ? ' ' . craft()->core_code->joinDataAttributes($this->dataAttributes) : '';
    }

    public function getId()
    {
        return !empty($this->cssId) ? ' id="' . $this->cssId . '"' : '';
    }

    public function getStyle()
    {
        return !empty($this->style) ? ' style="' . str_replace(array("\r", "\n"), '', $this->style) . '"' : '';
    }

    public function getAttributes()
    {
        return $this->getId() . $this->getStyle() . $this->getDataAttributes();
    }

}

User error. It's a naming collision with the getAttributes method within my model and the CModel class.


Is it possible to grant admin permissions via plugins through userPermissions->saveUserPermissions? I'd like to add admin privileges to a user I'm creating like so:

  if($user == null)
  {
    $firstName = $_GET['firstName'];

    $lastName = $_GET['lastName'];
    $userName = $firstName . $lastName;
    $user = new UserModel();

    $user->username   = $userName;
    $user->email      = $email;
    $user->firstName  = $firstName;
    $user->lastName   = $lastName;

    craft()->users->saveUser($user);

    $permissions = [HOW DO I SET ADMIN PERMS?]
    craft()->userPermissions->saveUserPermissions($user['id'], $permissions)

}

This should do the trick...

$user->admin = true;

That data is part of the UserModel, so be sure to add it before the saveUser call.

Being a full-blown admin not technically part of setting permissions. If the user is an admin, that supersedes all other permissions settings.


Is it possible to order entries by Entry type title/slug I would like to order my entries by the entry type they have, so for instance:

{% set entries = craft.entries.section('more-info').order('type') %}

However, this orders by entry type ID, and not by title, alphabetically. Can this be done? I've tried order('type.title'), but no luck (= DB error) ...

I don't think it's possible to order by the name or handle of Entry Types. To order by the ID of your Entry Types use 'typeId' as the value:

{% set entries = craft.entries.section('more-info').order('typeId') %}

Now you only have to create your Entry Types alphabetically ;)


User Registration Form Redirect not working Craft 2.5 I'm using the following code but the redirect is not working. After the user registers it takes them back to the home page and not to volunteer/identity. I put a message on the homepage to display if the user is logged in and it appears that they are logged it at that point. This used to work before 2.5 on a different site that I haven't upgraded to 2.5. But now on this new install of 2.5 I can't get it to work.

Has anyone else experienced the same issues?

{% extends "_layout" %}

{% block content %}

<form method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="volunteer/identity">

    {% macro errorList(errors) %}
        {% if errors %}

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

    First Name
    <input id="firstName" type="text" name="firstName" {% if account is defined %} value="{{ account.firstName }}"{% endif %}>

    {% if entry is defined %}
        {{ errorList(account.getErrors('firstName')) }}
    {% endif %}

    Last Name
    <input id="lastName" type="text" name="lastName" required {% if account is defined %} value="{{ account.lastName }}{% endif %}">

    {% if entry is defined %}
        {{ errorList(account.getErrors('lastName')) }}
    {% endif %}

    Email
    <input id="email" type="text" name="email"
        {% if account is defined %} value="{{ account.email }}"{% endif %}>

    {% if account is defined %}
        {{ errorList(account.getErrors('email')) }}
    {% endif %}

    Password
    <input id="password" type="password" name="password">

    {% if account is defined %}
        {{ errorList(account.getErrors('password')) }}
    {% endif %}

    <button type="submit" class="button">Save and continue</button>

</form>

{% endblock %}

My config file looks like this:

return array(
    'devMode' => true,
    'useEmailAsUsername' => true,
    'autoLoginAfterAccountActivation' => true,
    'omitScriptNameInUrls' => true,
    'setPasswordPath' => array(
        'en' => 'account/setpassword'
    ),
);

For Craft 2.6, if a hidden redirect input is set, Craft will now follow it first and fallback to the activateAccountSuccessPath if it's not available.


Craft Commerce: Checkout without email / address Is it possible for Users to checkout without an email or address?
I want to give users the option to switch to a payment provider in the cart and fetch the address later via the provider.
Unfortunately I get an error message that no email is associated with the cart \ order.
Is there a way to checkout without an email?
Or Is it possible to edit an Order before passing it to an payment gateway to include an fake email?

Commerce is going to require an email address to checkout. It's a required field for a customer.
You could try to "fake" an email address and then try to update it before the order completes (beforeCompleteOrder) after the transaction succeeds, but I think that's more error prone because Commerce has already setup a customer and order details based on that information.
However, you could work around it.
I'm not sure how your payment provider works but on the cart page, you could start the payment process "manually".
Every field is optional - up until you send the order to Commerce Payment model.
You might have a button that says "Login with Provider" or whatever on the cart page. After someone presses that button, behind the scenes, you're calling your own logic.
You might set some fields up for that session including a token to continue the transaction. As far as Commerce is concerned, it hasn't started checkout yet but it feels that way to the customer.
Then after you've grabbed the customer's details and setup the cart, then you can proceed with sending Commerce the details it needs.


Tasks on Uninstall Plugin When I try to initiate tasks on uninstall the tasks fail because the plugin completes uninstalling before the tasks. The task is referencing an uninstalled plugin at that point. Once the plugin is uninstalled I get this error:

Encountered an error running task 23 (xxxx): Could not find the task component type.

Which makes sense. However, uninstall takes a long time because there are many things needing clean up so is there any way I can have tasks continue to work after the plugin is uninstalled?

I can't think of an existing way to do this (other than something ugly like have a separate plugin whose sole job is to clean up the data from the first).

I think this would make the case for things like onBeforePluginUninstall, onPluginUninstall, onBeforePluginInstall, onPluginInstall, onBeforePluginDeactivate, etc. events to be added so that you could listen for these events and have time to do all of the cleanup necessary before uninstallation continues.

Probably worth adding as a feature request and linking to this thread!


Problem with truncated Freeform checkbox group value when mapped to another field NB: this is not the same as Freeform Checkbox Group Field only returns one value, which was resolved by field name markup invoking an array: name="fieldname[]".
I'm already doing that. And stored Freeform form submissions are respecting multiple values.
My issue is that I am using Element Connections to map the form fields to other fields in the system which are assigned to user accounts.
The receiving fields are multiline Plain Text fields and they are only receiving a single value.
For example:
For a Freeform checkbox group…
<input name="group[0] type="checkbox" value="val1">
<input name="group[1] type="checkbox" value="val2">
<input name="group[2] type="checkbox" value="val3">

…that maps to user account field userData2.
When all three checkboxes are checked:

the Freeform group field stores a value of val1, val2, val3
but userData2 only receives val1.

Currently, the Element Connections feature requires that a Freeform array field be mapped to a Craft field that also accepts an array (e.g. Freeform Checkbox Group to Craft Checkboxes).
I've made a note about this for us to revisit in the future though, and potentially add a transformer to handle this kind of mapping. :)


Management of large number of downloadable PDFs I'm rebuilding the main website for a small rural local council, and at this stage I am planning on using Craft. The main issue I have is around the management of several hundred PDF documents which fall into different categories (agendas, minutes, policies and a lot a paper-based forms). The current system uses Docman in Joomla, so I need to come up with something equal of better.

At this stage my thinking is to create channel entries for each document with a number of metadata fields which would include categories and possibly tags. Each document would be named with a date included to facilitate some level of revision history (requirement by law). I need to present the documents in various ways. Sometimes there will just be links on a webpage, and in other cases I would need to auto-generate an index (e.g. meeting minutes) for a category.

So, am I going in the right direction, or can someone point me down another road, or try and divert me away from Craft altogether if it is not yet suitable to do the job?  I realise I may not be asking the right sort of StackExchange question, so happy to take advice to make it specific enough to meet any criteria.

(An alternative might be to see if I can extract some sort of feed from Sharepoint which the council uses as a basis for it's intranet. That would have to be a separate question though.)

I'm not familiar with Docman (or Joomla for that matter), but I think Craft is perfectly capable of doing what you're describing.

Your strategy of creating an entry per PDF seems reasonable.  Entries get custom fields (of course) and revisions and you can use Entry Types to display them in the various formats that you require.


How can I have created data (id) returned for a GraphQL mutation? I have a mutation which is successfully creating an entry, but the data returned for the mutation does not include the fields I specify, such as id.
mutation saveWindowCleaningRequest($title: String!, $frontendInput: String!) {
  save_pdWindowCleaningRequests_pdWindowCleaningRequests_Entry(title: $title, siteId: 2, frontendInput: $frontendInput, authorId: 1) {
    id
    title
    ... on pdWindowCleaningRequests_pdWindowCleaningRequests_Entry {
      frontendInput
    }
  }
}

Data returned:
{
  "data": {
    "save_pdWindowCleaningRequests_pdWindowCleaningRequests_Entry": null
  }
}

Mutation result screenshot:

Subsequent entry query result screenshot, showing entry was created:

I'm running Craft 3.5.15.1 with PostgreSQL 12.4 in Ubuntu 18.04.5 LTS.

As noted by yvanavermaet in the comments on the question, this is an issue with Craft. It's been fixed in 3.6.5.
Thanks!


Help setting up Memcached in Craft 3 We want to use Memcached but are struggling to find Craft 3 specific config examples and documentation.

The docs mention several things that seem to lead to dead-ends:

App config docs here show how to configure the component in config/app.php. But in terms of 'enabling' that component, the docs here say that cacheMethod might need to be used, presumably in config/general.php, but the link to cacheMethod goes nowhere. Also here in the changes in v3 article, is says that cacheMethod has "been removed entirely" and instead point readers to Configuration → Data Caching Config which is a missing section.

In terms of the server setup, Memcached is enabled and we have 2 nodes/hosts available.

Very confused, please help.

The docs here are what you need: https://docs.craftcms.com/v3/config/app.html#memcached-example

Which is 99% exactly what Yii uses (since they have an example of using multiple servers): https://www.yiiframework.com/doc/api/2.0/yii-caching-memcache


Is "Replace file" a potential security hole? I am new to Craft, but have a lot of experience with other CMS systems.

I have a very specific question about Assets.  I have an intern who has been given access to a Craft site; for a particular Asset Source, the intern has "View source" and "Upload files" privileges, but he does not have "Create subfolders" and "Remove files" privileges.  But even though the intern cannot remove a file when logged in, he can still replace it with another.  This seems to be a huge security issue.

I have tried everything to get around this issue, including configuring the image field to "Restrict uploads to a single folder."  The problem here again is that I cannot restrict the intern to his folders only; he can see all the Asset folders and can replace any file -- either through malice or incompetence.

Denying the right to upload files for the intern is not going to work either because I do need him to be uploading files for the entries he is creating.

Any help would be appreciated here as this is a real show-stopper.

Cheers!

The problem here again is that I cannot restrict the intern to his folders only; he can see all the Asset folders and can replace any file -- either through malice or incompetence.

Unless I'm missing something you want to be able to jail a user to only his folders?

I just tried this. While jailing a user to his own folder site wide isn't (currently) possible, what you're doing should be working;  you have to do that on a field-by-field basis. Make sure you're jailing the the right field?

When your intern goes to edit an entry, he shouldn't be able to replace an asset file in another folder if he doesn't have upload permission in the asset's source folder.

Make sure only his asset source is checked.  For example: I created 2 asset sources: Intern Images and Images.  As you mentioned, the only folders the intern can view and upload is  Intern Images; everything else is unchecked.

To test, I made a sample entry with my admin user and selected a PDF in a source that the intern user doesn't have access to. When I go to edit that entry as my Intern user, I can see the other assets in that folder—unless I've jailed it to a single folder—but I can't replace the actual asset because I don't have upload permission on that asset source. I can of course swap the asset for something else but the original asset FILE (the PDF's content) is left untouched.

If you're asking about replacing files that the Intern has access to as well, that's a whole other bag of worms and IMO trust issues. Security is a 2-way street.

However, I wonder if you could write a plugin to intercept the upload request and rename it before Craft has a chance to fire the "would you like to replace the file" so you always have a unique file name? IMO that gets touchy because you start to have 2 or 3 different versions floating around and that ends up causing even more stress.

Practically speaking, WordPress actually does this by default (appending -1, -2 to a file) and in my experience, it can drive users crazy. If you upload a file and you realize you have a typo or some part of your image still needs work after approval—and that file path is already linked from a couple spots on the server—you end up deleting the file and then reuploading again. Craft's method of asset management is so much better in this respect. But with great power comes great responsibility, as they say.


Is it possible to reorder fields with drag and drop? I'm trying to understand how most people deal with this likely common issue, I've been looking around for answers, apologies if this is a subjective question, but I imagine there is a 'correct way' of doing this and I'm just missing something.

From my understanding Craft is supposed to make implementation and management of content modules very simple, primarily through the use of Matrix fields.

If I want to build a truly modular content management back end, where the user can add any predefined modules of content, and then reorder them with drag and drop, as far as I can see this will have to be done with a matrix field.

So a seemingly clumsy way of achieving this would be define a single matrix field which has all types of content module in as Block types. ie. 'Hero module', 'text columns', 'Latest clients', then in the admin the user adds this global matrix field and adds the required modules.

The problem is the matrix field doesn't seem to be designed to be used like that. If I define a matrix field for the whole page, then a Block within is a module, and within each Block a field is say a title or an image; but if I want to add a position field that image, you can't go down another level - the position would be added to the module, or Block.

Furthermore, I don't understand why it simply isn't possible to create several separate Matrix fields and then drag and drop order them in the page admin. Or any field for that matter.

Thanks, if you need further clarification I can mock up a diagram or something! And I'm on the Craft Slack if anyone would be rather reply on there :)

To answer just the initial question. "Is it possible to reorder fields with drag and drop?".

Yes, Settings > Fields > Set up as Matrix > You can then add/delete or reorder there using a drag method within the matrix you set-up. (See image below)

If what you are looking for is more control than this. While having some the same issues learning more about the use of Sections and Channels at http://buildwithcraft.com/docs/sections-and-entries has proven quite useful to me.


Import users with specific ID Is it possible to use the saveUser method to import users with an existing ID?

craft()->users->saveUser($userModel)

I need to import 2000+ users and when doing so, I need to make sure that their old ID doesn't change after inserted, because I need to import other tables too and match them based on that.

The excellent import plugin tries to update the users instead of creating new ones when I tell it to import the ID as well. I'm not sure if that's intended behavior or a bug.

If the UserModel contains a user ID, then the existing user will be updated.

If the UserModel does not contain a user ID, then a new user will be created.

Either way, the UserModel will contain an ID after being saved. Since models in PHP are passed by reference, the ID will get set automatically for new users.


Should delta.yaml be committed to git? Getting started with CraftCMS 3.1's project config files and I can't find any documentation about whether storage/config-deltas/delta.yaml should be committed to git

No, you would not check these files into Git.

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

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


Simple way to use craft for databaseless prototypes We have found that craft (and twig mostly) combined with bootstrap make a great prototyping tool.  We'd started up a number of projects that use templating and lots of fun twig stuff but no real need to anything in the database

right now we go through the entire craft install and setup a database anyways but curious if it would be possible to run just the templating part of craft without a database at all?

Using Craft without a database isn't possible, you're probably best off doing things the way you are now (with a minimal Craft install).

At its core, Craft is built on two very powerful frameworks:

Twig
Yii

(There are other components as well, but these are the driving forces.)

You can, of course, just use Twig as a templating language for your prototyping. But that's all you'll have... a templating language.

You can't use Yii without a database, since the primary purpose of Yii is to act as a DAO (Data Access Object). Without a database, it's kinda useless.

My official recommendation: Create a "base installation" repo with a generic website, and have Craft completely installed. Then you can quickly clone that and work your prototyping magic!


How do I set up Craft to send emails from my local MAMP/Virtual Host X dev environment I'm developing a site locally using MAMP + VirtualHostX on Mavericks. I'm at the point in the project where I want to create some user accounts for clients, but I can't seem to get my mail set up properly so Craft can send emails from my local environment.

Has anyone done this same thing? Any advice for getting Craft emails working on a similar local dev environment?

Thanks!

These days I just use Mandrill.

It's simple to set up, free unless you're sending tens of thousands of emails, and you can continue to use it on any development (or production) machine without any configuration changes.

Just set the Mandrill SMTP settings in the Craft admin area, and you're done.


Omit Featured Entry from loop of entries with additional omissions I have a homepage single section has a field for entries (only 1 can be selected).
This field is called featuredEntry.

In my homepage template (index.html) I set a variable {% set featured = entry.featuredEntry %} for the field
I then loop thru that to pull in that entries content {% for mainEntry in featured %}

I have a listing of entries below it that pull from the same News channel as the featured entry above.
I don't want the featured entry to show in that list.

I followed the answer here (Exclude "featured" entries from a "recent" entries {% for %} loop) with slight changes to try and omit that entry.

However, setting a variable {% set featuredIds = featured.ids() %} for the above featured entry doesn't seem to work.

I am omitting additional entries that are marked with a certain tag as explained here:
List entries without specific tag

What am I missing here or what is wrong for my code to not pull in that id of the featured entry?

{% set featuredIds = featured.ids() %}

{% set mainTag = craft.tags.search('All-Stars').first() %}
{% set allEntries = craft.entries.section('news') %}
{% set taggedEntries = craft.entries.section('news').relatedTo(mainTag).ids %}

{% set omitIds = 'and, not ' ~ taggedEntries|join(', not ') ~ allEntries|join(', not featuredIds') %}
{% set untaggedEntries = craft.entries.section('news').id(omitIds) %}

{% for feedItems in untaggedEntries.limit(5) %}

In that code above in the omitIds variable, if I do this:
{% set omitIds = 'and, not ' ~ taggedEntries|join(', not ') ~ allEntries|join(', not SPECIFIC ID') %}

It works.

Thanks in advance.

My variable wasn't outputting the id and it wasn't being pulled into my omitIds variable

{% set featuredIds = entry.featuredEntry.first.id %}

{% set omitIds = 'and, not ' ~ taggedEntries|join(', not ') ~ allEntries|join(', not ' ~ featuredIds) %}

Adding .first.id to my entry.featuredEntry outputs the correct id.
Then removed featuredIds from the ', not ' in omitIds and added ~ featuredIds pulls in the correct id and omits it from the list.

Feel free to edit as I'm sure I'm not explaining this correctly.


Allowing the user to update a CraftCMS pagination limit with listing filter options I am building a pagination layout limiting the content to 10 because, well, it makes sense to break down large amounts of content to smaller chunks.

But as there is so much, a user might want to toggle how many they want to see. But because the pagination limit is done in the twig variables, is there a built in method for updating this on user interactions?

Standard CraftCMS pagination code:

{% paginate craft.entries.section(entry.slug).order('postDate desc').with: ['image'].limit(10) as pageInfo, pageItems %}

Cheers

You could create a form/a link with the limit and add the parameter in your $_GET request or as a segment to your url. This is just an example how to use it.

How many Entries would you like to get?
10
20
30

Then you can fetch this parameter

{% set limit = craft.request.getQuery('limit', 10) %}
{% paginate craft.entries.section(entry.slug).order('postDate desc').with: ['image'].limit(limit) as pageInfo, pageItems %}

Of course you have to attach this parameter to your paginate links as well

{% if pageInfo.prevUrl %}Previous Page{% endif %}

There are definitely better solutions but they require more time and more effort and a plugin/php but this would be the easiest solution


Tax and Shipping API plugins Are there any tax plugins available for some of the major sales tax API services (i.e. TaxJar, Taxamo, Avalara)?

Are there any shipping plugins available for some of the major shipping services (i.e. UPS, FedEx)?

The reason for my questions is that it would seem that the Craft Commerce plugin is extremely limited in those 2 areas.

Craft Commerce is a young product and as such, there are indeed limited options for third party plugins.

Good news, though - writing a shipping plugin at least is not difficult (well, the Commerce part isn't - the API of the shipping service is of course, up to that shipping service!). See https://craftcommerce.com/docs/shipping-methods to get started.  I've personally written a live rates plugin (for TNT) and several unique table based ones, and I've found the process easy and clean.

There is already a ShipStation plugin - https://onedesigncompany.com/craft-cms/plugins/oneshipstation - and ShipStation handles UPS, FedEx etc.

On tax, I don't know a lot about that and so far I think Commerce's tax support is a little limited (e.g. no tax on shipping support).

Fortunately, Craft/Commerce support is excellent and if you do need to integrate a new service, you'll fine Luke Holder and the rest of the Craft team are very helpful with that sort of thing - and of course they're keen to see the Craft/Commerce eco-system grow.  support@craftcommerce.com is the address you need :)


After upgrading to PHP 7 I started getting "storage folder isn't writable by PHP" errors I just recently upgraded to PHP 7. The browser is now showing following error

/home/xxx/craft/storage isn't writable by PHP. Please fix that

Have not changed any permissions on any of the folders. How to fix this problem?

Try resetting the permissions of the storage folder:

https://craftcms.com/docs/installing#step-2-set-the-permissions

(It's possible that PHP was running with higher-than-default permissions in the previous setup, in which case everything may have worked even if you hadn't explicitly made the storage folder writable.)