Get All Line Items Checkout Event I'm looking to fetch all line items and send it as a POST request to an endpoint. I've had a look through the class references but can't seem to find a way to get all the line items that are currently active.
Event::on(
  Payments::class,
  Payments::EVENT_BEFORE_CAPTURE_TRANSACTION,
  function(TransactionEvent $event) {

        $transaction = $event->transaction;
        // @var LineItem $lineItem
        $lineItem = $event->lineItem;

        $client = new \Guzzle\Http\Client([
            // You can set any number of default request options.
            'Authorization'  => 'qdaiciDiyMaTjxMt, 74026b3dc2c6db6a30a73e71cdb138b1e1b5eb7a97ced46689e2d28db1050875',
        ]);

        // Add Cart Data to an Array
        $order_data = array(
            'product_id' => $lineItem->id,
            'quantity' => $lineItem->quantity
        );
...

Your error is in this bit:
        // @var LineItem $lineItem
        $lineItem = $event->lineItem;

Looking at the event in question:
https://craftcms.com/docs/commerce/3.x/events.html#beforecapturetransaction
...this shows that you get a Transaction model supplied in this event:
https://docs.craftcms.com/commerce/api/v3/craft-commerce-models-transaction.html#public-properties
...note that model gives you direct access to the related order element:
https://docs.craftcms.com/commerce/api/v3/craft-commerce-elements-order.html
...from which you can then retrieve all the line items (and products etc associated with them), by looping over order.lineItems


How do you display select Fields from a Matrix Block Type when there are multiple Fields? How do you display select Fields from a Matrix Block Type when there are multiple Fields?

I have 1 Matrix Field with Handle ‘Quotation’

The configuration for this Matrix is as follows:

1 Block Type with handle ‘quote’

This Block Type has 3 plain text Fields:
‘Quotetext’
‘QuoteBy’
‘QuoteUrl’

I havent been able to get any output at all from this Matrix following the documentation and into following HTML structure:

Quotetext

    QuoteBy
    QuoteUrl

Can anyone help me solve this issue?
Thank you

It might seem counter-intuitive in cases where you only have 1 block type (i.e. quote) and only a single block, but your Matrix field will always be an array, where the blocks (i.e. the "children" of the Matrix array) aren't directly accessible:

entry.quotation
    - block1 (quote)
    ...

Usually, you'll output your blocks by looping through the Matrix field, checking each block's type. I find that using a {% switch %} statement is often cleaner than an if/else:

{% for block in entry.quotation %}

    {% switch block.type %}

         {% case 'quote' %}

{{ block.quoteText }}

             {{ block.quoteBy }}
             QuoteUrl

    {% endswitch %}

{% endfor %}

You can, however, opt to only output blocks of a certain type. This is done by "filtering" the Matrix field using the type method, and removes the need for the switch or if/else statement. This is convenient in cases where you know you'll only have 1 block type:

{% for quote in entry.quotation.type( 'quote' ) %}

{{ quote.quoteText }}

         {{ quote.quoteBy }}
         QuoteUrl

{% endfor %}

If you know there's only 1 block, you can even remove the loop entirely by explicitly targeting the first block for your filtered block type. The actual amount of code will be about the same as the above example, though:

{% set quote = entry.quotation.type( 'quote' ).first %}
{% if quote %}

{{ quote.quoteText }}

        {{ quote.quoteBy }}
        QuoteUrl

{% endif %}


Tasks runs only after admin is logged in I have a plugin which runs a task on order complete. The tasks runs successfully without any errors. But the problem is the task is only completed when admin is logged in. So if someone has completed the order, they have to wait until an admin logs in to dashboard. What could I be missing? The code I'm using is :

CustomPlugin.php

craft()->on('commerce_orders.onOrderComplete', [$this, 'initializeTask']);

public function initializeTask(Event $event){
    $order = $event->params['order'];
    foreach ($order->lineItems as $lineItem) {
        craft()->tasks->createTask('Custom', null, [
            'id' => $order->id,
        ]);
    }
}

CustomTask.php

class CustomTask extends BaseTask
{
    protected function defineSettings()
    {
        return [
            'id' => AttributeType::Number,
        ];
    }

    public function getDescription()
    {
        return 'Custom Task';
    }

    public function getTotalSteps()
    {
        return 1;
    }

    public function runStep($step)
    {
        $orderId = $this->getSettings()->orderId;
        .
        .
        .
        return true;
    }
}

Is there any type of priority or setting that needs to be set?

Got it. Added the following code.

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

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


Smart Map - Output map locations from relationship file in a matrix I have "locations" section where each entry is a location, with a Smart Map field for the address.

I have another section "pages", where I have a matrix field which contains an entry relationship field, where I can select entries (locations) from the first channel.

I'm trying to output a map of all locations selected in my matrix field, but I'm getting an error:
Property "Craft\SmartMap_AddressModel.title" is not defined.

I'm using the code below to get the address fields from the individual entries, and put them into an array. I think maybe I'm not understanding what exactly needs to be in the locations array:

{% set locations = [] %}

{#  loop though all relationship fields for this entry #}
{% for block in entry.pageBuilder.type('listingGroup') %}

    {#  loop through related entries #}
    {% for member in block.listing %}

        {# get individual entry address #}
        {% set address = member.address %}

        {# add entry address to locations array #}
        {% set locations = locations|merge([address])%}

    {% endfor %}
{% endfor %}

{{ craft.smartMap.map(locations, options) }}

At a glance, your code looks perfect... but I think there's a subtle error. The locations parameter can be an array of elements, but you are building an array of Address fields (which is not valid).

https://plugins.doublesecretagency.com/smart-map/render-a-map-in-twig/

You can simplify the middle part of your code to this:
{# add entry to locations array #}
{% set locations = locations|merge([member]) %}

That way, locations will end up being an array of elements.


How can I set an absolute image url for Open Graph Image tags? I need the final tag to look like this:

<meta property="og:image" content="http://mysite.com/uploads/resources/_hero/myimage.jpg">

If I use something like this:

{% set seoImage = entry.featuredImage.one().getUrl('hero') %}

I end up with a relative URL:

<meta property="og:image" content="/uploads/resources/_hero/myimage.jpg"

So I thought "okay, I'll concatenate the site URL to the front and trim off one of the backslashes":

{% set seoImage = siteUrl ~ entry.featuredImage.one().getUrl('hero')|trim('/', 'left') %}

That worked fine until the server has to generate a new image using image transform. Then we end up, just the once, with a URL that looks like this:

<meta property="og:image" content="http://mysite.com/http://mysite.com/index.php/actions/assets/generate-transform?transformId=46">"

Darn, No idea what to do from here. Any ideas on how to get an absolute URL for the OG image tag EVERY time?

I'm pretty sure the reason this is happening is because you did not set an absolute Base URL in your asset settings. So if you use /assets/images/folder in your asset settings, that's what the urls will look like on the frontend. If you instead use http://my-project.com/assets/images/folder, your asset urls will include the domain name.

I'd recommend setting up Yii Aliases in your config (if you haven't already) and using those instead of hard-coding the url. So you'd do something like this in Craft's general.php config:

'aliases' => [
    '@assetBaseUrl' => 'http://my-project.com/assets',
    '@assetBasePath' => '/path/to/web/assets',
],

And then in your asset settings you'd be able to use @assetBaseUrl/images/folder instead of http://my-project.com/assets/images/folder. Just a way to keep everything as DRY and clean as possible

The above solution should solve your issue, but fwiw, I'm pretty sure you can force your site to use absolute urls regardless of your asset settings. If you use the url() method and specify what scheme you want, I believe it will always resolve to an absolute url. So something like the following should work (but it feels very icky to me):

{% set seoImage = entry.featuredImage.one().getUrl('hero') %}
{% set absoluteImageUrl = url(seoImage, '', 'https') %}


Craft 3.1 Beta - Email settings and categories not working I'm getting an "UnexpectedValueException" on the pages /admin/settings/categories/new and /admin/settings/email after updating to the beta.

Cause: Moved the template folder from / to /src/
This also apparently affect the backend / admin templates for some reason.

Solution: Update index.php to use the right path.


How to get matrix editor into frontend? I've currently setup a matrix-field for adresses. I added the field as required field to my user-group "Customer". Which breaks the registration, as a user can only be registered, when the matrix has at last one entry.

What im missing now is the possibility to add the specific input elements for one single address-block (or matrix entry) so the user has to add at last one address at registration.

When logged in and viewing the profile, the user should also be able to manage  his matrix entries, so managing multiple addresses.

Is there any documentation on how to get the backend-matrix-editor into the frontend? Can anyone link me an example without copying the whole backend stuff into the frontend?

Getting a Matrix field working on the front-end is going to require 2 things:

Setting up the field inputs so the data submits correctly.
Some custom JavaScript to make the blocks repeat and behave how you want them to.

Here's an example of the Matrix input code you'll need on the front-end.  You'll need to update all of the field handle values to fit your situation:

{# You need to include the 'type' input to identify the matrix block type you are submitting. #}
<input type="hidden" name="fields[contact][new1][type]" value="contacts">

{# You should include the 'enabled' input to specify whether the block should be enabled. #}
<input type="hidden" name="fields[contact][new1][enabled]" value="1">

{# All of your custom fields must be within a 'fields' array. #}
<input type="text" name="fields[contact][new1][fields][contactName]">
<input type="text" name="fields[contact][new1][fields][contactEmail]">
<input type="text" name="fields[contact][new1][fields][contactPhone]">

{# For new blocks, you'll want to use the naming convention 'new1', 'new2', 'new3' for each of your blocks. For existing blocks, you can update those values to be the block IDs. #}
<input type="text" name="fields[contact][new2][fields][contactName]">
<input type="text" name="fields[contact][new2][fields][contactEmail]">
<input type="text" name="fields[contact][new2][fields][contactPhone]">

As for the JavaScript, I won't give an example here, but you'll want to create a way for users to create new blocks, update the ID value appropriately using the new1 convention for new entries and the actual IDs for entries that are being edited.


Redactor fields not saving more than 252 characters? I haven't set any kind of character limit on my Redactor fields, but when I save a longer body of text, is always cuts it off at 252 characters. See screenshots:

Before save:

After save:

Here is my Redactor config:

{"buttons":["format","bold","italic","lists","link"],"plugins":["customstyles"],"formatting":["p","h3","h4","blockquote"],"linkNewTab":true,"toolbarFixed":true,"customStyles":{"style":{"dropdown":{"sourceCitation":{"args":"cite"},"strikethrough":{"args":"del"},"superscript":{"args":"sup"},"subscript":{"args":"sub"}}},"clearStyles":{"api":"module.inline.clearformat"}}}

EDIT: I have also noticed that if I save it with one spare character remaining, the WYSIWYG is inserting a symbol on save to fill the last spot?! Compare the previous screenshot with the next one and you'll notice i've just knocked off the final 't' and the space has been filled with a random symbol. This is sometimes an ampersand.

After save minus the last character:

Note that this is only happening on a production site and not locally.

The cause of this ended up being that the field_introduction column for the Redactor field in the craft_content table was set to varchar(255), which means it can only hold 255 characters.

No idea how it got that way. The Redactor field (under its advanced settings) has never had an option to be varchar(255), only text and mediumtext.

Regardless, going through all of the Redactor field settings and re-saving them correct adjusted the column data type back to text and resolved the issue.


Minifying Craft HTML templates Has anyone successfully minified Craft's HTML templates?

Had setup a Grunt task but it had parse issues with the twig template tags. I since found that the Grunt task "HTMLmin" is only for the purposes of minifying "vanilla" HTML.

Is this even possible?

Any help or direction is greatly appreciated.

Here's a plugin I made that does just that:

https://github.com/khalwat/minify


Eager Load Matrix Field with Assets Field Type I am trying to eager load an image asset assigned to a matrix. The template is pulling entries in from a section and each entry has the matrix field assigned to it that serves as an image gallery.

The error I am getting back using the syntax below is
Craft\EntryModel and its behaviors do not have a method or closure named "primaryImage".

Section Handle: products

Matrix Field Handle: gallery

Block Type Handle: productImages

Field Handle: primaryImage, Field Type: Assets

 {% set products = craft.entries({
     section: 'products',
         with:[
                    ['gallery.productImages:primaryImage', {
                      withTransforms: [
                      'heroImage'
                    ]
              }],
          ]
  }) %}

Template Code:

 {% for entry in products %}
      {% for block in entry.gallery %}
            {% if block.type == 'productImages' %}
                 {% set img = entry.primaryImage[0] ?? null %}
                       {% if img %}
                            <img src="{{ img.url('heroImage') }}">
                       {% endif %}
            {% endif %}
      {% endfor %}
 {% endfor %}

The line {% set img = entry.primaryImage[0] ?? null %} is looking for the primaryImage field on the entry inside your for loop. It is not looking for primaryImage for the current matrix field.

If primaryImage is a field within your matrix blog you will need to change the line to

{% set img = block.primaryImage[0] ?? null %}


Locked users' content fully blocked and unable to unlock Just ran into an issue where one of my users was locked out due to too many login attempts (or at least it seems that way).

This caused all sorts of havoc in my site:

The content that was created by that user was not accessible by
others.
The front end broke (though I guess I should've set an "if no
user rule")
The user couldn't be found in the users list.

In order to fix this I had to go into the database and change the locked status from 1 to 0.

Has anyone else experienced this?
Is there a better way of handling it? (while keeping the limit of attempts).
Craft Team, can this be modified to cause less trouble? e.g.: lock the users but not their content; make the user unlockable from within the CP

You're likely running into a bug that was fixed in 2.3.2636 where a locked user could cause all sorts of havoc on the CP.

If your version/build is before that, update to the latest and you shouldn't see it again.


Get an entry's last modified date Trying to determine if there is a method for getting an entry's last modified date, preferably date-time. Gave a good look over the docs and some searching and couldn't find anything other than the original creation date. Thanks.

You're looking for the dateUpdated property.

{{ entry.dateUpdated }}


where can I find manual for craft forms there is tool forms(/craft/app/templates/_includes/). But I cannot find usage manual, ex. options for forms.select etc. Where is it, guys? Thank you

At this time, there is no manual for it.

It's an incredibly useful chunk of code, but it's buried pretty deep in the system. I think the belief is that "if you're capable of finding it, you're capable of backwards-engineering it."

I'd actually suggest looking to other parts of Craft (and other plugins) to gain a better understanding of some real-world applications and examples.


Unexpected token "punctuation" of value "." ("end of statement block" expected) I'm trying to build an array of values from 4 entries so I can lay them out in a comparison chart. I figured the best way to do this would be to add all of the values to a nested array. So I've set this up...

{% set plandata = {
        'membership-type' : {
            'title' : 'Membership Type',
            'url' : '',
            'price' : '',
            'items' : []
        }
    }
 %}

then I'm iterating through a field and trying to add them to the items portion like so...

{% for amenity in entry.availableAmenities %}
    {% set plandata.membership-type.items = plandata.membership-type.items|merge(amenity.title) %}
{% endfor %}

However I am getting a Template Error:  Unexpected token "punctuation" of value "." ("end of statement block" expected).

Can anyone give me any insight as to what I'm doing wrong?

I see three problems here.

One of them is the - in membership-type. plandata.membership-type does not mean the membership-type field of plandata, but more something like (plandata.membership) minus (type). So you will either want to use membershipType or membership_type, or the less readable twig attribute function: attribute(plandata, 'membership-type').

The second problem is that the twig merge filter operates on arrays, and you are passing it a string. This won't work: |merge(amenity.title), this will: |merge([amenity.title])

The third problem is that the twig set assigns values to variables, and plandata.membershipType.items is not a variable. The only way (in twig) to "assign" to a field of an array is with the merge filter. So you will need something like this:

{# create your amenityTitles array #}
{% set amenityTitles = [] %}
{% for amenity in entry.availableAmenities %}
  {% set amenityTitles = amenityTitles|merge([amenity.title]) %}
{% endfor %}

{# merge those amenityTitles with membershipType (somehow preexisting) #}
{% set membershipType = membershipType | merge({items: amenityTitles})}

{# merge that membershipType with plandata #}
{% set plandata = plandata | merge({membershipType: membershipType}) %}

If you can figure out a less deeply nested structure than that plandata you will probably be happier given the limitations of twig.


Asset URL's return nothing in Craft 3 I have an Assets field assigned to my homepage. I can assign and upload images the same way I've always done.

When it comes to templating, I can loop through the images and output the filename. What I can't do anymore is get the URL. What am I missing?

{% set assets = entry.featured %}

{% if assets | length %}

Some great assets

    {% for asset in assets %}

          {{ asset.title }}

          {{ asset.url }}

    {% endfor %}

{% endif %}

The url's no longer return anything. I've also tried getUrl('someTransformHandle') too.

I can't see anything mentioned in the Craft 3 documentation for assets regarding any deprecations or significant changes.

Did you set up your Asset Volumes to have the proper paths/URLs? Do you have Assets in this volume have public URLs turned on?

Do you have a volumes.php configured to be multi-environment aware? It's not a necessary step, unless you require the now-deprecated environmentVariables settings:

https://docs.craftcms.com/v3/config/#aliases


"An error occurred while generating this PDF." in Commerce 2 Like the title says, I cannot output order PDFs in Commerce 2 and not sure how to debug this. Anyone else encountered the same issue?

Looks like there was a broken include in the order template. Sorted now though thanks.


How to find entries that are not related? Is there a simple way to find entries that do not have a relationship with another channel? I see similar questions here and here, but neither seem to work in this context (or I don't know how to adapt their answers).

I have 3 channels, 'accounts', 'clubs' and 'subscriptions'. Every 'subscription' has a required entries field (limit 1) for 'account' and 'club'. In this case, I'm trying to find 'accounts' that are not associated with a club (i.e. do not have a 'subscription'). Sounds like it should be easy, but not finding an answer.

Looking for something like {% set params = params | merge({ not relatedTo : subscriptions }) %}, which obviously doesn't work. I'm using merge because there may be other criteria as well (such as account status, etc).

Any ideas? Thanks.

You'll need to approach this in two steps:

Get all the entries that DO have relationships.
Filter those entries out of your ElementCriteriaModel, either by using the "not" syntax on the entries id parameter of the craft.entries variable, or by using the without Twig filter in your loop source.


Craft Locales and translatable image field I´m working in a multi country website ( resolved with locales ) with products, and each product will show information for each country and the product image could change from one country to another, but the picture will usually be the same. Because the image can change for each locale, i check it like a Translatable field, but i realize that the client will have to fill the image field with the same image for each of the 4 languages, resulting in extra work to enter each product... so my question is:

Is there a way to assign the image in the default locale, and the others locales taking this image as default, except that you specify an image for that language specifically?

Thanks!
Sebastian

One way would be to create two Asset fields. One is the default field and one is the field which is translatable into each locale.

You could then steer the two fields via conditional logic: If no image is present in the default field, switch to the localised field.

You could add a light switch field which disables the localized field for further safety & usability.


How can I get a related Asset of a specific field? I'm trying to grab an Asset which is a child of my Entry...

$criteria = craft()->elements->getCriteria(ElementType::Asset);
$criteria->childOf = $entryId;
$photo = craft()->assets->findFile($criteria);

For the most part, this works pretty well. But my entry has multiple Asset fields, and sometimes it grabs the wrong image.

I suspect that I just need to add another parameter to my $criteria, but I can't figure out what... theoretically something to denote which specific field I'm referring to. Any suggestions?

Found it! The specific field can be targeted like this:

$criteria->childField = 'myFieldHandle';


Password protect whole staging site. Redirect to original page not working I'm trying to password protect a staging site. So I've put a {% requireLogin %} at the top of my _layout.html inside of a conditional tag. It's working except the redirect after login always goes to the dashboard instead of the original page. What am I doing wrong?

I'm aware of the possibility of using htaccess protection, but I think doing it the "Craft way" is nicer.

{% requireLogin %} is intended for use with your own login form on the frontend rather than the standard /admin one. From the docs for loginPath:

  The URI Craft should use for user login on the front-end.

Which means you create your own frontend login form, and set that as the loginPath. As you don't have that, it's defaulting to the default login instead, which redirects users to the admin dashboard instead of the page they were on.


Redactor air not visible when code mirror is enabled I'm using Redactor 2 and I set config air: true and plugin: ['codemirror'].
The issue is when I click on html button the air toolbar disappears and is not possible to have toolbar on redactor again.

Is there a solution?

Thanks in advance.

I found a quick solution to show toolbar when hover code mirror

 callbacks: {
   init: function() {
   $('.CodeMirror-scroll').on('hover',function(){
         $('.redactor-air').css('display','block');
          });
       }
}

But the issue is the same when i have more then one redactor in same page, because it shows both toolbar...

Any help on this ?
Thanks


How to Generate Unique Slugs for a Section without ticking "Entries in this section have their own URLs" I am working on a site that has an events calendar with Future, Current and Expired events being shown. Which is completely fine when I am on the index page and have "Entries in this section have their own URLs" checked for that section. The problem I run into then is that the permalink page will only show entries that the are live. Pending and Expired entries will never be shown (As mentioned in this questions and answer).

We have a lot of events that have similar or the same name that happen on a weekly or monthly basis. For example "Live Music at Blue Skies Winery" produces a slug of "ive-music-at-blue-skies-winery" when I had Entries in this section have their own URLs it would increment the slug like live-music-at-blue-skies-winery1 and the next one would be live-music-at-blue-skies-winery2.

So as a result I have disabled it for my event section but as a result now entries with the same title have the same slug of live-music-at-blue-skies-winery without being incremented.

Is there a way to force the slugs to be unique either by incrementing the slug like happens when I have Entries in this section have their own URLs checked or is it possible to prepend the entry date 03-01-2015 to the slug name?

You should probably just set your event dates using custom Date/Time fields rather than the Post Date and Expiration Date fields. That way you don’t have to fight with Craft’s restrictions on non-live entries.


Is it possible to duplicate an entry as not enabled/live from the listing page? Is it possible to duplicate an entry as not enabled/live from the admin listing page? Just this means some user put pages live on the site that are just copies - they forget to quickly change it to disabled etc.

After talking with Brad in Craft support we came up with this to put in a plugin. So now when duplicate is called in the admin (list of entries) it is set to disabled. Normal Craft behaviour is to keep the same state as the entry being copied.
//if duplicate sets entry to not live / disabled
Event::on(
    Entry::class,
    Entry::EVENT_BEFORE_SAVE,
    function(ModelEvent $event) {
        $entry = $event->sender;

        // If the Entry is being duplicated.
        if ($entry->duplicateOf) {

            $entry->enabled = false;//set to disabled

        }
});


How to order by matrix field? I have a section where its entries have a matrix field (matrixField). In the first matrix block there is a date field (dateField). I want to get my entries ordered by that date field. Is this possible? Pseudocode:

{% for entry in craft.entries.section('dates').order(matrixField.first().dateField).limit(5) %}
    ...

My SuperSort plugin is built for use cases exactly such as this. It allows you to render each object in your array using a Twig object template and sort the array based on the rendered value.


403 Forbidden Assets I can't for the life of me figure out what's going on. When assets are added, they upload fine but when I add them to entries or try to view them in the browser, they won't display and show a 403 Forbidden page instead.
Help! :)

This article will help you set permissions properly for Craft CMS installs:

Hardening Craft CMS Permissions

It leverages Craft-Scripts to do the heavy lifting.


Dynamic fields layout based on categories I have entries called products. Those entries are organized in categories. I'm using fields to save technical data for each product ( ex. Flow rate, Pressure, Voltage, etc. ).
Not all fields suit all product categories ( ex. Voltage doesn't make sense for pneumatic pumps ).
Is there a way to associate some fields only to products in a specific category?

Thanks

So I'm going to add this as an answer just in case others find it a useful option to pursue.

I would create your fields; voltage, flow rate, etc. then I would create a Structure called Products with different Entry Types corresponding to the various categories you are using to sort your products. Then you can add your fields to the appropriate Entry Types. Then when you go to add a new product, you'll have a dropdown where you can select what Entry Type this entry should be.

That's how I would setup your site structure if I were in your place


Can I accept file uploads using the Craft Guest Entries plugin? Can I accept file uploads using the Craft Guest Entries plugin? Using input type="file" doesn't seem to be working.

I don't see why you couldn't. That is unless the plugin needs to handle file uploads as opposed to the Entry Model.

Take a look at Uploading Files from a Form. You need to make sure your form tag has enctype="multipart/form-data" and your file input has the name fields[fieldHandle]. If you are uploading multiple files, be sure to add and extra set of square braces on the end (fields[fieldHandle][]).


Need to access year/month variable when grouping entries by date Having issues trying to access the year & month variable when grouping entries by month-year. The code is outputting the desired results (ie. December 2014), however I would like to format the url by 'year/month'.

Archives

    Browse news & articles for the last year.

{% set allEntries = craft.entries.section('news').limit(null) %}

{% for date, entries in allEntries | group('postDate|date("F Y")') %}

{{ date }}

{% endfor %}

If I understand your example correctly, a simple hyphen would do the trick — "YYYY-MM" is a format the date filter recognizes.

{% set entries = ... %}
{% set entriesByMonth = entries|group('postDate|date("Y-m")') %}
{% for month, entries in entriesByMonth %}

        {{ entries | length }} entries in {{ month|date("F Y") }}

{% endfor %}


Get locale entry.title in other languages I'm trying to get the locale title (dutch: nl_nl) of an entry, in the english version of the same post. I want to do this so that on hover it shows the English title's Dutch version.

Any help is appreciated!

You can use the 'locale' and 'id' attributes in your query to request the same entry in another locale.

{{ entry.title }}<br>
{{ craft.entries.id([entry.id]).locale('nl_nl').first.title }}

Update. If there is any chance that the entry/section is disabled for that locale you can also check it first, like so.

{% set nlEntry = craft.entries.id([entry.id]).locale('nl_nl').first %}
{% if nlEntry %}
    {{ nlEntry.title }}
{% endif %}


Matrix Error - "Field Limit is too big for your chosen Column Type" I have a matrix field which is used a my main Body content field.
The site has just been updated to the latest version of Craft and I tried to add a block to the matrix field but when i try to save it I get the error on a plain text field:

Field Limit is too big for your chosen Column Type.

Even if i open the field and don't make any changes and jut save it I get the same error. The matrix field has 11 Block Types.

I have the same field in another website which actually has another couple of blocks in it and it can save without any issues.

I have found this thread: https://github.com/craftcms/cms/issues/2009
and possibly related to a MySQL issue.

But is the issue related to the size of the Matrix Field? Or overall the number of fields in the database?

But is the issue related to the size of the Matrix Field? Or overall the number of fields in the database?

Neither. :)

That error message isn't related to the linked Github issue (although I can see how you'd get them confused).

It's coming from the Craft's Plain Text field type: https://github.com/craftcms/cms/blob/develop/src/fields/PlainText.php#L126-L137

There's a discrepancy between one of the Plain Text field's settings in your Matrix field where the charLimit setting on the field is greater than the database Column Type setting for that field can hold (i.e. for MySQL varchar, text, mediumtext, etc.).


Craft 2 new locale and dealing with root-relative links Hi I am adding new locale which is jp and I have a huge problem with href tag.
Our paragraph field have href links using relative link like this:
 page a

When I hover to the link. It show "example.com/page_a" instead of "example.com/jp/page_a".
Our siteUrl was set up correctly which is shows example.com/jp.
Is anyone face this issue before and how to handle it.

Try using {{ url('/page_a') }}, this should generate the correct url.


Campaign UTM Tracking through to form My client has asked that I track and send campaign information through a contact form.

So basically a user might come to the site on this type of URL:

domain.com/?utm_source=Facebook&utm_medium=social&utm_campaign=paid16-03-2022

I can certainly get the query string information into a form (if they come directly to the form page) but if they go to multiple other pages and then fill in the form it gets a little more difficult to track.

My thinking was to:

Set a cookie to capture the query string variables when they come to the site
Put these cookie variables into a hidden contact form field/s  (if they go to this page)

I just wanted to double-check if this is the best way, if anyone had done this before or if there was a plugin or something else to help?

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

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

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

_layout.twig:

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

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

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

content block:

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

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


Change domain in entry.url I have a group website which has a main site and 3 sub sites all within 1 Craft Installation.
Each sub site has its own Structure Section for Content.

I am adding a Group Wide Search to the main site and sub sites.
Sub sites are accessed by subdomain of main site - e.g.  property.domain.com agents.domain.com

On a sitewide search if I get results from the subsites the entry.url will just contain the domain from the site it is being searched for.

So for my search results - I will check the handle of the entry to see if it is from the subsites - and then if possible replace the domain.

I can get the handle with:

{% set handle = entry.section.handle %}

Is there a handy way to replace the domain?

You could use the Craft/Twig |replace filter, which supports regex replacements.

Something like:

{% set handle = entry.section.handle %}

{% if handle == 'subSiteSectionHandle %}
    {% set newUrl = entry.url|replace('/regexMatchPattern/', 'replacedWith') %}
{% endif %}


How to create a new site (locale: de-AT) based on another site (de) within same installation? I manage a website with multiple languages. Each language has its own site and domain. Think: website.de and website.co.uk

I have to add another site with different locale (de-AT) to the Craft CMS installation. It should run on website.at

The Austrian site should be initialized exactly the same as the current German (de) site.
Afterwards some content will be edited but the foundation but the base should be the same (around 1000 entries).

What would be the best way to 'clone' the German website within the installation to the Austrian website?

It would be okay to manually configure all Sections but I don't want to add every entry manually.

Think if the de site is the default site and the sections are setup to propagate the entries to other sites with the same language (or within the same site group, if de and de-AT will be in the same site group), the entries should be copied to the new de-AT site.


How do you password protect a site in progress? Im wondering if there is a simple way to password protect  site thats in development using just Craft Personal?

I setup a login page and i got {% requirelogin %} to redirect but it seems with craft personal even the admin cant login via a front end login form?

Do they have to login at /admin and then jump to the front end of the site?

is there an easier way?

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

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


Calling unknown method: craft\models\Section::hasUrls() - Craft 3 upgrade I am migrating a site from Craft 2 - Craft 3. In my sitemap template I have the following code;

{% for section in craft.sections.getAllSections() %}
  {# We only care about sections that have URLs #}
  {% if section.hasUrls %}

{{ section.name }}

        {# Loop through each of its entries #}
        {% for entry in craft.entries.sectionId(section.id).limit(null) %}

{{ entry.title }}

        {% endfor %}

  {% endif %}
{% endfor %}

I am getting the error Calling unknown method: craft\models\Section::hasUrls()

I cannot find the equivalent or updated value in the Craft 3 docs. Can anyone advise as to how this should be rewritten or what I should use instead of if section.hasUrls in Craft 3?

In Craft 3, hasURL() is part of a section's siteSettings() as a section exists in multiple sites and can have URLs in one site but not another.

If you are not using multi-sites, a drop-in replacement for your code would be:

{% for section in craft.sections.getAllSections() %}
  {% for sectionSettings in section.siteSettings %}
      {# We only care about sections that have URLs #}
      {% if sectionSettings.hasUrls %}

{{ section.name }}

            {# Loop through each of its entries #}
            {% for entry in craft.entries.sectionId(section.id).limit(null) %}

{{ entry.title }}

            {% endfor %}

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


Possible to assign fields (or an image) to a category? I'm just getting to grips with Craft but it seems very flexible. To try it out I have set up a structure to store some sample products. These products have an image, text, tags and belong to a category (E.g cakes). I can sort and output products, display in groups even sort by tag - brilliant.

One thing I struggling with is how assign a image and other fields to the category? So that I can then have a page with a list of categories each with an image and text Or even output a single category that I want to highlight on another page?

Should this be a "parent" entry? If so how do I assign a set of fields to the parent item but not the child?

Possibly I am thinking about approaching this the wrong way and I should create a "types" structure in which the entries have a required field that is the "category" and use this to search for any products of matching category?

Confused - any pointers appreciated.

The Craft Categories page is very useful.

To assign an entry to a category, create a category field, and require it in the entry type (you are probably already doing this).

When you create a Category Group you can edit the field layout, and add an image field and a text field for the category. Then to edit that content, double click on the category itself (from the right-side category menu), and you will get a modal dialog where you can edit the text and image.

To list the categories in myCategoryGroup you do:

{% set categories = craft.category.group('myCategoryGroup') %}
{% for cat in categories %}
  {{cat.title}} - {{cat.image}} {# assuming image is the name of the image field #
{% endfor %}

Craft site has an article on How do I list the entries related to a category?.


How do I make site links relative? To get around a temporary issue where two urls go to the same site, I wanted to set all my site links to be relative rather than using the full url. Looking through the Craft docs I found that it's apparently possible to place something like this in the index.php file:

define('CRAFT_SITE_URL', "http://{host}/");

However this didn't seem to work - I just get '{host}' appearing in all my links. Instead I set the site url as below, which has had the desired effect...

define('CRAFT_SITE_URL', "/");

...but is this a bad idea?

I may be mistaken, but I feel like a standard multi-environment configuration should work for you in this situation... specifically the use of environment-specific variables.

When you setup your multi-environment configuration, just set one up for each of your domain names. You would include something like this in your config/general.php file...

'my.first.domain' => array(
    'environmentVariables' => array(
        'siteUrl' => 'http://my.first.domain/'
    )
),
'my.second.domain' => array(
    'environmentVariables' => array(
        'siteUrl' => 'http://my.second.domain/'
    )
),

Once you've got that setup, login to your Control Panel and go to:

  Settings > General

Change the value of Site URL to be "{siteUrl}".

Now, you can easily use any of these variations in your template:

{{ siteUrl }}/contact-us
url('contact-us')
siteUrl('contact-us')

It's a little tricky to explain the relationship between those three variations of "site url", but here's the gist of it...

When you set an environment-specific variable in your config file, it can be parsed by Craft (in certain circumstances) with the syntax {siteUrl}. Note the single set of curly braces, and the lack of spaces between the variable name and the braces.
The "Site URL" setting in your CP is capable of parsing out environment-specific variables. So when you put "{siteUrl}" in there, it represents whatever you put in your config file.
Now, when you use {{ siteUrl }} in your templates, it uses whatever value is represented by the "Site URL" value in your CP. Since we just told that field to use the environment-specific variable, that's what will be parsed through to the front-end.

In my example, I also mentioned url() and siteUrl(). These two functions will automatically prepend the "Site URL" value to whatever string you specify.

The difference between the two only really matters if you're rendering a template in the Control Panel (using a plugin). url() will prepend the entire site url, including the /admin/ segment... meanwhile, siteUrl() will only prepend the base site url.


Craft 3 - Cache tag increasing number of database queries I have a question about the {% cache %} tag with Craft 3. I am reading this article (https://nystudio107.com/blog/the-craft-cache-tag-in-depth), and trying out implementing the tags; however, when I check the amount of db queries before and after adding the tags, the amount of queries goes up instead of down as suggested in the article.

What would cause this to happen? This is the code I’m currently testing the cache tag on, there are 5000+ entires in the 'articles' section. Without the cache tag there are 19 database queries, with it there are 32 queries.

{% cache %}
    {% for entry in craft.entries.section('articles').all() %}
      {{ entry.title }}<br>
    {% endfor %}
{% endcache %}

When you first load the template using the {% cache %} tags, the number of queries will likely be higher because it still has to retrieve the correct data from the database.

Subsequent loads of that template should show a lower amount of queries because it's returning actual cached content at that point.

The same thing will happen once the cache is busted from expiration on the next template load as well.


Getting the last X number of pages in pagination I am working on a pagination for some articles. I am using a for loop to get the 3 pages after and before the current page .getPrevUrls(3) and .getNextUrls(3)
So far it looks like this, where 35 is the last page and the black one is the current page.

The problem I'm trying to fix is when the current page is within the 3 page range .getNextUrls(3) of the last page.

How can I create an if statement to hide the dots and the last page if my current page is within 3 pages of the last one so that I don't get the last page number twice.?

Here's my current code

{% paginate craft.entries.section('mySection').limit(10) as pageInfo, pageEntries %}

{% for page, url in pageInfo.getPrevUrls(3) %}
  {{ page }}
{% endfor %}

{{ pageInfo.currentPage }}

{% for page, url in pageInfo.getNextUrls(3) %}
  {{ page }}
{% endfor %}

...

{{pageInfo.totalPages}}

Thanks in advance.

As I already wrote in my comment 3 days ago something like this should work

{% paginate craft.entries.section('mySection').limit(10) as pageInfo, pageEntries %}

{% for page, url in pageInfo.getPrevUrls(3) %}
    {{ page }}
{% endfor %}

{{ pageInfo.currentPage }}

{% for page, url in pageInfo.getNextUrls(3) %}
    {{ page }}
{% endfor %}

{% if pageInfo.totalPages - pageInfo.currentPage > 3 %}
    ...

    {{pageInfo.totalPages}}
{% endif %}

[EDIT]: In the above script you will come across situations where the gap sometimes occurs between consecutive numbers, which can look silly.

To fix this you can add a little extra logic to it:

{% set amountVisible = amountVisible|default(2) %}
{% if pageInfo.currentPage > amountVisible + 1 %}
    1

    {% if pageInfo.currentPage == amountVisible + 3 %}
        2
    {% elseif pageInfo.currentPage > amountVisible + 3 %}
        ...
    {% endif %}
{% endif %}

{% for page, url in pageInfo.getPrevUrls(amountVisible) %}
    {{ page }}
{% endfor %}

{{ pageInfo.currentPage }}

{% for page, url in pageInfo.getNextUrls(amountVisible) %}
    {{ page }}
{% endfor %}

{% if pageInfo.totalPages - pageInfo.currentPage > amountVisible %}
    {% if pageInfo.totalPages - pageInfo.currentPage == amountVisible + 2 %}
        {{pageInfo.totalPages - 1}}
    {% elseif pageInfo.totalPages - pageInfo.currentPage > amountVisible + 1 %}
        ...
    {% endif %}

    {{pageInfo.totalPages}}
{% endif %}

Now this added logic will do two things:

If there is no gap, it won't render a thing.
If the gap only amounts to one page it will render a page number instead.

This results in the following:

As an added bonus: if you add the amountVisible variable on top with a default value you can put this in a twig partial which you can then easily implement on the paged view like so:

{% include 'partials/pager' with { pageInfo: pageInfo, amountVisible: 3 } %}

(Note that passing pageInfo explicitly is not required, but I do it for the sake of completeness and to prevent accidental cleanups of "unused" vars.)


Locale Switch not Affecting News Index Template So I have successfully set up two locales on my site, with a button to switch between, this works fine for all the sections that have the langauges set, but I cannot seem to get it to work for the news index template, my news feed. An individual entry will work fine, but the collated entries don’t. Is there a snippet I need to place at the top of the News index template to define what locale it should contain?

This Google+ thread may help: https://plus.google.com/116942350387086245334/posts/TBtR3XwuZGx

Current options as per above thread:

Create a Single for the News index template
Create a localized template as per http://buildwithcraft.com/docs/templating-overview#template-localization


Element API + checkboxes Using the Element API, I want to return the values from checkboxes (the $block->product field). These checkboxes are within a matrix that I am already gathering data from. Currently am doing this:

return [
'endpoints' => [
    'fullmembers.json' => [
        'elementType' => 'User',
        'criteria' => ['group' => 'fullMembership'],
        'transformer' => function(UserModel $member) {
            $businessCategories = [];
            foreach ($member->businessTypeMarketSectorsProducts as $block) {
                switch ($block->type->handle) {
                    case 'businessCategory':

                        $businessCategories[] = [
                            'businessType' => $block->businessType->value,
                            'marketSector' => $block->marketSector->value,
                            'product' => $block->product //Here you can see I'm calling the product field...
                        ];
                        break;
                }
            }

            return [
                'id' => $member->id,
                'companyName' => $member->membersCompanyName,
                'addressLine3' => $member->membersAddressLine3,
                'lat' => $member->memberAddress->lat,
                'lng' => $member->memberAddress->lng,
                'email' => $member->email,
                // 'profile' => '/directory/company/' . $member->id . '/' . $member->username,
                'profile' => UrlHelper::getUrl("directory/company/{$member->id}"),
                'businessCategories' => $businessCategories
            ];
        },
    ]
]
];

Here is a sample response:

    {
  "id": "1506",
  "companyName": "Airsprung Group Plc",
  "addressLine3": "",
  "lat": "51.33188454",
  "lng": "-2.20657303",
  "email": "email@email.co.uk",
  "profile": "http:\/\/craft.fira\/directory\/company\/1506",
  "businessCategories": [{
    "businessType": "Manufacture",
    "marketSector": "Domestic",
    "product": {
      "0": {
        "label": "Beds",
        "value": "Beds",
        "selected": true
      },
      "1": {
        "label": "Mattresses",
        "value": "Mattresses",
        "selected": true
      },
      "2": {
        "label": "Seating \/ upholstery",
        "value": "Seating \/ upholstery",
        "selected": true
      }
    }
  }, {
    "businessType": "Manufacture",
    "marketSector": "Contract",
    "product": {
      "0": {
        "label": "Beds",
        "value": "Beds",
        "selected": true
      },
      "1": {
        "label": "Mattresses",
        "value": "Mattresses",
        "selected": true
      },
      "2": {
        "label": "Seating \/ upholstery",
        "value": "Seating \/ upholstery",
        "selected": true
      }
    }
  }]
}

I would like the response to just show the values of the product checkboxes. Can you suggest a way to do this so that I am not returning the label and selected states? Ideally something like this:

"product": {"Beds", "Mattresses", "Seating \/ upholstery"}

You should be able to foreach the $block->product to include the selected values (or labels)

return [
    'endpoints' => [
        'fullmembers.json' => [
            'elementType' => 'User',
            'criteria' => ['group' => 'fullMembership'],
            'transformer' => function(UserModel $member) {
                $businessCategories = [];
                foreach ($member->businessTypeMarketSectorsProducts as $block) {
                    switch ($block->type->handle) {
                        case 'businessCategory':
                            $productValues = [];
                            foreach ($block->product as $product) {
                                if ($product->selected) {
                                    $productValues[] = $product->value;
                                }
                            }
                            $businessCategories[] = [
                                'businessType' => $block->businessType->value,
                                'marketSector' => $block->marketSector->value,
                                'product' => $productValues
                            ];
                            break;
                    }
                }

                return [
                    'id' => $member->id,
                    'companyName' => $member->membersCompanyName,
                    'addressLine3' => $member->membersAddressLine3,
                    'lat' => $member->memberAddress->lat,
                    'lng' => $member->memberAddress->lng,
                    'email' => $member->email,
                    // 'profile' => '/directory/company/' . $member->id . '/' . $member->username,
                    'profile' => UrlHelper::getUrl("directory/company/{$member->id}"),
                    'businessCategories' => $businessCategories
                ];
            },
        ]
    ]
];


Ensuring Image transforms use https I'm trying to get rid mix content warnings for https connection. The SSL certificate is installed and working fine but my image transforms are being requested over http hence the warning messages.

Looking into the docs I have tried:

url={{image.getUrl(thumb, null, 'https')}}

But that didn't seem to make a difference. Has anyone encountered this issue before?

ok - just figured it out after reading Brandon's answer here Asset URLs not HTTPS

The missing piece was to set the url setting of the asset source to root relate e.g. /uploads/images

Clear the cache and all sorted!


'Craft requires PHP 7.0 or later' I took the manual install route, unzipped the latest Craft version, and edited the .env file with my database settings, but when I direct my browser to /craft/web/index.php I get a plain page with

  Craft requires PHP 7.0 or later.

I have Bluehost Shared Site and have tried setting my PHP version to 7, but that justs adds a PHP 7 handler to my .htaccess file.  When I check the PHP version through the console it still says 5.6.

I have tried the composer route, and added --ignore-platform-reqs, but when I get to the ./craft setup step I get the exact same message.

I'm just not sure what to do from here.

Thanks

I'm afraid Craft 3 requires PHP 7. https://docs.craftcms.com/v3/requirements.html

Craft 2 will work with older PHP versions  (5.3 to 7.1.x) so you could fall back to using that. https://docs.craftcms.com/v2/requirements.html

Other than that, I'd say you would need a different host in order to run Craft 3.


Entries field: Output entries related to category I have an entries field (activityPicker) that links to other entries in a different section. These other entries have categories (things-to-do and things-to-eat), and I'm trying to figure out how to filter these entries by categories.

My first instinct was to do something similar to this:

{# Categories #}
{% set CatToDo = craft.categories.slug('things-to-do') %}
{% set CatToEat = craft.categories.slug('things-to-eat') %}

{# Entries #}
{% set toDo = entry.activityPicker.relatedTo(catToDo) %}
{% set toEat = entry.activityPicker.relatedTo(catToEat) %}

{# Output #}
{% for item in toDo %}
   {{ item }}
{% endfor %}

{% for item in toEat %}
   {{ item }}
{% endfor %}

however that didn't work so I tried playing with targetElement and sourceElement in the relatedTo parameter:

{% set toEat = entry.activityPicker.relatedTo({
   targetElement: catToEat
}) %}

[...]

but this still doesn't work. Basically I get that entry.activityPicker returns an array of posts, but I haven't figured out how to filter those posts in a meaningful way before they hit the template.

The targetElement and sourceElement take either an ID, an Element Model, or an array of either.

So, in your example, you'd want to do:

{# Categories #}
{% set CatToDo = craft.categories.slug('things-to-do').first %}
{% set CatToEat = craft.categories.slug('things-to-eat').first %}

{% set toEat = craft.entries.section('yourSection').relatedTo({
   targetElement: CatToEat,
   field: 'activityPicker'
}) %}

[...]

Notice the .first in there as the difference. You will only want the one category since you're passing the slug.

Note: This assumes that CatToEat is indeed the targetElement. See here for more information: http://buildwithcraft.com/docs/relations#the-relatedTo-param


Date range to include end date I am grabbing a date range from a URL query string like so:

https://website.com/qa/search-feedback-results?datestart=2019-01-01&dateend=2019-02-26

I can't figure out how to include posts that were submitted on the end date that is in the range. In the above example, any posts dated 2019-02-26 are not showing up in my results.

Here's my code:

{% set vDatestart = craft.app.request.getParam('datestart')|date('Y-m-d') %}
{% set vDateend = craft.app.request.getParam('dateend')|date('Y-m-d') %}
{% set vParams = vParams|merge({ postDate: ['and', '>= ' ~ vDatestart, '<= ' ~ vDateend] }) %}

have you tried setting a time for the end date? because I think Craft always saves time with your date fields.

{% set vDateend = craft.app.request.getParam('dateend')|date('Y-m-d') ~ ' 23:59:59' %}


Show related entries without current entry I'm trying to show related entries to current entry by tag ID (which is working fine) but getting hung up when trying to exclude the current entry from the loop. I think I'm having an issue with paginate tags requiring an element criteria model but I'm not able to figure out how to get around this.

{% set segment = craft.request.lastSegment %}
{% for entries in craft.entries.slug(segment) %}
  {% set current = craft.entries.slug(segment) %}
  {% set tagId = entry.myTagFieldHandle.first() %}
  {% set suite = craft.entries.relatedTo(tagId) %}

    {% paginate suite|without(current) as entries %}
      {% for entry in entries %}
        {{ entry.title }}
      {% endfor %}
    {% endpaginate %}

{% endfor %}

Excluding the without filter on paginate outputs everything fine, but includes the current entry. I know there are probably better ways of doing this and I appreciate any help, thanks!

You're wanting to show a paginated list of related entries from a single entry page based on a tag relationship, correct?

This should point you in the right direction:

{% set segment = craft.request.lastSegment %}

{% for entry in craft.entries.slug(segment) %}

    {% set tagId = entry.myTagFieldHandle.first() %}

    {% set relatedEntries = craft.entries.relatedTo(tagId).id('not ' ~ entry.id) %}

    {% paginate relatedEntries as related %}

        {% for entry in related %}

            {{ entry.title }}

        {% endfor %}

    {% endpaginate %}

{% endfor %}


Hide search results depending on field value This is my search results query:

{% set query = craft.request.getParam('q') %}
{% set miniCards = craft.entries.search(query).order('score').limit(12) %}

I have a lightswitch field called showInSearch. When it is set to 1 the entry should not appear in search results.

Problem
When I do this I always get zero results on my searches:

{% set query = craft.request.getParam('q') %}
{% set miniCards = craft.entries.search(query ~' -showInSearch:1').order('score').limit(12) %}

Whereas when I do the opposite I get all results with the search term and the lightswitch field set to 1.

{% set query = craft.request.getParam('q') %}
{% set miniCards = craft.entries.search(query ~' showInSearch:1').order('score').limit(12) %}

I also tried -showInSearch::1,-showInSearch::"1", -showInSearch:"1" and showInSearch:0 to no avail. What am I doing wrong?

Problem persists even after rebuilding search indexes.

Instead of adding the filtering criteria to the search parameter, I would use a custom field parameter for the showInSearch field.

{% set miniCards = craft.entries.search(query).showInSearch('not 1').limit(12) %}


Is it possible to pass a variable to an event in a plugin? I need to find out if any changes have been made to the entry on successful save.

Using events entries.onBeforeSaveEntry and entries.onSaveEntry seems to be a way to do it. Maybe.

Can I pass some entry variables as arguments to the function on event listener?

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

    $oldVar = "";

    //Event: onBeforeSaveEntry
    craft()->on('entries.beforeSaveEntry', function (Event $event)
    {
        $entryModel = $event->params['entry'];
        $oldVar     = $entryModel->fieldVar;
    });

    //Event: onSaveEntry
    craft()->on('entries.saveEntry', function (Event $event)
    {
        $entryModel = $event->params['entry'];
        $newVar     = $entryModel->fieldVar;

        if ( $oldVar !== $newVar ){
            // ...
        }
    });
}

This will not work as the field value will be the new value in both events. You'll need to get the old value from the entry that exists in Craft before saving the new entry, and then perform the comparison.

If the value has changed then store the entry ID to process once the entry has successfully saved.

Note that the $entryIdChanged variable in the anonymous event functions is not in the same as that in the init() method. You can resolve this as follows:

Bring the $entryIdChanged variable into the anonymous functions using the use operator.
PHP will by default "pass by value", meaning that if the value of the variable within the function is changed, it does not get changed outside of the function. So you should pass the variable in "by reference", using an ampersand & before the variable name, which will change it outside the function as well.

See the PHP guide on Passing by Reference.

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

    $entryIdChanged = null;

    // Event: onBeforeSaveEntry
    craft()->on('entries.beforeSaveEntry', function (Event $event) use (&$entryIdChanged)
    {
        $entryModel = $event->params['entry'];
        $newVar     = $entryModel->fieldVar;

        $oldEntry = craft()->entries->getEntryById($entryModel->id);
        $oldVar = $oldEntry !== null ? $oldEntry->fieldVar : '';

        if ($oldVar !== $newVar){
            $entryIdChanged = $entryModel->id;
        }
    });

    // Event: onSaveEntry
    craft()->on('entries.SaveEntry', function (Event $event) use ($entryIdChanged)
    {
        $entryModel = $event->params['entry'];

        if ($entryModel->id === $entryIdChanged){
            // ...
        }
    });
}


Craft Commerce - empty cart.adjustments data I'm having a Craft Commerce issue receiving cart.adjustments data in my twig templates. I've created a shipping category and shipping method with a rule to add a base rate of $10 to every order, but am not receiving any data from the front end; cart.adjustments is shown as empty. could someone please help me with resolving this issue? thank you

Sounds like you have not submitted a shipping method selection to the cart.


How can I access the Gateways services? I have been trying to access craft\commerce\services\Gateways; from a plugin but I can't figure out how I need to access it. I've used the following:

$gateways = Commerce::getInstance()->commerce->getAllGateways();

$gateways = craft\commerce\services\Gateways::getAllGateways();

The first one says Getting unknown property: craft\commerce\Plugin::commerce and the second one tells me
Non-static method craft\commerce\services\Gateways::getAllGateways() should not be called statically

Can anyone tell me the proper way of doing this? Thanks!

Figured it out:

use craft\commerce\Plugin as Commerce;

$gatewayService = Commerce::getInstance()->getGateways();
$variables = [
    'gateways' => $gatewayService->getAllGateways(),
];


Plugin to "check/uncheck" all matrix blocks while editing entries? I did a brief search and didn't pull anything up. Is there a native or easy way to "check/uncheck" all matrix blocks? We have a considerable number of them and this would be extremely helpful. Thanks.

There's a related feature request for this: "Expand/collapse all" UI for Matrix fields

In that feature request, Brandon Kelly explains how this is already supported (it works very well):

  There is a way to achieve this: Check one of the blocks, then hit
  Command + A to select all blocks. Then click the option button on any
  of the expanded blocks and click "Collapse" to collapse all blocks,
  and vise-versa to expand all blocks.


Separate cache per user or user group in Blitz cache We're using Blitz cache for a client website. Works fine.

Now we need to introduce variable content for different users (based on user groups)

Is it possible to have different cached versions per user or per user group?

For example, can we extend Blitz to alter the key (folder structure) under which a cached page is being saved?

No, it is not possible to store different versions of cached pages. Your best bet would be to use the dynamic content feature that Blitz provides for injecting the content that can vary based on the user into the cached page.


ANDing criteria in craft.entries This works:

            {% set entries = craft.entries({
                section: 'listing',
                listinglatitudenumber: '>=' ~ pluginResults.latmin
            }) %}

But I need to do this:

            {% set entries = craft.entries({
                section: 'listing',
                listinglatitudenumber: 'and', '>=' ~ pluginResults.latmin, '<=' ~ pluginResults.latmax
            }) %}

And I cannot for the life of me figure out the correct syntax for this.

I have been trying many different combos for the 'and' statement based on other answers I have seen in the Craft Stack Exchange but have not been successful. I have not been able to find any docs on this type of query.

Any help much appreciated :)

You need to separate your criterias with commas

listinglatitudenumber: 'and, ' ~  '>=' ~ pluginResults.latmin ~ ', <=' ~ pluginResults.latmin,


Twig: Parent template does not inherent what's ever inside the child template even using extends in the child I'm using twigfiddle.com for now because i want to simulate Twig templates before moving on using Craft.

Base.twig (main template)

{% block head %}
    {% block content %}{% endblock %}
{% endblock %}

Child.twig

{% extends "Base.twig" %}

{% block content %}
    Content from child.twig
{% endblock %}

I expect an output of "Content from child.twig" but instead get nothing.

You aren't able to nest blocks in the template where that block is output - all content inside a block in the parent template is replaced by the child templates content, hence why you don't see your content block being output inside your head block. Likewise you can't use multiple extends within one template.

You can however nest blocks in a child template and output them in your extended template.

Base.twig (main template)

// Will display "content" and "sidebar content"
{% block content %}{% endblock %}

// Will only display "sidebar content"
{% block sidebar %}{% endblock %}

Child.twig

{% extends "Base.twig" %}

{% block content %}
  Content
  {% block sidebar %}
    Sidebar content
  {% endblock %}
{% endblock %}

More info on the topic can be found in Twigs documentation.


How to find and delete with Active Record I'm trying to learn how to add and delete records using Active Record.

This works to add:

$instance = new Calendar37Record;
$instance->timestr = $timestr;
$success = $instance->save();

Given that I know the id of the record to delete, is the process to find the record and then delete it? Or can you just delete it?  I tried this, but it doesn't seem to find the record, and it complains 'The active record cannot be deleted because it is new.':

$instance = new Calendar37Record;
$instance->findByPk($id);
$success = $instance->delete();

Thank you for any help!

Have you tried

$instance = new Calendar37Record;
$instance->deleteByPk($id);


What do the values in /admin/utils/phpinfo mean? When two values are displayed for PHP Info, what does that mean? For example,

Why the two values?

I just made a change on my server (DigitalOcean w/ ServerPilot) which resulted in a double-value... Before my change, there was only a single value.

I can confirm that the top value is overriding the bottom value.

My server default was set to 1000. I used a .user.ini file to override that to 5000.

  ServerPilot: How to Change PHP Settings

  https://serverpilot.io/community/articles/how-to-change-php-settings.html


Select specific fields from query I'm trying to get tags out of the underlying craft DB and serve it as a REST endpoint - however, I'm only interested in exposing the tag id and title, so my data should look like this:

{id: 1, title: "hello"}, {id: 2, title: "test"}

I'm currently able to achieve this with the following query:

$tags = \craft\elements\Tag::find()->all();

The problem with this is that this returns all the fields the tag has. I then have to filter out the two fields I want by doing:

foreach($tags as $tag) {
   $out = [];
   $out['id'] = $tag['id'];
   $out['title'] = $tag['title'];
   return $out;
}

This is quite wasteful as I'm fetching a bunch of fields I don't need from the DB, then looping through all the tags and parsing out the two fields I need.

What I'd like to do instead is only fetch these two fields from craft in my query.

I found two possible ways of doing this - one of them uses the select method:

Something like

$tags = \craft\elements\Tag::find()->select(['id', 'title']).all();

The problem with the above code is that the SQL query which is executed by the above doesn't actually have fields called id and title due to aliasing and joins being carried out on multiple tables - therefore I'd have to know exactly which fields I want and in which table in the SQL schema they sit...this doesn't scale well for more complex queries.

I also found https://www.yiiframework.com/doc/api/2.0/yii-base-arrayable#fields()-detail which seems like it could be useful but I wasn't able to get this to work at all and the documentation isn't too helpful.

I tried eager loading before, and I couldn't figure out how to do it.

https://docs.craftcms.com/v3/dev/eager-loading-elements.html

Now I just query it using SQL. I know it's a bit hacking, but it gets the job done. The DB structure of craft_content table hasn't change since Craft 2 (when I started using craft), so its unlikely that future updates will break your code.

$command = Craft::$app->getDB()->createCommand("SELECT `ct`.`id`, `cc`.`title` FROM `craft_tags` as `ct` left join `craft_content` as `cc` on `ct`.`id` = `cc`.`elementId`");
$tags = $command->queryAll();

This is only a quick fix, if anyone had a better idea, just ignore this answer.


Obfuscating email set by global variable Is there a way to obfuscate an email address link that's generated by a global variable? I tried using Sprout's Encode Email, but it doesn't seem to work with an email address I've generated by a global variable. Specifically, the global variable doesn't work within an anchor tag. For example, the following doesn't work with Sprout's Encode Email:

{% set email = "{{ emailContact.emailField }}" %}
{{ email | rot13 }}

In the code above, "emailContact" is the global set and "emailField" is the associated handle for the actual email address.

It'd be great to figure this one out, especially because it seems a lot of folks would want to use a global variable for a contact email address. Thanks!

It might be that you're trying to parse the variables within quotes " as you set email so you're actually encoding {{ emailContact.emailField }} as a string, not the value it represents. Something like this should work:

{% set email = "" ~ emailContact.emailField ~ "" %}

{{ email|rot13 }}


Craft Commerce update variant field in plugin I'm trying to get, update, and save products &/or variants in my plugin controller, and am stuck on accessing/changing/saving updated fields.

// get product ID from post
$variant_id = craft()->request->getPost('variant_id');

// create criteria
$criteria = craft()->elements->getCriteria('Commerce_Variant');
$criteria->id = $variant_id;

// query
$variant = $criteria->first();

The above works just fine and gets the variant. But now I need to update a few fields and save it. Any idea how to do this?

$variant->getContent()->myCustomField = 'new value';

How would I then save $variant?

This is the general mechanism for updating custom fields on elements - use setContentFromPost and then call the element's save function.

    $variant->setContentFromPost(array(
        'fieldHandle' => $newValue,
    ));
    craft()->commerce_variants->saveVariant($variant);

You should catch exceptions around that really, to handle any errors that may arise (as the model gets validated during save etc.)


Repopulate dateTime field in plugin settings page In my plugin settings page, I have a startDate input which is a dateTime field.

_settings.html

{{
    forms.dateField({
     'label': 'Start Date'|t,
     'instructions': 'Choose a date'|t,
     'id': 'myStartDate',
     'name': 'myStartDate',
     'placeholder': 'mm/dd/yyyy',
     'value': settings.myStartDate,
     'errors': settings.getErrors('myStartDate')
    })
}}

My data is getting saved correctly - I can see it:

json

  ....
"myStartDate": {
    "date": "2015-04-13 05:00:00
}
  ....

So I thought cool. I just need: myStartDate.date and all is well. No luck.

What is curious to me, is when I fill out my start date, but my form fails validation, the date that I have entered is correctly repopulated. I don't have to re-enter the date.

But, once I successfully submit my settings, and then come back, my date field is no longer populated.

I've tried myStartDate and myStartDate.date and myStartDate|date("m/d/Y") but all with no luck.

I feel like I'm abusing this community with so many questions lately. I know the dateTime field needs to be a dateTime object - and I assume that's why it's not working for me. I'm not passing it what it needs.

Thank you for your time!

Long story short, this is a bug in Craft 2.x that's already been fixed in the Craft 3.x branch.

Considering there is a workaround for 2.x and the proper fix would be pretty ugly in 2, we're just going to let this one die a slow death with the release of Craft 3.


Importing content with feedme to single entry in 3 locales This is the situation:

I've got 3 locales (en, nl, fr)
I've got an XML file with content in those 3 locales
I've set up the field mapping in feedme

But what I can't seem to figure out is how to import the entries from the XML file into combined entries in Craft, meaning, I want elements from my XML file (the same content in 3 locales) to be 1 craft entry in those 3 locales.

Each time I do the import, I'm stuck with all of them being in the same locale.

Let me know if any additional information is needed.

Any pointers as to what I'm doing wrong would be much appreciated.

This is how I managed to do the import

Create extra field on entry to save common ID (will be used to link 3 locales together)

Set up feed for each locale with following settings:
- import strategy: create & update
- newly created field as unique identifier

Run each import separately

Feedme will than for the first locale create the entries, and for following locales, update the first one if the id field matches & add the translation to the entry.


cannot get relatedTo by slug only ID Can someone tell me why I am going crazy and cannot figure this simple relatedTo issue out?

So I have a categories section called Case Studies and several categories within. I am trying to filter the results to show all entries within a specific category.

{% set entries = craft.entries.section('caseStudies').relatedTo('municipal').find() %}

won't show any results but using the ID will.

{% set entries = craft.entries.section('caseStudies').relatedTo(422).find() %}

I've tried all sorts of slugs and nothing is showing. Why can I not figure this out. someone please point out my obvious mistake...

My entry field is called 'caseStudyCategory'

It does not work because the function does not accept slugs. Not sure what to answer here. It only accepts objects of type Element and ids as identifier.

You can see the magic here

foreach ($elements as $element) {
if (is_numeric($element)) {
    $relElementIds[] = $element;
} else if ($element instanceof ElementInterface) {
    $relElementIds[] = $element->id;
} else if ($element instanceof ElementQueryInterface) {
    foreach ($element->ids() as $id) {
        $relElementIds[] = $id;
    }
}

These are all kind of things that the relatedTo can use/work with. If you want to get a relation by slug you have to fetch the element first.

.relatedTo(craft.categories.slug('municipal').one())


Delete event from front end I am using Solspace Calendar plugin where front end user can add/edit events. Is there any functionality so that user can delete an event from front-end?

Unfortunately there currently isn't a built-in way for this to work. It is on the feature requests list for Calendar for future consideration, however.


Override a portion of an extends template I'll give you my specific use-case here and then see if it might also be more generally applicable in other scenarios: We have a new Craft PRO site running happily, and in our /templates/ we have a _layout.html file that every other template then uses and extends. That _layout includes common <head> content, main navigation, footers, etc. Nothing surprising.

But on one sub-page we are displaying Google Maps using various calls to Google's Mapping API. One requirement for the Google Maps, however, is that the  tag trigger Google's JS when the page loads and unloads:

  <body onload="load()" onunload="GUnload()">

Currently that <body> tag is in _layout.html so that it can be consumed by the mapping page. But for all other pages it's superfluous, and throws a minor error in the JS console when you inspect the page.

My question is: Is there a way to write a page template so that it _extends another base template but also overwrites just a small portion of it? For instance, could I remove the onload / onunload values from _layout.html and somehow have my mapping page INSERT them back into the <body> tag for just that page?

Or is there a more elegant way to have my mapping page draw upon _layout.html but keep the onload / onunload calls isolated to just that page? Or maybe have _layout.html look for what page is calling it and then return one <body> tag for the mapping and another <body> tag for all other pages?

The Google Maps API makes it pretty clear that this JS function be called at the <body> level, and not just on a <div>.

You could define a variable in you child template:

{% set bodyAttributes = 'onload="load()" onunload="GUnload()"' %}

And then output the value in your parent _layout.html template. Use the is defined test, so that not every template extending this file has to have that variable defined. I'm using ternary syntax here, to keep the code nice and lean:

<body {{ bodyAttributes is defined ? bodyAttributes : '' }}>

As I generally like to have as few logic in my Twig output tags as possible (in particular when they output classes and attributes to already cluttered HTML tags), I would write that code like so:

{% set bodyAttributes = bodyAttributes is defined ? bodyAttributes %}

<body {{ bodyAttributes }}>


how to check for the 2nd, 3rd, 4th… image in an asset's field I am currently "translating" our current website, which runs on the lastest expressionengine, to craft. we use imagegrids that are arranged by css.

so in an entrie's pulldown field choose between several grids (named q1, q1q2, etc.) and checked via conditionals in the code to know how to style the images and to give them the right "transformations"/sizes:

{# Imagegrid #}

        {images_start}
            {images_start:file}
                {# A (1 landscape) #}
                {if imagearrange == "q1"}
                    {if images_start:count == 1}

                    {/if}
                {# B (2 landscape) #}
                {if:elseif imagearrange == "q1q2"}
                    {if images_start:count == 1}

                    {if:elseif images_start:count == 2}

                    {/if}
                {# C (1 landscape / 1 portrait) #}
                    {if:elseif imagearrange == "q1h2"}
                        {if images_start:count == 1}

                        {if:elseif images_start:count == 2}

                        {/if}
                {# C1 (1 portrait / 1 landscape) #}
                    {if:elseif imagearrange == "h1q2"}
                        {if images_start:count == 1}

                        {if:elseif images_start:count == 2}

                        {/if}
                {# D (3 portraite) #}

now I want to bring this functionality to craft – and I already checked out how to check for the fields values e.g. {if:elseif imagearrange == "h1q2"}.

but: I can't figure out how to check for the 1st, the 2nd, the 3rd image in an asset field, like {if images_start:count == 1} in ee.

since craft seems in many ways more efficent than ee maybe this would be solved completely different and I am absolutely open to learn new ways of doing this.

thank you very much!

Since in Craft you will loop over an Assets field, you could use the loop.index variable: https://twig.symfony.com/doc/2.x/tags/for.html to check for the nth iteration.


DevMode Reveals Info to Everyone DevMode is awesome, but I wanted to post this as a bit of a heads up.

I'll preface to say yes, you shouldn't be developing live and yes, the docs do include a warning(yet very small and not really explaining why).

But I am assuming alot of you have it turned on right now.

It reveals the craft path, file system paths, plugins installed, field handles and a whole lot of other juicy stuff.

To everyone.

Couldn't we have, or is there a way to have, this wonderful feature only available if logged in and/or admin?

There already was a warning about it, but it didn’t really stick out, I guess.

Just gave it the actual Warning style treatment, so hopefully this helps the next guy:


Losing focuspoint on saveEntry by plugin I've implemented a plugin for synchronizing an external Database into my Craft project which also includes images.

Those images have a focuspointer but i lose the focuspointer onSaveEntry by my plugin.
(I'm using the Focuspointer Plugin)

Note: I only lose the focuspointer when updating an entry by my plugin, updating an entry by control panel works fine.

This is the code from the focuspointer plugin where the focuspoint get's deleted:

public function onAfterElementSave()
{
    craft()->focusPoint_focusPoint->deleteFocusPointRecordsByFieldIdAndSourceId(
        $this->model->id,
        $this->element->id
    );

    $hash = spl_object_hash($this->element);

    $value = isset($this->values[$hash]) ? $this->values[$hash] : null;

    if ($value && isset($value["focus-attr"])) {
        $i = 0;
        foreach ($value["focus-attr"] as $focus_attr) {
            craft()->focusPoint_focusPoint->createOrUpdateFocusPoint(
                $focus_attr["data-focus-x"],
                $focus_attr["data-focus-y"],
                $value[$i],
                $this->model->id,
                $this->element->id
            );
            $i++;
        }
    }

    parent::onAfterElementSave();
}

How can I prevent the loss of the focus point onSaveEntry by my plugin?

I recently had the same problem when saving entries in my plugin. I only wanted to update an entry field that had nothing to do with the focus image and save that entry. Turned out the focus image lost its value (I think it happens only when the field is required).

I solved it by getting the value of the focusImageField and just re-set it when saving the entry:

$entry->setContentFromPost(array(
// imageWithFocusPoint is required but returns empty,
// so set it with same value it allready had
   'imageWithFocusPoint' => $entry->imageWithFocusPoint->ids(),
));

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

More info that helped me here: http://goo.gl/soli9T

Another solution (and the one I used but maybe less of an option for you) is to disable validation on the entry save. By using:

craft()->content->saveContent($entry, false);

instead of saveEntry. The "false" as second parameter means it will not validate the entry which is not always necessary.


Simple nested navigation I'm new to Craft CMS. I have the following single level navigation code:

    Products

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

{{ entry.title }}

      {% endfor %}

How would i adjust this to show a second level navigation in within the parent li? I'm looking for something like this:

    Products

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

{{ entry.title }}
        if (child) { '

child.title
        }

        {% endfor %}

You could use the children tag:

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

        Products

            {% nav entry in entries %}

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

                            {% children %}

                    {% endifchildren %}

            {% endnav %}


dateTime values in settings page are always a day behind I've used this thread to successfully get my dateTime input fields to repopulate.

The problem I'm seeing now is that while values in the DB are correct, the field input values are always a day behind.

For example, the data in my DB looks like:

....
"startDate":{"date":"5\/4\/2015"}
....

But, the value that is getting rendered in the filed (from my settings page) is this:

5/3/2015

If I save the settings (no errors). The values in the DB will be 5/3/2015 - but then the field on my settings page will show: 5/2/2015

EDIT

Thank you @carlcs, I am sure you are right - I'm just not doing it...right.

Here is what I have tried:

MyPlugin.php

// this returns nothing when logged in error_log
$settings['myStartDate'] = DateTime::createFromString($settings['seasonStartDate']['date'] );

// this returns the date, but one day in the past
$settings['myStartDate'] = new DateTime( $settings['myStartDate']['date'] );

In my defineSettings() method, I am setting myStartDate to a Mixed type as there is a bug with dateTime.

  ....
  'myStartDate' => array(
       AttributeType::Mixed
   ),
   ....

I'm not exactly sure where prepSettings() should live. Here is the whole file:

MyPlugin.php

public function defineSettings()
    {
        return array(
            'myOpenings' => array(
                AttributeType::Number,
                'required' => true
            ),
            'myStartDate' => array(
                AttributeType::Mixed
            ),
            'myEndDate' => array(
                AttributeType::Mixed
            )
        );
    }

    public function getSettingsHtml()
    {
        $settings = $this->getSettings();

        if ( isset( $settings['myStartDate']['date'] ) )
        {
            $settings['myStartDate'] = DateTime::createFromString( $settings['myStartDate']['date'] );
         // $settings['myStartDate'] = new DateTime( $settings['myStartDate']['date'] );

            error_log($settings['myStartDate']);
        }

        if ( isset( $settings['myEndDate']['date'] ) )
        {
            $settings['myEndDate'] = new DateTime( $settings['myEndDate']['date'] );
        }

        return craft()->templates->render( 'plugin/_settings', array(
                    'settings' => $settings,
                ) );
    }

EDIT/SOLUTION

@carlcs and @Mats Mikkel Rummelhoff for their help.
For anyone coming to this post, here is what my "final" main plugin class file looks like hope it helps.

MyPlugin.php

....
public function defineSettings() {
    return array(
        'myOpenings' => array(AttributeType::Number, 'required'=>true),
        'myStartDate' => array(AttributeType::Mixed, 'required'=>true),
        'myEndDate' => array(AttributeType::Mixed, 'required'=>true)
    );
}

public function getSettingsHtml() {
    $settings = $this->getSettings();

    if(isset($settings['myStartDate']['date']))
    {
        $settings['myStartDate'] = DateTime::CreateFromString($settings['myStartDate']);
    }

    if(isset($settings['myEndDate']['date']))
    {
        $settings['myEndDate'] = DateTime::CreateFromString($settings['myEndDate']);
    }

    return craft()->templates->render('myplugin/_settings', array(
        'settings' => $settings
    ));
}

Update: Sorry dragonslovetacos, I just tested this and found out it doesn't work as expected. It probably is the right way to handle DateTime values when saved with attribute type DateTime.

You're probably not preparing the value for your template. Before saving your date to the database you convert it to a DateTime object and your system timezone gets calculated into the value. You now need to do the same thing before you render that value in your template.

Or maybe it's the other way round, and you're preparing the value for your template and save it unprepared.

Anyways, the helper function DateTime::createFromString() should be applied to your value in both, prepSettings() and getSettingsHtml().


Create Plugin to generate PDF files from content Rather than render content out as HTML, I need to create PDFs for a project I'm working on. I was planning on using TCPDF in a custom plugin, but having played around with it a little, it does seem very limited it terms of the HTML/CSS you can throw at it.

Are there any better solutions out there? It can either be PHP based or maybe Javascript instead.

Just in case anyone was wondering, it looks like I'll be going with mPDF, it seems to have better HTML/CSS support than either TCPDF or domPDF (which Printmaker seems to be based on).


Can't access plugin variable in a twig template? So i've got this little plugin named AnnuaireAdherents with a variable that i try to access from within a template :

annuaireadherents/
├── AnnuaireAdherentsPlugin.php
├── services
│   ├── AnnuaireAdherents_Service.php
│   └── Proxy.php
├── twigextensions
│   └── AnnuaireAdherentsTwigExtension.php
└── variables
    └── AnnuaireAdherentsVariable.php

The variable should return a dynamic array, but let's try a static one first :

<?php namespace Craft;

/**
 * Variables provides access to list of adherents inside templates
 */
class AnnuaireAdherentsVariable {

    /**
     * Liste d'adhérents
     *
     * @return array
     */
    public function adherents() {
        return array(
            array(
                "raison_sociale" => "JOHN DOE & Co",
                "contact" => "JOHN DOE",
                "cp" => "99999",
                "address1" => "DESTINY STREET",
                "locality" => "NOWHERE",
                "mail" = "john.doe@nowhere.net"
            )
        );
    }
}

I've tried every namespace variants i could think of to access it inside a template :

{% for adh in craft.annuaireAdherents.adherents %}
    {{ adh.raison_sociale }}
{% endfor %}

but i keep receiving the error :

  Method "annuaireAdherents" for object "Craft\CraftVariable" does not exist

Is it the correct namespace ?
Do i have to relaunch Apache and Craft between each code modification to retest my variable ?
Could there be another error that is masking me the true cause of this message ?

Thanks a lot for any clue /  direction to investigate.

Reinstalling the plugin after a database update just solved the problem : the database i sync'ed with didn't have the plugin installed (as it is still in development)

Sorry for that one... :)


What's the best way to create public profile and content forms? It's great to have Craft CMS on SE at last!

We're working on a Craft site that'll allow public visitors to register, maintain a profile, and create entries in an Events channel.

Should we create individual user templates (signup, profile, content), or is there a more automatic way to do this with Craft?

For example, some of our profile fields are dropdown menus, but they don't seem to render as form dropdowns without us manually recoding them to do so. Is this correct?

Look forward to some great answers!

User registration works just like front-end entry editing. You build the form on any page you like, and submit it to the action "users/saveUser".

All fields need to be coded by you, and extra profile fields can be filled in by setting the input name to "fields[handle]".

The Craft Documentation has an example registration form. The also have an example for allowing users to update their profile.


Need clarification on the need for a Single section being created I created a single called recList and the corresponding Entry Template is /rec/list.html

I created an entry and I can view the webpage as you would expect.

Question: If I disable the entry or even delete the recList entry it seems to have no effect on the corresponding entry template, meaning that everything still works fine.  So, can someone explain the necessity of defining the single template pages in the admin site and what we are missing when we delete single sections?

Thanks!

Chip

There are probably other points that can be added to this, but here are a few...

If you deleted the Single, and there was no change when the template is viewed, then you probably didn't need the Single. Were there any fields assigned to the Single, and were those fields referenced in the template? If the answer is "no", then the Single was definitely extraneous.
You can make a template hidden by prefixing the template name with an underscore: /rec/_list.html. This makes the template invisible on the front-end, unless it's being called up through a Single/Channel/Structure. Without the underscore, any template can be viewed directly. (Worth noting that the underscore can also be applied to the folder name, hiding all templates inside that folder.)

In summary, the value of a Single is to be able to manage your content via the Control Panel. Whatever dynamic data is stored in your Single will be pulled into your template. If you have no dynamic data, then the Single is unnecessary.


Why does getting a single block in NEO prevent getting the remainder of the blocks? I have blocks set up for nutritional values: Calories, Total Fat, Carbohydrates, etc. These are set up in NEO blocks.
I can successfully loop through all of the NEO blocks (about 20 rows total) and output the content using this for loop:
{% for block in entry.nutritionBuilder.level(1).all() %}
    ...
{% endfor %}

Later, I added a line ABOVE this loop to retrieve the content of a single block:
{% set item = entry.nutritionBuilder.type('blockCalories').one() %}
{{ item.nutritionValue }}

This works, in that it will output the value I need to retrieve. However, the for loop below this line now only outputs a single row from nutritionBuilder which is blockCalories row.
Can anyone see why this is happening?

This is because of a change in Craft 3 and you need to clone your query (docs).
I have not tested this but the below should work:
{% set blocks = entry.nutritionBuilder %}

{% set item = clone(blocks).type('blockCalories').one() %}
{{ item.nutritionValue }}

{% for block in clone(blocks).level(1).all() %}
    ...
{% endfor %}


Can't access control panel I moved my website from local to an online test server via git.

Everything works fine, except that I can

That error is not really related to Craft, but to your test server's environment.

Your php.ini file is trying to load an opcache.so module, but it can't find that module on the server's file system.

Once you correct that, this particular error will go away.


For loop, if statement, then limit I've created two global variables which my content creator is going to use to turn off a bunch of articles and turn on a bunch more which a slight change in the Global.  I have a page where there is a limit of 5 of these articles.

{% set entries = craft.entries.section('news').order('articleOrder desc').limit(5).find() %}

{% for entry in entries if entry.currentYear2 == currentEdition.currentYear2 and currentEdition.currentMonth2 in entry.currentMonth2 %}
    <h2>{{ entry.title }}</h2>
{% endfor %}

The problem with this is that the conditional only gets 5 entries to compare, and not the entire bunch. I want to first run an if statement on all the entries, then let me do a for loop with a .limit(5). I am not sure how to go about this. A conditional combined with a for loop in the same statement did not work either.

Entirely possible I'm misunderstanding what you're looking for, but I think something like this should do it:

{% set entries = craft.entries.section('news').order('articleOrder desc').find() %}
{% set matchCount = 0 %}

{% for entry in entries %}
    {% if entry.currentYear2 == currentEdition.currentYear2 and currentEdition.currentMonth2 in entry.currentMonth2 and matchCount <= 5 %}
        {% set matchCount = matchCount + 1 %}
        <h2>{{ entry.title }}</h2>
    {% endif %}
{% endfor %}


Show content if logged in user is in userGroup1 OR userGroup2? This is so simple in ExpressionEngine and yet I've tried everything for several hours and can't find a way to get it working in Craft???

I have 2 User Groups: userGroup1, userGroup2

If the currently logged-in User belongs to either of those groups, show them "==SECRET CONTENT==" that guests (not logged-in users) do not see.

The following IF will only show "==SECRET CONTENT==" to userGroup1:

{% if currentUser and currentUser.isInGroup('userGroup1') %}
    ==SECRET CONTENT==
{% endif #}

Now, based on everything I've found and read, it would seem the following SHOULD show ==SECRET CONTENT== to Users belonging to EITHER userGroup1 OR userGroup2:

{% if currentUser and currentUser.isInGroup('userGroup1','userGroup2') %}
    ==SECRET CONTENT==
{% endif #}

But it only shows ==SECRET CONTENT== to userGroup1. And if I switch the isInGroup values to the following, only userGroup2 see the ==SECRET CONTENT==

{% if currentUser and currentUser.isInGroup('userGroup2','userGroup1') %}
    ==SECRET CONTENT==
{% endif #}

I've tried Group IDs. I've tried every variation of formatting, array syntax, etc.
I've searched the docs and StackExchange dozens of times...

How can I display "==SECRET CONTENT==" to users belonging to userGroup1 OR userGroup2 ??

According to the docs, the userModel.isInGroup() method takes a "user group model, its handle, or ID" – in other words, it can only test for membership in a single group, not several.

What you want in this case is the or operator:

{% if currentUser and (currentUser.isInGroup('userGroup1') or currentUser.isInGroup('userGroup2')) %}
    {# secret content #}
{% endif %}