Trouble using events plugin I'm having trouble using the Pixel and Tonic's Events plugin. I actually have no clue where to start on how to get it to render events in a template. I'm currently trying to pass in:

{% for event in craft.events.events_calendars('calendarName') %}

Which is obviously wrong. Could anyone explain how I understand what methods and variables those methods take for custom Element types?

The events plugin by Pixel & Tonic is an example of how to use custom Elements if you're building your own plugin. I don't think it should be used in a production environment (but please correct me if I'm wrong).

If you want to use it, you should take a look at the only variable for this plugin.
This variable gives you the ability to get all events, filtered by your criteria. There's no way to get all calendars, only events:

{% for event in craft.events.events %}

{% endfor %}

One other plugin you could have a look at, is this one, still in private beta.


Plugin to maintain data integrity between related entries? I would like to develop a plugin to help better maintain data integrity between related records. Something like the following:

When deleting an entry, check whether the entry has "reverse related entries" (i.e. other entries that relate to this entry), and if so, interrupt the delete process and show a warning — something like: "This entry is currently being referenced by 'xyz' entry. Are you sure you want to delete this entry?". If the user selects 'cancel', then cancel the delete process. (Perhaps in a future version of craft this should even happen by default if the entries field is 'required' on the reverse related entry.)
Even better, would be an option to cascade delete "reverse-related" entries, with a message that said something like: "Are you sure you want to delete this entry and all related data?", which would then initiate a cascading delete process. Obviously you would want to specify which 'related entries' fields will initiate the cascade — perhaps a checkbox on the 'related entries' field settings that read "when deleting related entries, provide an option to also delete this entry".

From what I understand, as of a recent update, I believe we can now stop processes from within an event method (i.e. onBeforeDeleteEntry). So I can see how one might develop the first option fairly easily.

The second option is a bit more complicated, without also developing a 'custom related entries fieldtype'. Something that I would prefer to not do (to maintain future compatibility). Perhaps a separate panel that has a drop down to select from 'all related entries fields', those that should initiate a cascade, that can be used as a lookup table within the onBeforeDeleteEntry event?

I'm just curious if anyone has attempted anything like this? And/or if anyone can recommend a good approach.

I think you've pretty much nailed the options.

1) Seems completely doable and relatively easy as of Craft 2.3 just like you described.

2) Is more difficult. You could go a custom field type route where you have settings defined which define which entry fields the cascading entry deletions occur on.  You could also probably cram your own modal/dialog choices into that event to present to the user for specific cascading deletion options (which is what I think you're also describing).

It probably be a lot easier if you didn't need to be concerned about which fields it happened to and you could go scorched earth and just recursively delete all reverse related entries regardless of the field or depth.  But I doubt that's the desired behavior in most circumstances.

I'd also be curious to see what an example of the use-case for this would be. My limited imagination is having a hard time coming up with something.


Migrating custom routes from v2 to v3 I have a handful of custom routes configured on this project like

'action/(?P<custom_id>[a-zA-Z][0-9]{6})/(?P<slug>.*)' => 'action/_member',

If I'm reading the docs correctly, then those need to change to become

'action/<custom_id:[a-zA-Z][0-9]{6}>/<entrySlug:{slug}.*>' => [
        'template' => 'action/_member'
    ],

but that gives me a template not found error when I hit localhost/action/L100582/&session=115

If I simplify the rule to become

action/steven' => [ 'template' => 'action/_member' ]

and hit, localhost/action/steven the template loads just fine.

I can't wrap my little head around what I'm missing.

The {slug} token you’re using there is going to get replaced with Craft’s slug pattern:

(?:[\p{L}\p{N}\p{M}\.\_\-]+)

Since that’s not an optional pattern, the resulting regex isn’t going to match your example URL, which doesn’t have a slug after the custom_id.

I’d recommend you use two separate routes that both point to the same template:

'action/<custom_id:[a-zA-Z][0-9]{6}>' => ['template' => 'action/_member'],
'action/<custom_id:[a-zA-Z][0-9]{6}>/<entrySlug:{slug}>' => ['template' => 'action/_member'],

(And just in case it wasn’t intentional, worth pointing out that the slug is going to be called entrySlug as opposed to slug with that route, which is another change from your Craft 2 route. Use <slug:{slug}> if you didn’t mean to change the name.)


Using Symbolic Links for Very Large Image directories I'm converting an EE site to Craft. During the conversion we are establishing LOCAL > DEV > LIVE environments and using GitHub.

LOCAL = My local MAMP PRO setup.
DEV & LIVE = a single account at Arcustech.
    DEV = ~/www/dev_html/public
    LIVE = ~/www/public_html/public

The site currently has 354,000 images/thumbnail files in the /images directory. We'll eventually move images/assets to S3/Cloudfront, but for now/launch we're keeping them local.

Obviously I don't want to duplicate 354K images in the DEV directory, AND keep them sync'd, but want the DEV to correctly display images/assets for the client to see.

So I was thinking a /images symbolic link in DEV, pointing to /images in LIVE would maintain all the correct image/asset paths and display for the DEV site and Craft configs?

Does this make sense? Am I missing something or is there a better/easier/default way to do handle large numbers of images/assets across DEV & LIVE environments when they are on the same server/account?

Am I missing something or is there a better/easier/default way to do handle large numbers of images/assets across DEV & LIVE environments when they are on the same server/account?

Ideally you'd move them to a cloud-based solution (S3, etc.), but locally using a symlink is a perfectly fine option, too.  Just make sure that Apache is configured to follow symlinks.

Wither either the symlink or cloud-based solution, just remember if you've got dev and live using their own databases and you perform an Asset operation on one (upload a file, delete a file, rename, etc.), then the other database will be out of sync and you'd need to run the "Update Asset Indexes" tool to pick up the change.


How do I save a Matrix field with an asset block programmatically? I'm trying to submit an Entry programmatically from the front end.  Everything works flawlessly, except, the asset fields never save.  I've dug and dug through the Entries, Elements, and Content Services.  Through similar Controllers; the Element Model.  I can't find any errors, and no matter what I do, nothing seems to happen with Assets.  Any ideas?

This is a simplified version of my html form:

<form method="post" action="" accept-charset="utf-8" enctype="multipart/form-data">
    <input type="hidden" name="action" value="plugin/save/saveEntry">

    <input type="hidden" name="title" value="Woo hoo">
    <input type="hidden" name="authorId" value="1">
    <input type="hidden" name="sectionId" value="10">
    <input type="hidden" name="locale" value="en_us">

    <input type="hidden" name="fields[matrixField]" value="">
    <input type="hidden" name="fields[matrixField][new1][type]" value="imageBlock">

Upload Your Photo

    <input type="hidden" name="fields[matrixField][new1][fields][image]" value="">
    <input type="file" name="fields[matrixField][new1][fields][image][]" />

    <button>Submit</button>

</form>

And here's a simplified version of my Controller/Service (all jammed in the Controller for the convenience of sharing)

<?php
namespace Craft;

class Plugin_SaveController extends BaseController
{
    public function actionSaveEntry()
    {
        $this->requirePostRequest();

        // Fields
        $entry = new EntryModel();
        $entry->sectionId  = 10;
        $entry->typeId     = 11;
        $entry->locale     = 'en_us';
        $entry->postDate   = date('Y-m-d');
        $entry->authorId   = 1;

        // Tell our content model where to look for custom fields
        $entry->setContentFromPost('fields');

        // Content
        $entry->getContent()->title = "Fancy Title";

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

        $this->redirectToPostedUrl();

    }
}

This ended up being a Craft bug. We just released Craft 2.1 build 2562 with a fix.


Craft CSRF protection and Facebook Tab I have a Craft 3 installation and want to add a tab/app to Facebook like domain.com/facebook

Facebook sends a post request to the configured secure tab URL. Now when Craft's CSRF protection is enabled, Craft gives an error. If I disable CSRF protection the tab shows up in Facebook.

I don't want to disable CSRF - what could i do... plugin with a controller to render the template?

You can disable the token for a certain controller via

use Craft;
...
Yii::$app->controller->enableCsrfValidation = false;

or inside a Controller for a certain request

/**
 * @inheritdoc
 */
public function beforeAction($action)
{
    if ($action->id == 'my-method') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);
}

Take a look at $enableCsrfValidation property of yii\web\Controller.


Load a specific file/CSS only in a certain page I want to load a .css file only in a certain page.

What's the magic code I need?

You can register your file with Twig at the place you need it

{% do craft.app.getView().registerCssFile(alias('@assetUrl') ~ '/path/to/css') %}


Add entry with the select-entry-modal-field So I have a 'Single' that uses entries from different 'Structures'. I can choose one or more entries with the fieldtype. But often I want to select an entry that is not created yet .. so I have to go back create that entry and then select it ..

It would be so much easier if I could just say "create a new entry" right there

What I mean

Is there a plugin for that or anything ?

There isn't, as far as I'm aware of, but have a look at the Craft Plugin Library. If you write your own, you might have a look at the following to see an example of a modal that craft does use:

var modal = Craft.createElementSelectorModal('Entry');

Try typing that into your console on any page in the CP.

Categories use a different kind of model when double clicking a category item that actually saves data, so might have a look at that as well.

Also, the amcommand plugin provides a nice modal command palette with a command to create entries that also might be worth checking out.


Custom ASCII character mappings By default, if we use cyrillic in the names of entries, the slug is also created in сyrillic. This is not good. And here we need transliteration such as б → b, д → d, etc.
By the way, if we create for example a new section in сyrillic, the handle, Entry URI Format and Template is created almost correctly, the exception is the characters 'Ь' and 'Ъ' - they are replaced by a space.

Ok, in general.php add
'limitAutoSlugsToAscii' => true

to replace characters according to ASCII character mapping. Now slug in entries should be created correctly, but again a new problem with the characters 'Ь' and 'Ъ', they are not converted.

in general.php add
'customAsciiCharMappings' => [
    ' ' => ['ь', 'Ь', 'ъ', 'Ъ'],
],

and we get the same result as when creating a new section - space.
Tried this variant:
'customAsciiCharMappings' => [
    '' => ['ь', 'Ь', 'ъ', 'Ъ'],
],

does not work
In the correct convertation there should be no spaces or replacement, 'Ь' and 'Ъ' should be removed (Мальчик → malchik). How to remove these spaces?

Ignoring customAsciiCharMappings for the moment, Craft uses Stringy for this type of thing.

The have some special logic for German and Bulgarian character replacements and it looks like those particular characters will only get replaced if the locale of the site you're currently editing is bg: https://github.com/danielstjules/Stringy/blob/master/src/Stringy.php#L1874-L1877


Is it possible to make links open in a new tab by default? I have a website where by default I would like all external links to have the "open in a new tab" option to be selected by default. I'm wondering if this is possible either through craft or redactor? I came across this but think it may be overkill so I'm wondering if its possible without a plugin.

Merits of doing this aside, I agree that JS is probably the easiest way to go here.

This code adds target="_blank" to all external links.

// Make sure any offsite links (non js/mailtos) open in a new window
// from https://css-tricks.com/snippets/jquery/open-external-links-in-new-window/ - comment at end.
function openAllExternalLinksInANewWindow() {
    $(document).on('mousedown', 'a:not([href*="mailto:"],[href*="javascript"])', function(e) {
        var isInternalLink = new RegExp('/' + window.location.host + '/');
        if (!isInternalLink.test(this.href)) {
            $(this).attr('target', '_blank');
        }
    });
}


Routing: How can I ignore a parameter in route definition? I'm trying to route users to a "locations" structure entry that normally has a URL structure that looks like: locations/<slug>

My client wants to use the structure of links from their old site to preserve SEO and wants to have the URL structure of: locations/<state>/<slug> where state is a 2 letter string. So, I'm trying to set up a route rule that just ignores the  parameter and redirects to the regular route.

In routes.php I have the following rule:

'locations/<state:[a-z]{2}>/<slug:{slug}>' => 'locations/<slug>'

But when I try to hit a route (for example locations/ca/slug-name) I get an InvalidRouteException and an error message saying:

Unable to resolve the request "locations/slug-name"

So it looks like it's stripping out the state parameter successfully but I'm not sure why locations/slug-name isn't recognized as a valid route.

Is there something I'm missing? Is there an easier way to do this?

It sounds like you might be trying to blend Craft/Yii routing with Rewrites (if you're coming from an Apache background).

I believe what Craft interprets this as is an attempt to map a request to locations/or/my-entry-slug to the <slug> (literal) action of the locations controller (which doesn't exist).

If you just want to render a template for these entries, you can set up your route like this:

'locations/<state:[a-z]{2}>/<slug:{slug}>' => ['template' => 'locations/entry']

This way, you'll get a state and slug variable in the templates/locations/entry.twig template, with which you can look up the Locations Entry you want.

To troubleshoot further, we might need a bit more information about how your Locations Section is set up, and the goals for the route!

  If you're just looking to capture and redirect legacy URLs, be sure and check out the Retour plugin.

  Additionally (and for anyone who finds this in the future), I'd recommend reviewing the advanced routing docs.


Logging out users - logoutPath & logoutUrl In the general config settings, one can set a logoutPath, and one can use it using the logoutUrl Global.

However, it says also in the docs: Note that Craft will automatically redirect users to your homepage after going here; there’s no such thing as a “logout page”.

In short; is there any other way to log a user out, besides "triggering" a visit to the predefined logoutPath, which logs users out, but immediately redirects them to the homepage; as it would be more elegant and userfriendly to show some kind of "you've been logged out" message instead first.

Might be going overboard, but you could have a plugin with it's own controller that provided different logout behavior.

But it sounds like to me what you're looking for is something like a 'logoutRedirect' config setting.  Probably worth adding to the feedback site!


Flip PDF embed inside templates I have some 'Flip PDF' generated folders that I need only logged in users to be able to access. If I put them in templates I get the problem that the .jpg images 500. Is there a way of allowing .jpg images to be served from within the templates folder? This isn't as simple as using an 'internal assets' plugin and adding them manually as all of the flip pdf JS is created automatically and I don't want to have to edit it every time a new one needs to be uploaded.

I've searched high and low for the answer to this over the last few weeks as well as asking on slack but I've had no luck.

Edit: maybe there's a .htaccess file I can add in the template sub directory that will prevent images being loaded in the normal 'craft' way?

The folder structure looks like this:

craft
templates
    emag
        july-2018
            files
                mobile
                    *.jpg
                mobile-ext
                    *.jpg
                thumb
                    *.jpg
                    etc.
            mag
                javascript
                    *.js (loads fine)
                index.html <--- the 'magazine' that needs the jpg's

The contents inside 'july-2018' is what the software gives me. All works fine, except for the .jpg images.

You'll need to create custom route to access those files. This is just an example of a custom route in my current module, so you need to find a pattern that matches the one you receive from the tool

$event->rules[] = [
    'pattern' => '/userfiles/<fileType:\w+>/<fileName:\S+>',
    'route'   => 'thaff/profile/get-file'
];

And your Controller action could be something like this

public function actionGetFile($view, $fileName)
{
    // create an alias to your folderpath $view should be thumb/mobile-ext or mobile depending on the route
    $localPath = Craft::getAlias('@yourFolderAlias') . DIRECTORY_SEPARATOR . $view;

    // you can include several checks if the image should be visible for the current user or not...

    $resp = Craft::$app->getResponse();
    $resp->headers->set('Content-Type' /*, insert your mime-type here */);
    $resp->format = Response::FORMAT_RAW;
    // check if the file exists
    if ($localPath && file_exists($localPath . $fileName)) {
        // open the file
        $handle = fopen($localPath . $fileName, 'rb');
        // send the result to your response object
        $resp->stream = $handle;
        // send the response and close the file
        $resp->send();
        @fclose($handle);
    }
}

Note: this is just a little code snipped of my current project and I removed many conditional checks so it's easier to read.


How should we be setting up product categories/sub-categories? New to Craft CMS and currently don't understand the terminology or how things work together in the platform yet.

If I want to set up a category structure like the below in Commerce, how is the best way to achieve this in the backend?

Pets
+++ Cats
+++ Dogs
Fashion
+++ Clothing
+++ Jewellery
+++ Sports

Also using the 'Events' plugin too which has ticket types - should these be used for categories?

There's a lot of different ways to set up your store structure but categories in Craft are like folders you put stuff in. Entries/products are what goes into those categories.

Category Groups

The most basic way to set it up would be to create a new category group inside Craft and then start creating categories.  Category groups are like the filing cabinets you use to put the folders in.

You can make as many category groups as you need and they'll show up separately in the sidebar. If you only have a few categories you can usually get away with one category group but it can also depend on how you want users to search and filter on your store.

Sub Categories

Categories can also contain subcategories. To put Dogs underneath your Pets sub-category grouping, just drag it underneath after it's created). It'll start looking like the hierarchy you want in no time.

To get the categories relating back to products, you'll want to create a new category field that you'll use on the product (or variant). That will allow you to relate products back to categories and be able to search on them.

Product Types

Depending on how your store is setup, you may want to create different product types as well.

Like Category Groups, Product types are one of my favorite features in Commerce and can be very useful if your store sells different types of products that need different sets of fields/options for each. It's especially handy if your ordering process is going to be different for each product type.

It's also useful especially if you sell thousands of products; seeing pet stuff and fashion stuff in the same part of the control panel area can get confusing quickly.

In your case, I'd probably create another product type just for events since it's going to be very different than the physical products you sell.

Hope that gets the ball rolling...


Returning specific fields with elementCriteriaModel I'm writing a plugin that adds or updates users profiles in Craft from a JSON file. Every user profile could have a lot of custom fields in the future which store a lot of data.
To check if a user exist and if its data is up to date with the data in the JSON file, I need to retrieve 2 fields from every user profile. Is that possible with the elementCriteriaModel?

I've seen examples of the criteriaModel by which you filter which users are returned by adding parameters. And then you get an array back filled with users that match the criteria and all of their custom fields.

But I need all users returned, but not with all their custom fields. Because I think that will slow things down.
Is it possible to fetch all users but returning only 2 specific fields by using the criteria model? Or some other way?
I know I can filter the results afterwards and return another array, but then the slow database query is allready been made. I want to limit the amount of queries made and the amount of data retrieved to the bare necessities.

Not 100% certain, but I suspect that with a standard ElementCriteriaModel it's all or nothing, as craft generally returns the full userModel including all custom fields. If you're worried about memory limitations, then you might want to either process the users in batches and/or create your own custom query. Something like this perhaps:

// define query
$criteria = craft()->elements->getCriteria(ElementType::User);

$query = craft()->elements->buildElementsQuery($criteria);
$query->select(array('elements.id AS id', 'field_extid AS extid', 'field_lastupdatetime AS lastupdatetime'));
$query->limit(null);
$results = $query->queryAll();

foreach($results as $result)
{
    // compare craft values to json

    // var_dump($result['extid']) // uncomment to test
    // var_dump($result['lastupdatetime']) // uncomment to test
    // set $userExists equal to true or false if needed

    // create/retrieve user
    if ($userExists) {
        $user = craft()->users->getUserById($result['id']);
    } else {
        $user = new UserModel();
    }

    // update, save, etc
    // ...
}

You can also use var_dump($results) to test whether you are getting the expected results.


Error updating programmatically a plugin's setting I want to update programatically a plugin's setting:

public function init()
{
     craft()->on('commerce_orders.onBeforeOrderComplete', function($event){
        // Set InvoiceNumber
        $newInvoiceNumber = $this->getSettings()->currentInvoiceNumber + 1;
        $myPlugin = craft()->plugins->getPlugin( 'Ultraschall' );
        craft()->plugins->savePluginSettings( $myPlugin,
                                              array('currentInvoiceNumber', $newInvoiceNumber ));
    });
}

But I get this error:

PHP warning
array_key_exists() expects parameter 2 to be array, null given
/mnt/web209/c2/98/5363898/htdocs/dev.ultraschall-leinwand.de/craft/app/models/BaseModel.php(418)

417  // Is this the first time this extra attribute has been set?
418  else if (!array_key_exists($name, $this->_extraAttributeNames))
419  {
420     $this->_extraAttributeNames[] = $name;
421  }
422
423  $this->_attributes[$name] = $value;
424  return true;

I have added defineSettings() and getSettingsHtml() to the Plugin and can change values via CP without problems.

Why do I get this error?

I made a simple mistake by defining the array with the setting value.
I wrote array('currentInvoiceNumber', $newInvoiceNumber) instead of array('currentInvoiceNumber' => $newInvoiceNumber).


Anonymous saveEntry? I'm needing to allow users who aren't logged in to post new entries, but of course it always redirects to login. Any way I can allow saveEntry to be anonymous, preferably for a single entry type?

saveEntry will always require an authenticated user with the correct permissions to post the entry, but you can use the guest entries plugin from Pixel & Tonic to allow for guest submissions :)

https://github.com/pixelandtonic/GuestEntries


Search, by just one user field - fullName? I'm successfully listing user (authors) via search from the url, so

/author/Tom+Bowler lists data and entries by that name with

{% set getauth = craft.request.lastSegment %}
{% for authordetails in craft.users.search(getauth) %}

but we want to limit that search to 'fullName' (or what is best) ideally, as currently we are listing any authors not just the one that may mention "Tom Bowler" in their bio.

At what point, and how is best to filter down to that search?

There's a nice list in the Craft docs with lot of examples for supported search syntaxes. Here's two that probably do what you are after:

  body:salty → where the ‘body’ field contains “salty”.
  body::"salty dog" → where the ‘body’ field is set to “salty dog” and nothing more.

Combine it with your variable like so:

craft.users.search('fullName::"' ~ getauth ~ '"')


Using prefetch or prerender I'd like to use prefetching (All) or prerendering (Chrome only) to speed up my website performance. It pre-loads websites to instantly load them when navigating to them. Google does it for its #1 Searchresults.

<link rel="prerender" href="{{ url('mysubpage') }}">
<link rel="prefetch" href="{{ url('mysubpage') }}">

(css-tricks.com/prefetching-preloading-prebrowsing/)

The browser is initializing a prefetch as I can see in my DevTools, but when visiting the page, there is still another normal page load happening instead of using the cached version. I wonder if this is because Craft CMS is returning the HTTP Header

Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0

on every response? Does this prevent the prefetching? Does it make sense to disable this headers? I didn't found any mention on cache headers being a problem when using <link rel="prefetch">

Thanks for some insights.

Robert

Per Brad's answer, PHP is setting the cache control headers on the start of a new user session.

If you want to override this, Craft provides the {% header %} tag where you can set your own headers. Whether or not that affects Chrome, I couldn't say.

One other thing to note is cookies. This page mentions "prerendered or prefetched [pages] may set and read their own cookies as if you had visited them before -- even if you don’t visit the prerendered or prefetched pages after all" which seems to imply it'll use the current page's headers for prefetch requests.

If you do any cookie-based server-side tracking or analytics with Craft, that could wreck a little havoc. (Say your funnel is "load XXX page and then load the contact page." You'd be wondering why people visited the contact page but never filled it out.)

If you use prerender, it looks like Chrome will actually execute any javascript on the page as well, which would also defeat any JS based analytics packages.) Scary.

(For what it's worth, I haven't tested any of these techniques at all but it would be interesting to see what kind of mainstream traction they receive. I can see for a web app it might be more useful.)


Populate or change the selection options in one field based on selected option in another field in the CP I'm looking to change a select fields options with the onChange event from another select fields chosen option. Obviously this can be done with js on the frontend as per this post but has anyone done this for the control panel? I imagine it will need to be done via a fieldType plugin, but wondered if anything already exists for this type of functionality before I attempt to build something.

I would write a custom fieldtype (http://buildwithcraft.com/docs/plugins/field-types) with two selects. Makes sense to make it as one field if they are dependent of eachother.

Just store the field as json (AttributeType::Mixed) and inject your own javascript in the fields getFieldHtml()


Omitting repeated content in a for loop I'm trying to use this slightly differently:
How do I omit similar content in a for loop based on the first letter in title?

I have a for loop with several entries. One field is a drop-down with a bunch of vendors listed, and the user can select only one. I want a list of vendors that have been selected in the entries so that somebody can click on the vendor and see only the entries associated with that vendors. Clear as mud?

If no vendor is in any entries, then it should not be on the list.

{% set vendorArray = [] %}

{% for entry in craft.entries.section('orderBook').order('vendor').all() %}
  {% if entry.vendor not in vendorArray %}
    {% set vendorArray = vendorArray|merge([entry.vendor]) %}
  {% endif %}
{% endfor %}

{% for link in vendorArray %}
  {{ link }}
{% endfor %}

The above link shows this working with only using the first letter of a field. I  want to use the entire field. I removed the filter |first and then I start to get duplicate vendors. I think the solution has something to do with the operator "not in", but I'm a noob so not too sure.

Currently you are trying to compare objects with each other and of course they are always different since they have a different reference. entry.vendor is not a single selected value but the field with all it's options and possible values.

Please try

{% for entry in craft.entries.section('orderBook').order('vendor').all() %}
    {% if entry.vendor.value not in vendorArray %}
        {% set vendorArray = vendorArray|merge([entry.vendor.value]) %}
    {% endif %}
{% endfor %}


Database migrations on environments - in which env do I apply updates to Craft and Plugins? When developing a Craft 3 site on a multi-environment setup, where would I apply the Craft and Plugin updates?

Should I apply them locally and then commit and replace the database in the dev env, or in dev env and then pull down the database?

Or does Craft have some versioning of the database through db migrations that will help this issue? (Is this where project.yaml comes into play?)

You have options, but most people probably do the following...

Apply the updates locally.
Push those changes to the server.
Have Craft run any necessary migrations.

My deployment process ends with the following command being executed on the server:

composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev

And in my composer.json file, it runs this:

  "scripts": {
    "post-install-cmd": [
      "./craft migrate/all"
    ],
    "post-update-cmd": [
      "./craft migrate/all"
    ]
  }

Between those two commands, it ensures that (A) all of the plugins and libraries specified in my composer file are identical on the production server, and (B) any necessary migrations are run after that.


When to set Model properties I was just wondering when it's recommended to set the attributes on a custom model? Would it be ok to set them within the model's constructor or not? I guess it depends on when defineAttributes() is called, right?

Depending on how your plugin is setup, you should likely be setting model attributes in your Services. Create a new Model object, set its attributes, then pass that Model to the proper Record and save it.

Of course, this all varies based on what you're doing with it. If you provide more information, I'll see if I can lend a hand.


How can I only get the entries that are related to an active category In the product overviews and search results on my website are also products listed which are related to passive categories.
Is there a way to get only entries which are related to active categories?

The product with this category status should not be displayed at the website

You would first query for all active categories and then get the Product entries that are related to these categories.

{% set allCategories = craft.categories.group('Categorie') %}
{% set entriesWithActiveCategories = craft.entries.section('Products').relatedTo(allCategories) %}


How does Craft know when to generate an Image Transform I created an image transform called teamImage. My template code is below.

I want this transform to be created when I upload an image within a Team entry.

Team has it's own asset folder.

My questions is how does craft know when to create this transform and where in the directory does it create it?

{% for asset in entry.teamImage %}

{% endfor %}

Craft will make the image transform the first time the template is loaded in the browser and the getUrl() is called. The image will at first be saved in a temporary directory, then moved into a sub-directory in your assets folder. The subdirectory will be descriptively named according to the type of transform. For example, if my template calls for a 500 x 500 center-center crop at 75% quality, it will be saved in /uploads/_500x500_crop_center-center_75/img.jpg.

This works similarly when using a CDN like S3 or Google Cloud.


The Variable {{ siteUrl }} Produces Two /es/es/ On Multisite I'm getting example.com/es/es for my Spanish site instead of the expected example.com/es when using the {{ siteUrl }} variable.

The primary site is producing the expected example.com/

Any idea of how I did that incorrectly?

I figured out what was wrong, though I'm confused on why some of it was working fine... Maybe if it broke more fully I would have found it easier, haha. Mats was right, it was the Base URL in the Sites area of the admin control panel. I had entered @web/es thinking that I want it to be the root of the primary site, but that wasn't correct, I needed to just put @web/ because I already told it that it lived at /es through the index.php of that site folder.


Charset issue in Control Panel I'm trying to install Craft v3 on a web server currently running Craft 2. As far as I am aware all the required PHP extensions (including iconv) are installed; PHP v7.1.x

The front end works OK, but as soon as I go to the control panel I get this (devmode=true)

> PHP Notice – yii\base\ErrorException iconv(): Wrong charset,
> conversion from `UTF-8' to `UTF-16BE' is not allowed

I should note that my method of installation involves getting the site working on a local machine and then copying everything over, and editing the .ENV and general.php accordingly. There is no added content or plugins installed - just an empty Craft install (latest version).

As far as I can see the database charset is set up correctly (UTF8).

What else should I be looking at?

UPDATE: digging around further, if I run a PHP test file,  this line

> $res=iconv('utf-8', 'UTF-16BE', 'test1');

throws the same error message. So I am guessing it is a server problem.

I'm going to attempt to answer my own question now that I have had the issue resolved. Clearly this is a local server environmental issue. The explanation I have received from the hosting provider is not one I understand too well, but here it is for the record.

  For security reasons, the PHP FPM process on your server executes
  scripts in a separate chroot(2) environment, meaning that only a
  limited set of resources are available at runtime.  This sometimes
  causes problems when the chrooted program requires resources that
  don't exist outside the chroot environment that are loaded during
  runtime rather than being built in to the binary, or dynamically
  linked before the system chroot call.  The iconv extension has this
  problem, in loading .so binary data files corresponding to the
  encodings it's manipulating.  On your server, the files it loads were
  in /usr/lib/x86_64-linux-gnu/gconv, and had not been copied into the
  chroot environment at /srv/php-fpm/rdc.  Copying the contents of
  /usr/lib/x86_64-linux-gnu/gconv to
  /srv/php-fpm/rdc/usr/lib/x86_64-linux-gnu/gconv has fixed the issue.


Commerce Manage Settings for User Groups When setting User Group permissions for users for Craft Commerce, there are explicit options for:

Manage Orders
Manage Products
Manage Promotions

But nothing is listed for Manage Settings. Is this not controllable for User Groups? Seems like it definitely should be... some users would be allowed to manage product info but not Settings, while some users would need access to Settings for updating Tax or Shipping options.

This is currently not a native Commerce feature, but feel free to add a thumbs-up/comment to this feature request, which is what you're asking for: https://github.com/craftcms/cms/issues/1082


How long to wait until license modal stops appearing? I recently setup a pre-production environment of my fully purchased Craft site license, but Craft license management didn't think the sub-domain I was using was "dev-sounding" enough. Now that I've rectified that problem by creating a sub-domain included on CraftCMS's official list and destroying the previous one, how long will I have to wait before my production instance stops complaining about needing a payment for trial licenses?

Your production website shouldn't have been complaining about a different website using the same license key, as long as the license key is bound to the production websites domain name...
To get rid of the error, you can clear your Data caches. You can do this by navigating to Utilities > Caches in your Control Panel, and there you can unselect all but Data caches. Once you clicked Clear Caches, you reload the page and the message(s) will be gone.


If page is enabled, show div I'd like to show a 'Jobs' link in my navigation only if the Jobs page is enabled. Is there a way for craft to detect if the page is enabled, and show a div?

You can check the status of an entry with .status. https://craftcms.com/docs/templating/craft.entries#status

This code should work!

{% set jobsEntry = craft.entries.id(jobsId) %}

{% if jobsEntry.status == 'live' %}
    Jobs
{% else  %}
    Jobs is disabled
{% endif %}


Craft 3 updates & plugins without allow_url_fopen or SSH I have set up a Craft 3 site on shared hosting. When I try to update Craft or install plugins via the CP, I get the following error:

  The "https://composer.craftcms.com/packages.json" file could not be
  downloaded: allow_url_fopen must be enabled in php.ini

allow_url_fopen cannot be enabled on this hosting & there is no SSH access

What are my options for updating Craft & installing/updating plugins in this scenario?

Is the only option to avoid CMS access temporarily, copy down the live database, do any updating locally and then upload the file changes & update the live database?

Thanks

Is the only option to avoid CMS access temporarily, copy down the live database, do any updating locally and then upload the file changes & update the live database?

Pretty much.  You'll want to lock the version of PHP in your composer.json file to whatever your production PHP version is so you don't pull in dependencies locally running a higher version of PHP that you deploy live.  You can do that like so:  https://github.com/pixelandtonic/craftnet/blob/develop/composer.json#L46-L50

Note that allow_url_fopen is a Composer requirement... there are several issues in their repo of people running into this: https://github.com/composer/composer/issues?utf8=%E2%9C%93&q=is%3Aissue+allow_url_fopen


Twig Templates : Include dynamic data when using set I'm trying to use the Encode Email plugin to encode email addresses.

The email addresses are dynamic so I need to include the output from the database when I'm using set.

This is their example that doesn't use dynamic info:

{% set email = "Your Name" %}
{{ email | rot13 }}

And this is what I've tried that doesn't work.

{% set email = "{{ contactInfo.contactEmail }}" %}
{{ email | rot13 }}

Is there a way to include the dynamic variables into the set statement?

The main thing to remember about Twig... You never need to nest tags within other tags. So putting {{ }} within {% %} is never going to work.

To concatenate a string in Twig, use the ~ character...

{% set email = "" ~ contactInfo.contactEmail ~ "" %}


How to exclude entries by type? I did find this post while looking to do something similar, but I'm beginning to wonder if there's a bug.

With code along the lines of:

craft.entries.section("pages").type("not landing")

I'm unexpectedly getting no results. Looking at the logs, it's generating queries that includes:

SELECT * FROM `craft_entrytypes` `t` WHERE `t`.`handle`='not landing'

I have to think this is at least partly responsible for getting no results. Could anyone point out if I've got the syntax wrong or something?

.type("not landing") won't work. If you reread the post you linked it also states this — I believe it was more of a feature request. You will need to test each entry and either use it directly or merge it into an array for later use.

{% set entries = craft.entries.section("pages") %}
{% for entry in entries if entry.type != "landing" %}
    {{ entry.title }}
{% endfor %}

or

{% set filteredEntries = [] %}
{% set entries = craft.entries.section("pages") %}
{% for entry in entries if entry.type != "landing" %}
    {% set filteredEntries = filteredEntries|merge(entry) %}
{% endfor %}

As a side note, if you are using a structure with a hierarchy where landing pages are at the root level and all other entries are children, then you can also use:

{% set entries = craft.entries.section("pages").level('> 1') %}


Related to entries in categories in a plugin Ok I can do this in twig but after searching high and low I can't find a good example of how to do it in a plugin.

I have a user profile field called interests which holds an array of what they are interested in. I want to pull out all entries that are related to the category id's held in the interests array. So in twig I do this:

{% for interest in userinterests %}
    {% for entry in entries.relatedTo(craft.categories(interest)) %}

{{ entry.title }}

    {% endfor %}
{% endfor %}

In my plugin function I currently have this but it is not returning anything in the array so I'm currently stuck:

$userinterests = craft()->users->getUserById($userid)->getContent()->getAttributes();
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->relatedTo = array(
    'sourceElement' => $categories
);
$relatedEntries = craft()->elements->findElements($criteria);

I'm not sure what I am supposed to be adding to the relatedTo array but it also could be something else as I'm still trying to get my head around craft.

Any help much appreciated.

Ok worked this one out eventually myself. If anyone else finds this helpful.

$userinterests = craft()->users->getUserById($userid)->getContent()->getAttributes();
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->relatedTo = array(
        'targetElement' => $userinterests['relevantFieldToCheckAgainst'],
        'field' => 'EntryFieldToCheckIn'
);
$relatedEntries = craft()->elements->findElements($criteria);


SEOmatic plugin override global title in individual template I have problem whereby I can't override a single page's SEO by using a field, because the page has too many table rows in the database, due to being very field heavy. Don't ask.

So I'd like to manually override the global <title> that SEOmatic produces in the individual template page. But haven't been able to get it to work from the docs, as I'm just producing a second title tag.

Can someone help please?

Are you using the SEOMatic Meta fieldType?

What I do is create a field of this field type and assign it to the entry type you're dealing with. Within this field, there are all sorts of values you can override. For instance, you can point the SEO title field to one of your other fields via a dropdown, or you can manually type in a new SEO title just for this particular entry.


Is it possible to restrict access to an asset to logged in users? i.e. is there a type of loginRequired functionality for assets?

Or even better - can I restrict access to a single group, or a require a certain permission?

In the "permissions" tab for users/groups I can only give access to uploading/deleting assets.

There is two similar plugins that look's like it might do the job (I have tested neither).

Internal Assets
MemberAssets


Force specific language for user activation mail and edit localized email templates I'm trying to figure out how to set the default language for new users and user activation emails. I have found the defaultCPLanguage config setting which does indeed change the default language of new accounts created through the backend. However, the activation email doesn't use that default language. Based on testing I have determined that the account activation email will be sent in the language that the user creating the new account has set in their account preferences. So if I create a new user account with my admin account, which is set to English, the activation email will be in English as well. If I set my language preference to German, the activation mail will be in German.
Is there a way to change this? The CP doesn't provide a way to change the language preference of a new account. I would prefer it if the activation mail always used the language set as defaultCpLanguage.
As a sidenote, the templates for account emails are editable from Utilities -> System Messages. However, I can only edit those templates for my current language preference. To edit the messages in a different language, I have to set my account preference to that language first. This is weird and unintuitive. Is there a better way to edit System Messages across different languages? Or at least have the System Messages tab always display the messages in the defaultCpLanguage?

When using a frontend form to create a new user it is actually straight forward, because you can easily send a preferredLanguage attribute with the request that sets the language on creation (see this line in the user controller). However, if you want to use the CP form to create a user, there doesn't seem to be an out of the box solution for your problem. Here is what you could try:
There is a template hook in the user edit template. You could use this to inject an input that sets the preferred language. You could even show that input for new users only. In the simplest case it could look something like this:
<input type="text" name="preferredLanguage" value="de">

You surely would want to have a select or something with the available languages. To inject the markup into that template you would have to create a module or plugin and then follow the docs for template hooks.
PS: If you wonder where the user language is stored, it has an extra table called userpreferences storing stuff like this in JSON format.


Delete / change Status from CP via Ajax (trigger event) In a plugin init function I'm listening to entries.saveEntry and entries.deleteEntry. This works perfectly if I'm editing entries from their detail view. If I 'bulk' change or delete entries, these events are not fired. I saw in the SetStatusElementAction class an event called onSetStatus is triggered but how can I listen to it? The same goes with the delete action.

Somehow the following doesn't get triggered for me:

craft()->on('entries.setStatus', function($event){ dd($event); });

What am I missing here?

Unfortunately, this is a known bug in Craft. Bulk actions do not trigger their respective events.

I'm not sure when (if?) a solution will appear. I'm guessing that it won't be fixed in the 2.x branch, since this bug has existed for quite awhile now. With any luck, it'll be fixed when Craft 3 launches.


Matrix loop (nesting?) issue using switch First let me say this: I'm new to Craft and Twig. So: my apologies for probably overlooking the obvious. I hope you can offer me some help... I've been trying for a couple of days to solve this puzzle. Nothing seems to work. ;-S

I'm trying to create a simple events calendar using Craft 3, Twig and Bootstrap 4. The calendar exist of two parts: 1. a section with 3 columns (col-4) that lists the events; and 2. a divider (col-12) that contains the month and year. I used the Matrix field in Craft to be able to be flexible in sorting events within a certain period of time.

The Issue:
I expected to see the three columns to neatly sit beside each other horizontally (on the desktop version of the site). But this doesn't seem to work right now: because I use a for loop to enable switch, the for loop I need for outputting the event-items results in the same row of events being repeated a couple of times instead of just once.

What am I doing wrong?

I very much appreciate any thoughts.

Greetings from The Netherlands, sorry for my bad English,

Mars

{% block calendar %}

    {% for block in entry.calendarGroup.all() %}

        {% switch block.type %}

            {% case "events" %}

                    {% for entries in entry.calendarGroup.type('events') %}

{{ block.eventDate }}

{{ block.eventTitle }}

{{ block.eventType }}

{{ block.eventTime }}

{{ block.eventLocation }}

{{ block.eventDescription }}

                    {% endfor %}

            {% case "months" %}

{{ block.month }}

{{ block.year }}

            {% endswitch %}
        {% endfor %}

{% endblock %}

I'm not entirely clear what your Matrix blocks/fields are setup like, so it's a little hard to tell what's going on here.

But I'm going to take a stab at it.

Your outer loop is looping through all the blocks in the calendarGroup Matrix field.

Then you're using a switch to determine which piece of code to execute based on which one of the two block types each block is.

All that looks ok.

But here is I think where your problem lies:

{% for entries in entry.calendarGroup.type('events') %}

{% endfor %}

This loop is starting fresh and looping over all the Matrix blocks in the calendarGroup Matrix field, except this time it's only getting the blocks of the event block type.

Then, inside that loop you are using the {{ block.fieldName }} variables again. But block is set in your parent loop. And nowhere are you referencing entries from your inner loop.

So there is a mismatch in your logic. I think you can simply do away with the inner loop, it's it's going to out put all of the event blocks inside each event block in the outer loop.  That, to me, seems like the issue.


When to choose a Structure over a Channel? Structures look interesting because you can reorder entries manually, generate breadcrumbs and visually see a hierarchy of entries. Besides this, what are the primary consideration when choosing a Structure over a Channel?

Ordering and Hierarchy are the main benefits but they create a couple of side benefits such as the ability to

get the "children" and "parents" of an entry
get siblings including next and previous siblings

The best part is there no real downside, they have all the features and functions of a regular channel PLUS the structure.


How do I pass custom field contents from cart to order cart.billingAddress and cart.shippingAddress are both are set to the same address and include custom1 and custom2 fields.

After submitting the order, order.shippingAddress and order.billingAddress have all the correct address information from cart except custom1 and custom2 which are blank.

This is a slightly simplified version of my payment submission form. It's using the manual gateway, no money is taken and the order is set with a status "Payment Pending" and paid status "Unpaid". Invoices are paid elsewhere for now.

<form method="POST">

  {{ csrfInput() }}

  {{ redirectInput('/account/invoice?number='~cart.number) }}
  <input type="hidden" name="action" value="commerce/payments/pay"/>
  <input type="hidden" name="gatewayId" value="2"/>
  <input type="hidden" name="savePaymentSource" value="0" />

  <button type="submit" class="button">Confirm order and generate invoice</button>

</form>

Why isn't the information in the fields custom1 and custom2 being set on the order addresses?

This was a bug in commerce and it has now been fixed.


What is the significance of craft.app.request.segments|last == _self While reading this blog article about RSS templating, I came across the following twig code

if craft.app.request.segments|last == _self

I understand that the above command, in general, yields URL components as an array. But I don't understand under what scenario is the above condition true. What does _self mean in this context?

In Twig 2, _self seems to reference the name of the current template file.

Running {{ dump(_self) }} from the file /templates/test/index.twig would return the string test/index.

So what it's being used for in this example...

{% if craft.app.request.segments|last == _self %}

... is to test wether the last segment in the URL matches the template file. Or "is this template being loaded directly from the file-based routing or is it being included from another template?"

I would point out tho, this only matches the last segment. It assumes your feed.rss file it in the root templates directory. A more flexible approach would be to math the entire URI path.

{% if craft.app.request.pathInfo == _self %}

Later _self is used to generate a link with {{ url(_self) }}. This is the same as {{ url('feed.rss') }} but would update if you changed the file name (e.g. news.rss).

The whole point of that conditional is to replace the {% include 'feed.rss' %} with a <link rel="alternate" type="application/rss+xml" href="{{ url('feed.rss') }}">. Which seems a little complicated. After all, it provoked this Stack Exchange question. ;)


How to get Structure parent title and ancestors on search results page I'm having trouble getting the Structure parent title on a search results page.

I followed these instructions but I'm getting a "Impossible to access an attribute ("title") on a null variable" error.

In the following code the all ancestors do print except the first level Structure title.

{% set query = craft.request.getParam('q') %}
{# {% set entries = craft.entries.search(query).order('score') %} #}
{% set entries = craft.entries.section().search(query).order('score') %}

  {% for entry in entries %}

  {{ entry.title }}
  {% set parent1 = entry.getAncestors().level(1) %}
  {% for item in parent1 %}
      / {{ item.title }}
    {% endfor %}
  {% set parent2 = entry.getAncestors().level(2) %}
  {% for item in parent2 %}
      / {{ item.title }}
    {% endfor %}
  {% set parent3 = entry.getAncestors().level(3) %}
  {% for item in parent3 %}
    / {{ item.title }}
  {% endfor %}

  {% endfor %}

Found the answer in getSection()

{{ entry.title }}

  {% set section = entry.getSection() %}
   {{ section }}
  {% set parent1 = entry.getAncestors() %}
   {% for item in parent1 %}
    / {{ item }}
   {% endear %}


Pass the rendered template HTML string to an external function I want to use all of the Craft features to render a page from template, but instead of serving it to the front-end visitors I want to send it to an external mail delivery service (something like MailChimp) using cURL.

I guess I need to get the rendered HTML into a string and then pass it to my cURL function. How can I achieve this, any tips?

You would need to build a plugin that fetches the HTML string and then passes it on to cURL or whatever you choose.

For a specific solution on how to get a template HTML string with all the parameters you need check out this answer


Charge 2 - Stripe form fields not showing I just had a fresh install of Charge 2 and my Craft version is Craft CMS 2.6.2989. However as long as I have {{craft.charge.setPaymentOptions()}} in my template, all my form fields disappear and show up again after I remove this line.

{% extends "_layout" %}
{% set title = "Bookings" | t %}

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

{% block content %}

            {% if entry.heading | length %}

{{ entry.heading }}

            {% endif %}

            {% if entry.featureImage | length %}

            {% endif %}

            {% if entry.introText | length %}

{{ entry.introText }}

            {% endif %}

            {% if entry.body | length %}
                {% include '_partials/_body' %}
            {% endif %}

{{ "Make a Payment" | t }}

                <form id="charge-form" method="post" data-publicKey="{{ craft.charge.publicKey }}">
                    {% set chargeOptions = {'planAmount' : 99} %}
                    {{craft.charge.setPaymentOptions(chargeOptions)}}
                    <input type="hidden" name="action" value="charge/charge"/>

                    Receipt Email
                    <input type="text" name="customerEmail" value="{{ currentUser ? currentUser.email }}" id="customerEmail"/>

                    Card Number
                    <input type="text" data-stripe="number" placeholder="•••• •••• •••• ••••" id="cardNumber"/>

                    Card Expiry
                    <input type="text" data-stripe="exp" placeholder="mm / yy" id="cardExpiry"/>

                    Card CVC
                    <input type="text" data-stripe="cvc" placeholder="123" id="cardCvc"/>
                </form>

    {% includeJsResource('charge/js/jquery.charge.js') %}
    {% includeJsResource('charge/js/stripe_v2.min.js') %}
    {% includejs %}
        $(this).charge();
    {% endincludejs %}
{% endblock %}

I can't see what's wrong with my setup...

After looking into the source code of the encrypt function, the craft.charge.setPaymentOptions() function calls mcrypt_module_get_algo_key_size and because my vagrant box (ubuntu 14.04) didn't have php5-mcrypt installed, it failed there.

To fix it: run apt-get install php5-mcrypt && sudo php5enmod mcrypt.


Determine if entry has a specific category I am using a supertable (or matrix) to create rows.
In each row, I have a Category Field. Multiple categories can be selected for each matrix row.
As I loop over each row, I want to determine if the category field in that row has a specific category selected.
Example:
Matrix Row1:
-> Colour (Category Field):
--> Red, Orange, Blue

Matrix Row2:
-> Colour (Category Field):
--> Red, Blue

In the above example, in Twig, when I render out the row, I want to know if that row should be "Orange" or not, based on whether or not the "Orange" category was selected in the "Colour" field.
I can loop through every selected category in the category field, and plaintext match against it (example below), but I wondered if there is a cleaner/simpler way to do this.
{% set colourFlag = false %}
{% for class in row.rowSettings.rowColour.all() %}
    {% set colourFlag = (class == "orange" ? true) %}
{% endfor %}
{{ colourFlag == true ? "yes-orange" : "no-orange"}}

Any advice would be grateful.

You could explicitly try to fetch orange and check whether you get a result or not:
{{ row.rowSettings.rowColour.slug('orange').one() ? 'orange is set' : 'orange is not set' }}


Is there a fieldtype in Craft like "Content Elements" or "Bloqs" for ExpressionEngine? I have been using EE for over 5 years now, and am just starting to get into Craft (and I love it!).  In my recent EE sites, I've used Content Elements, and it has been a great way to give my clients flexibility in adding content to pages and blog posts, etc.

Is there a similar fieldtype available for Craft? Or is there another simple method to accomplish the same thing?

Thanks!

You should check out the Matrix fieldtype.


Craft Commerce - Free Shipping Field So there is this field called «Free Shipping» for each product.

But I can't find anything about this in the docs. I found out that I trigger it with

  product.freeShipping

But when activated it has no effect on shipping costs whatsoever.

What's the idea behind this thing, and how do I activate it?
(I'm fiddling around in the standard templates)?

I thought about creating a Free Shipping Category and then activate it via conditional. Or what's the idea about this?

The free shipping flag on individual products stops costs being calculated by any shipping rule that is a per item rate or weight rate.

See https://craftcommerce.com/docs/product-model#freeshipping


Entries form in control panel won't display if I have a Matrix field enabled I'm new to Craft, and have a local installation of version 2.6.2789

I have created a section with its own field layout. Everytime I enable a matrix field in the field layout, the section entry form won't display anything.

Attached is the screenshot of the entry form itself.

Not sure what I'm doing wrong.

This usually happens if xdebug is installed with the default nesting limit. You can either disable xdebug as PHP itself does not have a function nesting limit,

change the setting in your php.ini:

xdebug.max_nesting_level = 400

or in your PHP code:

ini_set('xdebug.max_nesting_level', 400);


Getting entries from different structures and level I need to loop through the 6 latest entries from 3 different structures. The problem is, the entries are located on different levels. One of the structures has entries on level 3, and the other two has entries on level 1.

If you explicitly need only the entries at level 3, and those at level 1, I think combining two queries works best:

{# Get ids for all entries from the different structures and levels #}
{% set entriesAtLevelThree = craft.entries.section('level-3-section').level(3).limit(6).ids() %}
{% set entriesAtLevelOne = craft.entries.section(['level-1-section-1', 'level-1-section-2']).level(1).limit(6).ids() %}

{# Combine those IDs #}
{% set entryIdsCombined = entriesAtLevelThree | merge(entriesAtLevelOne) %}

{# Get all entries (so, no IDs this time), using your IDs #}
{% set allEntries = craft.entries.id(entryIdsCombined).limit(6).order('postDate DESC') %}

{% for entry in allEntries %}
    {# do your thing #}
{% endfor %}

You can, of course, cache this by wrapping it in {% cache %} tags.


Install Zoho CRM SDK (or any SDK for that matter) For a client I need to connect a rather complex contact form with the Zoho CRM. They're offering a PHP SDK which sounds great, but I can't get it to work. It's very likely that I'm just stupid, because I can't even include the SDK to just call the initial setup method.

The documentation says (under "Using the PHP SDK") to include the following line where needed:

require ‘vendor/autoload.php’

That doesn't seem to be needed, as it's already done in the main index.php by Craft itself.

I want to use the SDK within a service class I've created under modules/services. So within my class I tried the following:

require "../vendor/zohocrm/php-sdk/src/index.php";

That's getting the the index.php from the SDK but when I'm calling the method ZCRMRestClient::initialize() I just get the following error message:

  Class 'modules\services\ZCRMRestClient' not found

I'm probably missing some really basic stuff but I just don't know what else to do.

Assuming you've got Composer installed from the command line, you can navigate to your project's root (where your project's composer.json file lives), then run this from the command line:

composer require zohocrm/php-sdk

From there, Composer and Craft pretty much take care of everything, including setting up the autoloading and you can reference ZCRMRestClient::initialize(); from your module/service.


Plugin CKEditor outputs something with nothing? I have a problem with the CkEditor for Craft CMS.
If I leave the textfield empty and save it, the output in the browser will still contain <p>&nbsp;</p> when I want it to be blank. I am thinking about to filtering out with javascript, but I hope someone has a better idea about what to do.

This has been fixed in the master branch, but not yet tagged in a release: https://github.com/craftcms/ckeditor/pull/6

Until it's tagged, you won't be able to get that fix in from the Plugin Store, but you can pull it in with Composer in the command line if you want.

FWIW, it's currently a pretty minimal beta version of the plugin using an older dev preview version of CKEditor 5, so I wouldn't rely on it too heavily until it gets updated.


.htaccess max_execution_time I want to change the max_execution_time in the .htaccess file. I tried it in this way: <IfModule mod_php5.c> php_value max_execution_time 300 </IfModule> but then I got a 500 internal server error.
My .htaccess file also includes this:

<IfModule mod_rewrite.c>
    RewriteEngine On

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

Any idea why I got this error? Or how I can change the max_execution_time in an other way?

(I sadly do not have the possibility to change the php.ini)

You can alter the index.php file and add [set_time_limit][1](300); anywhere below the <?php tag.

You can also try to set it by ini_set('max_execution_time', 300);

For the reason why it returns a 500 Internal Server Error, the server does not support the php_value and php_flag parameters through the htaccess file or it doesnt use the php5 module. You can try setting the php_value directly and check again for errors, or contact your hosting provider for support


Restricting access to fields based on user group I saw this thread Check user is in User Group / Custom User Permissions had an idea. Can I use USER group to limit who can see the Author dropdown on the entries form? Is this even permitted the craft license. I really need to remove that field from view of two user groups. Also would be nice to be able to limit which fields a user has access to when creating an entry.

You can use the Control Panel User Group plugin to automatically add special classes to the <body> tag in the CP.

Once those classes are in place, it's easy to use CSS or JavaScript to hide fields from certain user groups (or trigger other behavior based on user group status).

* Disclaimer: I'm the author of all of those plugins. :)


Populating an RSS feed with full post content? I'm using Matrix to give loads of flexibility with blog posts, but it means things aren't as simple when it comes to RSS than if just using a single field called Body.

How is everyone else dealing with this?

EDIT: As Christian points out, I'm party asking what is best practice for RSS feeds. But I'm also exploring the extra flexibility or complexibility offered by using Matrix for blog post content. Best practice is constantly evolving, and I think it quite possible best practice for creating an RSS feed using Craft may turn out to be different best practice to feeds generated by something else, simply because the flexibility is there (just as long-form content is becoming more commonplace as CMSs start to deal with it better). For example, using Matrix we can pick and choose which types of content are included within the feed to a much greater degree. Or do we just say, no, a feed should contain this, this and this and you shouldn't mess with that, no matter what the tool?

I would use a lead paragraph field that you could then call into the RSS feed. Or you could add a post summary field. You could then call that whenever you need to, RSS or otherwise.


Users relatedTo multiple categories Trying to get users in a members group related to multiple categories.

{% set services = craft.categories.group('services').slug('service-1, service-2') %}
{% set locations = craft.categories.group('locations').slug('location-1') %}

{% set members = craft.users.group("members").relatedTo("and", { targetElement: services }, { targetElement: locations } ) %}

{{ members | length }}

Number of members returned is zero.

Any ideas?

Try passing your relatedTo parameters as an array:

{% set members = craft.users.group('members').relatedTo([ 'and', { targetElement: services }, { targetElement: locations } ]) %}

or a little easier to read:

{% set entries = craft.users({
    group: 'members',
    relatedTo: [
        'and',
        { targetElement: services },
        { targetElement: locations }
    ]
}) %}

Edit:

If you want to get only those users that are related to both services, add another relation to your parameter array:

{% set service1 = craft.categories.group('services').slug('service-1') %}
{% set service2 = craft.categories.group('services').slug('service-2') %}
{% set locations = craft.categories.group('locations').slug('location-1') %}

{% set entries = craft.users({
    group: 'members',
    relatedTo: [
        'and',
        { targetElement: service1 },
        { targetElement: service2 },
        { targetElement: locations }
    ]
}) %}

Update:
(Copied the solution from Sean's other question, because it also fits here!)

If you need to add those relations programatically, that's how I would do it:

{# Compose the relation param #}
{% set relationParam = ['and'] %}

{# Add to the relation param #}
{% if condition1 %}
    {% set service1 = craft.categories.group('services').slug('service-1') %}
    {% set relationParam = relationParam|merge([{ targetElement: service1 }]) %}
{% endif %}

{% if condition2 %}
    {% set service2 = craft.categories.group('services').slug('service-2') %}
    {% set relationParam = relationParam|merge([{ targetElement: service2 }]) %}
{% endif %}

{# Get users of group "member" #}
{% set users = craft.users.group('members') %}

{# Further filter users - avoid passing an array with `['and']` only #}
{% if relationParam|length > 1 %}
    {% set users = users.relatedTo(relationParam) %}
{% endif %}


Page redirects permanently to itself I am posting this in case anyone will encounter this problem. I also reported a potential bug about that. (see here: https://github.com/craftcms/cms/issues)

When you start to suddenly get redirection loops with HTTP-302 redirects to our own page, you might want to check your loginPath value in general.php.

After we spent hours investigating into the usual .htaccess and other places for redirection loops, we eventually figured out, that loginPath set to '/' will cause that behaviour.

We wanted to redirect users to the homepage if they were not logged in and tried to access a page that required a login.

Our setting was:

'loginPath' => '/'

which proved to cause the redirection loop.

The correct setting instead was:

'loginPath' => ''

I hope this saves somebody else from future pain :)

Answer is provided in the original post and this can be assumed solved.


How to Use defineAttributes To Specify NOT NULL and DEFAULT '1' in MySQL Record How to Use defineAttributes  To Specify NOT NULL and DEFAULT '1' in MySQL Record

I am porting a plugin from another framework and it has the following
MySql tables structure. Is there an easy way to create the same
table structure within craft plugin?

CREATE TABLE IF NOT EXISTS `exp_shortcut_shortcuts` (
`shortcut_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`site_id` smallint(3) unsigned NOT NULL default '1',
`entry_id` smallint(3) unsigned NOT NULL default '0',
`field_id` smallint(3) unsigned NOT NULL default '0',
`autogenerated` char(1) NOT NULL default 'y',
`shortcut` varchar(100) NOT NULL default '',
`full_url_model` varchar(255) NOT NULL default '',
`full_url` varchar(255) NOT NULL default '',
`entry_date` int(11) unsigned NOT NULL default '0',
`edit_date` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`shortcut_id`),
INDEX (`shortcut`)
) ;;

namespace Craft;

class ShortcutRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'shortcut_shortcuts';
    }

    public function primaryKey()
    {
       return 'shortcut_id';
    }

    protected function defineAttributes()
    {
        return array(
            'shortcut_id' => array(AttributeType::Number, 'column' => ColumnType::PK),
            'site_id' => array(AttributeType::Number, 'column' => ColumnType::TinyInt),

I see how to add TinyInt. How do I specify NOT NULL and default '1'?

For NOT NULL use 'required' => true and to default to 1 use 'default' => 1.


Craft 2 categories locale issue I have a craft2 site running quite happily with 8 languages.

I noticed recently that a dropdown selection of category entries is not working when the locale is changed to chinese (locale = 'zh').

So the list of countries to search on does not  render fully - only some countries are shown.

Here is the real world example
https://seafarerhelp.org/en/seafarers-directory
https://seafarerhelp.org/zh/seafarers-directory

check out the search country dropdown. It is using this template code:

{% set countries = craft.categories({
    group: 'locations',
    limit: null,
    level: 1,
    order:['title asc']
   })
%}

In english we get the full list.
In Chinese (select the locale) we get only a handful.

Other countries seem fine. I am stumped. Have looked for oddities in structure but can find none. Ironically this area of the site is not translated but this doesn't present any problem with other locales/languages

This ended up being because not all categories were properly resaved after a new locale was added. Resaving the categories solved it.


Create a GUID in a template Is there a straightforward way of creating a GUID or some other type of unique identifier within a Twig Template?

I'm aware of StringHelper.UUID (mentioned in a different question), but it doesn't look like I can use it directly in a template.

I'm comfortable creating a small plugin to expose this, or alternatively creating a twig filter to use a relevant PHP method, I just didn't want to go re-inventing the wheel if there's already a good solution I don't know about.

If a simple timestamp is unique enough, you can use:

{{ now|date('YmdHis') }}

Which will give you something like:

20150723170500


Conflict with assets folder and section URL I have come up against an issue, and I want to check the best way to resolve this; here is a brief explanation.

So by default I have setup the craft assets folder to be called 'resources' and this lives in the top level of the website (although I think location is irrelevant). The client has now introduced a section called resources that has several child pages and a top level page. Which is accessed at /resources/ - I think the most sensible change is to rename my resources folder that holds all the uploaded assets. I will probably rename it uploads. However, what is the best approach to rename this without upsetting the system or having big issues.

I should also mention my resources folder also contains several sub folders for assets too.

You should be able to rename the directory on the server and then update the Asset Source settings changing the URL and system path. It should take care of it as Asset folders are stored relative to the top folder.


Redirect user to the page they wanted after login I have some pages that require login from the user. What I'd like is for the user to get redirected to the page that they wanted after they've logged in rather than sent to the page that they were on before they attempted to view a 'login required' page.

At present I have this in my login form:

<input type="hidden" name="redirect" value="{{ craft.request.getUrlReferrer }}">

Is there a craft request method I can use instead of getUrlReferrer to accomplish this?

If you are using {% requireLogin %} tags, then the Craft UserSession service has a getReturnUrl() method which should give you what you want. It is accessible in your templates via craft.session.returnUrl. Here is a link to the docs. Hope this helps!


Is it possible to validate whether all assets in an entry have been uploaded? Is it possible that all assets are uploaded in a single entry and display success or fail in a friendly way?

Use case: Client uploads 2000 photos at a time in an entry and has to keep scrolling to the bottom of the asset popup box to see if all photos have actually "uploaded" or not.

I do not believe there is an easy way to do this with Craft out of the box. Uploading 2k images to an entry is a bit of an edge case. I would recommend uploading all of those images directly to the asset volume.

That being said, you might want to search the plugin store to see if anyone has created a plugin like this. You could also create your own plugin, copy the code for the asset field, and extend to notify when the upload is complete.

Good luck!


Craft 3: Update database after CMS upgrade via console command Is there any craft command command (shell) which can be used to perform the database updates necessary after a CMS update? (e.g. Craft3 beta-28 to beta29 or multi version updates)

Background: We are deploying our projects with Jenkins and I would want Jenkins to call such a command after each deployment (or after each CMS update). Going to the /admin/ Panel manually to be told that the database needs to be upgraded is not ideal.

You can use Yii's migrate console command.

Triggered in Craft 3 via craft migrate --type=app.


Issue with uploading files from frontend I'm currently trying to implement a simple file-upload form with CraftCMS.

However, even though there are no errors on submitting the form, no file actually seems to get uploaded.

This is the form:

<form action="" method="post" accept-charset="UTF-8" enctype="multipart/form-data">
        <input type="hidden" name="action" value="entries/saveEntry"/>
        <input type="hidden" name="sectionId" value="29">
        <input type="hidden" name="enabled" value="1">

        <input type="file" name="useruploads" style="margin-bottom: 30px"/>

        <select class="form-control" id="sel1" style="margin-bottom: 30px">
            <option>x-challenge auswählen</option>
            {% for entry in craft.entries.section('challenges') %}
                {% for ch in entry.allOverChallenge %} %}
                    <option>( Tirol ) {{ch.allOverName}}</option>
                {% endfor %}
            {% endfor %}

            {% for entry in craft.entries.section('xSpots') %}
                {% for ch in entry.standaloneChallenges %} %}
                <option>( {{entry.title}} ) {{ch.standaloneName}}</option>
                {% endfor %}
            {% endfor %}
        </select>

        <input type="text" class="form-control" id="challenge_select" placeholder="Titel eingeben" style="margin-bottom: 30px">

        <textarea class="form-control" rows="5" id="challenge_description" placeholder="Beschreibung eingeben" style="margin-bottom: 30px"></textarea>

        <input type="text" class="form-control" id="challenge_customtags" placeholder="Hashtags ( max. 3 )" style="margin-bottom: 30px">
        <div style="margin-bottom: 30px">
            <input type="reset" value="abbrechen">
            <input type="submit" value="hochladen">
        </div>
    </form>

I'm attaching two screenshots that show both the actual field and the section:

When submitting the form in it's current state, no entries actually get added to the field as shown in the image below. Am I doing something wrong here? I'd appreciate some help on the topic.

Have you tried enabling devMode in the craft/config/general.php file? You can do this by adding 'devMode' => true to the array. You should then be able to see an error on submission.

If this fails to output anything then it could be that your input requires square brackets adding to the name, e.g. name="useruploads[]"

Even though you have limited the field to 1 upload, it may still be expecting an array to be posted to it.


Entry field not outputting after {% set... %} code in template I have an {entry.footer} field outputting just fine everywhere before {% set entry... %}
Added {% endset %} tags after closing anchor tag and caused an error. Any idea what the issue is?

{% extends "_layout" %}

{% block home_slider %}
{% include 'global/home-slider.html' %}
{% endblock %}

{% block content %}

                                     {{ entry.body }}

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

                                                    {% if block.image|length %}

                                                    {% endif %}

{{ block.imageTitle }}

                                    {% endfor %}

                                    {% set entry = craft.entries.slug('get-a-quote').first %}
                                    request a quote
                                    {% endset %}

                            {{ entry.footer }}

{% endblock %}

Here's your problem... You're redefining entry halfway down the page.

This page clearly uses the section's built-in routing functionality. I can tell because you use entry.body near the top of your page without explicitly declaring the value of entry.

However, you later on use {% set entry %} to reassign the value of entry. Based on the new value of entry, the entry.footer property no longer exists or is empty.

How to fix it...

Instead of {% set entry %}, use a different variable name:

{% set getQuoteEntry = craft.entries.slug('get-a-quote').first %}
request a quote

This will leave the original value of entry untouched, and you'll still have access to entry.footer at the bottom of the page.


Running console (yiic) under MAMP (Windows) I am running Craft 2 under MAMP (PHP 7.0.9) on windows and have a site that works under it. However if I use GIT to cd to the yiic console folder...

/c/mamp/htdocs/website/craft/app/etc/console

... and type ...

php yiic help

... I get an error message ...

Fatal error: Uncaught Error: Class 'Craft\ErrorHandler' not found in C:\MAMP\htdocs\website\craft\app\framework\YiiBase.php:213

... However, if I use PHP 5.6 (the one that I use to run the site - and which therefore has a different php.ini) I get a different message ...

exception 'CDbException' with message 'CDbCommand failed to execute the SQL statement: SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected.

... even though the database settings must be OK as Craft works.

How do I get yiic to work?

PS: I have put some debugging into console\yiic.php and the paths that are getting returned match what I would expect.

I have also looked at Error Connecting To (MAMP Pro) Database in Console Command but the modification it suggests to craft/config/db.php refers to a file that does not exist: mysql.sock

I may have found my own solution. It looks as if Yiic was not picking up the .env file.

The file ... craft\app\etc\console\yiic .. must therefore be changed from ...

#!/usr/bin/env php
<?php
require_once(dirname(__FILE__).'/yiic.php');

... to ...

#!/usr/bin/env php
<?php
require_once('../../../../vendor/autoload.php');
try {
    $dotenv = new Dotenv\Dotenv('../../../../');
    $dotenv->load();
    $dotenv->required(['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS']);
} catch (Exception $e) {
    exit('Could not find a .env file.' . $e);
}
require_once(dirname(__FILE__).'/yiic.php');

Hope this is of use to other people.


Relating testimonials to Products So I am new to Craft and I am attempting a site build with Craft Commerce.
I currently have a channel for Testimonials. Within this I have a relatedProducts field to assign products to testimonials.

What I am trying to achieve is to pull out the specific related testimonials on each specific product page.

Here is the code for my testimonials.

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

    {{ testimonial.body }}

        {{ testimonial.citation }}
        {% if testimonial.relatedProducts|length %}

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

        {% endif %}

{% endfor %}

Is anyone able to assist or offer some guidance on how I can achieve this?

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

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

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

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


Additional Fields aren't sent within Contact Form email I am using Contact Form v1.9.0 with latest version of Craft.
I've additional fields to the form so that the inputted values appear in the email message. However, the only field being sent within the message is the message[body] field.

A link to a gist of my form code is below:
https://gist.github.com/anonymous/f380c316ad14864aed7aa95dbb2cafc8

I am using jquery to copy and replace the value of fromName and fromEmail, which you'll see are hidden fields.

This exact form has been used on numerous sites in the past few months, using Contact Form 1.8.1.

Any thoughts on why those additional fields aren't being attached to the email message?

This issue is this:

<textarea name="message" name="message[body]" cols="30" rows="6" placeholder="Questions or Comments"></textarea>

You're defining name twice.  The 2nd one gets ignored (which is required if you're using the array syntax for other fields).


How can I get field data for the current locale in a plugin? So I have a plugin with a service. Part of the service function is to grab a field (body) from an entry object that has been passed into the function.

<?php
namespace Craft;

class MyPlugin_ExampleService extends BaseApplicationComponent {

    public function example($entry) {
        return $entry->body;
    }

}

The function will be called via Twig.

{{ craft.myPlugin.example(entry) }}

How do I go about getting the field data for the users current locale?

You're pretty close... You'll need to do this in a Variable, not a Service.

If your method already exists in a Service, or if you'll need to access it via PHP as well, then you can keep it in the Service. In that case, you'll still need a Variable method, but it can simply be a wrapper for your existing Service method.


Upgrade to 3.0.0 RC1 failed due to 504 Gateway Time-out I got a notification in the Craft 3 beta versions I have been working on to upgrade to 3.0.0 RC1. I clicked update and it began updating only the throw the following error. Any ideas what may have happened?

Status: Gateway Time-out

Response:
<title>504 Gateway Time-out</title>

504 Gateway Time-out

nginx/1.12.2

If it's of any help, this is a composer install using Valet to run.

Updated using composer update craftcms/cms


Keep on getting logged out when deploying using Capistano I keep on getting logged out whenever I deploy using Capistrano, despite the sessions being stored persistently (in the craft/storage folder).

The problem is that the basepath changes each time you deploy (Capistrano uses versioned release directories). The basepath is used to generate a session key, which is invalidated each time a new deployment is made.

The answer is to add the appId parameter to config/general.php. The docs give a good explanation

  The application ID, which is used for things like storing data caches and user sessions. If it’s not set, Craft will automatically generate one based on the server path. Setting it will help avoid the loss of data caches and user sessions when Craft is deployed using a deployment script that will store Craft in an inconsistent location, such as Capistrano.

So add this to general.php:

'appId' => 'chooseyourownrandomstring',


How to Get Asset Volume Name Trying to figure out how to get the "name" and "handle" of an asset volume, given the volume ID. Tried all the obvious things, no luck!

The Volumes service is available via craft.app.volumes, so you can do
{% set volume = craft.app.volumes.getVolumeByHandle('volumeHandle') %}
{{ volume.name }}

or
{% set volume = craft.app.volumes.getVolumeById(123) %}
{{ volume.name }}

Additionally, if you have an Asset model available, you can get its volume like this:
{% set volume = asset.volume %}
{{ volume.name }}


Building an area for users to add content for Craft site We're building our first project in Craft. It requires an area for users to submit events to the site, and the submissions will wait in an approval queue. We do not want these users to have access to the craft backend.

Also we are using Rackspace cloud hosting for images, and we would need the users to be able to submit their own photos to the site.

Are their any mechanisms in place in craft that we could leverage to keep plugin development to a minimum? I understand this is a broad question, but being our first Craft project I'm sure it has a lot of functionality we are not aware of and it would be a shame to recreate it just because we were unaware.

Welcome to Craft!

For starters, I would definitely recommend checking out the Pixel and Tonic Guest Entries plugin, brought to you by the guys who built the CMS. As the title suggests, it allows users to create entries from a custom form on the website front-end.

So, from your example, you can have an 'Events' channel and allows users to create entries (events) using the form.

These entries can then be moderated like any normal entry.


How do I display entries 1 by 1? I need to display entries that contain an image, and a piece of text, on the home page of my website.

When someone clicks 'next', I would like it to go to the next entry (by post date) and display that entries image and text. I also need the user to be able to click on 'previous' (by post date again) and 'random'.

How do I go about this?

Thanks!

You could use the getNext() and getPrev() methods on your entry like this:

{% set params = craft.entries.section('yoursection').order('postDate asc') %}

{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}
{# to access url, I use #}
{{ prevEntry.url }}
{# to access title, I use #}
{{ prevEntry.title }}

NOTE: I've shamelessly pinched this code from the answer here.

You need to setup the params variable so that it would create a list of entries which would include your current entry and the next/prev entries you expect. So include your ordering by postDate etc.


Try out Craft Client and Pro on multiple development URLs? I'm aware that running craft locally from "craft.dev" or "ontherocks.dev" will enable you to try out the Client and Pro versions (which is a super-cool feature!) - but just wanted to ask if there are any plans to allow any domain at *.local or *.dev.

Obviously totally understand not wanting to open it up too much, but just working on a few projects under development, which is a little hard to juggle on the one domain.

You can always use this "super-cool feature" with sub-domains of "craft.dev" or "ontherocks.dev"! You can have as many as you want:

"craft.dev"
"pro.craft.dev"
"license.craft.dev"
"testing.craft.dev"
"is.craft.dev"
"super.craft.dev"
"cool.craft.dev"

:D


Adding all the Matrix Block field types of the same kind to get a total I have a Matrix block with a description field and a number field for hours. Let's say while creating an entry I add in 3 of these blocks with each having a different amount for the hours.

How can I add each of those 3 amounts and get a total amount?

I've spent quite a while researching and can't figure out what kind of syntax would make this work.

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

Something like this should work for you:

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

{% for block in entry.matrixFieldHandle %}

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

{% endfor %}

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

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

{% set totalHours = 0 %}

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

Total Hours: {{ totalHours }}


How to correctly format API requests for Mandrill using Fetch plugin? Getting error "you must specify a key value" I want to use the Fetch plugin (v 1.2.0; Craft Pro 3.3.13) to send messages from a Twig template in some circumstances.

To test the setup, I'm just trying to ping Mandrill, according to the /users/ping.json call: https://mandrillapp.com/api/docs/users.JSON.html#method=ping.

I've tried a bunch of variations, but I keep getting this error:

1 - Server error:
`GET https://mandrillapp.com/api/1.0/users/ping.json`
resulted in a `500 Internal Server Error` response:
{
  "status":"error",
  "code":-1,
  "name":"ValidationError",
  "message":"You must specify a key value"
}

According to this answer (admittedly from 2013), "This particular error is common if the JSON is invalid for some reason."

I've looked at Jalen's excellent answer on another Fetch question, but that's for a different API and I'm not sure what to do.

Here's my current code:

      {% set client = {
          base_uri : 'https://mandrillapp.com/api/1.0/',
          timeout : 10
        } %}

        {% set options = {
          key: 'REDACTED',
        } %}

        {% set destination = 'users/ping.json' %}

        {% set request = fetch(client, 'GET', destination, options) %}

I've also tried it with POST, and with various permutations of quotes around the key and api key; same error.

Two things I'm noticing about your code snippet:

You'll want to use POST per the Mandrill API docs.

  All API calls should be made with HTTP POST.

The options object should only contain valid Guzzle request options (key is not an actual request option); I think what you're trying to do is pass your key parameter in the request body. There are multiple options for sending data in the request body (form_params, body, json, or multipart), but since the Mandrill API is expecting a json request body we'll use the json option like so:

{% set options = {
  json: {
    key: 'REDACTED',
  }
} %}

All together, this should give you a working API call:

{% set client = {
  base_uri: 'https://mandrillapp.com/api/1.0/',
  timeout: 10
} %}

{% set options = {
  json: {
    key: 'REDACTED',
  }
} %}

{% set destination = 'users/ping.json' %}

{% set request = fetch(client, 'POST', destination, options) %}


Impossible to access an attribute (title) on a string variable I have a Video section with a field called videoCategory. I'm trying to pull in the first category on the _entry.html template.

I'm pretty much following the the last example in the documentation at: http://buildwithcraft.com/docs/categories-fields

...with this code:

 {% set entryCategory = entry.videoCategory.first() %}
 {% if entryCategory %}

{% for category in entryCategory %}{{ category.title }} {% endfor %}

 {% endif %}

But I can't get around this error message:

  Impossible to access an attribute ("title") on a string variable ("19")

What is it that I'm missing?

entryCategory is already a single category because of "first()". So no need for the for loop. Just {{ entryCategory.title }} should do the trick here.

{% set entryCategory = entry.videoCategory.first() %}
{% if entryCategory %}

{{ entryCategory.title }}

{% endif %}


How to add year and month to Entry URL Format I'd like to make the Entry URL format of a channel look like this: /news/2015/06/my-slug-here

What would I need to enter into the Entry URL Format field in order to do this?

The closest I could manage was this:

news/{postDate|date("Y")}/{slug}

But that only outputs this: /news/2015/my-slug-here

Thanks for any help.

You're close! For the month part you need postDate|date("m") (this page has the php date formats).

news/{postDate|date("Y")}/{postDate|date("m")}/{slug}


Trouble parsing JSON with getBodyParams() I'm trying to use getBodyParams() to parse a JSON posted to a module controller action from an API. The incoming headers have content-type set as application/json; charset=utf-8, and I've tested to make sure there is a valid JSON string in the body. But when I try to get the retrieve the body  using getBodyParams(), I only get an empty array as a response. The documentation makes it sound like it's possible to parse JSON and other content types. Does anyone know the correct way to use getBodyParams() to parse a JSON body?

Got in touch with P&T support and got the following response back:

  We don't currently support parsing JSON via getBodyParams(), however I'm looking into it and looks like Yii can be configured to support that, when the request's Content-Type header is set to application/json. We would need to enable that feature ourselves though.

  In the meantime you could do:

$body = Craft::$app->request->getRawBody();
$data = craft\helpers\Json::decode($body);


Best way to find a folderId I'm iterating through a folder using craft.assets, to select the folder I'll use the folderId.

What's the best way to find the folderId of a specific folder?

The only way I've found is to go the the Asset Settings page in the CP and hovering over a folder to see the url in the status bar in my browser.

Related Problem:

I created a folder in the CP Fields page (see image) and there seems no way to get this folderId as I cannot get to it in the Asset Settings page. As I only have a small number of folders I was able to figure it but it got me wondering if I was missing the obvious somewhere?

Thanks

John

You can find the id in the database in the craft_assetfolders table. Creating a field with uploads restricted to a single folder does not create an asset folder. The asset folder only gets created when you actually have an asset in that folder, so before that point there is no id.