Programatically change a lightswitch value on an entry on save I have a simple plugin that fires some events entries.onSaveEntry based on if a lightswitch is turned on with that entry. What I would like to do as the last event in my plugin would be updating the value of the lightswitch with that entry to be turned off (or 0) so if you went back in to the entry it would be turned off again.

Would appreciate any guidance.

You can set the value and save like so:

craft()->on('entries.onSaveEntry', function(Event $event)
{
    $entry = $event->params['entry'];
    if ($entry->section == 'mySection') {
        if ($entry->getContent()->myLightSwitchField == 1) {
            $entry->getContent()->setAttributes(array(
                'myLightSwitchField' => 0
            ));
            craft()->entries->saveEntry($entry);
        }
    }
});

However, you might consider using onBeforeSaveEntry so that you don't have to save the entry twice (and/or run the risk of creating an endless loop).

craft()->on('entries.onBeforeSaveEntry', function(Event $event)
{
    $entry = $event->params['entry'];
    if ($entry->section == 'mySection') {
        $entry->getContent()->setAttributes(array(
            'myLightSwitchField' => 0
        ));
    }
});


Can't update past CraftCMS 3 RC15 I am currently developing my first website using Craft 3 and I'm loving it overall. I seem to have a small issue that I can't quite figure out. When I go to the updates section in the admin panel, I am proposed multiple updates to Craft and 2 of my plugins (see screenshot). However, I can't figure out how to actually do these updates! According to this page in the docs, a button should appear at the top of the page.

I've also tried via composer : composer update craftcms/craft, but it says 'Package "craftcms/craft" listed for update is not installed'.

And I've tried : composer update craftcms/cms and that gives 'Nothing to install or update'. Same thing if I try to update plugins such as redactor that way.

I had started out on RC14 and I was able to update to RC15 properly via the button, but since then, the button no longer shows. Since I am new to Craft, I am not sure which log would contain pertinent information for the problem. I will be glad to share some logs if necessary. If it changes anything, I purchased a Pro license before the license changes on Apr 04.

Sorry if this is a noob question, any help is appreciated!

As a silly mistake, I had set the allowUpdates config setting to false...hope this helps anyone making the same silly mistake.


Booking & Reservation System I asked a similar question previously but it was a bit too vague (and slightly different) to what I actually need. I'm about to start building a site that requires a booking system.

Essentially the site owner is available 24/7 (with the exception of some dates and times that they would set as unavailable). So users need to be able to book a service for ANY time except the times the site owner has set as unavailable.

In addition to that, the visitors of the site will be booking specific services that have pre-set durations. For instance one service may be 2 hours, another might be 3 hours, etc. When someone books a service the time-slot should no longer be available for another individual to book. For instance if customer X books a service that is set to take up 3 hours on November 16th 2014 to start at 8:00 AM PST, then customer Y can not book any services between 8:00 AM - 11:00 AM PST on that day.

Payments should also be processed when they make a booking, i'd think i could use something like CHARGE for that.

My question then is not only how would i go about building a system like this sans-plugin? I know it's a pretty complex question but i'd really appreciate a little help in the right direction as I'm having a bit of a hard time wrapping my head around how to accomplish this. Thanks a bunch in advance.

This would be really tricky without a plugin but you could (and this is a stretch) manipulate the entry channel to accept "reservations" where as the reservations date and time use the date and time field types.

You could then output all the reservation entries to show if/when times are still available. There's no getting around this though, you'd need to work extensively with the saveEntry form, jQuery and a date/time picker to get everything to line up correctly.

The best way to do would be to create a reservation plugin that does specifically this instead of wrangling entires to do the same thing. Either-way I'd say you're looking at some in-depth development time.


Combine variables with text to make variable How can I create a variable that is a combination of two variables with text?

For example, I know the following is wrong but is something like this possible:

{% set foo = 'foo' %}
{% set bar = 'bar' %}
{% set foobar = 'Hello' foo,bar %}
{{ foobar }} #Outputs Hello foobar

You can concatenate variables like this:

{% set foo = 'foo' %}
{% set bar = 'bar' %}
{% set foobar = 'Hello' ~ foo ~ bar %}
{{ foobar }} #Outputs Hello foobar

It's explained by Brandon here.


Display Count of Entries posted today I'm trying to display a notification badge on how many new entries were posted today only. But I cannot get the following to work.
{% set timeAgo = now|dateModify('today') %}

{% set recentMerchantsOffers = craft.entries.section('offers').postDate(timeAgo).relatedTo(recentMerchants) %}

Any help would be great :)

I'm not sure what recentlyViewed() is and what it returns but to query today's entry, you can do:
{# Today in atom format #}
{% set timeAgo = date('today') | atom %}

{% set recentMerchantsOffers = craft.entries()
    .section('offers')
    .postDate(">= #{timeAgo}")
    .all() %}


Sharing a template with identical category and tag name I'm trying to stay as DRY as possible here and sharing one template for a news list view; all, category and tag all sharing the same template (and trying to refrain from having a category or tag segment). My query isn't returning any results when the segment 2 (in this case the url encoded tag or category slug) when there is a tag and category that share the same name. Example, 'design' is a category for design related posts; 'design' is a tag for posts that featured a design service within the 'portfolio' category. My template code is below. Is there a work around here or do I need to have a second segment for tag/category (i.e. .com/news/category/design and .com/news/tag/design - or one or the other to differentialte)

{% if category is defined %}

    {% set newsPosts = craft.entries.section('news').relatedTo(category).limit(5) %}

{% elseif tag is defined %}

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

    {% set newsPosts = craft.entries.section('news').relatedTo(tag).limit(5) %}

{% else %}

    {% set newsPosts = craft.entries.section('news').limit(5) %}

{% endif %}

If the url for posts with the category design is .com/news/design and the url for posts with the tag design is also .com/news/design, then you are not going to be able to see both lists. You do need that extra segment in the url.

What I do to stay DRY is let Craft route tags and categories to different templates (so you don't have to repeat the is this a category or a tag logic). Then on the different templates, use a macro or include for the common code.

Here is what the categories page looks like with a macro:

{% extends '_layout' %}
{% import '_macros/_news' as news %}

{% set newsPosts = craft.entries.section('news')relatedTo(category).limit(5) %}

{% block content %}

Entries with category {{category.title}}

  {{ news.index(newsPosts) }} {# all the shared code is in news.index() #}
{% endblock content %}


Display all entries matching field of a section I have two sections:
Games
Publishers

Games has a field called 'GamesPublisher' that is Entries type (set to Publishers)

I have a publisher called 'Microsoft' with an ID of 49.

I want to display all Game entries for the Publisher 'Microsoft' (ie ID 49)

I also want to set the order of the displaying in ASC order based on the field 'GamesCatalogNumber' which is in the section Games.

So far, it looks OK, but I have yet to figure out to limit entries to a specific Publisher.
http://www.colorcomputergames.com/tandy-catalog/

{% set entries = craft.entries.section('games').relatedTo(entry) %}

    {% for entry in entries.order('GamesCatalogNumber desc') %}

{{ entry.GamesCatalogNumber }}: {{ entry.title }}

    {% endfor %}

    {# Set parameters for prev/next elements list #}
    {% set params = craft.entries.section('publishers').order('title asc') %}

    {# Get the prev/next elements #}
    {% set prevEntry = entry.getPrev(params) %}
    {% set nextEntry = entry.getNext(params) %}

    {# And make sure to only output the links if the element exists #}
    {% if prevEntry %}Previous Publisher{% endif %}
    {% if nextEntry %}Next Publisher{% endif %}

Looks to me like your solution is mostly correct, except for handling the gamesCatalogNumber. For that you could either:

test for specific publisher(s) by id or slug
test if gamesCatalogNumber is empty on the first entry (and assume that the publisher doesn't use catalog numbers), or
(recommended solution) add a checkbox or lightSwitch field to the publisher called 'usesCatalogNumbers' and test for that.

Something like:

{# publisher template #}

{% if entry.usesCatalogNumbers %}
    {% set games = craft.entries.section('games').relatedTo(entry).order('gamesCatalogNumber desc') %}
{% else %}
    {% set games = craft.entries.section('games').relatedTo(entry).order('title asc') %}
{% endif %}

    {% for game in games %}

{% if entry.usesCatalogNumbers %}{{ entry.gamesCatalogNumber }}: {% endif %}{{ entry.title }}

    {% endfor %}

{% set params = craft.entries.section('publishers').order('title asc') %}
{% set prevEntry = entry.getPrev(params) %}
{% set nextEntry = entry.getNext(params) %}
{% if prevEntry %}Previous Publisher {% endif %}{% if nextEntry %}Next Publisher{% endif %}

I recommend this (instead of the other options) because it's a bit more explicit and extensible (i.e. allows you to add other publishers that use catalog numbers without modifying the templates).


Cannot access assets - unable to open image I'm on Craft 2.7.8 and cannot access some of my assets - getting
Unable to open image ../html/assets/xxx.jpg error all the time.

I've checked the owner, group and permissions dozen of times, currently everything set to root and 777.

I can access the images when I go directly to that URL in a browser, but for some reasons I cannot access them in a template.

In the Craft Admin Panel I changed the Source type to Amazon S3 bucket but that didn't work too. I can see the access/secret keys are correct (can display available buckets) but getting the same error "403 - unable to open".

Double checked with Postman and confirmed the images are there - looks like it's a Craft's or the Imager plugin issue.

Any ideas, please?
I'm using html as the root of my website (instead of public) and running on Apache.

Thanks

The solution to my problem was installing the ImageMagick package.

Regarding the S3 bucket - Craft 2 doesn't support my region (Frankfurt) - read more here.


Help with Venti Events Plugin I'm using the Venti events plugin to add recurring events to my site. However, I just want to show the most upcoming event and not all of them. This is a listing page which lists all of my events. This is what I currently have which lists all events.

{% set events =
  craft.venti.allEvents()
  .startDate('and', '>= ' ~ now)
  .limit(70)
  .relatedTo(categories)
  .order('startDate asc')
  .find() %}

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

I found this in their documentation that supposed to show the next event, but this was on a detail page, not a listing page, so not sure exactly how to do this.

{% set next = craft.venti.nextEvent(event.id) %}

Sounds like a feature request for the developers of Venti, but this code should help you achieve what you need.

{% set upcomingEvents = [] %}
{% set upcomingEventIds = [] %}

{% for event in events %}
    {% if not event.eid in upcomingEventIds %}
        {% set upcomingEvents = upcomingEvents|merge([event]) %}
        {% set upcomingEventIds = upcomingEventIds|merge([event.eid]) %}
    {% endif %}
{% endfor %}


Unverified emails blocking user registration craft()->users->saveUser seems to check email for uniqueness across ALL users, not just verified ones.

It seems like it should only check against verified ones to me.

Example:

boob@gmail.com registers (only he fat fingered and it was supposed to be bob@gmail.com). Bob never gets his verification email, but that's his fault. Boob gets one, doesn't know what it is and ignores it.
Later, the real boob@gmail.com now tries to register, but he can't because boob@gmail.com is sitting there unverified, squatting on that email.

At this point you could have an option to resend the activation code, however once boob@gmail.com get that and verifies it, his account will now be the account that the other guy actually signed up for, so if you're doing stuff with accounts, it might have data associated with it you don't want.

I'm not sure that I agree with your analysis.  At a minimum maybe it's a feature request with a config setting to change the behavior.

But if you're really concerned about the behavior, you can currently set the purgePendingUsersDuration config setting to something like 24 hours so they don't hang around very long.


How can I get the same random array key? I am creating a mad libs type of global. My global set is actually called madLibs.

Within that set, is a matrix field - that can have unlimited blocks. Each block only has two fields. actualRole and pretendRole.

What I have is working - but sometimes I might get the actualRole from one matrix, and the pretendRole from another. Ideally, I'd like to get the same fields from the same random matrix.

{# Get all of the matrix blocks for the global set #}
{% set globalSet = craft.globals.getSetByHandle('madLibs') %}

{% if globalSet|length %}

    {# Find out how many matrix blocks exist #}
    {% set madLibsCount = globalSet.madLib|length %} // 2

    {# Generate a random array key. Remember array is zero based #}
    {% set range = range(0, (madLibsCount - 1)) %}

{{ globalSet.madLib[random(range)].actualRole }}

{{ globalSet.madLib[random(range)].pretendRole }}

{% endif %}

Sometimes, this is happening:

{{ globalSet.madLib[0].actualRole }}

{{ globalSet.madLib[1].pretendRole }}

I would really like to have this each time:

{{ globalSet.madLib[0].actualRole }}

{{ globalSet.madLib[0].pretendRole }}

Thank you for any suggestions!

You need to create a common reference to the random number you are creating. Otherwise, you are getting a random number twice - and it's just luck that they show up as expected.

Try this:

{# Get all of the matrix blocks for the global set #}
{% set globalSet = craft.globals.getSetByHandle('madLibs') %}

{% if globalSet|length %}

    {# Find out how many matrix blocks exist #}
    {% set madLibsCount = globalSet.madLib|length %} // 2

    {# Generate a random array key. Remember array is zero based #}
    {% set range = range(0, (madLibsCount - 1)) %}

    {# Capture a single (random) number #}
    {% set key = random(range) %}

{{ globalSet.madLib[key].actualRole }}

{{ globalSet.madLib[key].pretendRole }}

{% endif %}


Existing website written in PHP Zend Framework I manage our corporate marketing website, which is written in PHP and the Zend Framework and is hosted on LAMP servers.  I've been tasked with moving the website to a CMS so other folks on the marketing team can update content without having my dev team be the bottleneck for content publishing and changes.

However, our existing site is more of a web application, in that we use the Zend Framework and PHP code for back-end integrations with HubSpot, WebEx, etc. and various CRON jobs that hit endpoints on our site to do various jobs.

My concern is - how do I maintain the site as a web application without having to rewrite all that functionality in the language of the CMS.  I'm trying to see if I can split the site into two pieces 1) the majority of the static pages powered by the CMS, and 2) the web application stuff that can remain powered by Zend Framework.  Does anyone have experience doing this?

My concern is if I send some traffic to www.site.com/A and other traffic to www.site.com/B (A being the CMS and B being the web app) how do I handle common layout code like navigation and footer?  Meaning if you update the nav in the CMS, this won't magically appear on the web app side.

We've successfully implemented a setup that will solve your issue with several sites. Unfortunately we haven't been able to open source things yet, but this is our general process:

We set up a Craft install on a separate domain (or subdomain, in our case). Then we serve the content as JSON instead of html in our layout template.

Our entry templates are totally normal, outputting html like any other template does. This layout just wraps the whole thing in a json object (and does not include the header/footer etc).

Then on the ZF side, we wrote a module to pull in the data from the separate domain and output it in our app, using the normal layouts that already existed. It is also obviously heavily caching the content it receives from Craft.

So, ZF is actually handling all of the requests by end users, and the only things going to Craft are actually curl requests from ZF.

We have ZF send along a Header telling Craft that the request is coming from ZF, and then we have Craft check for that header. If it exists, it uses layout.json, and if not, it uses layout.html.

layout.html has a dummy version of the header and footer, and is only used for Live Preview basically. The layout.json file serves our content as json to the ZF app.

Here is our layout.json:

{% header 'Content-type: application/json'
%}{% set response = {
    success:true,
    metadata: {
        {# some custom data #}
    },
    data: {
        meta: (head is defined ? head : {}),
        body: block('content')
    }
} %}{{ response|json_encode()|raw }}

So, while this doesn't mess with custom routing, it will allow you to keep your ZF app going and have Craft handle marketing/static pages.


Unexpected output from Twig set variable My entry has a custom field to set a social image for Facebook.

In the entry template, I'm defining the output like so:

{% set social_image = "" %}
  {% for image in entry.metaImage %}
    {% set social_image = image.getUrl() %}
  {% endfor %}

Then in the layout I have this

<meta property="og:image" content="{% if social_image is defined %}{{ social_image }}{% endif %}" />

and this works great. However, when that field hasn't been, I want to fallback to a custom field that will always have an image set.

I tried to change the layout to {% if social_image is not null %}{{ social_image }}{% else %}{{ social_image_fallback }}{% endif %} setting social_image_fallback within the entry template of course, but that outputs a null value.

I originally had {% if social_image is defined %} but of course if defined would always evaluate to true.

I'm missing something simple here right?

Try {{ social_image|default(social_image_fallback) }}. I've had good results using Twig's default filter over testing variables, even with multiple fallbacks. (like this).


Is it possible to use _includes/forms outside of the Control Panel? From working on plugin development, importing (I believe the correct term for this is macro) the 'forms' to quickly generate text areas, selects and etc. is incredibly useful. Adding the import now fails as '_includes' is only accessible from the control panel.

So in my template I could add this line:

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

Then use something similar to this to output my forms fields?

{{ forms.textField({
    label: "First Name"|t,
    id: 'firstName',
    name: 'firstName',
    instructions: "First name (i.e John)",
    placeholder: "John",
    first: true,
    autofocus: true,
    required: true
}) }}

I know when using Symfony and Twig you can specify the namespace on where to grab the template from. Does Craft include a way to access those templates from the front end? Has anyone managed to perform this outside of the control panel?

Edit: if this is not possible, or p&t doesn't plan on making this possible (for security concerns) is there a way for a plugins template path to allow anonymous access? This way the developer could create an '_includes' and allow people to access it in the same manor?

I've been able to render CP templates in the front end using some methods in PathService and TemplatesService, which you could use inside your own Template Variable to render the macros:

class YourVariable {

    public function renderFormMacro($macro, array $args)
    {
        // Get the current template path
        $originalPath = craft()->path->getTemplatesPath();

        // Point Twig at the CP templates
        craft()->path->setTemplatesPath(craft()->path->getCpTemplatesPath());

        // Render the macro.
        $html = craft()->templates->renderMacro('_includes/forms', $macro, array($args));

        // Restore the original template path
        craft()->path->setTemplatesPath($originalPath);

        return TemplateHelper::getRaw($html);
    }
}

Which would be used like:

craft.yourVariable.renderFormMacro('textField', { label: 'Name' })

I've not tested it but I think that should be close.


Path and Entry Template problems when developing locally I feel this a simple problem to fix, but I can't find an answer anywhere.

I am developing locally on using MAMP.

Everything on my site is working great until I call up page using a template inside a folder inside the templates directory. At that point the paths are broken to any and all assets (CSS, images, etc.)

For example, if I set the Entry Template for a section in Craft to say news/_entry and then view a news article page... I get an un-styled page.

I am including the CSS like this:

<link rel="stylesheet" href="../public/assets/css/nav.css">

and the images like:

<img src="../public/assets/images/swf_logo.png" alt="" />

Your image/CSS/JS URLs should be either absolute, protocol-relative, or root-relative:

<link rel="stylesheet" href="http://example.com/assets/css/nav.css">

<link rel="stylesheet" href="//example.com/assets/css/nav.css">

<link rel="stylesheet" href="/assets/css/nav.css">

Relative URLs (which start with either ./, ../, or no slash at all) are generally a bad idea, since the URL will need to vary depending on the number of segments in your URI.

For example if you were to access http://example.com/, the relative path to your nav.css would be assets/css/nav.css, but if you were to access http://example.com/about/ (with a trailing slash), then the proper relative URL would be ../assets/css/nav.css.

That’s not to say that relative URLs are impossible. The main issue with your URLs is not that they’re relative, it’s that you’re treating them as relative from the physical template file location. Keep in mind that these front-end resource URLs are resolved by the browser, not by the server, and browsers have no idea how the resulting HTML gets generated, let alone that it came from a template that happened to live a couple directories up from your web root, and in a craft/templates/... subfolder. So they need to be relative based an the apparent location of the webpage, as defined by its URI (e.g. “/news/some-slug”).


Using relative paths for assets for heroku deployment I cant quite wrap my head around the way the way the heroku file system works, so I'd like to use relative paths for my asset File System Paths. Is that even possible?

I've tried to use CRAFT_BASE_PATH in the general settings file to define an environmental variable, but no real luck getting my assets folders to be recognized.

Take a look at Multi-Environment Configs and specifically environmentVariables. Then you can add your variables to the settings in the Craft CP.

Note: you'll have to figure out Heroku's paths by trial and error or ask their support staff for help.


Cached entries and postDate / expirationDate How does the {% cache %} tag handle a situation where an entry reaches its post date or expires?

Currently, it will ignore them and will only invalidate according to any explicit parameters you've told it to.

However, I think it should take into account an entry's post and expiration date so I've added it to our todo list.


System language, can I change it after installation? I have Craft on local (Pro edition) that was installed with French as the system language.  Is there a way to change to another language (English for example) for the control panel? I want to change the system language, not the content of my entries (localisation).

If you go to Settings->Locales in the control panel, you can add "English - en" as a new locale/language to Craft.

From there, you can can what language the Control Panel will display on a per user basis by going to the user's account and setting the "Preferring Language" setting.

As J. Baptiste pointed out, you can also set what the default Control Panel language should be for all users by setting the defaultCpLanguage config setting.


Same content on different slugs I hope someone can help me to understand this.

I have a Channel called eg. "My channel". In that channel i have two entries: Post 1 and Post 2. Those two entries have different titles and content.

If I go to "my-channel/post-1" in the browser, and then to "my-channel/post-2" they have the same content based on the Post 2 (last created entry).

If I make "Post 2" inactive, then Post 1 will have the correct content.

What am i forgetting here?

Because your Entry URI is setup as my-channel/{slug} , When you go to my-channel/post-slug-1 Craft automatically sets the variable 'entry' to the entry post-slug-1. You don't need to loop through the channel at this point. You can just use the entry variable.

entry.fieldName
entry.slug
entry.url

etc...

So just remove your for loop and use 'entry'

Using

{% for entry in craft.entries.section('my-channel').limit(1).all() %}

Will get the first entry of the my-channel section. That's useful for pages where you need to list out all of your entries in that section or get specific ones.


Move users with Feed Me Is it possible to move users along with their passwords? I can see the mapping option, but how do I output password in a template (I'm moving data between craft installations).

The below code does not work.

{% for user in craft.users().status(null).all() %}
    <password>{{user.password}}</password>
{% endfor %}

Password hashes aren't included in the default user query for security reasons, but if you want to force them to get added, you could use:

{% for user in craft.users().status(null).addSelect(['users.password']).all() %}


Dependency Conflict Updating to Craft 3.5 I'm trying to update to Craft 3.5 from 3.4.3 but running into this error message:
Composer output: Package "craftcms/vue-asset" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

Problem 1
- Conclusion: remove tcb13/substringy 1.0.0
- Conclusion: don't install tcb13/substringy 1.0.0
- Conclusion: remove danielstjules/stringy 3.1.0
- Installation request for tcb13/substringy (locked at 1.0.0) -> satisfiable by tcb13/substringy[1.0.0].
- Installation request for craftcms/cms 3.5.5 -> satisfiable by craftcms/cms[3.5.5].
- Conclusion: don't install voku/stringy 6.3.1
- craftcms/cms 3.5.5 requires voku/stringy ^6.2.2 -> satisfiable by voku/stringy[6.3.1, 6.3.0, 6.2.2].
- don't install voku/stringy 6.3.0|don't install danielstjules/stringy 3.1.0
- don't install voku/stringy 6.2.2|don't install danielstjules/stringy 3.1.0
- tcb13/substringy 1.0.0 requires danielstjules/stringy ^3.1 -> satisfiable by danielstjules/stringy[3.1.0].
- Conclusion: don't install danielstjules/stringy 3.1.0|install voku/stringy 6.3.1

I've uninstalled a bunch of plugins but still running into the issue. Uninstalling anything else may be problematic, so is there any way I can track down where the conflict is occurring?
For reference, this is my composer.json:
{
  "require": {
    "craftcms/cms": "3.4.30",
    "craftcms/element-api": "2.6.0",
    "craftcms/redactor": "2.6.1",
    "doublesecretagency/craft-cpcss": "2.2.1",
    "elivz/craft-single-cat": "1.2.1",
    "ether/tags": "1.0.7",
    "jungleminds/nethooks": "1.1.2",
    "venveo/craft-bulkedit": "2.0.5",
    "verbb/cp-nav": "3.0.13.1",
    "verbb/image-resizer": "2.0.10",
    "verbb/super-table": "2.5.4",
    "vlucas/phpdotenv": "^2.4.0"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "sort-packages": true,
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ]
  }
}

Not a true fix, but on the off chance this helps someone, here are the steps I took:

Create a local clone of the live Craft install with a dummy database, but the same composer.json and project.yaml files.
Delete the storage and vendor folders, and the composer.lock file.
Run composer update.
Install a plugin from the live admin panel.
Delete the vendor folder and composer.lock file on the server.
Upload the new local vendor folder to the server.
Uninstall the plugin again, causing composer to run.

Then when I went back to the updates panel and reran it, Craft upgraded without any issues.


Find entries with multiple categories with an and/or twist I have 2 categories, model and feature which I've added as a field to an entry. I want to find entries with the model category using "or" but the feature category using "and". I believe the "relatedTo" functionality only allows one kind which is very restrictive.

{% set model = [24, 25, 26] %}
{% set feature = ['AND', 46, 47, 48] %}

{%
    set entries = craft.entries({
        relatedTo: [model, feature]
    })
%}

The code above is an example, but it returns no results.
How else can I achieve this?

Ok, I was close :P

The trick is to create an object to pass instead of an array. The documentation for this is sketchy and confusing so I hope this snippet helps someone.

Notice I am setting 'and' at the root of the object, but this only applies to the objects that follow, not to targetElement arrays. So by separating all the features into separate objects, the 'and' is applied to them, but not the models.

{% set models = [24, 25, 26] %}
{% set features = [46, 47, 48] %}

{%
  set relatedTo = ['and', {
    targetElement: models,
    field: 'model'
  }]
%}

{% for feature in features %}
  {% set relatedTo = relatedTo|merge([{
    targetElement: feature,
    field: 'feature'
  }]) %}
{% endfor %}

{%
  set entries = craft.entries({
    relatedTo: relatedTo
  })
%}


How to use Craft CMS? I've manage to install Craft CMS with command line, I've the message "installed craft successfully" so I guess it worked, plus my database has been completely populated.
But then, how do we access the CMS lol ?
I've installed it at localhost/craftcms/ but then I don't know where I have to go to use the tool.
I use wamp ( on Windows of course).
Thanks for all, and sorry for my question that I'm sure is stupid but I can't find an answer

The default URL to access Craft is /admin.

Note also this can be changed to anything you like using the cpTrigger config variable.


Entries inside controller I'm trying to bring back a list of entries from a section. Currently I have the following:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'airports';
$criteria->airportcode = 'BCN';
$airportPrefHotels = craft()->elements->findElements($criteria);

The airport section has a multiple entries field. I want to loop over them.

Is it possible?

You first need to query for the “airport” entry by using the first() method. $airport->myEntriedFieldHandle then returns an ElementCriteriaModel prepared to get all the entries selected in the Entries field.

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'airports';
$criteria->airportcode = 'BCN';
$airport = $criteria->first();

if ($airport) {
    $criteria = $airport->prefHotels;
    $airportPrefHotels = $criteria->find();

    if ($airportPrefHotels) {
        // do useful things with $airportPrefHotels
    }
}


Query section entries based on start/end date and type I'm having the following layout on a page: a messages page that shows events and news that are grouped in a section called messages. The page starts with current events, then upcoming events and finishes with all messages (old events and news).

The queries i need to run:

Current events

section messages
entry type event
where startdate is = or < now (starting today or earlier)
and enddate is = or > now (ending today or later)
ordered by startdate

Upcoming events

section messages
entry type event
where startdate is > now (starting later than today)
ordered by startdate

All messages

section messages
entry type all (event and news)
that exclude current events
and exclude upcoming events
with pagination

My current code where some parts are working:

Current events

{% set entries = craft.entries.section("messages").type("event").orderBy('startDate asc').all() %}
{% for entry in entries %}
  {% if entry.startDate < now and entry.endDate > now  %}

{{ entry.title }}

  {% endif %}
{% endfor %}

Upcoming events

{% set entries = craft.entries.section('messages').type("event").orderBy('startDate asc').all() %}
{% for entry in entries %}
  {% if entry.startDate > now %}

{{ entry.title }}

  {% endif %}
{% endfor %}

All messages

{% paginate craft.entries.section("messages").limit(9) as pageInfo, pageEntries %}
{% for entry in pageEntries %}

{{ entry.title }}

{% endfor %}

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

{{ page }}

  {% endfor %}

{{ pageInfo.currentPage }}

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

{{ page }}

  {% endfor %}

Two questions i have:

How do i query current events so startDate is < AND =? And endDate is > AND =?

And how do i query all messages (news and events), excluding current and upcoming events but with past events?

Update

Found the solution for my first question.

For current events my working solution is:

{% set entries = craft.entries()
  .section('messages')
  .type('event')
  .startDate('<= ' ~ now|date('c'))
  .endDate('>= ' ~ now|date('c'))
  .orderBy('startDate asc')
  .all()
%}

{% for entry in entries %}

{{ entry.title }}

{% endfor %}

For upcoming events a simpler solution is:

{% set entries = craft.entries()
  .section('messages')
  .type('event')
  .startDate('> ' ~ now|date('c'))
  .orderBy('startDate asc')
  .all()
%}

{% for entry in entries %}

{{ entry.title }}

{% endfor %}

I can't figure out how to get my second question working.

I need to query all messages (type: news and events) and exclude current and upcoming events. The output: all messages of type news and all messages of type events that happened in the past. Including pagination.

It should be a combination of this i think:

{% set news = craft.entries()
  .section('messages')
  .type('news')
  .all()
%}

{% set events = craft.entries()
  .section('messages')
  .type('event')
  .startDate('< ' ~ now|date('c'))
  .endDate('< ' ~ now|date('c'))
  .all()
%}

Together combined with ordering by post date and pagination. Help! :-)


Can Control Panel Settings page become very slow with some plugins? Despite my best intentions to build sites with minimal use of plugins (in any CMS) I have resorted to a dozen or so on one Craft site with about 25 sections and 1000 entries, to help with both CP and front-end things. Since the v2.5 upgrade (I think) I noticed that the Settings page had become impossibly slow to load (about 30 seconds, and this often within the Settings area too) which stretches my tolerance when I am working. I disabled all loaded plugins and suddenly everything was good again. I then added plugins one by one and tested the Settings page loading time. It eventually came down to two (Cache Warmer and Sitemap) that slowed loading time, and the effect seemed to be cumulative (i.e. one plugin was only half as slow). Is it a reasonable assumption that some plugins may affect Settings page loading time, and has anyone else noticed this? What can I do about it?

I guess someone will mention the L-word (logs) but I always have a hard time understanding which log files to look at and what to look for.

Is it a reasonable assumption that some plugins may affect Settings page loading time

It's very reasonable.  A plugin can do all sorts of things that might slow down CP rendering and it's reasonable to assume that all plugins don't test with databases that have 25 sections and thousands of entries.

The log files you want to look at are in craft/storage/runtime/logs. craft.log is the most recent and craft.log.1, .2, etc. being older. Do it with devMode enabled and you want to be looking at the timestamps for each entry to see where all of the time is being eaten up.

Alternatively (or in addition to), you can create a Github issue for CacheWarmer and let them know what you're seeing.

Sitemap is commercial, so you can go through the developer's usual support channels.


How can I get the last Matrix block of a certain type? I have a Matrix field with some different block types; images, videos, text, etc. When I loop over the blocks I have some extra code (facebook and twitter sharing, back-button, etc) that should only be output for the last "text" block.

How can I know, inside the loop, if the current block is the last of its type?

What about comparing the currently looped block ID with the ID of the last block of type "text"?

_entry.html:

{% set lastTextBlock = entry.simpleMatrix.type('text').last() %}
{% set lastTextBlockId = lastTextBlock ? lastTextBlock.id : null %}

{% for block in entry.contentBlocks %}
    {% include '_blocks/' ~ block.type|lower %}
{% endfor %}

_blocks/text.html:

{% if block.id == lastTextBlockId %}
    ...
{% endif %}


How do I query multiple element types in one query I have Craft Commerce installed, and I wanted to search title against both product title and variant title. I looked up in the database, I noticed that products and variants are of two element types, Commerce_Product and Commerce_Variant. As far as I know, with ElementCriteriaModel you can only query against one element type, like what I have now:

$criteria = craft()->elements->getCriteria('Commerce_Product');

Is it possible to query against multiple element types in one db call?

This is more of a limitation of Craft than Commerce, but it's currently not possible in one query... you'd need to do two and perform some merging/filtering logic.

Consider thumbs-upping/commenting on this feature request which would enable what you're looking for.


Search for related entries based on tags On an entry page I search for related entries based on the tags assigned to the respective entry. The following example works:

{% set tags = entry.q_tags.first %}

{% for tag in entry.q_tags.offset(1) %}
    {% set tags = tags ~ ' OR ' ~ tag  %}
{% endfor %}

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

I just wonder whether there is a smarter solution?

This should work:

{% set tags = entry.q_tags %}
{% set entries = craft.entries.relatedTo(tags).order('score').find() %}


How to display an asset (pdf) from both site languages on both sites? How do I display an asset (PDF) from both site languages on both sites? I would like to offer both German and English versions of a PDF on both the English and German sites.
I now have {{ entry.PDF.url }} and wondered if I can add a .site() direction to the entry query.

You could try and fetch the other pdf by creating an entry query for the different language, and getting the pdf from there.
{# if you have only 2 languages: #}
{% set otherLanguage = craft.entries().id(entry.id).siteId(['not', entry.siteId).one() %}
{{ otherLanguage.PDF.url }}

{# if you have more languages (and want all the PDFs: #}
{% set otherLanguages = craft.entries().id(entry.id).siteId(['not', entry.siteId).all() %}
{% for $otherLanguage in $otherLanguages %}
    {{ otherLanguage.PDF.url }}
{% endfor %}


Setting user password on creation / without full admin rights I'm trying to set a password for a user account while logged in without Site Admin permissions (the user does however have 'Edit Users+Administrate users+Assign Groups and Permissions + Remove User permissions all enabled). - Despite this they still can't change a password for a current user or even create a new user with a set password that can login to the system.

This is partially problematic as 'Verify email address' is not something the company is interested in so I'm looking for a solution to create a user on the backend that can login once their account is created without verifying or really receiving any email and without having to give full administrative access to my client just to set passwords? Seems like something that should be achievable especially with the permission 'Administrate Users' enabled.

Cheers.

Currently there isn't a way to do what you're looking for from the control panel, even if a user has "Administrate Users" permissions.

In the control panel, only current administrators can change an existing user's email or password and they must supply their existing administrator password to do so.  And even administrators can't set an initial password for a user from the control panel.

On the front-end, if you're running Craft Pro and you've enabled public registration, a user can set an initial password from the public registration form.


Route breaks Single Entry I'm following the documentation to create a thank-you page when the user submits the form.

I have a single created for /contact-us/ and I want the user to be redirected to /contact-us/thank-you/ when they submit the form.

I have created the route so contact-us/thank-you shows the contact-us template, but when I go to that URL I get a template error saying Variable "entry" does not exist.

So it looks like it's showing the template correctly, but not loading the data from the single.

Craft automatically includes the entry variable if the slug matches the url:

  If the URI matches an entry’s or category’s URI, the
  section’s/category group’s template will get loaded, and the matched
  element will be made available to the template via a pre-populated
  entry or category variable.

In your case contact-us gets matched automatically, but contact-us/thank-you does not. This means you have to set entry yourself.

Just add this to the top of your template:

{% if entry is not defined %}
    {% set entry = craft.entries.section('contact-us').first() %}
    {# Fetch single which has 'contact-us' as a handle #}
{% endif %}


Active class on node with NAVEE I have a simple nav tag

{% set navConfig = {
    'startwithActive' : true,
    'maxDepth' : 2,
    'activeClassOnAncestors' : true,
    'ancestorActiveClass' : 'active',
} %}
    {% nav node in navigation %}

        {{ node.title }}
        {% ifchildren %}

{% children %}

        {% endifchildren %}

{% endnav %}

This works fine all but with the News section entries. my-site/news adds the active class to the link, but my-site/news/new-entry doesn't add the class to the ancestor.

I have tried most configurations with the available parameters and variables, but I cannot work it out.

Any help would be brilliant!

I think what you want to look at is the Regular Expression option under the advanced tab for your my-site/news node. You could add something like:

 /^my-site\/news/i

This way all of the child pages in that section will mark the News page as active.

MW


Find Dropdown Option Labels That Are Assigned in a Section I can get a list of option labels available in a dropdown field using the code below.  Is there a way to get a list of option labels that have been assigned to entries in a specific section?

{% for cocktailTypes in craft.fields.getFieldByHandle('cocktails').getFieldType.options %}
    <p>{{ cocktailTypes.label }}</p>
{% endfor %}

I think you need to loop all entries of that sections to "collect" them.

{% set cocktailTypes = [] %}
{% for entry in craft.entries.section('mySection') %}
    {% set cocktailTypes = cocktailTypes|merge([entry.cocktails]) %}
{% endfor %}

{% for cocktailType in cocktailTypes|sort %}
    <p>{{ cocktailType }}</p>
{% endfor %}


Use paginate info in another block I'm trying to get my head around the following issue. I have a site which uses a base layout template base.twig, on which 3 layout templates are build (using extends). One of them is main.twig.

I want to use the paginate information variable pageInfo (see docs) in a block that's defined in the base template, to show the total number of entries found in the {% block pageTitle %}{% endblock %}. I tried a number of things, including defining a pageTitle variable in the base.twig template, to override in the content block, but all without any luck.

These are stripped down versions of my files:

_layouts/base.twig

        <title>{{ title }}</title>

        {% block header %}{% endblock %}

            {% block pageTitle %}{% endblock %}
            {% block main %}{% endblock %}

        {% block footer %}{% endblock %}

_layouts/main.twig

{% extends "_layouts/base" %}

{% block main %}

        {% block content %}{% endblock %}

{% endblock %}

posts/index.twig

{% extends "_layouts/main" %}
{% set title = 'My posts listing' %}

{% set entries = craft.entries... %}

{% block content %}
    {% paginate entries as pageInfo, pageEntries %}

            {% for entry in pageEntries %}

{{ entry.title }}

            {% endfor %}

        {% block pageTitle %}

{{ pageInfo.total }} entries found

        {% endblock %}

    {% endpaginate %}
{% endblock %}

I know this has to do with variable scopes, but how can I use the paginate information outside my content block? One solution I tried does indeed works, but do I really need to copy the {% paginate %} statement inside my pageTitle block to get this working? That seems to be very inefficient to me:

posts/index.twig

{% extends "_layouts/main" %}
{% set title = 'My posts listing' %}

{% set entries = craft.entries... %}

{% block content %}
    {% paginate entries as pageInfo, pageEntries %}

            {% for entry in pageEntries %}

{{ entry.title }}

            {% endfor %}

    {% endpaginate %}
{% endblock %}

{% block pageTitle %}
    {% paginate entries as pageInfo, pageEntries %}

{{ pageInfo.total }} entries found

    {% endpaginate %}
{% endblock %}

Hope you can help me out or point me in the right direction. Any tips regarding a better structure for the blocks are also welcome. Twig seems so popular, so you'd think it can't be that hard for such simple tasks? Maybe I'm using the whole block concept totally wrong in the first place.

As of Craft 2.5.2750, you can leave off the {% endpaginate %} tag, then move your {% paginate %} tag up outside of the blocks in the posts/index.twig template, and your pageInfo variable should be available to the whole template, including the parent template that you're extending.


Updated Image Transformation Aside from Defining Transforms in the template (http://buildwithcraft.com/docs/image-transforms) is there a way to go back and trigger an image transformation?

We've got a number of assets that have been uploaded to rackspace that need image an image transformation but the transformation was created after the images were uploaded.

Is there a way to kick this off?

I forgot we added a tool for this, too, under Settings->Tools->Clear Caches Tool->Asset Transform Index.


HappyLager Demo Site Forcing 'https://' on XAMPP When I try to load the demo site in my browser I get the following error:

https://imgur.com/8jVvweN "Your connection is not secure"

I have added the following to my hosts file:

127.0.0.7        happylager.dev

and this to my httpd-vhosts.conf file:

<VirtualHost *:80>
    DocumentRoot C:/xampp/htdocs/HappyLager/public/
    ServerName happylager.dev
    ServerAlias http://happylager.dev
</VirtualHost>

Content of .htaccess files:

The .htaccess file in the public folder contains:

<IfModule mod_rewrite.c>
    # 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>

The .htaccess file in the craft folder contains:

deny from all

XAMPP versioning information:

PHP Version 7.04
phpMyAdmin version 4.5.1

This error occured during step 7 and 8 on this page:

https://github.com/pixelandtonic/HappyLager

Rebooted as well just in case. When I try to resolve 'happylager.dev' or 'http://happylager.dev' the error still persists. The virtual hosts resolve other names without error. Any idea what I might not be considering? Any help will be greatly appreciated.

The issue here is actually the use of the TLD .dev. Google now owns that extension and in Chrome (which later, other browsers including Safari and Firefox enforced) it now forces the URL to go over SSL. If you don’t want to deal with all that self-signed certificate stuff to get SSL working locally, your best bet is to just switch the extension to something like .test and it should work just fine.


How do I create database tables for a craft cms plugin on install? I am absolutely new to craft plugin development and could not find any documentation on creating database tables specific to a new plugin. How are new tables created when a plugin is installed?

I am browsing through the source code for the CocktailRecipes plugin: https://github.com/adrianmacneil/cocktailrecipes/ and I cannot find how the craft_cocktailrecipes_ingredients table gets created when I install it.

Is it merely a matter of defining a record class like CocktailRecipes_IngredientRecord and then overriding the getTableName and defineAttributes methods?

Is that how craft cms builds the tables?

PluginNameRecord.php is how Craft installs database tables. You can also have multiple tables by using PluginName_TableRecord.php where 'Table' will be the name of the new table in the database.

Might also be worthwhile to mention that the cocktails recipe you linked to has a lot of issues as it has not been updated for the latest versions of Craft.

Sean Delaney updated that plugin and the new repository is here:

https://github.com/seandelaney/cocktailrecipes


How do I maintain paragraph formatting on textarea Guest Entries submission? I have set up a guest entries form that receives data from the textarea snippet below and saves it into a rich text field.

<textarea name="fields[comment]" placeholder="Join the discussion..."></textarea>

When I view the entry on the front-end there is no formatting, but on the backend there is formatting. Then when I save the entry on the back-end, suddenly there is formatting on the front-end.

Is there anyway to bypass having to re-save the entry to get the desired formatting?

RichText fields make use of the Redactor plugin library, which if I understand correctly, essentially parses line-breaks and wraps lines in properly formatted html <p> tags via javascript. However, when you save from the front-end, it doesn't have a chance yet to parse the data. Only when you view the data on the back-end and re-save does redactor get a chance to do it's thing.

You could use redactor on the front-end, although this is not recommended for various reasons as described here.
Or you could change the fieldtype to a regular textField and wrap everything in a <pre> tag in your template. <pre>{{ entry.myTextField }}</pre>
Or you could parse the string yourself via javascript before submitting it, wrapping your own <p> tags (hopefully it won't get double encoded).

There might be other options as well.


Build array from nodes from RSS where keys contain colons Probably pure twig:

I am building an array from nodes taken from a RSS-feed where one of the keys contains a colon which of course breaks everything. Like so:

Node in feed:

<media:thumbnail url="stuff I like to get." />

My twig:

{% for node in feed %}
        {% set latestArticles = latestArticles|merge([{
                'timestamp': node.pubDate|atom,
                'title': node.title,
                'uri': node.link,
                'description': node.description,
                'thumbnail' : node.media:thumbnail,
            }]) %}
        {% endif %}
    {% endfor %}

So how do I get media:thumbnail?

I have tried different things but without luck.

As @mats-mikkel-rummelhoff suggested, that data type is an array. So I was able to get the desired value by using:

'img' : node['media:content'][1]['@url']

Thanks, Mats.


Can only submit my Sprout Form form if I'm logged into my site I have a basic Contact form built in a site I manage for a client. But for some reason, the form fails to submit if I'm (or the user using the site) isn't logged into the site (CMS). But this site is a basic marketing site, so visitors to the site do not have Craft CMS user accounts. Any idea what could be happening here? The logs don't help.

This might not help but I've had a similar problem with a couple of my own modules and then with LInkVault that I went around in circles with. It suddenly stopped allowing non logged in users from downloading files. I contacted support who spotted the issue and fixed it in minutes. They gave this message:

Link Vault’s FrontEndController class has the allowAnonymous property set to true so that can’t be part of the problem

then a few minutes later:

Apparently, a recent Craft update added some logic in the craft\web\Controller::init() method that converts boolean allowAnonymous values to an integer which was part of the check that determines whether guests should be able to access a controller action. Link Vault’s front end controller had its own init() method but it wasn’t calling the parent’s init() method. So that is fixed now.

I leave this here in case it's any help either to this specific problem or anyone else with modules that run in to this issue.


SuperTable queries on fields in fields I have Event entries which contain (among other things) a SuperTable holding the schedule for that event.  Each row of the SuperTable contains (among other things) a field for a Session entry, in a column called sessions.  A Session entry contains (among other things) a field for a Person entry, called sessionSpeaker, who is the speaker for that session.  I also have a list of (usually) the same speakers in an Entries field outside the SuperTable; this is called eventSpeakerList.
What I’m trying to do is, for each speaker, find the ID of their session so I can output it as part of a hyperlink in a preview grid of speaker cards which points to the session in the detailed agenda.  So…
{% set speakers = entry.eventSpeakerList.all() %}
{% for speaker in speakers %}

[something something something]

<a href="#s{{ sessionID }}">
{% endfor %}

The problem is, I can’t figure out how to do the [something something something] to get the ID of a session based on the ID of the speaker.  When I say ID here, I meant the Craft ID, not a bespoke ID text field or whatever.
I’ve tried relatedTo() queries on the table, but never get anything back, probably because I didn’t structure the queries correctly.  I’ve tried search() queries; again, nothing.  Or, in some cases, massive object structures that didn’t contain anything I could figure out how to use.  I also tried looping through rows and trying to peer into the fields within fields, but couldn’t figure out how to make that work either.  I’ve searched this SE for similar questions, but the posts I found that seemed similar either had answers I couldn’t make work (again, quite possibly due to inexperience), or had no answers at all.
Maybe there’s a really simple way to do this and I can’t see it, or maybe it requires relation queries and I’m too inexperienced to understand how to structure them, or who knows.  But I could really use some help.  Let me know if you need clarifying details on the above, and I’ll edit them in.
--
EDIT: here’s a screenshot from the admin interface showing the supertable and the fields within fields.

I think I followed this breakdown, but a screenshot of the admin could be helpful as well if this answer isn't accurate...
{% set speakers = entry.eventSpeakerList.all() %}

{% for speaker in speakers %}
    {# Get the session entries for each speaker row #}
    {% for session in speaker.sessions.all() %}

        {# Get the person entries for each session #}
        {% for person in session.sessionSpeaker.all() %}

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

This is likely the first step to confirm it's getting the value you need. There are a couple of optimizations that we can make depending upon if there can only ever be a single session related to a speaker and if only a single person can be related to a session.
{% set speakers = entry.eventSpeakerList.all() %}

{% for speaker in speakers %}
    {% set session = speaker.sessions.one() %}
    {% set person = session.sessionSpeaker.one() %}

{% endfor %}

The next step would be to optimize the performance, by taking advantage of Eager Loading.
{% set speakers = entry.eventSpeakerList.with([
    'sessions',
    'sessions.sessionSpeaker',
]).all() %}

Then, that means you are getting arrays back instead of Element Queries. So something like this should work (against assuming only one session and one person is allowed in those respective entries fields)
{% set speakers = entry.eventSpeakerList.with([
    'sessions',
    'sessions.sessionSpeaker',
]).all() %}

{% for speaker in speakers %}
    {% set session = speaker.sessions[0] ?? null %}
    {% set person = session.sessionSpeaker[0] ?? null %}

{% endfor %}

Ok, here's an updated version after seeing the Admin UI, not sure if those field names are exactly right, since I can't tell from that UI:
{# Get all the super table rows and eager load the sessions and speakers #}
{% set scheduleSuperTable = entry.scheduleSuperTable.with([
    'sessions',
    'sessions.sessionSpeaker',
]).all() %}

{# Loop through the rows #}
{% for row in scheduleSuperTable %}
    {{ row.eventDay }}
    {{ row.timeSlot }}

    {# Assuming there can only be one session #}
    {% set session = row.sessions[0] ?? null %}

    {% if session %}
        {{ session.title }}

        {# Loop through all of the speakers in the session #}
        {% for speaker in session.sessionSpeaker %}
            {{ speaker.id }}
            {{ speaker.title }}
        {% endif %}
    {% endif %}
{% endfor %}


Can I get the value of an environment variable in routes.php (or other config files)? I am trying to get the value of an environment variable (defined in the general.php config file) in the routes.php config file. Is it possible or not? I tried $environmentVariables = craft()->config->get('environmentVariables')['myVariable'] but that throws an error: Call to undefined function craft().

I think you'll just need to do something like this in your routes.php file:

$general = require __DIR__.'/general.php';

return array(
    'foo' => $general['environmentVariables']['bar'],
);


Imager - connection refused error All assets on my website work properly, however I cannot resolve an issue with Imager plugin on a single page template.

My template:

    {% set profileImage = entry.user.photoUrl('original') %}
    {% set transform = {width: 90, height: 90, effects: { grayscale: true, gamma: 1.2 } } %}
    {% set transformedImage = craft.imager.transformImage(profileImage, transform|merge({width: 180, height: 180})).getUrl() %}

        {% if profileImage %}

        {% endif %}

When I try to open a page which uses this template I got the Craft Exception:

  cURL error “7” encountered while attempting to download
  “http://127.0.0.1:8001/cpresources/[...]/myImage.jpg/?d=1553875482”.
  The error was: “Failed to connect to 127.0.0.1 port 8001: Connection
  refused”

But when I open the image link directly it works normally. Checked permissions many times. What can be an issue here?

Thanks

Ok, so @brad-bell suggested a fix and the solution was to disable ::1 localhost rule from my /etc/hosts file. After that change all images are working properly.

More details can be found here https://stackoverflow.com/questions/22952676/curl-failed-to-connect-to-localhost-port-80

Thanks!


Remove the last comma in an inline list of tags? In a list of tags I'd like to remove the last comma. So is there something that works like the Ee backspace parameter?

There's a couple of special variables available while for looping through an array. In your case I'd make use of loop.last.

{{ tag }}{{ not loop.last ? ', ' }}

This is the expression using the ternary operator to keep the syntax short.


How do I print the number of entries assigned to a category? Okay, all I want to do is list all categories AND the # of entries associated with each category.

{% set numofEntries = craft.entries.section('posts').relatedTo(category).total() %}

    {% for categoryName in craft.categories.group('markets') %}
        {{ categoryName.title }}-{{numofEntries}}
    {% endfor %}

No error is thrown (and I am in dev mode), but the number that appears (49) is the same for all categories (and doesn't even equal the number of total entries).

A few things...

market group = markets ...
the category field handler = marketName

You'll want to query for the number of entries inside the for loop.

{% for categoryName in craft.categories.group('markets') %}
    {% set numofEntries = craft.entries.section('posts').relatedTo(categoryName).total() %}

    {{ categoryName.title }}-{{numofEntries}}
{% endfor %}


Display children's order numbers I thought this was going to be easy; showing the order number of children against their parent, but the only answer I can find is in this thread

and I'm unsure how to implement this into my code.

{% for chapter in entry.descendants %}

Part {{ chapter.orderNumber | numbersToWords }}

{% endfor %}

Resulting in: Part One

Note: numbersToWords is the Helpers Plugin by carlcs

If you're getting all the descendants in the for loop, you can use loop to get the index of the current iteration:

{% for chapter in entry.descendants %}

Part {{ loop.index | numbersToWords }}

{% endfor %}

See the documentation for loop in the Twig docs for more details.

This gives you the index of the current iteration in the for loop though, not the actual position of the child in the structure. So if you query only a subset of the descendants, or reorder and manipulate the descendants, this won't work.


How to remove siteName from the og:title tag with SEOMatic SEOMatic automatically adds the siteName after your title tag, which seems smart, but I don't think it's necessary for social sharing. Is it possible to tweak the og:title and twitter:title tag output in SEOmatic to remove the siteName?

My current seomaticMeta array looks like this:

{% set seomaticMeta = {
  seoTitle: entry.title,
  seoDescription: entry.shortDescription,
  seoImage: entry.thumbnailImage.first(),
  seoKeywords: '',
  canonicalUrl: entry.url,
  twitter: {
      card: seomaticMeta.twitter.card,
      site: seomaticMeta.twitter.site,
      creator: seomaticMeta.twitter.creator,
      title: entry.title,
      description: entry.shortDescription,
      image: entry.thumbnailImage.first(),
  },
  og: {
      type: seomaticMeta.og.type,
      locale: seomaticMeta.og.locale,
      url: entry.url,
      title: entry.title,
      description: entry.shortDescription,
      image: entry.thumbnailImage.first(),
      site_name: seomaticMeta.og.site_name,
      see_also: seomaticMeta.og.see_also
  }
} %}

However, the entry.title tag returns the title with the siteName appended.

Yes, it's definitely possible to do that, but you'll need to use Twig as per: https://github.com/nystudio107/seomatic/wiki/10.-Dynamic-Twig-SEO-Meta

However, you might not want to do that. Sometimes it's nice to have the site name show up in the title that's shared via social media, to tie in the branding. Your call tho!


How can I pass an array to an api call from my plugin? This isn't entirely Craft specific, but I am using this in my plugin so I guess if I get booed out - I deserve it.

I am working on a plugin that makes a call to a 3rd party API. I am using Guzzle to make the post/put requests and all is working well.

I am struggling though, now that I want to move beyond a 1:1 parameter:value query.

For example, I have this:

$client = new \Guzzle\Http\Client('http://site.com/api/');
$uri = 'users?id=' . $event->params['user']->id .
       '&first_name=' . $event->params['user']->firstName .
       '&last_name='  . $.event->params['user']->lastName;

$request = $client->post($uri, array('content-type' => 'application/x-www-form-urlencoded'));
$request->send();

So far so good.

Now I would like to add an "activities" parameter. Any user could have more than one activity. I am displaying them as a checkbox on my registration form - and I'm able to get the values. I am just not sure how to pass those values in my plugin to the api call.

$activities = $event->params['user']->activity;
$selectedActivities = array();

foreach ($activities as $option) {
    if ($option->selected) {
        $selectedActivities[] = $option->value;
    }
}

error_log(print_r($selectedActivities, true));

// [0] => 2
// [1] => 3
// [2] => 4

Each value is the id of the activity I am passing along.

How does that array get passed into my existing call? This is obviously incorrect, but here is what I am trying to do:

...
$uri = 'users?id=' . $event->params['user']->id .
       '&first_name=' . $event->params['user']->firstName .
       '&last_name='  . $.event->params['user']->lastName .
       '&activities=' .$selectedActivities;
...

I've tried using serialize() but I get some funky results.

Thank you for any suggestions!

EDIT

I have updated my calls accordingly - thank you for the tip!

I'm seeing all values come across except the activities array.

$client = new \Guzzle\Http\Client('http://mysite.com/');
$uri = 'api/students?api_token=123';

$post_data = array(
    'first_name' => $event->params['user']->firstName,
    'last_name' => $event->params['user']->lastName,
    ...

  );

$request = $client->post($uri, array(
    'content-type' => 'application/json'
));

foreach ($selectedActivities as $option) {
    $request->getPostFields('activity', $option);
}

$data = json_encode($post_data);

$request->setBody($data);
$response = $request->send();

Everything is coming across and getting saved correctly, I'm just not seeing 'activity' in the request at all.

Thank you again for your help!

You're right, this won't work— PHP doesn't know how to flatten an array into a URL param.

But! Guzzle has it's own way of collating multiple values for one param.

Basically, you build your query with Guzzle's API, then repeatedly add values to the same param with the getPostFields()->add() method.

# Note that the second argument below may need to be populated with your custom headers— but Guzzle may also take care of this when using this method…
$req = new \Guzzle\Http\Client('https://www.site.com/api/')->post('users', [], [
  'param' => 'val' # …and any other single-use keys can be set early
]);

foreach ( $selectedActivities as $option ) {
  $req->getPostFields()->add('param-name', $option->value);
}

I can't tell you how to visualize the URL this eventually builds, but I think the key is sending data in the body, rather than trying to manually build a query string (which still ought to work, but there are odd behaviors when duplicate params exist).


Craft plugin for input fields on the front end to check existing user I am trying to create a functionality in Craft where the user enter an email and the system is able to tell the user if the user exists or not similar to the attached screen:

I am very new to plugin development, and I am not even sure if I need one, I found this post, which looks very helpful, only thing is I really don't know how to implement it.
How to tell if user exists

Should I develop a plugin? And I don't understand the information on plugin website and I can't find an example where there is an input field on the front end.

If you are creating these as actual users in Craft, it should be possible to do it straight from the template without the need for a plugin, as long as you have Craft PRO (without PRO you anyways wouldn't be able to create more than one "admin" user, and one "client" user anyways):

See the documentation here:
https://craftcms.com/docs/templating/craft.users#email

Basically, you should be able to call craft.users.email('your.email@address.com') to check if it exists. Again, I haven't tested this myself, but it will then return the user if it exists, and otherwise I assume it will return null.


Migrating my Blogger site to CraftCMS Has anyone migrated a Blogger site to CraftCMS? I'd like to migrate comments and posts. What is the best way to go about this? Could I import my site to Wordpress and then to Craft?

I migrated a Blogger site by writing a Craft plugin to parse Blogger's XML and save images, posts, and categories into the Craft setup established with the client. The challenge with Craft is that last part: you're the one deciding how things will work, the CMS doesn't come with opinions about how your blog posts will be constructed or organized.

You can use the Feed Me or Sprout Import plugins to migrate your Blogger data, but you'll still need to set up your blog in Craft and decide how to map the Blogger data to your Craft install.

Comments are another animal. It may be easiest to move them to Disqus. I've not used this comment plugin, but expect it would be solid.


Make Redactor toolbar not fixed? How can I make the Redactor toolbar to not affix to the top of my viewport? I tried to modify the config files, but I had no luck!

The toolbar is now set to be fixed by default, even if you don't have that setting in your Redactor config file at all (this applies to all Craft installs before version 2.0.2527).

To make it scroll with you page again, edit you config file in craft/config/redactor/[config name].json and set or modify the following property to:

toolbarFixed: false

(This is not a typo! The property name changed from toolbarFixedBox to toolbarFixed with Redactor 10 / Craft 2.3. Craft's default configs will be updated with the next release got updated with today's release. Thanks to Brandon for the support!!)


View Sprout Form Entries in CP displaying error I'm running the latest Craft and Sprout Forms as of today.

On a clean install of Sprout Forms whenever I create a new form (even with just one text input field), I cannot access that specific form's entries in the CP. The "All Entries" view works, however.

There are two "unknown error" notifications in the CP. Here are the relevant errors in the log.

2016/02/23 11:40:06 [error] [system.db.CDbCommand] CDbCommand::fetchAll()
failed: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'form' in 'on
clause'. The SQL statement executed was: SELECT `elements`.`id`,
`elements`.`type`, `elements`.`enabled`, `elements`.`archived`,
`elements`.`dateCreated`, `elements`.`dateUpdated`, `elements_i18n`.`slug`,
`elements_i18n`.`uri`, `elements_i18n`.`enabled` AS `localeEnabled`,
`entries`.`id`, `entries`.`ipAddress`, `entries`.`userAgent`,
`entries`.`dateCreated`, `entries`.`dateUpdated`, `entries`.`uid`,
`forms`.`id` AS `formId`, `forms`.`name` AS `formName`, `forms`.`groupId` AS
`formGroupId`, `form-request-an-audit`.`title`, `form-request
an-audit`.`field_test` AS `test`

~

2016/02/23 11:40:06 [error] [exception.CDbException] exception 'CDbException'
with message 'CDbCommand failed to execute the SQL statement:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'form' in 'on clause'.
The SQL statement executed was: SELECT `elements`.`id`, `elements`.`type`,
`elements`.`enabled`, `elements`.`archived`, `elements`.`dateCreated`,
`elements`.`dateUpdated`, `elements_i18n`.`slug`, `elements_i18n`.`uri`,
`elements_i18n`.`enabled` AS `localeEnabled`, `entries`.`id`,
`entries`.`ipAddress`, `entries`.`userAgent`, `entries`.`dateCreated`,
`entries`.`dateUpdated`, `entries`.`uid`, `forms`.`id` AS `formId`,
`forms`.`name` AS `formName`, `forms`.`groupId` AS `formGroupId`, `form
request-an-audit`.`title`, `form-request-an-audit`.`field_test` AS `test`

I've uninstalled, re-installed, and everything in-between with the same outcome.

The form handle can't contain special characters like - or *, the validation of that field is not working, but we'll fix that in the next release. In the meantime please update the form handle.


Craft not loading custom 404 template for errors Whenever I hit a non-existent page on a dev site, I only get Craft's native 404 page, not the one I have at /craft/templates/404.html. The site has no routes. Any ideas why this might be?

Turns out the general.php file had the following line (docs) in it:

'errorTemplatePrefix' => "_errors/"

Once I'd created the proper folder and files, all worked as expected.

Thanks, @CraftCMS Twitter person!


How to handle soft delete behavior for a custom Element with custom content tables I have a custom Element (a Form Element) that adds a custom content table for each Element that gets created (similar to how the Matrix Field creates a custom content table for each field). Users can submit data to another custom Element (Form Entry Element) that stores data in that content table.

In my case, when a Form Element is soft-deleted it would need to preserve the custom field layout, tabs, fields, and related content table for the Form Element, along with all the related Form Entry Elements that get added to the content table.  And then, if the item was not restored, when Craft purges old Elements from the Trash, all of those items would also need to be deleted.

What are the general considerations I need to know about to handle soft deletes correctly? Are there any specific files or methods in the Craft codebase I can take a closer look at to better understand how this behavior works at the point of the initial soft delete and during the cleanup when things get hard deleted?

Yo, read the docs.

He says to himself quietly, having not visited the plugin docs in a while.


How to save a Matrix with Super Table in it I have an entry with a Matrix field, inside this field I have a Super Table as block type.  My fields data looks like below:

"title" => "test1"
"matrixHandle" => array:2 [
  0 => array:2 [
    "type" => "sponsorshipRow"
    "fields" => array:2 [
      "sectionTitle" => "blablabla"
      "superTableHandle" => array:5 [
        0 => array:3 [
          "fields" => array:10 [
            "relatedArticle" => 325051
            ...
          ]
        ]
        1 => [...]
  1 => [...]

Then I loop these fields

foreach ($fields as $key => $value) {
    $entry->setFieldValue($key, $value);
}

And last, I save the entry:

Craft::$app->elements->saveElement($entry);

But every data is saved except for the super table block. The super table block is not even created. Any idea please?

In the super table array, there has to be a type there:

"superTableHandle" => array:5 [
    0 => array:3 [
      "type" => 1//the field's id
      "fields" => array:10 [
        "relatedArticle" => 325051
        ...
      ]
    ]
    1 => [...]

For me, this id is 1. It can be found in database by running this SQL

select * from supertableblocktypes;

But I ran the code below before and found out the field's id is 81 which is not working for me, I don't know why

dd(Craft::$app->fields->getFieldByHandle('matrixHandle')->blockTypeFields);


Show posts related to entry AND all posts not related to any entry I'm struggling to get my head around relations. It seems overly complex for the simple thing I want to do.

I am using an entry field on my post to set relations by city. These entries are limited to a structure that has a list of cities. I am outputting a global variable that is the current location (city).

With the following code, I am able to get any posts from the current city.

{% paginate craft.entries.section("news").relatedTo(currentCityFilter).order("featured desc").limit(10) as pageInfo, pagePosts %}

{% for post in pagePosts %}

{{ post.title }}

Posted on {{ post.postDate.format("F d, Y") }}

        {{ post.body.getPage(1) }}

Continue reading

{% endfor %}

The problem is, I don't want to force the user to set every city when they wish to have a post display for every location.

What's the proper way to show any posts that don't have a city set and still filter posts that do have a city by the current city?

Similar question with no answer here: Get entries where relation matches or is empty

Building on this answer, and this question, here is what I would try:

Get the posts from the current city:

{% set currentCityPostIds = craft.entries.section('news').relatedTo(currentCityFilter).ids() %}

Get the posts with no city (uses search):

{% set noCityPostIds = craft.entries.section('news').search('-city:*').ids %}

Make one list of all the ids (twig merge filter):

{% set postIds = currentCityPostIds|merge(noCityPostIds) %}

Get all the posts with those ids:

{% set postsToPaginate = craft.entries.id(postIds) %}

Now you can paginate them:

{% paginate postsToPaginate.order("featured desc").limit(10) as pageInfo, pagePosts %}


Adding Google Analytics Code I'm 5 minutes new to Craft and G&T, but my client needs GA installed on their new site.

Any thoughts about how to do this?

Also, general SEO questions: are there SEO plugins a la wordpress that you guys can point me to?

Installing GA is easy... you can either put that info into a Global field, or include it as a separate Twig template.

As for general SEO... Check out the SEOmatic plugin or the Sprout SEO plugin.


Receiving duplicate Sprout Form submissions We're seeing duplicate submissions.  It's between 2 - 15 of the same submissions, usually 7. They come in irregularly over the next couple minutes after the first one. And only sometimes. They are all distinct in the database, and seem like copies of a legitimate user submission.

Does this sound like a known issue? What's the best way to approach troubleshooting this?

--- Update 19/11/2019 ---

Duplicate form submission protection through Invisible Captcha is enabled.

I'm using custom form templates with:

  {{ getCsrfInput() }}
  {{ craft.sproutInvisibleCaptcha.protect() }}

But not

  {% hook 'sproutForms.modifyForm' %}

--- Update 25/11/2019 ---

Setting the required time on form to 15 seconds, disabling the Enable Sprout Forms Protection option which automatically adds Invisible Captcha support for all Sprout Forms using the craft.sproutForms.displayForm() tag, removing {% hook 'sproutForms.modifyForm' %}, and keeping {{ getCsrfInput() }}{{ craft.sproutInvisibleCaptcha.protect() }}, allowed a submission to be recorded 13 times over the course of 2 minutes.

--- Update 27/11/2019 ---

The duplicate submissions came from from another, unprotected, instance of the form with it's own template. It submits without loading the redirect URL, clearing the form, or presenting any messages, leaving the user to click the button multiple times.

I believe the issue here is most likely that you just need to add the modifyForm hook to your custom templates. All the Captchas look for that hook and output the necessary hidden input fields and javascript that they need to do their thing when the form loads.

You can see how we include the modifyForm hook in the default templates. It can be added anywhere within the  tags.


Entry publishing workflow I am considering using Craft to develop a website for a client.
One of the requirements is that members have access tot he backend to edit a single entry.

Here is the use case:

entry is created manually by admins, unpublished
members are in a group with "editEntries:[SectionID]" permission only (no create, delete and others)
members edit their entry and submit for review/approval
admins publish the entry
members come back and edit the entry if necessary and submit for review/approval of changes
admin reviews changes and amend or approves the changes

The question is what would be the best way to achieve the following:

When a member comes back, edits and submits the entry (step 5), it create a new revision for review/approval by admins (step 6), but keeps the current revision published in the frontend.

Any thoughts on how to achieve this?

With a mixture of the permissions you mention above and user groups, you should be able to use the Workflow plugin to get the results you are looking for.


Developers or experts for Craft CMS V3 in Costa Rica I am looking for a Craft CMS developer in Costa Rica to help us with occasional issues

The best places to look for this are workwithcraft.com and the Craft CMS Discord #jobs channel


'Invalid argument supplied for foreach()' using Shopfiy Craft Plugin I have set up the Craft Shopify plugin on a new build.

I have also created a 'Shopify Product' field in the CMS on my entry within my Products channel.

However, whenever I try to view the product in the back end I get this error:

Any help would be massively appreciated.

Thanks,
Jay

Turns out this was an issue with 'https://' being in the store's URL in the CMS.


Is there any way which does not remove Specific Html tags from the redactor editor using striptags only? Is there any way to do it with striptags only or we have to use another filter?

You can simply use striptags filter which removes all HTML tags. But if you want an html tag to be not removed by striptags so you can pass it as argument, then It removes other tags except the ones you pass in.
In other words, if you don’t  want to remove  tag, just use it in this way:
{{entry.content|striptags('<strong>') | raw }}


Stop Redactor adding paragraph tags I'm using a Rich Text field for captions beneath images, so that I can add bold, italic and links. But I'd like the output HTML to be a single line; ie, no block-level tags like <p>, or line breaks. At the moment Redactor automatically adds <p> tags, around a single line of text.

I've tried setting both paragraphize and replaceDivs to false in my Redactor config JSON, as suggested in this answer but that seems to have no effect for me:

{
    buttons: ['bold', 'italic', 'link'],
    minHeight: 50,
    paragraphize: false,
    replaceDivs: false
}

Adding these 2 lines worked for me:

linebreaks: true,
enterKey: false

So the entire config is now:

{
    buttons: ['bold', 'italic', 'link'],
    minHeight: 50,
    paragraphize: false,
    replaceDivs: false,
    linebreaks: true,
    enterKey: false
}


Clicking New field on /admin/settings/field/new hangs site Running 3.2.4, and clicking on "new field" which calls /[admin]/settings/fields/new times out on our AWS servers where the DB is hosted in the cloud. It isn't an issue when everything's running localhost, but that's the only things we can see as a difference between them.

On the AWS hosted site, the CP and front end become unresponsive for that user in that browser for 15-20 minutes, but a newly created session from another browser works.

Could anyone else who similarly has their DB hosted on another machine try clicking Settings->Fields->New and see if it returns fast?

We discovered that the verbb/icon-picker plugin makes a call out to retrieve a file from it's cpresources cache and this was done with a fully qualified URL. Our AWS machines in CI/CD can be auto-provisioned and as such won't have their own name in the /etc/hosts file. So a call to https://fully.qualified.url/cpresources/577762fa/json/font-awesome.json?v=1556336828 was failing and hanging the site because it tried to get it five times in a row.

I've registered an issue with the Verbb folks, and put a PR together, so crossing my fingers!


Multiple Listeners (Handlers) on Event Is it possible to register multiple EventHandlers?
I mean something like this:
    Event::on(
        Entry::class,
        Entry::EVENT_AFTER_SAVE,[
           NotifyWhenCookPostedArticle::handle,
           RunSomethingElse::handle,
           DeSomethingDifferent::handle
        ]

I tried it and got a PHP Warning – yii\base\ErrorException call_user_func() expects parameter 1 to be a valid callback, second array member is not a valid method
Is there a notation or helper to get this to work?
Thanks in advance .
Michael

I don't think that syntax is possible, and in any case it could get a bit confusing. Why not simply use a single anonymous function and then call your individual handlers inside that e.g.
Event::on(
    Entry::class,
    Entry::EVENT_AFTER_SAVE, function(Event $event) {
        $this->NotifyWhenCookPostedArticle();
        $this->RunSomethingElse();
        $this->DoSomethingDifferent();
    }
);

public function NotifyWhenCookPostedArticle() {
    return 'woop';
}

(Depending on how separate those things are and/or how large and complex you expect the site to be/become, you would typically abstract them further into your Services layer for reusability and encapsulation).


Social sharing plugin for Craft 3 Is there a social sharing plugin ready for Craft 3? There is no listing in the new plugin store nor do the V2 offer a revision.

Here are the social media plugins I see on https://plugins.craftcms.com (which is the public version of the plugin store).

Sharing related:

https://github.com/boscho87/facebook-connector
https://github.com/Rias500/craft-notifications
https://github.com/Rias500/craft-telegram-notification-channel

Integrations that don't appear to deal with sharing:

https://github.com/bymayo/craft-dribbble
https://github.com/dukt/facebook
https://github.com/dukt/social
https://github.com/dukt/social-github
https://github.com/dukt/social-linkedin
https://github.com/dukt/twitter


Display entries based on 'entries fields' I want to display blog entries within the related entry template linked together with 'entries fields':

-- Entrysection Bla

Blog
-- Blog entry 1 (Linked to Entrysection Bla via 'entries fields')
-- Blog entry 2 (no relations)

Now I want to display Blog entry 1 in Entrysection Bla

{% for entry in craft.entries.section('bla') %}
  {% for entries_fields in craft.entries.section('blog'){# related to ??? #} %}
     {{ entries_fields.title }}
  {% endfor %}
{% endfor %}

I figured it has to be done with relatedTo but I cant get it done. How do I have to write this?

-- Edit:

Now my code on Entrysection Bla looks like this:

{% set entries_fields = craft.entries.section('blog').relatedTo({
   sourceElement: entry,
   field: 'blogSaisonKategorie'
}) %}

{% for xy in entries_fields %}
   {{ xy.title }}
{% endfor %}

That prints out nothing. No error is displayed as well.

You are correct in your assumption! Using relatedTo with the associated field:

{% set entries_fields = craft.entries.section('blog').relatedTo({
    sourceElement: entry,
    field: 'fieldHandle'
}) %}

Note that field can be the field handle of your Entries Field but it can also be a field ID.


Why is ElementsService forgiving of an element type whose populateElementModel() method doesn’t return an actual element model In the 2.3 release notes, one item reads:

  ElementsService is now forgiving of an element type whose populateElementModel() method doesn’t return an actual element model.

I'm curious what the use case is here — When would populateElementModel not return a BaseElementModel, and why would that be okay?

Someone requested it. They had a use case for it where they couldn’t simply prevent the rows from getting selected in the DB query with a conditional (which is still definitely the recommended way to go). The only reason I decided to add it was for the sake of defensive coding.


getTransactionByHash() must be of the type string, null given I'm building my first Payment Gateway (offsite gateway) for Commerce 2.  This one is for Moneris.  I'm hitting an error when the page returns the response.

Argument 1 passed to craft\commerce\services\Transactions::getTransactionByHash() must be of the type string, null given

I'm pretty sure I need to do something in completePurchase with the response given, but I don't really understand where to start.  I've looked at Mollie and Paypal Express for exemples and I can't figure it out.  Can anyone point me in the right direction?

Here is the Post Moneris is sending me back:

$_POST = [
    'response_order_id' => '85a6df720018874fde293aa3418e7a97',
    'date_stamp' => '2018-09-11',
    'time_stamp' => '08:37:36',
    'bank_transaction_id' => '660186290010010030',
    'charge_total' => '88.10',
    'bank_approval_code' => '945622',
    'response_code' => '027',
    'iso_code' => '01',
    'message' => 'APPROVED           *                    =',
    'trans_name' => 'purchase',
    'cardholder' => 'Test Card',
    'f4l4' => '4242***4242',
    'card' => 'V',
    'expiry_date' => '2108',
    'result' => '1',
    'txn_num' => '3-0_11',
    'cvd_response_code' => 'M',
];

Thank you!

When you redirect to the gateway's site to accept payment, within the data they receive, they usually ask for the URL to return to after payment is made.

This URL should point to the PaymentsController::actionCompletePayment() controller action, but have the param ?commerceTransactionHash=YOUR_TRANSACTION_HASH appended to it.

My guess is that the error you are getting is being triggered in PaymentsController::actionCompletePayment() on line 346:

$hash = Craft::$app->getRequest()->getParam('commerceTransactionHash');

$transaction = Plugin::getInstance()->getTransactions()->getTransactionByHash($hash);

Where it is passing null to getTransactionByHash.

Once it is able to get the transaction, it will call your gateway's completePayment method where you can inspect the request data from your gateway.

Hope that helps.


Hide/show element actions dependent on tab I have a custom element index with an element action to 'Approve' elements.
The element index has 'Live' and 'Staged' sources.
Where/how do I set it to only show this action on the 'staged' source OR just on a selection that contains an element that is not approved (latter probably better).
I've looked at the existing 'Delete' action and see that this uses a data attribute on the element index items 'data-deletable', how do I inject my own data attribute into the listing i.e. 'date-approvable'?

I've figured out how I can do it, but it doesn't feel like the best way.
What I've done is hooked on to the showActionTrigger event, then hidden the button if the source != 'staged'
showActionTriggers: function() {
    this.base();
    if (this.$source.data('key') != 'staged')
    {
        $('#button-id').hide();
    }
}

I have a feeling the best way is to build the JS on the element action class, under getTriggerHtml, but this will do for now.
Slowly getting my head around the CP js


Feedme plugin - importing users into craft commerce I have few questions about importing users into Craft CMS using feedme. These users would be also Craft Commerce customers.

Users will be imported without passwords. Would this provide some kind of security risk, for example, someone being able to log in with empty password?
Setting new passwords for users - would I need to write custom module to send password reset form to each imported user? Would not sending 5000 emails at once choke Craft - maybe I should use tasks for that?
Addresses - do i need to write some custom plugin for importing adddress data along with basic user data like email? I didnt saw any fields for setting up user address when i tested importing users using feedme. Did someone managed to tackle this issue in the past?

Users will be imported without passwords. Would this provide some kind of security risk, for example, someone being able to log in with empty password?

I don't think the imported users will be able to login at all without a password.

Setting new passwords for users - would I need to write custom module to send password reset form to each imported user? Would not sending 5000 emails at once choke Craft - maybe I should use tasks for that?

I handled this by setting a message on the login and forgot password pages, skipping the need to send an email. Something like "Our systems were upgraded on 10-20-2020, if you've not logged in since then you'll need to reset your password first".

Addresses - do i need to write some custom plugin for importing adddress data along with basic user data like email? I didnt saw any fields for setting up user address when i tested importing users using feedme. Did someone managed to tackle this issue in the past?

Yes, you will need to use a custom module/plugin and listen to feedme events and handle address import with your code.
Something like:
 Event::on(Process::class, Process::EVENT_STEP_AFTER_ELEMENT_SAVE, function (FeedProcessEvent $event) {
   /// your code here dealing with $event->feedData;
});


How do I change a cart into an order? I'm building a site that is driven by Craft Commerce but does not take payment online. Rather, the customer adds what they need to a cart and submits to the company for a quote.

I need to build a contact form that allows the customer to submit their name, email, phone, and company name. When submitted, the form should also turn the cart into an order. I've tried setting 'isCompleted' to 'true' and setting the 'dateOrdered' but cannot seem to get the cart to transition into an order.

Below is the code I've been testing to try to get the cart to convert into an order. I feel like I'm missing something obvious. Any advice is appreciated.

<form method="POST">
    <input type="hidden" name="action" value="commerce/cart/updateCart">
    <input type="hidden" name="isCompleted" value="1">
    <input type="hidden" name="dateOrdered" value="{{ now.format('Y-m-d H:i:s')}}">
    {{ getCsrfInput() }}

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

Edit: Here's the working code as suggested below, where "2" is the ID of the manual payment method I created.

<form method="POST">
    <input type="hidden" name="action" value="commerce/payments/pay">
    <input type="hidden" name="paymentMethodId" value="2">
    {{ getCsrfInput() }}

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

I don't think you can do it like that - in Commerce, the order gets completed when a payment is made.

Fortunately, you can use the manual payment mechanism, which automatically completes the order, as the fake 'payment' type to get this to occur.  Just go in to Commerce settings and create a new payment type of 'manual' set to 'authorize only', and give it a name like 'Get Quote'.

To actually complete the order, you'll need to post the manual paymentMethodId to a call to commerce/payments/pay.  If you're doing this in a contact form, you'll have to intercept the form submit and post this via AJAX I guess.

Alternatively you could write your own controller to complete the order with some plugin code, but the above solution is essentially built in an intended for this sort of thing.


Trouble understanding eager loading I've tried to apply eager loading per Craft's docs, but it doesn't seem to work. When I do this, will I have access to all the entry fields? If not, do I have to include all the fields I want in the with attribute?

{% for entry in craft.entries.section('news').with['image'] %}
  {% set image = entry.image[0] ?? null %}
  {% if image %}
    <img src="{{ image.url }}">
  {% endif %}
  {{ entry.title }}
{% endfor %}

When I tried it, the code barfed when trying to output {{ entry.title }}.

The original answer is good, but as noted, somewhat incorrect, at least concerning a chainable .with() method.

Here's my attempt to explain things: Speed up your Craft CMS Templates with Eager Loading


Invalid plugin: No plugin exists with the handle - Craft 3 I had an issue with my site running Craft 3.1.15 where I wasn't able to update the site to the most recent 3.1.16, and also wasn't able to install any plugins. Every plugin I tried would throw this error:

  Blockquote Invalid plugin: No plugin exists with the handle "plugin-slug"

I tried creating a fresh install of craft through composer, this time running 3.1.16, and I'm faced with the same error. All my other craft sites run locally seem to update fine and have no issues installing new plugins. Is there an issue with the latest craft updates? Or is there something I need to do to resolve this?

For future reference, I had the same error and resolved it with Craft Support.

In my case the project.yaml file got out of sync with what was in the database.

Running craft project-config/rebuild from the project's root resolved the issue and allowed us to re-enable the plugins


Adding file uploads to commerce product line items? Does anyone have any experience with adding file uploads to the add to cart forms on product pages within commerce? I've seen some examples of users attaching them to orders (didn't work for me), but I'm looking to give customers the ability to attach per each line item.

You will not be able to upload an asset into a line item at Commerce 1 or 2.

You only 2 options are

1) Upload the asset to an order custom field(s). Submit a new question with your code if this is not working for you.

2) Upload the asset anywhere else, (including optionally the order), and then put the URL of the asset into the line items options data. See https://docs.craftcms.com/commerce/v2/adding-to-and-updating-the-cart.html#line-item-options-and-notes