Structure Navigation - Not returning sub nav entries

Is there a chance that you're getting the another entry with the the same slug as your mainEntry? I'd try to further filter it down by adding section() for example.

As I wrote in the comments, try to loosen the second ElementCriteriaModel by removing the level parameter.

Another idea would be to use the dump() function on your mainEntry (only works with dev-mode turned on).


Making Craft\DateTime Object from string in Twig

Unfortunately, what you're trying to do, is not possible without writing a simple plugin to return a Craft\DateTime object that the day picker can work with.

The global variable now, is a Craft\DateTime object, which the date picker is happy to work with because it can call localeDate() on it.

However, anything returned by date or date_modify twig filters, will be a \DateTime object, which lacks functionality that the date picker relies on.

Your only option would be, to create a simple plugin that can take your date parameter, and return a Craft\DateTime object, which you can pass as a value to the date picker/date macro.

This is one of those things that you think, "this should be easy or at least possible", but I haven't found a twig-only solution yet.


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

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


I don't think it's possible out-of-the-box, but you might be able to get something like that working with a shortcode approach. You could make a custom shortcode with a link parameter, and in the function for that shortcode, look up that link parameter's corresponding entry and find out its status. Then the shortcode could output a link if the entry was published, and just the original text otherwise. Here's a plugin that lets you add shortcodes: https://github.com/samhernandez/craftcms-shortcodes. If you wanted to get really fancy, you could even make a new redactor (the WYSIWYG editor Craft uses) button that inserts the shortcode instead of the normal anchor HTML.

This approach would probably take a bit of work, though. I'd be interested to see if anyone else has a better solution.


Template output when grouping matrix blocks

If by grouping you mean wrapping each groups in a
 for example, this should do it for you:

{% set groupCount = 0 %}
{% for block in entry.blocks %}

    {% switch block.type %}
        {% case "headingBlock" %}
            {{ groupCount > 0 ? '
' }}

            {{ block.header }}
            {% set groupCount = groupCount + 1 %}

        {% case "richtextBlock" %}
            {{ block.richtext }}

        {% case "imageBlock" %}
            {{ block.image.one().url }}
    {% endswitch %}

{% endfor %}

Changing the fields/blocks name accordingly of course.


Matrix Error - "Field Limit is too big for your chosen Column Type"

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

Neither. :)

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

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

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


How do I limit entries retrieved except those with a sticky lightswitch on the entry?

One method is to check to see if item is not in array before merging. The downside is that the entries will just be appended vs sorted by meetingDate.

{% set stuck = craft.entries.section('meetings').relatedTo(subcategory).sticky('1').order('meetingDate desc').find() %}
{% set entries = craft.entries.section('meetings').relatedTo(subcategory).order('meetingDate desc').limit(2).find() %}

{% for stuckEntry in stuck %}
    {% if stuckEntry not in entries %}
        {% set entries = entries|merge([stuckEntry]) %}
    {% endif %}
{% endfor %}

The other method is to grab the ids from the 2 queries and then merge them together, and perform a new query which can be sorted.

{% set stuckIds = craft.entries.section('meetings').relatedTo(subcategory).sticky('1').ids() %}
{% set entryIds = craft.entries.section('meetings').relatedTo(subcategory).limit(2).ids() %}

{% for id in stuckIds %}
    {% if id not in entryIds %}
        {% set entryIds = entryIds|merge([id]) %}
    {% endif %}
{% endfor %}

{% set entries = craft.entries.id(entryIds).order('meetingDate desc') %}


How can I delete entries from an entries field from a front-end from?

Here is what I came up with that seems to be working well. Please let me know where there is room for improvement so others (including myself) can benefit!

JS

var arr = [];
var data = {};
$('.remove').click(function (event) {
    var clicked = $(this).data('id');

    $('input[name="fields[myEntriesField][]"]').each(function (key, val) {
        var value = $(val).val();
        arr.push(value);
    });

    // Check if we are sending anything.
    if (arr.length == 0) {
        data.arr = null;
    } else {
        data.arr = arr;
    }

onRemove(data, function (response) {
    // response
});

function onRemove(data, callback) {
    data[window.csrfTokenName] = window.csrfTokenValue;
    ...
    // ajax
}

Controller

 $userModel->getContent()->setAttributes([
     ...
     'myEntriesField' => craft()->request->getPost('fieldHandle'),
 ]);

Now if I click the "Delete" button, each entry is removed from the user's profile. If I delete the last entry, I pass null to the controller. This tells Craft that there are no entires to save in the entries field.

Hope this helps someone else!


What is the URL of the page, where the link to /about is shown?
Make sure you do not have a  tag in the source of the page
Make sure you are not switching from http:// to https:// (SSL), which could also cause the 404 if the host is not available on http:// AND https://


Is it possible to update a Freeform submission via twig?

Update: Solspace informed me this could be accomplished with a custom module and using a Freeform event, specifically this one:
https://docs.solspace.com/craft/freeform/v3/developer/submission-events.html#before-a-submission-is-submitted".
So, in my example, I will need to move my lat/lng logic into the custom module so it happens before the submission is submitted. Then, on the result page, grab the lat/lng from the submission data.


Currently, the "file kinds" list is hard-coded and doesn't expose itself to a config setting or plugins.

You can definitely make a feature request to open it up, though!


Craft will automatically 'rotate' logs into new files as each current file reaches the maximum size (~1MB).

This is why, if you look in /craft/storage/runtime/logs, you may see craft.log, craft.1.log, craft.2.log, etc.

(I think Craft keeps a max of 5 files around before rotating them off into the ether.)

At present, the max size, naming convention, and max log file count, are all not configurable. (To my great chagrin.)

If you want to rename/archive logs for your own purposes, you'll have to create your own workflow for that, either by scripting it and running it as a cron job, or by using a third-party aggregation/archival service such as Papertrail.


How can I retain entry category filtering on entry pages' pagination

So, the solution, as provided by @Maverick in their comment above, is just to pass the variable as a query param (?cat=foo), and check for that query param's value in the template.


You'll need to use the global set's element ID as the reference part (second segment) of the reference tag:

{globalset:51:siteUrl}

To find the global set's ID, go to CP -> Settings -> Globals. The URL to the global set will have the ID as the last segment (e.g. http://yoursite.craft.dev/admin/settings/globals/51)

Also, see the this SE thread for a little more info: How can I use a reference tag with a global set using the handle (not the ID)


In your Twig example your '.picutures' class name includes a leading dot. Maybe not what you want there.

Also in your slick configuration 'slidesToShow' should be 1 if you only want to show one slide at at time.

And slick is going to operate on the direct descendants of the selector class identified in the configuration so the intervening divs may be causing a problem depending on the associated CSS.


The error you’re getting is a bug in Craft. (Just fixed that for the next release.)

To work around it, replace the {% set authors ... %} tag with:

{% if bookIds|length %}
    {% set authors = craft.entries()
        .section('authors')
        .relatedTo({ sourceElement: bookIds, field: 'books' })
        .all() %}
{% else %}
    {% set authors = [] %}
{% endif %}


Craft 2.3 upgraded Redactor to version 10, which comes with a completely new API for plugins. This broke RedactorStyles which relied on the old API.

I've updated the plugin now, so downloading version 0.3 should make it work with Craft 2.3. Beware that the plugin isn't 100% backwards compatible, due to changes in Redactor and its API, so read the docs.


I'm not sure if it's the same thing, but if the queries you are caching are complex (nested queries, etc), it may be caused by the queries being serialized in Craft 3. Have a look at Brad's answer to a question I had a while go, to see if it covers your case as well:
Caching in Craft 3 causes out of memory when including grouped for loop

I ended up using the Cache Flag plugin to work around this.


Running a console command produces an error mentioning sessions. How do I resolve?

You probably have a plugin which is listening to the userSession.onLogin event and trying to access the current user from the session.

The solution is for the plugin developer to wrap the event listener to ignore console sessions like this:

    if(!craft()->isConsole())
    {
        craft()->on('userSession.onLogin',
            [
                craft()->market_customer,
                'loginHandler'
            ]
        );
    }


How would you template for Infinite Scroll?

Got it.  Using the CraftCMS paginate example - I just needed to add the pagination url for the next page.


Populating TAG page when using the kebab filter

For your link, change {{ tag.title | kebab}} to {{ tag.slug }}

Then on your tag.html page change your tag variable to this:

{% set tag = craft.tags.slug( craft.request.segment(2) ).first() %}

This is how I have it set up and works fine.

Edit: Forgot the route needed: Add this to your routes.php: 'tags/{slug}' => 'tags/tag',


I don't think you're going to be able to do what you're looking for purely through Twig.

You can, however, write a plugin that either uses a service and variable or a Template Hook, so you can drop down to the PHP level and use DbCommand's where to apply your extra date conditionals to your SQL query directly.


How should I set an arbitrary session value in a plugin?

Try this:

$cookie = new HttpCookie('myCookieName', $data, [ 'expire' => time() + 3600 ]);
craft()->request->getCookies()->add( $cookie->name, $cookie );

Your code for reading the cookie is fine.

Also – since you use the term "session value" and tagged your question w/ "security" – I'd like to point out that cookies and session variables are different things. The former is stored on the client (the browser), the latter only on the server.

Unless you specifically need a cookie (e.g. because you want the data to persist a certain amount of time) it might be better to just create a basic session variable, using the HttpSession service:

craft()->httpSession->add( $key, $value ); // Set the session variable
craft()->httpSession->get( $key ); // Get the session variable

Read more about session variables vs. cookies here


I want to display entries that have a field that is the same as a field in a global variable

Since you've confirmed that the issue is in the if statement and I can see your comparison, I'll clarify usage and propose a solution.

The in operator, is a containment operator and it expects a scalar|primitive value on the left and an array|iterable on the right.

I am assuming that entry.publishYear is an int or a string: 2017. However, I'm not sure about currentEdition.currentYear. It seems like it's also an int or string: 2017.

If the currentEdition.currentYear is not an array or an iterable item, you should use == instead of in.

{% if entry.publishYear == currentEdition.currentYear %}

Have you tried that? Or can you try it and let me know?


Adding multiple slashes after the site URL breaks the current entry, but still loads the template

Are you getting the About template or the layout template it extends?

In a test with a local site I have running, I was able to trigger a 404 for any bad requests by putting

{%  redirect 404 %}

inside the main block in the _layout template.

This works in my case because that block is overridden on every request. If it's not, something has gone wrong and I need to exit out since the layout template should never render on its own.


How to add a non-breaking space to a rich text field?

What about using CSS white-space: nowrap; instead of &nbsp; characters? I guess that's semantically more correct and this also allows you to prevent your text to break at any other character (great for phone numbers etc.).

CSS:

.nobr {
  white-space: nowrap;
}

Markup:

my phone number is +1 800-275-8777

To add this easily to your Redactor fields markup, have a look at the inline format API or the formattingAdd config setting (I actually had mixed experiences with that setting).

If you'd like to be able to add this with the click of a button, I also just added this to my Redactor Inline Styles plugin, which is a collection of (optional) buttons to apply inline styles to your Redactor texts (Quotes, Code, etc.).


How do I use an if/else statement to determine if a field is filled in?

You can use the length Twig filter for that.

{% if entry.featureImage | length %}
    {% set image = entry.featureImage.first() %}

{% endif %}

If there isn't an image in featureImage then nothing will be output.


convert_encoding is screwing up Spanish-language characters

You shouldn't need any convert_encoding here. From your results, the special characters are coming out fine, it's your &nbsp that is your problem.

For this to go you can use the |raw Twig filter.


Yii does have the equivalent populateRecord and populateRecords on CActiveRecord.

However, on both the populateModel(s) and populateRecord(s) methods, you should be very cautious of blindly mass-assigning untrusted inputs to models/records that participate in the Active Record pattern (like Craft/Yii does).

They can be susceptible to what's known as the Mass Assignment Vulnerability that many popular frameworks have been a victim of.

Yii does what it can to protect against this, but my personal preference is to explicitly assign each individual attributes on the model/record in the case of untrusted input to avoid the issue altogether.


Is there a way to prevent Craft from backing up the database before updating?

Yes you can use the backupDbOnUpdate config setting:

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


Database Connection Error after updating from Craft 2 to 3

Does the table prefix value in you .env file need to be in quotes? eg
DB_TABLE_PREFIX="craft"


Passing Entry to craft()->templates->render()

You can just pass in the EntryModel straight to the view.

$html = craft()->templates->render('path/to/template', [ 'entry' => $entryModel ]);


How to remove relationships between entries

A relationship field expects an array of element IDs. So to remove a user, you'd just get all the current IDs and remove
the one you want to delete.

// Get the current member IDs
$members = $entry->accepted->ids();

// Remove a member ID
$key = array_search(52, $members);
if ($key !== false) {
    unset($members[$key]);
}

// Add a new member ID
$members[] = 83;

// Update the member IDs
$entry->setContentFromPost(array(
    'accepted' => $members
));


What's the best approach to building a photo gallery in Craft?

Craft is so flexible there are many ways to do most things, it is up to you to determine what is best for your needs.

As far as photo galleries go, there are two main ways that I normally approach this:

Method 1:

Define asset fields for the images, where you define the photo title and description, etc.  These fields are accessed by double clicking the image, which will pull up a form with the fields you have defined.  This method associates these fields directly to the assets themselves, and the data will be available site-wide, not just in the gallery.

While this is simplest to code, it does have the drawback that clients will often skip over the asset fields and add images to the gallery that have not been assigned all of the data needed for the gallery.

Method 2:

Use a matrix block to define the gallery and create matrix fields for the assets and associated fields.  This is much easier for clients as they can see each bit of data they need to enter, and you can even make the fields required so they do not avoid entering them.

While much simpler for the client, this method does has several drawbacks. First, the data entered into the matrix block will only be available in the context of the gallery and not anywhere else in the site. Second, a gallery built from matrix blocks can become quite lengthy in the back end and take up a lot of space on the edit page. And lastly, this method is a bit more complex to code than just a simple assets loop. Once you get the hang of it it is no biggy, but you will need to work through nested matrix/asset loops the first time.

Here is the code I use for a very simple matrix based gallery w/o titles or descriptions, best of luck :)

{% set vertParams = {
  height: 800,
  mode: 'crop',
  position: 'center-center',
}
%}
{% set horzParams = {
  width: 800,
  mode: 'crop',
  position: 'center-center',
}
%}
{% set thumbParams = {
  width: 120,
  height: 120,
  mode: 'crop',
  position: 'center-center',
}
%}
{% set images = contentBlock.galleryImages %}
{% if images | length %}
  {% if contentBlock.galleryTitle | length %}

{{ contentBlock.galleryTitle }}

  {% endif %}

    {% for image in images %}

      {% if image.getHeight() > image.getWidth() %}

      {% else %}

      {% endif %}

    {% endfor %}

{% endif %}


Craft 3 updates & plugins without allow_url_fopen or SSH

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

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

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


Have a look at the slice filter. To return 140 characters max. you would do something like this:

{% if entry.body %}
    {{ entry.body|slice(0, 140) }}
{% endif %}

See this other question on a similar topic if you want to apply this on a rich text field. Because this solution only works with plain text.


Returning entries that contain both categories

Answer for Craft 2
Your final result should not look like relatedTo('and', '1,2') but
relatedTo('and, 1, 2')

Or
relatedTo(['and', 1, 2])

So you just need to do
relatedTo('and,' ~ param)

Keep in mind to code defensively, so you might want to check if your query param is not null or something
Answer for Craft 3
relatedTo(['and', ['element' => 1], ['element' => 2]])


Can't install Craft 3 when deploying to AWS EC2 instance - Template not found: install Template not found: install

I suggest you to read the documentation about how to install Craft there is no such install process anymore. You just need to follow these steps, install it via composer, run the setup ./craft setup and you are done. So there is no admin/install anymore like in Craft 2


PHP Login & Sessions without Craft Commerce?

If you're trying to create a front-end login form, I'd suggest using this as a starting point: https://docs.craftcms.com/v3/dev/examples/login-form.html


Based on your screenshot, you're using the Personal version of Craft, which only allows for one user, which is why you won't see a Users section in the sidebar or the Settings screen. If you upgrade your install to Client or Pro you'll see those Users sections appear

Also worth a note, in Craft 3 and the latest version of Craft 2, the editions have been renamed to Solo and Pro. Solo is just like Personal: only one user allowed, whereas Pro allows for more than one user.


For local development the Caddyfile looks like this (assuming that php-fpm runs on port 9000, you may have to adapt root to point to your web root relative to the location of the Caddyfile):

localhost:2020 {
    root public_html
    fastcgi / 127.0.0.1:9000 php
    rewrite {
        r .*
        to {uri} {uri}/ /index.php?p={uri}&{query} /index.php?{query}
    }
}

Edit: For Caddy >= 0.9.x the rewrite has to be changed to this:

rewrite {
  to {path} {path}/ /index.php?p={path}&{query} /index.php?{query}
}


Can you set async defer when using {% includeJsFile %}?

As of Craft 3 (Tested using RC5) you can do it like this:

{% do view.registerJsFile("path/to/script.js", {"async":"async", "defer":"defer"}) %}

Source: Documentation for Yii's view.registerJsFile()


Is it possible to disable `requireUserAgentAndIpForSession` for specific instances?

Currently, no... it's an all or nothing thing and you'll have to disable it globally.


How to Auto-generate a Title based on a multiple entries titles? (using a Entries field type)

Not sure if this can be done in the shorthand syntax, but you can do this using Twig for the dynamic title format. The key is to use map to turn an array of entries into an array of titles and then join them. Something like this should work:
{{ object.movies.all()|map(movie => movie.title)|join(', ')|default('No movies selected') }}

Also note the default filter, which is a nice fallback in case no entries are selected in your movie field.


Is it possible to replace uploaded assets?

This actually is possible if you navigate to the folder or sub folder where you are trying to add the asset and then upload a file with the exact same file name.

Craft will ask you if you want to replace the existing file or upload another version with an appended name (for example "my-file-1.txt")


Personally I would use categories for a 'facetted search' filter you describe, as categories are less likely to get out of control. e.g. If tags are seldom re-used then a search for a tag may only produce a single result.

This plugin may help you: https://github.com/iainurquhart/FacetedNav_CraftPlugin

If you're going to use tags then I suggest making use of Craft's search functionality as this will allow you to submit the tag as a search term and also display any entries which contain the word/tag in ANY field of the entries within Craft.


Updates available on local copy but don't show on live site

Generally, it’s perfectly safe to update locally and push the changes live.

Two things to keep in mind:

If there were any migrations in the update, your production site will be put in Maintenance Mode when you deploy the update, and you will need to visit the Control Panel and click the Finish Up button to complete the update. You can tell if this is going to be necessary by checking craft/app/Info.php and seeing if the CRAFT_SCHEMA_VERSION has changed, or by checking to see if there are any new files within craft/app/migrations/.
If you update locally and then a second update is immediately available, the chances are that you hit a “breakpoint update”, which means that you have to update TO a certain release before you can update PAST it. That will apply to your production site as well, so in that case, you will actually need to deploy the first update to production, click that Finish Up button if there is one, and then run the second update locally, deploy it, and once again click the Finish Up button.


Customizing Craft Commerce Template Paths

You'll need to keep any action URLs as commerce/, as these point to controller actions inside the Commerce plugin, not templates in your store directory. So if you find:

<input type="hidden" name="action" value="store/cart/updateCart">

That will need to be restored to:

<input type="hidden" name="action" value="commerce/cart/updateCart">


Displaying Craft User Profile based on First and Last Name

See: https://docs.craftcms.com/v3/dev/element-queries/user-queries.html#lastname

{% set slug = 'first-last'|split('-') %}
{% set firstNameSlug = slug[0] %}
{% set lastNameSlug = slug[1] %}

{% set user = craft.users.firstName(firstNameSlug).lastName(lastNameSlug).first %}

We only need to split once, so I spit the slug variable instead.

You were passing slug to the first name method, but you would want to pass firstNameSlug.

Alternately this can be written like this if you know the slug is correct:

{% set slug = 'first-last' %}
{% set user = craft.users.slug(slug).first %}

But you said you don't want to do that so I'll assume you know what you are doing.


It was a simple misunderstanding of how the general.php should be structured.

I had environmentVariables outside of the '*' => array(

So it's now:

return array(
  '*' => array(
    'omitScriptNameInUrls' => true,
    'sendPoweredByHeader' => false,
    'devMode' => getenv("CRAFT_DEVMODE") == "true",
    'environmentVariables' => array(
      'baseAssetUrl'  => 'http://192.168.99.100:8080/',
      'basePathPublic' => realpath(dirname(__FILE__)).'/../../html/',
    ),
  ),
);
?>


Bad Request POST param “redirect” was invalid

UPDATE and final answer: The culprit was having the general config setting validateUnsafeRequestParams => true and not having my redirect value hashed ({{ 'account/profile' | hash }}). I had completely forgotten I had that setting turned on. Mijingo has a good explainer of how this setting works: https://mijingo.com/blog/hashing-redirect-params-in-craft

I'll still use the flash notice below for this particular case, but now I know what this error message comes from.

My goal was that I was trying to redirect the form back to the same template, only with an appended parameter on the URL so I could write an update notice.

I never found out why I got the error, but ultimately it didn't matter as I found a better way of creating that notice through this answer here. Just by adding this to my template.

{% if craft.session.getFlash('notice') == 'User saved.'|t %}

Success message!

{% endif %}


I wouldn't do it, personally.  Especially if your plugin interacts with the database and you'll be creating/deleting tables, altering the schema, needing to restore the database, etc.

Too much risk in breaking the live site and very little benefit.


Any chance you're out of disk space? That error shows that it can't create a file in /tmp which means either the permissions on /tmp are wrong, or potentially you're out of disk space.

c.f.: https://stackoverflow.com/questions/11997012/mysql-cant-create-write-to-file-tmp-sql-3c6-0-myi-errcode-2-what-does

As for the error page, if you just want to view the page, you can navigate to it directly... if you want to force a 500 error to happen, just change the db password in your .env to something that doesn't work.


How can my plugin render a generic Matrix block in the Control Panel?

I was able to pull this off by referencing MatrixInput.js and /_components/fieldtypes/Matrix/input.html.


For the second part of your question, look into Element Sources. You might be able to pull off  something fancy in a module, where certain users have access to different sources.
For the first part of your question, look into the EVENT_REGISTER_TABLE_ATTRIBUTES and EVENT_SET_TABLE_ATTRIBUTE_HTML events. Here is a rough example of how it will look...
// Add index table attributes
Event::on(
    Entry::class,
    Element::EVENT_REGISTER_TABLE_ATTRIBUTES,
    static function(RegisterElementTableAttributesEvent $event) {

        $event->tableAttributes['computedColumn'] = ['label' => 'Computed Column'];

    }
);

// Modify index table display values
Event::on(
    Entry::class,
    Element::EVENT_SET_TABLE_ATTRIBUTE_HTML,
    static function(SetElementTableAttributeHtmlEvent $event) {

        /** @var Entry $entry */
        $entry = $event->sender;

        switch ($event->attribute) {
            case 'computedColumn': // How to identify a computed column
                $event->html = 'any valid HTML';
                break;
            case 'field:101': // How to identify a normal field
                $event->html = 'whatever you want it to be';
                break;
        }

    }
);


.getPrev and .getNext sounds like what you're asking for:
http://buildwithcraft.com/docs/templating/entrymodel#isSiblingOf

{% set params = {
    section: 'cocktails',
    order:   'title'
} %}

{% set prevCocktail = entry.getPrev(params) %}
{% set nextCocktail = entry.getNext(params) %}

{% if prevCocktail %}

Previous: {{ prevCocktail.title }}

{% endif %}

{% if nextCocktail %}

Next: {{ nextCocktail.title }}

{% endif %}


Conditional Logic to show or hide fields in the admin?

Check out the Reasons plugin... sounds like exactly what you need:

  https://github.com/mmikkel/Reasons-Craft/


Advanced layout: Best way to create a tabbed page with variable content in each tab

This really is a case for nested Matrix fields. It’s something we definitely plan on adding at some point, but that won’t help you here.

Looks like you’re using nested Structure entries to accomplish it right now – that’s probably your best bet for the time being.


Friendly order number - start sequence at specific number

Once you have created the sequence (starting at 1) with your sequence key/id you can manually reset/update the number in the craft_sequences table in the next column. Obviously if you reset the number, you could get duplicate order reference numbers though if you are not careful.

Alternatively, you could just let the sequence start at 1 and use twig to add 11000 to the sequence number within the Order Reference Number Format.

Your Order Reference Number Format would look like this: 11000+seq('mySeqId')


Is there a way to remove or filter out duplicate entries?

First you would need to figure out how to identify duplicates.

Craft doesn’t allow duplicate entry slugs; it will append “-1”, “-2”, etc. to them to keep them unique. So that would probably be a good starting point.

Use this query to get a list of all entries that have a number appended to the end of the slug. It’ll tell you the entry title, its section’s name, and the URL to edit it in the control panel. (Just update “example.com” with the actual host name.) Go through those and use your best judgement to decide which ones should be deleted.

SELECT c.title, s.name AS sectionName, CONCAT('http://example.com/admin/entries/', s.handle, '/', el.elementId) AS cpUrl
FROM craft_elements_i18n el
INNER JOIN craft_content c ON c.elementId = el.elementId
INNER JOIN craft_entries en ON en.id = el.elementId
INNER JOIN craft_sections s ON s.id = en.sectionId
WHERE el.slug REGEXP '\-[0-9]+$'


Is there a way to query for a list of values belonging to a specific field in a queryset?

Yep! It's not super well documented, but there's a little information about it down in the Advanced Element Queries section of the docs. It would look something like:
  {% set titleList = craft.entries.section('articles').select('title').column() %}

One thing to note, if you're selecting a field value instead of the title, the select parameter will look something like select('field_fieldHandle')


Show custom field on Submissions page in CP

You can click on the wheel icon below Volunteer and check if the field is available there, if not you can modify the ElementType and change it's defineAvailableTableAttributes function in order to add the field/fields you want.

I don't know how this plugin was build but I made several custom ElementTypes in Craft 2 with or without a custom layout and it works every time the same.

Here is the function for Craft entries. You can then set these values in the getTableAttributeHtml function


How to get a Task's description inside runStep()?

The description you define in getDescription() is just the default description in the event that no description was specified when craft()->tasks->createTask() was called.

The actual description for the task is saved on the TaskModel, which you can get via $this->model from your Task class:

$description = $this->model->description;


You can read the technical details of it here: https://github.com/craftcms/cms/issues/1507#issuecomment-633147835
Craft no longer keeps track of element queries needed for cache invalidation in the database, but they are stored in Craft's data caches Craft::$app->getCache(), which uses the file system by default and it uses more of a tag-based cache invalidation strategy (similar to https://plugins.craftcms.com/cache-flag if you've ever used that).


Commerce Product - show shipping category in template

Product:

Shipping Category: {{ product.shippingCategory.name ?? 'None' }}

Tax Category: {{ product.taxCategory.name ?? 'None'}}

Variant:

Shipping Category: {{ variant.product.shippingCategory.name ?? 'None' }}

Tax Category: {{ variant.product.taxCategory.name ?? 'None' }}


Creating a editable table with Element Select in column

For my specific case, Super Table was the answer.

You can also check Neo


Associating related entries to a new entry when using the API

I dont think you can build arrays in PHP that way and you end up passing array(0 => '1021,1047,1076,1123') to the param.

Not shure if passing the string is supported:

'article_countries' => $article_countries

If not you could build the array like so:

'article_countries' => array_map('trim', explode(',', $article_countries))


Assets Control Panel searches only current folder, not sub folders?

Correct... currently searching in Assets does not search across sub-folders.


When creating a fieldtype how do I provide methods to be used in the templates?

Like plugins, fieldtypes can have their own settings as you're aware but while you can grab your plugin settings from pretty much anywhere, fieldtypes are a little more contextual.

In any case, like @Bryan pointed out, your fieldtype needs to implement prepValue($value) and ideally return a model containing the value as defined in defineAttributes() and the maxNumber as a property.

This basically means that when Craft calls your fieldtype's prepValue($value) which it does when the value of your field is needed (editing/outputting) you can return a model with the value and maxNumber.

EDIT:

// MyFieldType.php
public function prepValue($value)
{
    $model = new MyFieldModel;

    $model->setAttribute('value', $value);
    $model->setMaxNumber($this->getSettings()->getAttribute('maxNumber'));

    return $model;
}

// MyFieldModel.php
// Explicit getter/setter for $maxNumber rather than defining it as an attribute
protected $maxNumber;

public function setMaxNumber($value)
{
    $this->maxNumber = $value;
}

public function getMaxNumber()
{
    return $this->maxNumber;
}

public function defineAttributes()
{
    return array(
        'value' => AttributeType::Number,
    );
}

// _entry.html or other template name
{{ entry.myFieldHandle.value }}
{{ entry.myFieldHandle.maxNumber }}

@selvinortiz


Working locally after cloning Craft 3 from Hyperlane

Solved. The config/db.php cloned from Hyperlane refers to different env variable names than those used within my .env file. Changing the names in config/db.php solved the issue.

Before:

return [
    'driver' => getenv('DB_DRIVER'),
    'server' => getenv('DB_HOST'),
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'database' => getenv('DB_NAME'),
    'schema' => getenv('DB_SCHEMA'),
    'tablePrefix' => getenv('DB_TABLE_PREFIX'),
    'port' => getenv('DB_PORT')
];

After:

return [
    'driver' => getenv('DB_DRIVER'),
    'server' => getenv('DB_SERVER'), // changed
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'database' => getenv('DB_DATABASE'), // changed
    'schema' => getenv('DB_SCHEMA'),
    'tablePrefix' => getenv('DB_TABLE_PREFIX'),
    'port' => getenv('DB_PORT')
];


How to display an entry id multiple times?

I would write something like this:

{% set ids = craft.request.param('ids')| split('|') %}
{% for id in ids %}
    {% set entry = craft.entries.id(id).first() %}
    …
{% endfor %}

Alternatively, to reduce the queries, store all the entries in a variable and then loop through ids and find the right match in this smaller set.


Craft's Date/Time field extends PHP's DateTime class so (since 5.3.0) you can use the Diff method like so:

yourDateTimeField.diff(now).format('%y')


I haven't directly tried this myself, but I believe the answer is yes, you are correct.

To be fair, this is barely even a Craft question... This is 99% about Redactor, and what it is capable of. Skimming the Settings > Clean page of the Redactor docs, it seems like Redactor already takes steps to normalize content from MS Word, and pastePlainText is simply one piece of the puzzle.

Here are some steps you can take to further assess whether you're getting the output you want from your Redactor settings...

Look at how the data is being stored in your database. Specifically, keep an eye on your field's column in the craft_content table.
Try various settings from the Redactor "Clean" options. The developers behind Redactor are clearly aware of MS Word, and all of it's bizarre behavior. If you don't get the results you want right away, try mixing & matching Redactor settings until you get the desired behavior.

Hope that helps!


That is returning an ElementQuery. I'm assuming you only need to get the first category. You need to use .one to get the category element.

{% for row in entry.matrixField.all() %}
    {{ row.matrixChild.one.slug }}
{% endfor %}

If you wish to display more than one category you can use a {% nav %} or {% for %} to loop through them. See the category docs.


How can I Prevent CSRF Tokens from being Cached?

You can do something like this:

// First, set all your cached content to a variable:
{% set myContent %}
  {% cache %}
    {# YOUR CACHED CONTENT #}
    %%MY_CSRF%%
  {% endcache %}
{% endset %}

// Then, run a replace on your cached content to insert the new CSRF
{{ myContent|replace({'%%MY_CSRF%%': getCsrfInput()}) }}


Remove white space and parenthsis from global from entry variable

I haven't tried this but I think that you can use the twig replace function. Something like:

{{ global.phone|replace({"(":"", ")":"", "-":"", " ":""}) }}

Update In your case, since the prefix (1-) is required, and "-" are allowable, the replace string for "(555) 555-5555" would be:

{{ global.phone|replace({"(" : "1-", ") " : "-"}) }}


Need help with filling matrix images into CSS grid

There is no way to determine if an image should go to the first block.type == 'A' if statement or the second one

you could write something like this:

{% switch block.type %}
    {% case 'A' %}
        {# images for both case a1 + a2. write the loop number into the class name #}

 {# your image #}

    {% case 'B' %}
        {# images for case b #}

 {# your image #}

{% endswitch %}

That's just one of lots of possibilities


Plugin Development: extending a vendor plugin

In your example, if you do this:

$var = new \XXX();
$var->doThis = 'CONTENT HERE';

Then doThis will never exist for class \XXX because \XXX isn't where the method was defined.  It would work from your extended class, though:

$var = new YYY();
$var->doThis = 'CONTENT HERE';

Keep in mind that (usually) if the vendor plugin instantiates any instances of that class internally, it will always be of instance \XXX, not your YYY class.

Where that wouldn't be true, is if the vendor plugin supports dependency injection where they allow you to inject your extended YYY class wherever \XXX would usually be referenced.


saving user field type custom field - Failed to set unsafe attribute

In order to set field values there is setFieldValue function

$element->setFieldValue('fieldHandle', [Craft::$app->getUser()->getIdentity()->id]);

All relation fields only accept the values as an array [1] rather than integer 1


Any reason why {% requirePermission 'editEntries:1' %} would stop working within the past week or so?

Assuming you've recently updated to Craft 3.1, if you look in your userpermissions table you'll see that they're now lowercase and using UIDs rather than integer IDs, like this:

editentries:3bb69b06-3e65-4ae5-8d70-6c47c1a88fbe

The only place I can find anything like this documented is in the "Updating Plugins for Craft 3.1" guide

https://craftcms.com/guides/updating-plugins-for-craft-3-1#update-element-source-key-references


How can I convert a dropdown field value to an integer within a hash?

Give this a shot:

 {% set cacheTime = sidebarBlock.twitterFeedCacheTime.value %}


Different behavior when looping through a list of variables

Make sure your section.first() returns an element. The error occurs because section.first() is null => no element was found with your criteria. And the value null has no function getSection.

However - keep in mind your sectionHandle variable is not the handle of the section, but the SectionModelthus your code as it is currently is not really performant


Related Items in a Category not Appearing in Results

The code above was missing a space after not

.id('not'~entry.id) should have been .id('not '~entry.id)

This one is an easy one to miss and I have done it a million times.


Add product to cart using checkbox and AJAX

You are going down the right path with MultiAdd.

I have an application that on a single product page, I am also selling additional products that are an add-on of the parent. They are separate products, but they exist together. As in, the parent product is the only place the additional products are sold.

When the administrator is creating the parent product, I give them the option (mainly checkboxes) "Include option B". When checked, the additional product will show.

This is kind-of how it works...

<form method="post" action="" accept-charset="utf-8">
    <input type="hidden" name="action" value="multiAdd/multiAdd">
    <input type="hidden" name="redirect" value="shop/cart">
    {{ getCsrfInput() }}

...

{# This is the primary/parent product. #}
<select id="myVariant" name="items[1][purchasableId]" class="form-control required" required>
    <option value="">Select Option</option>
   {% for purchasable in product.variants %}
       <option {% if purchasable.stock <= 0 and purchasable.unlimitedStock == false %}disabled {% endif %}
           value="{{ purchasable.purchasableId }}"
           data-position="{{ purchasable.myVariant }}"
           data-price="{% if purchasable.price == 0 %}Free{% else %}
          {{ purchasable.price|currency(cart.currency) }}{% endif %}">
              {{ purchasable.myVariant.label }} &ndash; {% if purchasable.price == 0 %}Free{% else %}{{ purchasable.price|currency(cart.currency) }}{% endif %}
        </option>
    {% endfor %}
</select>
<input type="hidden" name="items[1][qty]" value="1">

...

{# This is the additional product. #}
{% if product.myOption|length %}
<fieldset>
    {% set options = product.myFirstOption %}
    {% if options|length %}
        <legend>Some Optional Thing</legend>

            Option
            <select id="option" name="items[2][purchasableId]" class="form-control required">
                <option value="">Select Option</option>
                    {% for option in options %}
                        <option value="{{ option.defaultVariant.purchasableId }}" data-price="{{ option.defaultVariant.price|currency(cart.currency) }}">
                            {{ option.title }} &ndash; {% if option.defaultVariant.price == 0 %} Included with registration {% else %} {{ option.defaultVariant.price|currency(cart.currency) }}{% endif %}
                        </option>
                   {% endfor %}
            </select>
            <input type="hidden" id="optionQty" name="items[2][qty]" value="0">

    {% endif %}
</fieldset>
{% endif %}

What is important to note is this:

<input type="hidden" name="items[1][qty]" value="1">
...
<input type="hidden" name="items[2][qty]" value="0">

That's how MultiAdd knows what to add to the cart.

Once I choose my options and click "buy" any option(s) are added to my cart until I go into my cart and remove them.

There is an example for ajax in on the MultiAdd page. Instead of a traditional post, you are sending the same information to a url via ajax.

Hope this helps!


What is the best way to generate email messages with attachments from Twig files?

You can do this with a simple Craft plugin.  You can generate the boilerplate plugin code here.

Your form on the front-end will set its hidden action input to your plugin's controller's action.

From there, you can use Craft's EmailModel (along with addAttachment()) and EmailService's sendEmail() to send whatever email contents you wish.


Updating fails (except it does indeed update)

My guess is that you're bumping into your php.ini file's memory_limit and/or max_execution_time setting.  It just happens to be towards the end of the update process where Craft is (for all practical purposes) updating, and it fails in the "cleaning up" portion of the update process.

Bump those up to something like 256M and 120 (respectively) and see if that helps going forward.

  Since the prior update pseudo-failure there was a message about maintenance mode and a button to continue (which I'm assuming is a flag set somewhere from the prior update).

Yup, it's a flag set that never gets reset if there's a fatal PHP error (live above).  It'll go away after the next successful update.


List Orders with datePaid is within last 14 days using the Element API plugin

Here's an example elementapi.php that should get you going...this is returning shipping details but you can modify the transformer for whatever data you need of course...

return [
'endpoints' => [
    'api/json/orders/whatever.json' =>  [
        'paginate' => false,
        'elementType' => 'Commerce_Order',
        'criteria' =>   ['dateOrdered' => '>'. date('Y-m-d', strtotime("-2 weeks")),
                         'isPaid' => true,
                        ],

        'transformer' => function(Commerce_OrderModel $order) {
            return [
            "id" => $order->ISOrderNumber,
            "fullname" => $order->shippingAddress->firstName ?? '' . " " . $order->shippingAddress->lastName ?? '',
            "firstname" => $order->shippingAddress->firstName ?? '',
            "lastname" => $order->shippingAddress->lastName ?? '',
            "company" => $order->shippingAddress->businessName ?? '',
            "street1" => $order->shippingAddress->address1 ?? '',
            "street2" => $order->shippingAddress->address2 ?? '',
            "suburb" => $order->shippingAddress->city ?? '',
            "state" => $order->shippingAddress->stateName ?? '',
            "postcode" => $order->shippingAddress->zipCode ?? '',
            "phone" => $order->shippingAddress->phone ?? '',
            "mobile" => $order->shippingAddress->phone ?? '',
            "email" => $order->email ?? '',
            ];
        },
    ],

    // Next api thing to go here...

],

];


Between the two, I'd say that craft()->request->userHostAddress is going to be a more reliable method.   It tries to take into account things like clients going though proxy servers, shared ISP IP addresses, etc. whereas you don't know any of that just relying on $_SERVER['REMOTE_ADDR'].

But, as you pointed out, none of this is guaranteed to be reliable.


Yeah. The contact-form plugin of craft is rather rough around the edges. I especially miss a error-handling. The form plugin just fails silently.

As a replacement I'd go for

AM Forms
Sospace's Freeform


How to create a query to group alternate language pages?

This query cannot be created in the "ideal" way described in the question using craft()->elements->getCriteria. It required several steps to build the results needed. The final solution was a bit specific to our needs. Here is some pseudocode that represents a solution:

$urls = array();

// Fetch all enabled locales
foreach (craft()->i18n->getSiteLocales() as $locale)
{
    // Confirm there are elements in a specific locale and get them
    ...
    $criteria->locale = $locale->id;
    $elements = $criteria->find();

    foreach ($elements as $element)
    {
        // Add each location indexed by its id
        $urls[$element->id][] = array(...);
    }
}

// Process what we created above and adjust it to fit our needs
$urls = $this->processUrlsIntoTheRightFormat($urls);


Bit of a late reply (But hope you can use this!), but I created a plugin to output barcodes within Craft templates via Twig:

https://github.com/madebyshape/barcode

I created it because one of our clients required a barcode to be output in to a generated PDF that got sent to their customers.


Searching entries by title's first initial only

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

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

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


Return entry where matrix field is not empty

Currently the only way to find entries that have Matrix rows is with the search param:

{% set entry = craft.entries.section('entries').search('quote:*').order('RAND()').limit(1) %}


Get selected values from all of an entry’s Multi-select fields

You can loop through all of the selected values of a multi-select field like this:

{% for value in entry.myFieldHandle %}

{{ value }}

{% endfor %}

(See the Multi-select field docs for other examples.)

The easiest way to loop through all of your multi-select fields’ values would be to manually merge all of their values into a new array:

{% set values = entry.fieldHandleOne
    |merge([entry.fieldHandleTwo])
    |merge([entry.fieldHandleThree]) %}

{% for value in values %}
    {{ value }}
{% endfor %}

If you really don’t want to hardcode the field handles in your template, then you can go the getFieldLayout() route. That field.getField() function will give you the actual FieldModel that represents the field. You can use its handle property to access the field’s selected values on your entry:

{% set values = [] %}

{% for tab in entry.getFieldLayout().getTabs() %}
  {% if tab.name == 'Spec' %}
    {% for field in tab.getFields() %}
      {% set handle = field.getField().handle %}
      {% set fieldValues = entry.getFieldValue(handle) %}
      {% set values = values|merge([fieldValues]) %}
    {% endfor %}
  {% endif %}
{% endfor %}

{% for value in values %}
  {% for selected in value %}

{{ selected}}

  {% endfor %}
{% endfor %}


I was looking for an answer to this myself and found Running module migrations
It is basically saying you can only create the tables as part of your craft project - but not specific to your module. To create this project-wide migration run in your craft project folder (not your module folder):
php craft migrate/create [my_migration_name]

This will create the migration file and class in your craft's projects 'migrations' folder (it will display the exact path and file name after running the above command). For more info about the Migration class see https://craftcms.com/docs/3.x/extend/migrations.html#creating-migrations


Accessing Commerce ‘Product Fields’ in events hooks

I believe you're looking for something like:
$purchasable->product->yourEntriesFieldHandle->one()->title


Interacting with table fields via plugin

If you use:

$partnerProducts = $currentPartner['0']->productInfo;

Then you should be able to do:

foreach ($partnerProducts as $pp)
{
    echo ($pp['sku']);
}


How do I migrate a Wordpress project to Craft CMS?

At this point in time, you have a few options:

Import Plugins

As of this post, there are a few partial import plugins available and rumors that a few others might be on their way.

Sprout Import - Sprout Import supports over 40 data types such as Entries, Users, Assets, Products, Orders, Forms, Email, and Redirects; and more can be added as needed via plugin integrations.
Feed Me - Feed Me is a Craft plugin for super-simple importing of content, either once-off or at regular intervals. With support for XML, RSS, ATOM or JSON feeds, you'll be able to import your content as Entries, Categories, Craft Commerce Products (and variants), and more.
Import - Handles Entries and allows you to map them to fields in
your Entries Sections
EE/Craft Import - While this plugin has EE
in it's title, it looks like it's framed more around XML imports in
general and promotes itself as being a starting point if you have
other custom import needs.

Import Service

Full disclosure, my company offers a migration service to help folks migrate to Craft.  We use a combination of a private plugin, custom scripts, and manual processes when necessary.  We find, in most cases, many things about your data architecture can be improved when migrating to Craft.  So, while an import plugin can help with some heavy lifting, being able to make architecture decisions on how to import certain types of content outside of what a plugin would allow is useful for improving user experience and getting the most of of Craft.  For example, content that fits nicely in Singles and Matrix Fields don't always have equivalents in other CMSs, yet frequently other CMSs have content that fits these use cases.

The Great Migration

Do It Yourself

If you want to roll up your sleeves, you can create a utility plugin or script for your own needs.  If you need to go this route, you probably want to import your data using Craft's Service Layer and the save methods for each of the individual Elements you are importing.

You can see some examples of this in the plugins available on GitHub above, or read up more on the service layer in the Craft docs.  A good place to start may be the Entries Service.

You will need to get your data into a format that matches the EntryModel and then you can pass that information to the saveEntry method:

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

That's a fairly simple explanation, but the gist of where to start. All of the other Elements are going to have similar Models and save methods you can use to import your data.


Disable activation link email for a specific user group

Off the top of my head, the pseudocode would be something like:

Listen for the EVENT_BEFORE_SAVE_ELEMENT event.
Check if it's a new user registration.
If so, check the user group status.
Apply account activation email logic based on #3.


Best location for Craft development? Local or Server? Subfolder of production?

The best way to do it would be to develop locally, ideally managed with a version control system like Git and then push your site to your server. Craft handles a multi-environment workflow very well.

From the Craft docs on Mult-Environment configs

A good screencast from Straight Up Craft

There are also several questions and answers dealing with this topic in Stack Exchange here.


Yes simply add a sale with no product conditions which will apply to all products.


How to create a user editable dropdown field?

I'm not 100% I follow, so I apologize if this isn't what you are looking for. Are these values being managed/edited within the CP? Or are the editors adding these values from a front-end form?

A project I worked on needed a base set of values in a drop-down field for each entry. But each entry that was created by the author could have additional values (or less). The way I did this was to create a table field in the CP. It consisted of two columns label and value.

This way I could have a "default" set of values that each entry would inherit. The author could then add additional rows (or remove) as they needed.

In the template, I just treated the table as a drop-down (in your case it will be a multi-select).

<option value="">Select</option>
    {% for option in entry.myField %}
        <option value="{{ option.value }}">{{ option.label }}</option>
    {% endfor %}
</select>

Hope this helps!

Edit/Update

I still think if you don't want to go the category route, you could do this within a field. I've attached a screenshot of what this looked like on a similar project. The label is the left column, and the value is the right. Each row is a new value in my drop-down field that is created on the front-end.

By default all of these values are in the dropdown for each entry. The author can add/remove whatever they want in addition to the default data. But, whenever "New Entry" is pressed, each entry starts with the same data.

Where it might get tricky is if you want these added/removed values to persist from entry to entry. You'd probably have to write some sort of plugin that saved the new values back to the original field.


You were close!

Just don't use the Twig hash/array syntax when using the |replace filter if you want Craft to process it as regex.  This should do what you're looking for:

{% set svg_image_output = svg_image|replace('/#[a-zA-Z0-9]{6}|rgb\\((?:\\s*\\d+\\s*,){2}\\s*[\\d]+\\)|rgba\\((\\s*\\d+\\s*,){3}[\\d\\.]+\\)|hsl\\(\\s*\\d+\\s*(\\s*\\,\\s*\\d+\\%){2}\\)|hsla\\(\\s*\\d+(\\s*,\\s*\\d+\\s*\\%){2}\\s*\\,\\s*[\\d\\.]+\\)/', '****') %}


Is a migration needed if defineContentAttribute is changed from false to an AttributeType

Does a migration need to be written to account for this change?

Yes.

  how would this be written since it is the specific input name that is added to the content table?

Just thinking out loud:

Select all fields from the database that have your field type.
Determine if they are in a Matrix context (craft_matrixHandleContent) a global context (craft_content).
For each grab their handles and build the column name.
Alter table to add the column to the appropriate table.


Can I make the front-end entry form send an email to a user group?

You can write a simple plugin that listens for the onSaveEntry event.

When that event fires, you plugin could check the $isNewEntry param to make sure it's a new entry being saved and also check the entry's section to make sure it's the front-end section you're expecting and might as well check craft()->request->isSiteRequest() to make sure it's a front-end request.

If all of those match, you would get the users in a group, then loop through all of them sending an email with craft()->email->sendEmail() for each user.

Something like (pseudocode):

$element = craft()->elements->getElementType(ElementType::Users);
$element->group = 'groupHandle';
$users = $element->find();

foreach ($users as $user)
{
    // compose email body, header, etc.
    $success = craft()->email->sendEmail($email, $variables);
}


Best way to do this would be creating a small plugin (recommended on every Commerce install, to be able to easily extend it). In this plugin's init method, you could listen to the OrderComplete event and send the mail. This is untested, but should get you started:

public function init()
{
    craft()->on('commerce_orders.onOrderComplete', function($event) {
        $order = $event->params['order'];
        $note = $order->getContent()->shippingNoteFieldHandle;

        if ($note) {
            //Send Mail
            $email = new EmailModel();
            $email->toEmail = 'address@tospam.com';
            $email->subject = 'New order completed';
            $email->body    = $note;

            craft()->email->sendEmail($email);
        }
    });
}

You can use pluginfactory.io to quickly create a plugin, then put the init method in the plugin's base class.


Are you sure you're not simply hitting the default limit which is 100?

Try this

{% set entryIds = craft.commerce.products({limit: null}).ids() %}


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 %}


How can I get the current user who purchased a product from the onOrderComplete event?

Since this is happening from the onOrderComplete event, the easiest way to get the currently logged in user is with UserSessionService::getUser():

$user = craft()->userSession->getUser();

Alternatively, if you want to go through the actual Commerce_OrderModel that was passed as a parameter on the event, you can do this:

$user = $event->params['order']->getCustomer()->getUser();

Either way, it’s a good idea to verify that $user gets set to something, just in case:

if ($user) {
    // ...
}


How to build contact form from scratch (no plugin)

Here’s an example of how you can do exactly that using only the CraftQL plugin: Using Vue.js + GraphQL to make Practical Magic

You can also do it with a frontend Entry form without any any plugins at all, and without JavaScript or GraphQL: Craft CMS Entry Form Example

And in general can do a whole lot without plugins: Cutting was he Cord: Removing Craft CMS 3 Plugins


How to handle Belongs To User relationship

Assuming your plugin is going to be the only thing referencing this Active Record relationship, your plugin could have its own MyUserRecord that extends Craft's UserRecord and does something like:

public function defineRelations()
{
    $relations = parent::defineRelations();

    $relations['myUser'] = array(static::BELONGS_TO, 'MyUserRecord', 'id', 'required' => true, 'onDelete' => static::CASCADE);

    return $relations;
}

And you would just utilize MyUserRecord instead of Craft's UserRecord in your plugin.


How do I pull related entries and assets?

The data in Craft is handled mostly by Models (and arrays of Models). Before pulling actual information, you define your criteria in an ElementCriteriaModel using generic parameters and parameters specific to what you are trying to get (entries, assets, etc.). You then use one of the ElementCriteriaModel's functions to pull the actual data. You will get either a model or an array of models to loop over. This works the same for most things in Craft because most things are Elements.

You can look under the Variables heading in the side menu of the templating docs to see the kinds of models you will get.

On your homepage, you start with an automatically created entry model (this is created on every page that Craft recognizes as an entry's page). Here's the basic code you need:

{% for event in entry.featuredEvent %}
    {# Output some event code here #}
    {% set block = event.articleBody.type('image').first() %}
    {% for image in block.image.find() %}
        {# Output some image code here #}
        <img src="{{ image.getUrl(image.size) }}" class="{{ image.alignment }}">
    {% endfor %}
{% endfor %}

So an explanation of the above. In Craft, related elements are not automatically pulled from the DB. Instead each field that points to a related element (entries, assets, categories, users, etc.) is an ElementCriteriaModel so that you add more criteria before pulling. So entry.featuredEvent is an ElementCriteriaModel that points to all of your featured event entries.

When working with ElementCriteriaModel you have a few options to pull the data and use it. In the above code, when you give a for loop ElementCriteriaModel it will automatically pull the data and give the loop entries. So we take the entry.featuredEvent, and loop over the entries that's given to us when we use it in the for loop.

Inside the for loop, we pull the first image block in event.articleBody. Because matrix blocks are elements, we get the same features. So we set the type, and pull the first one.

In the next for loop, we are grabbing all of our images in the image block. The tricky part here is that we can make the code a little more efficient by simply pulling all of the images and looping over them. If you have very different html you plan on using for one image and multiple images, you will need to set the images as a variable like we did the block. You can then check the number of images using the length filter, and either Craft's switch tag, or a couple if statements.

Personally, I recommend using the loop, and using CSS to make the style differences you need.

Finally, we output each image. Because you're using a transform on them, we can't use each assets getImg function. Instead we write the img tag manually and grab the transformed url using getUrl.

The next bit is making a couple assumptions. I'm assuming that size is a image transform handle. I'm also assuming that these fields are on the asset. If they're on the matrix block, replace image.size and image.alignment with block.size and block.alignment.


Serve remote files instead of local ones (with a nitro setup)

There's a couple different ways to handle this.
Base URL on Asset Volume
One way is just to treat the asset volume like you might a CDN.
Unlike other CMS (ahem WP), Craft doesn't hardcode URLs into the database and will build them up on-the-fly.
On the local dev server, you just need to set the base url (i.e. server name) of a volume to that of the production server instead of serving locally.
Your Asset volume config might look something like:

Instead of setting a value in the control panel, you can also use an alias if you want to advantage of Craft's multi-environment support.
Server Rewrites
If you have other assets that aren't necessarily managed by Craft, you can do some server rewrites like you did using Apache's .htaccess config.
Nitro uses nginx as the web server, not Apache, so there's not quite a direct equivalent of .htaccess other than editing the configuration (which is easy enough to do).
You'd want to ssh in to the appropriate container and then edit the nginx config (usually located in /etc/nginx/sites-enabled/yourtestservername.
To make the server rewrite work, try something like:
location ^~ /images {
return https://productionserver.example.com$request_uri;
 }

Place this before the closing bracket "}". This assumes your asset volume is stored at "/images". If you have any others, you can add them separately. nginx will redirect any content that's in /images to the production server.


I believe you'll need to look at using the following syntax:

craft.entries.relatedTo('and', { targetElement: tags })

You might have some luck using the Similar plugin.


How can I access a template variable from an include that is loaded via ajax?

Since you are only trying to access the existing entry model, you should be able to do something like this:

portfolio/_entry.twig

{% set project = entry %}
...
<h1>{{ project.title }}</h1>


Redactor image caption not saved and formatting lost

I copied your Redactor settings to a clean installation of Craft (2.6.2945) and added an image to a Rich Text field set to use those specific settings. Initially I encountered the same behaviour. However, unlike in your experience, after disabling the Purify HTML? option on the Rich Text field, the figcaption element persisted after saves.


How to list the latest 5 entries per entry type?

craft.entries() fetches entries.

To fetch the entries with a given entry type, you use type. So to get the Article entries, either craft.entries.type('Article') or craft.entries({type: 'Article'})

To fetch the latest 5, you want the entries sorted by postDate, descending (this is the default sort order), and then limit that to 5. Combining with the entry type, you have: craft.entries.type('Article').limit(5) or craft.entries({type: 'Article', limit: 5})

And you have four entry types, so might as well loop over those:

{% for entryType in ['Article', 'Video', 'Photo', Quote] %}
  {% set latestFive = craft.entries({
    type: entryType,
    limit: 5
  }) %}

  {% for oneEntry in latestFive %}
    {# list that entry #}
    {{ oneEntry.title}} is of type {{ entryType }}
  {% endfor %}

{% endfor %}


Craft 2: Locale throwing 404 in frontend

However, when I try to access any page apart from the homepage in my
  2nd locale in the frontend I get a 404 error.

Could it be, that as a result of your settings, URL's for /en do not get rewritten correctly? I don't know how you redirect SEO-friendly urls, but most of the times (at least in my life) if accessing all pages but the homepage fails, it has something to do with URL rewriting.


Setting a variable assets field, depending on the URL?

I'd probably do it like so:

{% if craft.request.getSegment(1) == 'special' %}
    {% set assets = entry.assetfield_1 %}
{% else %}
    {% set assets = entry.assetfield_2 %}
{% endif %}

{% for asset in assets %}
    ...
{% endfor %}


Issues with picture and image transforms

You might try putting putting something like:

<IfModule mod_php5.c>
  php_value max_execution_time "30"
  php_value memory_limit "256M"
</IfModule>

inside your .htaccess. file.

You can tell what your PHP values are right inside Craft... unless you changed your admin trigger, just visit http://server/admin/utils/phpinfo and search for memory_limit and max_execution_time. That'll give you some clues as to what's going on.

Some hosts set these values really low but the default execution time is 30 and memory limit is 128M.

If you run PHP as a cgi, some hosts allow you to use ini files in lieu of .htaccess. Typically these are at the root of your home folder but they could be stored elsewhere. Put memory_limit = 256M in one and throw it up in your home folder. Running php_info() would tell you the location of the current in use one.


Not in the near, probably not in the long and a pretty slim chance in the very long-term future.

We'll add support for additional relational databases (MSSQL, SQLite PostgreSQL, Oracle) long before a NoSQL solution and they will each bring their own level of additional support and challenges.


Traits are just a PHP thing not related to Craft at all so yes, you could use them.  But you'd be limiting your plugin to PHP 5.4+ only since that's when they were introduced.

Craft 2.x supports back to PHP 5.3.

You might also want to look at Yii's Behaviors, which have similar functionality to traits and works with PHP 5.3.

Craft 2.x uses a few behaviors of its own.


Save field inputs upon submission of front end form for reuse in new form?

I don't know if we can compare the problem I usually have but here is my way.

Whenever I build a website where users can login and save "entries" they also need to stay connected to it off course.
I make sure the title of the new made entry got the users ID in it. So if someone makes a new entry they go to a succes page after the form is submitted. This success page is actually the entry they created. The moment they land on that page the "second" form will be automatically filled in with the details I need and then save/update whatever needs to be updated (most of the times for me that would be saving the entry to a user profile). After the second form submit's I redirect them to the page I want.

This would include some javascript.


Ok - think I figured this out.  Our dev site is hosted on a sub-domain of our production site, which is served over HTTPS.  Seems like the CRAFT_CSRF_TOKEN
cookie set by our production site is the same that's trying to be set by our dev site, and since dev is served over HTTP, it's unable to overwrite the one set by the production server.  Clearing out cookies on production fixed the problem. I imagine setting up HTTPS on dev would also do the trick, but clearing the prod cookie is a quicker fix at the moment.


Faceted navigation plugin problem installing

At the time you tried this, that plugin wasn't available on Packagist, hence it's not available to install from the command line (see the tip here in the plugin developer documentation: https://docs.craftcms.com/v3/extend/plugin-store.html#registering-your-plugin).

The plugin author has since added it on Packagist so your command should work now.


Limiting image rows by 5 but an unknown number of section entries

Something like this should work:

{% for images in craft.entries.section('pages').type('events').order('eventDate desc').eventDate('<=' ~ now).search('gallery:*') %}

    {% set image_set = images.gallery %}
    {% for i in 0..4 %}
        {% if image_set[i] is defined %}

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


Locale case sensititvity on AWS instance

Oh, I am blind.

Rather than delete this embarrassment, I will post this mea culpa for anyone else that may experience a similar brain fart.

I had subconsciously typed the directories in html/ using the common POSIX/ISO standard without realising it, so html\en_US\. Of course, this works on OS X because the OS is case insensitive by default, and does not on Linux, because it is case sensitive. Renaming to all lowercase solved it.

As for the CP rewrites, it was simply that Craft was not picking up that rewrite was correctly enabled. Simply adding omitScriptNameInUrls fixed that immediately.


Installing and using super-filter plugin

This is an option to modify the html element that is being used by the search field. You will have to specify the folder in your site template path what template file to override. You can start by copying and pasting sample html template in vendor/pdaleramirez/super-filter/templates to the specified template override folder.


Found out that entry can be accessed with $this->element->owner


Add the following tags around your {% pagination %}

{% cache %}
{% endcache %}

Those tags will refresh every time the content changes, and when the content hasn't changed, it'll reduce your database queries significantly.

For more info see:

The craft docs
What are the best practices for using the cache tag


In your config, you can set activateAccountFailurePath to something like:

'activationAccountFailurePath' => 'members/failed?access=1'

In your template, you can check for the URL parameter 'access' and 404 if it is not set.

Template:

{% if craft.request.getParam('access') != '1' %}
   {% exit 404 %}
{% endif %}

{# rest of your template if parameter is available #}

Of course, someone could still access the page if they had the full URL with the parameter, but it should help limit access.


CP assets uploads are reverse ordered after upload

Did some more tests. In my finder I have two files:

1.jpg
2.jpg

When I upload these files, 1.jpg is uploaded first and 2.jpg second. In the control panel 2.jpg is the latest uploaded file and therefore the first visible asset. This clarifies the reversed order.
A little trick when uploading multiple files from the finder and keeping the same order, is to reverse the file order in the finder (start with Z and end with names starting with A).


Solspace FreeForm assign notifications recipient in entry

Not sure if I understood the question correctly but why don't you make use of the Freeform Forms Field if you want to attach a form per entry.

{% if entry.myFreeformfieldname is defined and entry.myFreeformfieldname is not empty %}
    <h3>{{ entry.myFreeformfieldname.name }}</h3>
    {{ entry.myFreeformfieldname.render() }}
{% endif %}


You're over-thinking it a little bit. To save your widget settings, you don't need a controller class, you only need

a) a method called defineSettings() in your widget class, returning the settings you need, e.g.

protected function defineSettings()
{
  return array(
    'url'   => array(AttributeType::Url, 'required' => true, 'label' => 'URL'),
    'title' => array(AttributeType::Name, 'required' => true),
    'limit' => array(AttributeType::Number, 'min' => 0, 'default' => 5),
  );
}

You can take a look at the AttributeType class to see which attribute types Craft support.

b) a template to render your settings – you don't actually need to create the actual <form> element or add hidden action or redirect inputs in this template; Craft wraps the fields you render inside a form tag. Here's an example settings template corresponding to the settings from the defineSettings() example method above (this is the whole template):

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

{{ forms.textField({
  label: "URL"|t,
  id: 'url',
  name: 'url',
  value: settings.url,
  required: true,
  errors: settings.getErrors('url')
}) }}

{{ forms.textField({
  label: "Title"|t,
  id: 'title',
  name: 'title',
  value: settings.title,
  required: true,
  errors: settings.getErrors('title')
}) }}

{{ forms.textField({
  label: "Limit"|t,
  id: 'limit',
  name: 'limit',
  value: settings.limit,
  size: 2,
  errors: settings.getErrors('limit')
}) }}

Save the template to /yourplugin/templates/widgethandle_settings.html. Finally, you need

c) a method called getSettingsHtml(), also in your widget class, which simply renders the settings template you added above:

public function getSettingsHtml()
{
    return craft()->templates->render('yourplugin/widgettitle_settings', array(
        'settings' => $this->getSettings()
    ));
}

With these three things in place, you should be able to click the cogwheel that appears when you mouse over your widget in the Dashboard, which will display your settings form.

To be clear, this is actually exactly the same way plugin settings work, although for plugins themselves the defineSettings() and getSettingsHtml() method should exist in the primary plugin class. In short – you don't need a controller and you don't need the <form> tag, neither for plugin nor widget settings.


This is available as of 3.2. Make the alt text field required for the asset volume, then check the "related element validation" box when creating an asset field.


Element-API: Access the first url of an asset array

you could use array_values() to fetch the first image:

...
      'transformer' => function (Entry $entry) {
        foreach ($entry->images as $image) {
          $images[] = $image->url;
        }
        return [
          'images' =>  array_values($images)[0],
        ];
      },
...

or use reset()

...
      'transformer' => function (Entry $entry) {
        foreach ($entry->images as $image) {
          $images[] = $image->url;
        }
        return [
          'images' =>  reset($images),
        ];
      },
...


"Impossible to access an attribute on a NULL variable"

That message is telling you that gatewayHandle can't be accessed from video, because video is NULL. You're expecting the videos field to always contain an object, but in this case it is not.

I would suggest that you ensure that video actually contains a value before you attempt to reference one of its properties...

{% set video = entries.video %}

{% if video %}

    {% if video.gatewayHandle == 'youtube' %}
        ...
    {% endif %}

{% endif %}


Problem connecting to MySQL db on installing Craft 3

Thanks for your help Brad. After going round and round in circles, deleting the database and setting up a new one sorted it. Ah the mysteries!


It's the short syntax for the translate filter. Set up a translation file as described in the docs and the string you apply that filter to is translated according to it.


Can I set an environment var for SMTP mail servers?

Not an easy way to do this in Craft 2, but this is possible in the upcomgin Craft 3 (currently in beta) using craft/config/app.php, which is multi-environment aware.


Pantheon hosting alternative for Craft CMS

From what I understand it is possible to host a Craft site on Pantheon but they will not offer the same level of support that you would get using WordPress or Drupal. This is what I've been told by Pantheon technical support, at least.

The workflow you're looking for could be mostly set up on Heroku using review apps, however, to my knowledge they don't have the same workflow where new branches can be created with cloned content from whichever environment or branch you'd like.

I think that this would be possible by running postdeploy script from app.json, which fires once when the review app is created. You could write a script that pulls production content and clones an S3 bucket into a new one, giving you a Pantheon-esque workflow.

If you're going to go down this route you might want the AWS CLI Buildpack, the ability to use environment variables in Craft (see Matt Stauffer's site for this) and you'll probably want to use Jaws for MySQL since, in my experience, it's much faster than ClearDB.

I'm in the same boat as you, coming from a WP heavy background and very reliant on Pantheon, so currently looking into a similar set up myself. Hope this provides some direction.

It would be amazing if Pantheon just offered Craft support out of the box.


Each project should be a separate repository, definitely. After that - feel free to include what you like. Personally I follow something like this and ignore my /app folder: https://deploybot.com/guides/deploy-craft-cms-to-digitalocean. But you could also include the /app directory and plugins.

Also: Git Workflow and Multi Environment - how to approach

And: https://craftcms.com/support/craft-storage-gitignore


I'm going to assume that, as per the use cases in the documentation, embed is a good fit for your requirements.

If you're not sure, extends and include are probably a better choice, as they're much easier to understand and work with.

Moving on, in your example you appear to have confused the roles of the template being embedded, and the template doing the embedding.

Here's how it should look:

{# Page (doing the embedding) #}
{% embed "_partials/sidebar" %}
    {% block subscribe %}
        The custom subscribe block content.
    {% endblock %}
{% endembed %}

{# Embed (being embedded) #}

        {% block subscribe %}
            The (optional) default subscribe block content.
        {% endblock %}


How to overrule Craft error messages with custom setError()?

I recently asked P&T about a similar issue, although it was for the onBeforeSaveEntry event (not onBeforeDeleteEntry) -- it turns out that you need to set the error on a specific field, not the entry as a whole. I don't know if this is the case for your problem, but perhaps worth trying something like this:

$event->params['entry']->addError('title', 'Cannot delete because blah blah blah');


PHP error when rendering a template from __toString()

In PHP, nothing can throw an exception inside of a __toString() method, or else you'll get the error you're seeing.

Not only is that a questionable design decision, it also hides the underlying exception message and stack trace from you.

If you do this, at least you'll be able to log the underlying error and fix that:

public function __toString()
{
    try
    {
        return $this->render();
    }
    catch (\Exception $e)
    {
        Craft::log('ERROR: '.$e->getMessage(), LogLevel::Error);
    }
}

Then you can look in your craft/storage/runtime/logs files for [error] to see the exception message.


Update form entry using the Guest Entries plugin

In Craft 3 / Guest Entries 2, you could pull this off without hacking Guest Entries by writing  a module that listens to the beforeSaveEntry event, and sets the id on the entry.

use Craft;
use craft\elements\Entry;
use craft\guestentries\controllers\SaveController;
use craft\guestentries\events\SaveEvent;
use yii\base\Event;
use yii\web\BadRequestHttpException;

// ...

public function init()
{
    // ...

    Event::on(SaveController::class, SaveController::EVENT_BEFORE_SAVE_ENTRY, function(SaveEvent $event) {
        $request = Craft::$app->getRequest();

        // Get the entry being edited
        $entryId = $request->getValidatedBodyParam('entryId');
        $currentEntry = Entry::find()->id($entryId)->anyStatus()->one();

        if (!$currentEntry) {
            throw new BadRequestHttpException('Invalid entry ID: ' . $entryId);
        }

        // Populate the guest submission with the entry ID, UID, and content ID
        $event->entry->id = $currentEntry->id;
        $event->entry->uid = $currentEntry->uid;
        $event->entry->contentId = $currentEntry->contentId;
    });
}

Then in your form, add an entryId input set to the hashed entry ID.

<input type="hidden" name="entryId" value="{{ entry.id|hash }}">

It’s important that you hash the entry ID and use getValidatedBodyParam() instead of getBodyParam() so users can’t repurpose the form to edit any entry on your site.


How can I get cookies that were set in javascript from a twig template?

So far the only solution I have found is to use a plugin, and Lewis Jenkins' LJ Cookies plugin does the trick nicely:

{{ craft.lj_cookies.get( NAME ) }}

It also allows you to set and delete cookies within templates.


Setting a new / override shippingAddress via axios

Stumbled over the old questions, this is how it works:

updateShipping() {
        const options = {
            method: 'post',
            url: '/actions/commerce/cart/update-cart',
            headers: {
                'X-CSRF-Token': window.Craft.csrfToken,
            },
            data: qs.stringify({
                shippingMethodHandle: 'standardShipping',
                shippingSameAsBilling: 0,
                shippingAddressId: 123, // remove if it doesn't exists or is new
                shippingAddress: {
                   id: '', // only needed if address is new
                   firstName: 'test',
                   ...
                },
            }),
        };
        axios(options)
            .then(response => {...})
            .catch(error => {...});
    },


How do I set a specific entry in a template with "set"

You need to add .first where you are setting the entry variable:

{% set entry = craft.entries.id(43).first %}

That way you can avoid doing a for loop.


This was a bug in Craft that's been fixed for the next (post 2.4.2696) release.

Once that release is out, devMode output will be written to the craft/storage/runtime/logs files just like a normal web request would with devMode enabled.


"Invalid username or password" when registering and logging in a user


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.


You can use dot notation:

craft()->request->getPost('fields.notes');


SimpleMap plugin - How to render it on a webpage?

Someone asked this question on the Simplemap Github issues, read the answer here.

I've copy/pasted pasted the answer below in case that link dies, but stress this is not my code, the credit goes to Tam

The plugin returns an array containing lat, lng, and others (see docs). You can use these as the location for any front-end map library (e.g. Google Maps or Mapbox).

Using Google Maps as an example:

And Mapbox:

<link href='https://api.mapbox.com/mapbox-gl-js/v0.21.0/mapbox-gl.css' rel='stylesheet' />


From the documentation on events, they follow this pattern:

craft()->on('component.eventName', function(Event $event) {
    // ...
});

So in your example, it'd be something like this and you'd want to add it to your plugin's init() method in the main plugin class.

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

    craft()->on('users.onDeleteUser', function(Event $event) {
        $user = $event->params['user'];
        $userToTransferContentTo = $event->params['transferContentTo']
    });
}

The full list of available events and the parameters they have can be found here.


A for loop within a for loop that is split

How about this; you get the pull quote index by dividing the loop index by 4 (will always return an int) and then you modulo that index against the length of your quotes array:

{% if loop.index % 4 == 0 and not loop.last %}
      {% set entry = pullQuotes[(loop.index / 4) % (pullQuotes | length) - 1] %}

          {{ svg('@icons/quote.svg', class="w-20 h-20  text-lime-500 flex-shrink-0 fill-current") }}

          {{ entry }}

{% endif %}


Commerce 2: Custom product fields not showing up in order

First you need to figure out which one you are using.

LineItem Options:
Here is the doc for it.
https://docs.craftcms.com/commerce/v2/adding-to-and-updating-the-cart.html#line-item-options-and-notes

One thing worth to mention is that options store in lineItem, which is one set of options for each purchasable/variant. So in your form you should put the options in your for loop of the product.getVariants().
And have the loop index in front just like the purchasable. e.g.

<select name="options[0][max]">
        {% for i in 1..max %}
            <option value="{{ i }}">{{ i }}</option>
        {% endfor %}
</select>

Same with your "qty" it needs to have loop index in front as well.
See the documentation link for example:
https://docs.craftcms.com/commerce/v2/adding-to-and-updating-the-cart.html#adding-multiple-purchasables-to-the-cart

Order Field:
Didn't find documentation for it in craft CMS commerce 2 docs.
Order field stores with order object. One order has one value for a unique field handle.
You can use <input type="your-choice" name="fields[customFieldHandle]"/> in "commerce/cart/update-cart" action.
You can retrieve it by calling order.customFieldHandle.

Before you use one custom field in the twig template you need to go your control panel and create a custom field first. "http://your-site.com/admin/commerce/settings/ordersettings". Find the "order fields" (name maybe different due to the version of craft, I don't think P&T have ever changed it since beginning.) tab, and create a field just like you would create a field for entry.

Try this form:

<form method="POST" name="main">
    <input type="hidden" name="action" value="commerce/cart/update-cart">
    <input type="hidden" name="paymentCurrency" value="{{ currency }}">

    {{ redirectInput('cart') }}
    {{ csrfInput() }}

    {% set max = product.max %}

    {%- for purchasable in product.getVariants() -%}
        {% if purchasable.isAvailable %}
            <input type="hidden" name="purchasables[{{loop.index}}][id]" value="{{ purchasable.id }}" />
            <select name="options[{{loop.index}}][max]">
             {% for i in 1..max %}
                <option value="{{ i }}">{{ i }}</option>
             {% endfor %}
            </select>
            <input type="hidden" name="purchasables[{{loop.index}}][qty]" value="1"/>
        {% endif %}
    {%- endfor -%}

    {%- for purchasable in product.getVariants() -%}
        {{ purchasable|currencySalePrice('' ~ currency ~ '') }}
    {%- endfor -%}

    <input type="submit" value="{{ "Add to cart"|t }}" class="button"/>
</form>

If you want customer to choose one options and apply for all the purchasables.

Just put a hidden input in the for loop and then use JavaScript function to update options in the loop on change.


We haven't given a hard date for the official release of Craft other than before the end of the year.

A Craft 3 compatible version of Commerce (Commerce 2.0) will be released at the same time Craft 3 is officially released.


As long as Apache and PHP are working like they’re supposed to, this is fine. Files that end in .php should always get processed by PHP before they’re served to the client.

Here are the risks:

If PHP is ever disabled, or the server is misconfigured so .php doesn’t get processed by PHP, then Apache will start serving that file directly, exposing all of your code (and in this case, your DB credentials).
Every PHP file that gets loaded after index.php will be able to see those constants, and potentially echo them out. (Most likely this would be your own doing, e.g. you might be echoing out everything from get_defined_constants() while trying to debug something.)

If you can live with those, go for it. Personally, I’d say it’s just not worth it.


How to get started with ElementAPI & Ajax

I don't think I quite understand, so I apologize in advance for what will be some revised answers.

news.json doesn't really exist. Meaning, I don't have a physical file called news.json in the filesystem anywhere. It is just an endpoint, and you'll want one for each of your calls.

For example: news.json or blog.json or events.json

  I have many pages where I need to fetch data with different parameters

That's no problem. I would still keep your javascript in the _layout template just to keep things clean. If you put js in each of your templates, you'll end up having chunks of js all over.

You can define different listeners for different things within a single docReady

$(function(){
    $('news').click(function(){
        // Ajax for news
    });

    $('events').click(function(){
        // Ajax for events
    });

    $('blog').click(function(){
        // Ajax for blog
    });
});

  Like how would I debug/ look at the return values from news.json

I use chrome for all development - so I'll right click anywhere and choose "Inspect Element". I'll then click on the network tab. That way I can see the XHR requests.

Once you click the button, you can see the request being made, and the response that is returned. It will look something like this:

 {"data":[{"title":"We just installed Craft!","url":"http:\/\/craftsandbox.dev\/news\/2016\/we-just-installed-craft","jsonUrl":"http:\/\/craftsandbox.dev\/news\/3.json"}],"meta":{"pagination":{"total":1,"count":1,"per_page":100,"current_page":1,"total_pages":1,"links":[]}}}

From there you will parse through the response and handle it however you want. In the past I've used things like mustache to keep the templates as clean as possible.

Hopefully this helps a little? Let me know and I can revise the answer to help get you rolling. There is much about the ElementAPI I am unfamiliar with myself, but since you were referencing a thread I answered I thought I'd try and help.


how to specify entry type on front end entry form?

You just need to specify a hidden input with the typeId set correctly.

i.e.

<input type="hidden" name="typeId" value="{{ entry.typeId }}">


Sprout Email not triggering from Sprout Form

Variables in Craft are case sensitive.  You'll run into the same error if you try to output the Craft {{ siteName }} global as {{ SITENAME }}.

Updating the casing to {contactFullName} or {{ object.contactFullName }} should get things working for you.

An extra note regarding the comments above. Luke is onto the right answer in the comments, however, one more distinction needs to be made. There are multiple variables available to your Sprout Email templates. To quote the docs linked in Luke's comment:

  In your notification templates you can use any Twig code that you
  would use elsewhere in your templates. Additionally, Sprout Email
  Notifications give you access to the Notification Email Object (entry)
  and any Dynamic Object provided by the event (object)

Your variable contactFullName is not a field on your Notification Email Entry, it's a field on your Sprout Forms Submission Entry.  It's correct that you would get an error trying to refer to it as {entry.contactFullName} because 1) the Notification Email doesn't have that field and, 2) the shorthand syntax is going to add the object variable behind the scenes, so the variable would be seen as {{ object.entry.contactFullName }}.


Getting "Invalid verification code." on password reset

In case anyone makes the same silly mistake I did, I had a conditional on the sign-in page that redirected folks to the page they were on before signing in.

After a password reset, it was trying to redirect back to the Set Password screen with the reset token, resulting in the error.

I just adjusted the conditional so it ignored the referrer URL if it was a control panel action. Problem solved.


If you have $entry, you should be able to get the tags by the field name, (codes, in your case).

$tags = $entry->codes;
foreach($tags as $tag)
{
    echo "<li>".$tag->title."</li>";
}