Adding description and other information to channels This might be a little difficult to explain thoroughly and correctly, bear with me. :)

The Problem

The news website I'm working on has different categories based on topics, location, and "genres" (news, editorial, press release, etc). In addition, we also have other channels that work independently from the primary articles.

I am having a difficult time finding the best approach to provide information such as heading, description, a cover image, etc — for these different channels in a way that is organized, makes sense and can be easily edited from the CP.

Example

The Main channel could have an image and a description which states that the articles in this section are written by the members of the company.
A channel managed by a writer from the community could also have its own cover image and description stating that this channel contains chronicles and critics by him and other authors.
A channel managed by a collaborator/correspondent could focus on a specific topic, such as technology; the image and description of the channel would explain this.
Another channel could provide news related to the company alone.
Another channel could be from the developers in the team.
etc...

Note how these secondary channels are different from the main content. These should not be mixed together and are often accessed by different users.

So... Has anyone dealt with this problem? How have you solved it? I have a few ideas in mind but I'd like to see what other practices are out there.

I have a channel of index pages, where each entry in the index page channel serves as the index page for some channel. I use ljdynamic fields and have a 'chanel' field which is a dropdown to select the channel. Description and etc. could be other fields in this index page channel.


Craft 3 doesn't see my Commerce plugin I am running a local install of Craft 3 Pro dev preview using MAMP and Sequel Pro on my iMac.  I downloaded the Commerce plugin to try it out and dropped the 'commerce' folder into my craft/plugins folder.  When I visit the admin control panel and click on plugins, I can't see the Commerce folder/plugin I just added. Any suggestions as to why?

The whole plugin API has gotten an overhaul in Craft 3, so all plugins needs to be rewritten/updated to work with Craft 3.

Craft Commerce hasn't been updated yet. If it had there would be separate versions for Craft 2 and 3 for download.


Any working RSS feed examples out there? Do you only have to build the .rss template file and then you use that URL for your RSS feed? Based on the documentation at hand, that's what it seems like.

I'm attempting to parse an RSS feed using the Google Feed API (https://developers.google.com/feed/) and it's having issues reading the output - so I just want to see if anyone else out there is using RSS in Craft so I can see their output vs mine. When I view mine, it doesn't look like a traditional xml output.

Here's the boilerplate I've been using for RSS feed templates. I just name the file rss.html and call it a day.

This assumes a channel is set up with a description and title field.

{% header "Content-Type: application/rss+xml" %}
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">

{% set rss = craft.entries({ section: 'yourChannel' }) %}

<channel>
  <title>Title Your RSS Feed</title>
  <link>http://www.yourlink.com/</link>
  <description>Enter a description here</description>
  <language>en-us</language>
  <atom:link href="{{ url() }}" rel="self" type="application/rss+xml" />

  {% for item in rss %}
  <item>
    <title>{{ item.title }}</title>
    <link>{{ item.url() }}</link>
    <description>{{ item.description }}</description>
    <pubDate>{{ item.postDate.rfc2822() }}</pubDate>
    <guid>{{ item.url() }}</guid>
  </item>
  {% endfor %}
</channel>

</rss>


Show a child's Matrix within a Structure I want to show a child entry and can so:

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

    {% switch entry.level %}
        {% case '1' %}
            {# level 1 #}

{{ entry.title }}

        {% case '2' %}

            {# level 2 #}

{{ entry.title }}

        {% case '3' %}

            {# level 3 #}

{{ entry.title }}

        {% case '4' %}
            {# level 4 #}
            4

    {% endswitch %}

    {% endfor %}

but I can't get a matrix field to show for the child entry, using:

{% for block in entry.myMatrix %}

            {{ block.intro }}

{% endfor %}

within any of the cases?

This should do it, user2569

{% for block in entry.myMatrix %}
    {% if block.type == 'intro' %}
        {{ block.intro }}
    {% endif %}
{% endfor %}


How to set hero image for root and children in a structure I am puzzling the best way to implement hero images per 'section' of a site.
I can set a global default hero image no problem. But I want to set one header image for the root and children of a particular section.
I can't use url segments as the site is multi-lingual and it will change.

I've tried detecting the root of the current structure to base my template code on.

{% set rootEntry = entry.getAncestors().first() %}

But this returns null - like there is no model returned.

UPDATE:
NO answer yet but a repharasing of the question.
IN order to do this you need to get the top level entry based on where you are in the site structure/tree. This link Building a nav from the top level page of a structure demonstrates great working code.

However the assumption in the above posts and many others is that the structure is built out of the actual entry pages themselves.

I have two structures. Pages and menus. The menu structure has related entry fields that 'point' to the pages.

So in in my scenario the menu structure is built out of related entry fields - not the entry being viewed. Hence, the reasons getAncestors was not working was because it was taking the existing entry a visitor was viewing and looking for a hierarchy structure that was flat.

So the question is now more complex - how do you get the top level tree branch of your structure menu based on the current entry viewed when that current entry is a related entry field in your structure menu? It seems very complicated to achieve. Especially just for flexible headers per sections....

FINAL UPDATE
Thanks Mats - i couldn't have done this without your diligent replies.
Below is my final solution to find out what the top level root is. It is expressed as sub navigation for structure menu but it does two things - build s the sub nav and identifies the root of the tree where you are. NB macro is used for active links.

{# Get the sidebar structure subnavigation #}
{# check for entry so channels do not break #}
{% if entry is defined %}
    {% set navEntry = craft.entries.section('menu').relatedTo({
    targetElement: entry,
    field: 'entryLink'
    }).first() %}

    {# get the root entry of the structure set to null if we are at top #}
    {% set root = navEntry ? craft.entries.ancestorOf(navEntry).level(1).first() : null %}

    {# setup variables in switch for ouput of heading and sub links#}
    {% switch root %}
        {% case null %}
            {% if navEntry.hasDescendants() %}
                {% set heading = navEntry.title %}
                {% set thisSubMenu = craft.entries.descendantOf(navEntry) %}
            {% endif %}
            {% set rootEntry = navEntry %}
        {% case true %}
            {% set heading = root.title %}
            {% set thisSubMenu = craft.entries.descendantOf(root) %}
            {% set rootEntry = root %}
    {% endswitch %}
{% endif %}

{% if heading is defined %}

{{ heading }}

{% endif %}

{# Get entries to build the sub-menu #}
{% if thisSubMenu is defined %}
{% set subMenu = thisSubMenu %}

    {% for entry in subMenu %}

        {% if entry.entryLink.first|length %}

            {% set subNavLink = entry.entryLink.first().uri %}

        {% elseif entry.customMenuUrl|length %}

            {% set subNavLink = entry.customMenuUrl %}

    {% endif %}

        {{ entry.title }}

    {% endfor %}

{% endif %}

Something like this should do the trick (obviously, change navStructureHandle and entriesFieldHandle to real values):

{# Get the related nav entry for the current entry being viewed #}
{% set navEntry = craft.entries.section('navStructureHandle').relatedTo({
    targetElement: entry,
    field: 'entriesFieldHandle'
}).first() %}

{# Get the root (top level parent) structure entry for the nav entry #}
{% set rootEntry = navEntry ? craft.entries.ancestorOf(navEntry).level(1).first() : null %}

{# If a root entry was found, print out the title #}
{% if rootEntry %}
    {{ rootEntry.title }}
{% endif %}

With the above, rootEntry will be null if the current entry doesn't have a related nav structure entry, or if a top level parent can't be found for the nav entry (i.e. the nav entry is top level).

I wouldn't worry too much about the performance with the above, but if you do feel it's too complex for printing a header, you could consider using the Preparse plugin instead. Preparse basically lets you create a custom field containing Twig code that will be parsed whenever the entry is saved. This basically lets you "cache" the result of costly Twig operations to a plain text, custom field on an actual entry.

Using Preparse, you could add a field called navHeaderTitle to your child entries (i.e. not the nav section). The field should contain the Twig code above, in addition to actually printing out the rootEntry title if a root entry is found (note that it's a good idea to wrap the whole thing in a {% spaceless %} tag pair):

{% spaceless %}
    {% set navEntry = craft.entries.section('navStructureHandle').relatedTo({
    targetElement: entry,
    field: 'entriesFieldHandle'
}).first() %}
    {% set rootEntry = navEntry ? craft.entries.ancestorOf(navEntry).level(1).first() : null %}
    {{ rootEntry ? rootEntry.title }}
{% endspaceless %}

Then, you could simply do something like this in your template:

{# No need to pull any entries; just test for the `navHeaderTitle` field #}
{% if entry.navHeaderTitle %}
    {{ entry.navHeaderTitle }}
{% endif %}

Of course, the caveat with the Preparse approach is that if you ever change your root entry's title, you'll have to re-save all your child entries in order to re-parse the Twig and update the entries' navHeaderTitle value.

A good compromise could be to use Preparse, but echo out the root entry ID instead of the title – then you could do this in your template:

{% set rootEntry = entry.navHeaderEntryId ? craft.entries.id(entry.navHeaderEntryId).first() : null %}
{% if rootEntry %}
    {{ rootEntry.title }}
{% endif %}


Plugin development - Querying related data I am working on a Craft plugin.

I have a main entities are 'Courses' and 'Entries'. If I click on an Entries in the CMS there is an option to select and associated 'Course'.

In my controller I can get a Course as follows:

$course = craft()->entries->getEntryById($variables['pathId']);

So far so good, but now I want to get all related 'Entries', so I do the following:

$entries=$course->entries->find();

This gives the following error:

Property "Craft\EntryModel.entries" is not defined.

What am I doing wrong? Clearly the two are related so why isn't this method working?

I think this works but is it an acceptable solution:

$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'checkin';

$criteria->relatedTo = array(
     'targetElement' => $entry,
     'field' => $field
);

$checkin = craft()->elements->findElements($criteria);


Linking to a plugin setting page? I'm trying to add a "convenience" link from within a plugin to it's general settings page. In the General Settings custom cpTriggers and baseCpUrl can be set to custom values and I'm wondering if there is a easy Craft variable to retrieve a link to the site's correct settings page. It would create something like this in a template.

http://mysite.com/customadminword/settings/plugins/mypluginname

Any thoughts? I could write some logic in the plugin to dig it out but it seems like I might be overlooking something obvious. Any thoughts?

Add a public getSettingsUrl() function to your main plugin file that returns a URL string.

A full URL is not required -- you can simply return "pluginname/settings".
If this is left blank, a simple settings page will be provided, filled with whatever getSettingsHtml() returns.

You can then get the URL from elsewhere in Craft using the PluginsService.
craft()->plugins->getPlugin('pluginname')->getSettingsUrl();

or PluginsVariable:
{{ craft.plugins.getPlugin('pluginname').getSettingsUrl }}


How can I create a template macro within my plugin for use within front end templates? I have a plugin that I am writing and I want to make available a macro that can be used within the front end sites templates. What is the best way to do that?

I'm not aware of this being possible. The control panel uses a different template path than the front end. This makes plugin templates generally inaccessible. One possible option is to create a template variable that runs a macro or renders a template on behalf of the user. Something like:

{{ craft.pluginHandle.macro(arguments) }}

You will need to make sure that the template path is set to the Control Panel so that your macro can be found, and that it's set back afterwards. At the start of the function set this:

craft()->path->setTemplatesPath(craft()->path->getCpTemplatesPath())

Then when you are done rendering your macro (preferably to a variable to return later), you set it back:

craft()->path->setTemplatesPath(craft()->path->getSiteTemplatesPath())


Freeform forms fieldtype I see there is a freeform forms fieldtype available after the plugin was installed. What exactly does this field do and how to render it correctly (within matrix)?

From the Freeform docs:

  The Freeform Form (or Submissions) fieldtype lets the user assign any
  Freeform form (or form submissions) to any element: a section entry,
  categories, assets, etc.

In a nutshell, this means you can embed forms to any entries you have, like so:

This section within the docs shows you how to correctly code your templates.


Extending the matrixinput class I'm trying to call the addBlock function from the Matrix fieldtype. Whenever a block is added i need to run some basic javascript.
Does anyone have an idea how to go about this?
thanks!

You can listen to the add button's click event like so:

$('.matrix > .buttons > .add').on('click', function(e) {
    // your js
});


Entries not being searched in the control panel I have a 'person' channel that does away with the title field and instead uses custom fields like so {lastName}, {firstName}.

However, I've noticed that when I'm looking at the entries listing in the control panel and I search for 'Hamilton' as an example (I have 3 entries where the surname is Hamilton) - only 1 of the entries returns.

I even tried adding myself as an entry to the channel but searching for Grant or even Steven - I get no returns.

Can't figure out why this would be?

Updating the search indexes was the solution here. In addition, I also enabled Fuzzy Searching for partial matches


Filter out duplicate entries in array? I have some matrix fields containing a date. I then loop through the entries in a category looking for entries containing a matrix field with a date during the next month. Everytime a matrix field is found, the entry id is added to an array of entries. Like so:

{% for event in craft.entries.section('events').type('eventWithMultipleDays').relatedTo(category).find() %}
    {% for date in event.dates if date.multiDate >= now | date("Y-m-d") and date.multiDate <= now | date_modify('+1 month') %}
        {# ADD THE FILTERED EVENT TO THE CATEGORYSEVENTS ARRAY #}
        {# NOTE SQUARE BRACKETS CREATE AN ARRAY - NECESSARY FOR THE MERGE #}
        {% set categoryEvents = categoryEvents | merge([event]) %}
    {% endfor %}
{% endfor %}

Not surprisingly, some entries contain several matrix blocks with dates falling within the next month, which means the array is containing duplicate entries. That means when I output the entries array, I'm getting repetition, using this, as you'd expect:

{% for event in categoryEvents %}
    {# details output #}
{% endfor %}

Is there a way to only get unique values out of this array? Or, if not, a better way to create the array perhaps?

Thanks,
Clive

Holy moly! I've solved it already, Batman. Check the array before adding the event to it, like so:

{% if event not in categoryEvents %}
        {% set categoryEvents = categoryEvents | merge([event]) %}
{% endif %}


How can I use    within a redactor/rich-text field? We need to be able to add super and sub-text to a rich text field without having the client dive into the markup. Has anyone successfully added this as a redactor or Craft plugin?

There are keyboard shortcuts that can accomplish super and subscript.

From the Redactor changelog:

Superscript shortcut now crtl+h (high, super) instead of old ctrl+l
Subscript shortcut now crtl+l (low, sub) instead of old ctrl+h


Where and how should you listen for entry delete in plugin? When an entry is created with my plugin's field type, data is saved to a separate table with entries id for reference. I need to delete that data if the entry that is associated with the data is deleted.  How and where should I listen for entry delete event to execute a method to delete this separate data?

You can add something like this to your plugin's init() method:

craft()->on('entries.onDeleteEntry', function(Event $event) {
    // Do your custom logic here.
    // Note that you can access the entry that was just deleted via $event->params['entry']
});

Or, better yet, from your custom table, make sure the foreign key that you've created on your entryId column back to the entries table has a CASCADE DELETE setup on it so that when Craft deletes the entry, it will cascade down and delete it from your table as well.


Using the Charge plugin for membership subscriptions A project I'm working on requires that publicly registered users pay a fee upon registration, and when payment is successful an Entry belonging to them should automatically be created.

I have component pieces of this working but am struggling with how to tie them together.

I currently have a basic plugin I wrote which handles the creation of an Entry when a user is Activated. The plugin has no money-taking facility. It works fine; the public user registration form posts to the built-in 'users/saveUser' action, and the plugin listens for the users.activateUser event which is fired when an admin manually activates their account.

We want to take that 'manual' step out by having the system automatically activate the user if a Charge has been successful. This means integrating Charge into the public registration form. Which would seem to involve me having to change the action for the form to 'charge/charge', so Charge can do its thing.

How then do I also get it to create the user?

I see that Charge has an event for successful payment, which I'd like to hook onto and trigger the 'user/saveUser' like what's already working - but how, and how do I pass the username/email fields through from the form to 'user/saveUser' via Charge?

Developer of Charge here.

Setup for installs up to (and including) 2.0.x  :

The simplest setup would be to use the onBeforeCharge event.

This fires at the very start of the charge request, after validation but before anything has actually happened.

You'd use that to jump in, and create your user, entry, or anything else you might want to do. As part of that same event you can modify the actual ChargeModel which will be used in the payment request too.

The onBeforeCharge event fires before we pull out the user for the request, so as long as you're creating the user at that point, you won't need to do anything else to have all the subsequent steps properly associated to that user either.

Of course be aware that a payment can fail for any number of reasons, so check in that onBeforeCharge event if you actually do need to create the user before blindly going ahead.

Additionally, you can use the onCharge event to later perform any clean up you might need once the payment has actually succeeded.

Setup for installs from 2.1+

2.1 (not yet released as of 25/04/16) is bringing inline user registration to the payment forms, so in that case you'd just pass a new flag on the request to registerUser = true, and let Charge do the rest.

Charge will only attempt to register a new user if required, and will use the customerEmail as the default base, but that can be overridden with other parameters and inputs on the form.


Get parameters from referrer Is there a way to get the parameters from the referrer url?

I've tried this:
{{ craft.request.urlReferrer.getQuery }}
but that’s not working.

It can be done with some Twig code:

{% set referrer = craft.request.urlReferrer %}

{% if referrer %}
    {# Remove everything before the `?` #}
    {% set queryString = referrer|replace('/^.*\\?/', '') %}

    {# Split the query string into individual params #}
    {% set params = queryString|split('&') %}

    {% for param in params %}
        {# Split this param on the `=` sign #}
        {% set parts = param|split('=') %}
        {% set name = parts[0] %}
        {% set value = parts[1] is defined ? parts[1] %}

        {# Do something with it... #}
    {% endfor %}
{% endif %}

Note that this could would require Craft 2.2 or later, which comes with a regex-enabled replace filter.


Entry element query missing user field data when user is suspended I have a channel in which each channel entry has a "users" field type that is limited to one user. My code below works fine when the user is not suspended, however if I suspend the user, the then $entry->user field is null rather than set to the array of one user like its normally set to.

Here is my code:

        // do criteria code to get pending transfers from patients channel
    $account = $userIdentity->getFieldValue('account')->first();
    $entryQuery = Entry::find()
        ->section('networkAssets')
        ->relatedTo(['targetElement' => $account, "field" => "account"])
        ->orderBy('title asc');

    // Execute the query and get the results
    $entries = $entryQuery->anyStatus()->all();
    $assets = [];
    foreach($entries as $entry) {
        $user = $entry->user->one();
        $assets[] = [
            'id' => $entry->id,
            'slug' => $entry->slug,
            'title' => $entry->title,
            'email' => $user->email,
            'first_name' => $user->firstName,
            'last_name' => $user->lastName,
            'address1' => $entry->address1,
            'address2' => $entry->address2,
            'state_province' => $entry->stateProvince,
            'city' => $entry->city,
            'postal_code' => $entry->postalCode,
            'country' => $entry->country,
            'username' => $user->username,
            'password' => '',
            'status' => $user->getStatus(),
            'date_created' => $entry->dateCreated->format('m/d/Y') . "
" . $entry->dateCreated->format('H:i:s T'),
            'last_login' => $user->lastLoginDate ? $user->lastLoginDate->format('m/d/Y') . "
" . $user->lastLoginDate->format('H:i:s T') : 'Never',
            'phone' => $entry->phoneNumber
        ];
    }

    return $assets;

You can see in the foreach loop that Im getting the user from the looped entry result and storing it in a $user variable.

When I try to use $user I get a notice because $user is null.

How can I force this code to return the linked user in the user field even  when the user is suspended?

User queries by default will only return active users, not pending or suspended ones.

To include suspended users, change this line:

$user = $entry->user->one();

to this:

$user = $entry->user->status(['active', 'suspended'])->one();

Or if you want to include pending users as well (users who haven’t activated their account yet), you can do this:

$user = $entry->user->anyStatus()->one();


Possible to Get grunt-uncss Working with Craft? I'm working on a site that uses bootstrap so has a very large CSS file with many selectors that are not being used. To reduce the size of the file, I'd like to use the grunt-uncss task, but it does not work as well with CMS-based sites, as opposed to static HTML files.

I've seen guides for how to make it work on Wordpress but the guide includes Wordpress specific plugin-ins that I don't believe are available on Craft.

Curious if anyone is using the grunt-uncss with on a Craft site and how it was set-up to make it work effectively? Would like it to run on all pages of the site, ideally. Thanks!

So to close the loop on this one, I actually ended up using a different grunt tool that essentially accomplishes the same goal called purifycss. I was able to target purifycss at the craft template folder, get it to look at bootstrap css selectors actually in use in the templates, compare it to the full bootstrap css files, and then have it output only the css that was being utilized in a final minified css file.

It ended up being that I was only using about half of the available bootstrap css selectors so it cut a bunch of unused css out of a very large file.

Also, I believe I could have taken the same or similar approach with uncss so if you prefer that tool, I believe you can use it in the same way (though I did not personally so can't speak in detail to it).

Here is the excerpt from my gruntfile.js:

purifycss: {
  options: {
    minify: true,
  },
  target: {
      src: ['./craft/templates/*.{html,twig}','./craft/templates/**/*.{html,twig}','./craft/templates/**/**/*.{html,twig}','./craft/templates/**/**/**/.{html,twig}'],
      css: ['./public/lib/css/dev/vendor/_bootstrap-theme.min.scss','./public/lib/css/dev/vendor/_bootstrap.min.scss'],
      dest: './public/lib/css/dev/vendor/_bootstrap-purified.min.scss'
  }
},


How to export client-entered content for a specific channel to keep my local database in sync with staging I'm in the process of developing a site for a client and I'd like to give them access to the control panel on the staging server so they can begin to enter content for their "News" channel, which is set up and ready to go, and for which they have lots of historical content to enter.

The issue is that I'm still developing the rest of the site and want to come up with the most painless way possible of keeping their content in-tact in the database without breaking my development workflow as I continue to create additional fields and templates for the remaining sections of the site.

Is there a way that I can easily export just their "News" channel content from the staging database periodically, importing it into my local database and eventually migrating my more complete local database back to staging as I finish more sections?

There's currently not an easy or clean answer for this.

There are some great answers here on different solutions for handling data syncing/migrations across multiple environments.

We've got some ideas of our own on how we'd like to make this less painful for users (it's a PITA for us as well), with syncing / importing / exporting data between Craft installs, but unfortunately we don't have an ETA on it.


Is it possible to setRouteVariables when redirecting after a successful form submission? I have a form.  It submits.  It saves.

I'd like to pass the newly-created, complete form object back to the 'thank you' page template so that I can display the values that were submitted.

I do not want to pass the ID or any identifiable information in the URL.  Ideally, I'd like behavior just like using setRouteVariables

craft()->urlManager->setRouteVariables(array(
    'form' => $form
));

However, setRouteVariables does not work when using $this->redirect() or $this->redirectToPostedUrl().

I can successfully pass query string parameters back using the redirect method in the following way:

$this->redirect(array($redirectUrl,'dog'=>'cat'), true);

Is there any way to do this with posted variables that are not visible to the user?

Other than the query string, you're options are:

Save it to a cookie and retrieve it from the next page with something like this plugin.
Save it to cache (craft()->cache).
Save it to PHP's $_SESSION, which Craft wraps with HttpSessionService (craft()->httpSession).
Writing a plugin with a Twig function that wraps Craft's craft()->userSession->setFlash() method, which will store a key->value pair in session for exactly one request. You can retrieve the value via craft.userSession.getFlash().

Note that there are limitations to the size and complexity of the data you can pass along with all of these and in almost all cases, the data needs to be serializable.


Checking if current entry exists in an entry custom field in a different entry I thought this would be simple but I am having no luck with it. I have a channel called "Posts" and for each Post there an "entry" custom field which lists all "Projects" (a structure). The user can select up to 3 of these within a Post.

The idea is to relate a current news Post with an existing project. In my Project entry template I basically want to check to see if the current project has been selected in the "relatedProjects" entry field. If it has, I need it to show a "Related Posts" title and then below that list each Post.

The thing I can't fathom out is how to have a section title that doesn't appear in the loop for each Post.

You can get the posts related to your "entry" (the currently shown project) with a
craft.entries element criteria model where you set the relatedTo parameter like so:

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

Then check if this does find anything using Twig's length filter:

{% if relatedPosts|length %}
    <aside>
        {% for relatedPost in relatedPosts %}
            {{ relatedPost.title }}
        {% endfor %}
    </aside>
{% endif %}


Don't use localized slugs for templates We are building a multilingual site.

We have different domains and slugs for German and English pages/sections  i.e. projects is called projekte...

Right now the template used is called "projects.html" which we want to use for all languages, but Craft is looking for each slug's language template and not the English one?

Do we need to duplicate each template or?

Thanks in advance.

You can create new template files for your second locale and simply use Twig include to only maintain one template for all of your locales.

projekte.html:

{% include 'projects.html' %}

Use a locale specific subfolder (craft/templates/de/) to separate the german templates from your main / first locale templates (see the Template Localization article in the Docs on how this works).

Another way to handle localized URIs is to not use "URI to template matching" (pt. 6 in the Routing article) but configure an entry that loads your template instead (pt. 4).

Create a single section with "projects.html" for the template that should get loaded if the single's URL is requested. The template's filename is irrelevant for the URI matching and you can set the entry's slug to whatever you want in both of your locales.

Before creating many single sections now, also consider using a "Pages" structure section instead.


Auto Expire on entries I need to automatically set the expire date of a new entry (only) from a specific section.

I know that it's possible to do this via the frontend twig templates, however I need the user to have the flexibility to change the date from the default that's set if they want to.

So when they create a new entry it'll have an expiration date of today + 3 months, but if they wanted they could change this date to next Wednesday or whatever they wanted.

Thanks for your help

If you haven't solved it yet with a custom solution, have a look at my Auto Expire plugin. You would add a new expiration rule with the expiration date set to:

{ 'now'|date_modify('+3 month 5am')|date('c') }

or

{ postDate|date_modify('+3 month 5am')|date('c') }

and make sure the option to allow user changes is checked.


The timezone could not be found in the database This one is new to me. I've got the timezone set in my admin panel to Denver but I get this this error when I try using a global in my template...

DateTime::__construct(): Failed to parse time string (End Date) at position 0 (E): The timezone could not be found in the database

Here is my code in the template

{{ endDate | date("U") }}

My global is called End Date (endDate) and is using a date field type

Is this a custom template global from a plugin or is it a field on a Craft global set, because those you usually access with {{ myGlobalSet.endDate }}.


Visiting admin brings up the installer I recently moved a Craft 2 install from a server running PHP 5.x to one running PHP 7.x. All seems to be well. The custom "system offline" message appears as expected when visiting the home page, anyway. It also appears when visiting a random URL.

But when visiting the admin URL I'm redirected to the installer. I'd obviously rather not do this as the system and DB are already there.

Do I have any options here?

Sounds like it's viewing the DB as being empty. The access credentials are correct (it's technically connecting to the database), but it's not seeing any tables in the database.

Does your site use a prefix (ie: craft_) before the database tables? Check to make sure that the prefix specified in config/db.php matches the actual table prefixes.
Double-check to make sure you're connecting to the right database.


Modifying search scoring algorithm Is there any way to tweak the way search score is calculated? For example, I would like words in the title field to be scored higher than the same terms in other fields.

Seems to be the new standard since version 2.2.2582:

"Entry and category search results now place a 5X weight on search term matches within Title fields."


How to suppress server errors in Craft? On certain pages of my site, I download and display resized (using the Imager plugin) images from remote site.

Now, sometimes that remote site returns error and in such case Imager is throwing exceptions, blocking the whole page from being viewed.

Now, is there a way to suppress server errors when possible, e.g. write them to log file and don't stop page processing?

devMode is set to false.

It depends on the type of errors that are being thrown.  If they are Twig/template errors, then you can can set the suppressTemplateErrors config setting to true and they will simply get logged and the page request will continue as usual.

If they are non-Twig exceptions, then you'd have to do something more fancy like make a plugin that's essentially a facade for the Imager plugin and wraps all of it's calls in a try/catch block that just swallows any exceptions.

Or make a pull request that added support for it to the plugin itself.


SEOmatic and Global Variables We have a Craft site with nearly 800 entries. For SEO purposes we need to change the page title and page (SEO) description for each entry, a laborious task to say the least.

Is there a way to have, say, a PageTitle variable which we apply to all entries with SEOmatic, and if we need to change the structure of the title, we just have to change the PageTitle variable once. This variable itself would have variables within it, e.g:

  Beautiful {villaBedrooms} bedroom villa in {villaLocation.last.title}, Bali. From just ${villaPrice}. {villaHook}

So for Craft 2.x, what I'd suggest is just doing this via Twig. This is discussed here: https://github.com/nystudio107/seomatic/wiki/10.-Dynamic-Twig-SEO-Meta


CP form submissions occasionally reaching PHP's 300 second timeout Occasionally—I'd say about 30-40% of the time—when submitting a form in the backend, be it saving an entry, updating a custom field, etc, the page will just sit there, loading. This can and often does continue for ~ 299.88 seconds, after which it will proceed to the next screen as if nothing ever happened.

I've looked through the console log, but all the timestamps seem to be within a second of each other, so nothing jumps out as the step where things are getting hung up. I suspect a server problem, but I'm posting here just in case anyone can point me in a more specific direction than "there's a problem somewhere".

To date, this has not occurred on the frontend, but there aren't any frontend forms to submit, either.

Pastebin of the console log (the load time is on line 725): https://pastebin.com/aB4JkrBv

I can think of a couple things why this is happening:
1) Custom code doing a save operation.
If you're hooking into onSaveEntry for example,  Craft also lets other plugins have a chance at calling their own save code as well.
So when you do a saveEntry (or other element), Craft is going to repeat that call when you do it from your own code, basically putting you into an infinite loop because it keeps getting called until the server times out.
The fix is to make sure  you only call saveEntry once. There's a couple ways to do this depending on what you're trying to do.
One way to debug this would be to a create super simple plugin, using Business Logic or PluginFactory that listens for the saveEntry event and logs it.
If you see the plugin's log fill up, then some plugin is putting itself into a loop more than once.
2) runTasksAutomatically is not being called
Over time, Craft generates a lot of cache files, sessions, etc. Craft will automatically do some housekeeping for you and clean this up, however, the runTasksAutomatically config doesn't run on some server setups, forcing you to do the maintenance yourself. It's like a stuffed up drain, if it doesn't run for awhile, it takes longer to purge.
If your server doesn't support cron, you could use an uptime monitoring service like Uptime Robot or Pingdom to trigger the task call for you periodically.


Charge Model "amount" and "userId" not always populated I'm using the onCharge event to populate a separate purchases table that I can query elsewhere (combining both stripe and my other Paypal payments system).

The onCharge event is mostly working, but it's not populating the $chargeModel->amount.

It's also not populating the $chargeModel->userId if a new user is being registered (it only populates if there was a previously existing user).

Any idea why the charge model wouldn't have all of its information during the onCharge event?

Here's what I have in my plugin:

craft()->on('charge.onCharge', function(Event $event) {
    // Adding New Charges to Purchases Table
    craft()->purchases_newPurchase->addChargePurchase($event->params['charge']);
});

I'm pretty sure this issue is caused because the model is being passed to the event without being populated first (it only has the EXACT details that are manually populated when the record is created, not the additional functions).

I was able to use $chargeModel->planAmount just fine, and I was actually able to re-look up the model based on the passed model id, which properly populated the model before passing it back.


Entries related to BOTH categories I've got categories setup like this (Parent & Children):

Type
    Tops
    Dresses
    Pants

Colour
    Black
    Red
    Yellow

When I use this in a category filter and choose Dresses and Black, it works fine in terms that it will return entries that are in Dresses and entries that are in Black.

But how can I edit my code so that it returns entries that are ONLY in Dresses and Black (Black Dresses only!)

Below is what I have so far...

{% set productSegmentCategory = craft.categories.slug(craft.request.lastSegment()).first() %}
{% set productCategoriesArray = ['and'] %}

{% set productValues = {
    keywords: craft.request.getParam('keywords'),
    category: craft.request.getParam('category') ? craft.categories.slug(craft.request.getParam('category')) : null,
    order: craft.request.getParam('order') ? craft.request.getParam('order') : 'title asc',
    limit: craft.request.getParam('limit') ? craft.request.getParam('limit') : entryLimit,
} %}

{% set productParameters = {
    search: productValues.keywords,
    order: productValues.order,
    limit: null,
}%}

{% if productSegmentCategory|length %}
    {% set productCategoriesArray = productCategoriesArray|merge([{ targetElement: productSegmentCategory, field: 'productCategories' }]) %}
{% endif %}

{% if productValues.category|length %}
    {% set productCategoriesArray = productCategoriesArray|merge([{ targetElement: productValues.category, field: 'productCategories' }]) %}
{% endif %}

{% if productCategoriesArray|length > 1 %}
  {% set productParameters = productParameters|merge({ relatedTo: productCategoriesArray }) %}
{% endif %}

{% set productEntries = craft.commerce.products(productParameters) %}

{% if productSegmentCategory|length %}
    {% set entry = productSegmentCategory %}
{% endif %}

You can limit to only products that have multiple related categories like so:

{% set dressesCat = craft.categories...first() %}
{% set blackCat = craft.categories...first() %}

{% set products = craft.commerce.products({
    relatedTo: {
        targetElement: ['and', dressesCat, blackCat],
        field: 'productCategories'
    }
} %}


Sprout Forms: Passing Checkbox variable in url parameter I'm trying to create a "teaser" form in Sprout Forms.
First form has radio buttons and a group of checkboxes, and it's easy to pass the radio value (via redirect), but I'm not finding the documentation on how to pass checkbox fields as URL params.
Redirect: /contact/?radio_button={radio_value}&checkbox={fields-goals-1}
The second form will accept those params and ask for contact information.
Anyone got an example of how this?

There are a few possible ways to do this right now (Sprout Forms v2.3.4), all likely with a few trade-offs. We do have this situation on our radar to improve on in the future.

You could consider updating how you are storing those checkbox fields to use one or multiple Sprout Fields Hidden Fields. With this method, the first page with your initial options doesn't need to be a part of the Form and you could dynamically populate the hidden field with the value of whatever is selected. The trade-off here may be in how you wish to create reporting around your data, and whether this format makes that easier or harder.
You could manage a multi-page form using a Javascript library on the front-end (something like parsley.js). The trade-off here is that you have to add a javascript library to your setup, if you don't already need it for other things. We do have multi-page form support on our list.
You can also do this by building your Form using Custom HTML. The trade-off here is that things become harder to maintain for a fairly small item.
It might be possible to use Template Overrides and modify how the "value" parameter gets processed to make the value variable for your checkbox field use the initially selected items.  I expect this path would get tricky. The template you'd probably want start with when overriding things is the field.html template and the line that sets the value: {%- set value            = ... %}.


Target a certain entry type on the entries fieldtype I have all of my entries as single pages, but of different types depending on the section. I need to create a field that allows users to link to another page entry, but I need to ensure they only select one of a certain type.

Is it possible to only allow users to choose entries of a certain type using the entries field? I can't see the option, so perhaps if not there's a plugin that could do this? Has someone come across a good solution.

This is not possible by default in Craft. Check out the Entries Subset plugin, though, I think it can do what you want.


How to determine source of Elements save event We need to send notification emails when entries of a particular type are created, updated, or enabled/disabled. The entrypoint for this happens in a module's init() method:

Event::on(Elements::class, Elements::EVENT_AFTER_SAVE_ELEMENT, function (Event $event) {
    // do stuff
}

We recently updated to Craft 3.3.0, which resulted in many many many emails being sent. I think these have something to do with queue tasks that are generated as a result of system updates. During the update, the craft_queue table contains many rows. The first row's description is "Updating entry drafts and revisions" and the many subsequent rows show a description value of "Updating element slugs and URIs".

First, is it correct to assume that some system updates trigger queued resaves of all entries?

Second, we need to prevent the notification emails from being sent unless the save event is triggered as the result of a user action. I see the sender property of ElementEvent, but it seems that that has to do with the current method and doesn't bubble up the event chain.

We've thought about disabling versions on these entries, but that feels more like a bandaid.

Is there a way to determine the originating source of an ElementEvent's save event? If so, is that the best way to gain more control over when these notification emails are sent? In general, I'm wondering if we can detect whether an element is being saved as the result of a system update/queue task vs a manual user action.

First, you'll want to check if what is being saved is a draft or revision, and if so, ignore it for your purposes. You can check via:

use craft\helpers\ElementHelper;

if (!ElementHelper::isDraftOrRevision($element)) {
}

Next if you want to avoid doing anything during "bulk saving events", on Craft 3.1.22 or later there is:

if (!$element->resaving) {
}

...which was added in Craft CMS 3.1.22

Some additional discussion that might be useful: Improve behaviour for automatic resaving of entries when saving an entry type


Craft 3 large log file sizes I've noticed that Craft 3 log files in storage/logs e.g. web-404s.log and web.log don't seem to have a max size or rotate like with Craft 2.

The web-404s.log file is nearly 10 megs for 1 site now.

Should the log files continually grow like this or is there just an issue with my setup?

Are there config settings to set the max log file size or disable certain logging that I'm missing?

Thanks

Craft goes with Yii 2's defaults in the FileTarget class, which is 10MB for a log file before rotating. https://www.yiiframework.com/doc/api/2.0/yii-log-filetarget#$maxFileSize-detail

You can overwrite that behavior from your config/app.php file by using something like:

'components' => [
        'log' => function() {
            $log = Craft::createObject([
                'class' => yii\log\Dispatcher::class,
                'targets' => [
                    [
                        'class' => craft\log\FileTarget::class,
                        'levels' => !YII_DEBUG ? yii\log\Logger::LEVEL_ERROR | yii\log\Logger::LEVEL_WARNING : yii\log\Logger::LEVEL_ERROR | yii\log\Logger::LEVEL_WARNING | yii\log\Logger::LEVEL_INFO | yii\log\Logger::LEVEL_TRACE | yii\log\Logger::LEVEL_PROFILE,
                        'maxFileSize' => 5120, // 5MB
                    ],
                ],
            ]);

            return $log;
        },
    ],


Doing something with the success response from a Webhook Craft Webhooks is great for sending one POST to a service... but if you need to parse the response from that hook... is there a way to do that? I can't see it as any option in the plugin, and I can't see a Service or anything for having Craft listen to that event?

I'm trying to get it so when a new User is created it's also subscribed to an Active Campaign account. I've no problem creating the Contact in Active Campaign through the Webhook plugin - it works flawlessly. But you can't then add the new Contact to an Active Campaign List because that requires a second POST that includes the new ContactID and a pre-defined List ID.

Craft has no clue about the new ContactID because it wasn't listening or parsing the response to the first successful Webhook (which contains an object with that data in it).

Likewise, it doesn't look as though it's possible to perform both actions in one API call.

You might want to look into creating a simple Craft plugin to do this. You can make the first call to add the contact and get the ID in response. Then use that ID to add to a campaign.

Do not be intimidated by plugin development, your problem is fairly easy to solve. If you are on Mac, I like the Paw app to test API calls.


Load Category in Plugin I have a category that I'm trying to load via a plugin. Looking at the categories service I see there is a function called "getCategoryById" but I don't know what the ID is so instead I'm loading the category group thinking that the ID provided there is what I need, apparently it is not.

Kinda of stumped on this one. Any advice?

Thanks,

Depending on what you are searching by, you can use something similar to this. You can see the properties you can search by in the documentation.

$criteria = craft()->elements->getCriteria(ElementType::Category);
$criteria->group = 'CategoryGroupName';
$criteria->title = 'CategoryTitle';
$criteria->limit = 1;

$category = $criteria->find();


Localized {siteUrl} setting - confused Has something changed recently regarding the ocalized {siteUrl} setting? I'm setting up a new localized site on MAMP PRO and the old config code I used on several other projects is throwing an error "Array to string conversion".

This works fine:

return array(
'*' => array(
    'omitScriptNameInUrls' => true,
),

'pazzo.dev' => array(
    'devMode' => true,
    'environmentVariables' => array(
        'fileSystemPath' => '/Applications/MAMP/htdocs/pazzo/',
        'siteUrl' => 'http://pazzo.dev:8888/'
    )
),

'*.pazzo.be' => array(
    'devMode' => false,
    'cooldownDuration' => 0,
    'environmentVariables' => array(
        'fileSystemPath' => '/opt/www/pocopazzobvba/web/www.pazzo.be/',
        'siteUrl' => 'http://www.pazzo.be/'
    )
)

);

This (what I have used before) throws the error.

return array(
'*' => array(
    'omitScriptNameInUrls' => true
),
'pazzo.dev:8888' => array(
    'devMode' => true,
    'environmentVariables' => array(
        'siteUrl' => array(
            'en' => 'http://pazzo.dev:8888/en/',
            'fr' => 'http://pazzo.dev:8888/fr/',
            'nl' => 'http://pazzo.dev:8888/'
        ),
        'fileSystemPath' => '/Applications/MAMP/htdocs/pazzo/'
    )
),
'www.pazzo.be' => array(
    'cooldownDuration' => 0,
    'devMode' => false,
    'environmentVariables' => array(
        'siteUrl' => array(
            'en' => 'http://www.pazzo.be/en/',
            'fr' => 'http://www.pazzo.be/fr/',
            'nl' => 'http://www.pazzo.be/'
        ),
        'fileSystemPath' => '/opt/www/pocopazzobvba/web/www.pazzo.be/'
    )
)

);

Am I missing something obvious??

siteUrl works with an array of locales if you're using the actual siteUrl config setting.  What you're currently doing is creating a separate 'siteUrl' environment variable, which places in the control panel aren't expecting to be in array format.

More good info on the different ways to set siteUrl here.


How do I list entries from a single author? I'm returning the username as the second segment /blog/username and then setting the username var to craft.request.segment(2).

I'm looking to list a group of entries by that author (username). I've tried:

{% set blogPosts = craft.entries.section('blog').relatedTo(username) %}

I've also tried this:

{% set blogPosts = craft.entries.section('blog').relatedTo({ targetElement: username, field: 'author' })%}

Anyone have a way to list through entries related by author?

Try this:

{# First, grab the username from the URI #}
{% set username = craft.request.segment(2) %}

{# Then, grab the user based on the username %}
{% set user = craft.users.username(username).first() %}

{# Make sure we actually found a user #}
{% if user %}
    {% set blogPosts = craft.entries.section('blog').authorId(user.id).find() %}

    Found: {{ blogPosts|length }} blog posts.
{% endif %}


Craft 2 use different template for the same structure I have a site with projects which each has a projects structure with an associated category and a number of images.

The URL is set as projects/{projectCat.first.slug}/{slug}

I want to use the structure first for a set of thumbnails for each project (easy - no problem) and then for a gallery page with full size images. Both pages will have the same set of images.
The URL for the first is .com/projects/category/project-name.

The only way I have been able to do it is to make the links from the thumbnail page using:

<a href="/projects/gallery/{{ category.slug }}/{{ entry.slug }}">

and then using routing:

/projects/gallery/slug/slug to projects/gallery/_entry

This works but if I have a project in two or more categories with the same name it doesn't take account of the category in the URL and is also a bit messy.

Is there a better way?

I finally managed to answer my own question. I changed my routing to

/projects/slug/slug/gallery to projects/gallery/_entry

So was able to use a proper absolute link with /gallery added to the end

.com/projects/category/project/gallery

In the gallery _entry I used the following code to get the entry

{% set projectSlug = craft.request.getSegment(-2) %}
{% set categorySlug = craft.request.getSegment(-3) %}
{% set category = craft.categories.slug(categorySlug).first() %}
{% set entry = craft.entries.section('projects').slug(projectSlug).relatedTo(category).first() %}

This then worked fine, even if the same named project was used in two different categories

I would still prefer to do this without routing if anyone has any suggestions please?


Listen to onSetStatus event I wanted to listen to the onSetStatus event of the SetStatusElementAction and used the same code like in the EntryElementType class:

$setStatusAction = craft()->elements->getAction('SetStatus');
$setStatusAction->onSetStatus = function(Event $event) {
  MyPlugin::log('maybe');
}

But it didn't work and I had to hack into the core making following code changes:

in the ElementsService class:

/**
 * Fires an 'onSetStatus' event.
 *
 * @param Event $event
 *
 * @return null
 */
public function onSetStatus(Event $event)
{
    $this->raiseEvent('onSetStatus', $event);
}

in the EntryElementType::getAvailableActions method where the onSetStatus is called:

craft()->elements->onSetStatus($event);

This way I'm able to listen to the event in my plugin:

craft()->on('elements.setStatus', function() { ... });

The problem is that with the next update I have to do the code changes again. Is there a better way to listen to the event or is this worth a push request?

As you've discovered, you should be using the more generic elements.onBeforePerformAction or elements.onPerformAction events.  They get fired when any action takes place and you can check their action parameter to determine if it was a SetStatus action.


Displaying entries with pagination on a category page where the entry's last category in the array is the current category I want to only display entries on the category page which is the last in the array of the entries category, so that it doesn't also show on parent category page.

Let say these are my categories:

Shop

List item
Shoes
T-shirts

Entries with a category of "shoes" displays under both "shop" and "shoes" because of the way categories work as an array. My aim is to have it show only on "shoes", not "shop".

Here is my current code:

    {% set params = {
      section: 'shop'
    } %}

    {% if category is defined %}
      {% set params = params | merge({
        relatedTo: category
      }) %}
    {% endif %}

    {% set blogEntries = craft.entries(params) %}

    {% paginate blogEntries.limit(9) as pageInfo, pageEntries %}

      {# for entry in pageEntries if category.id == entry.productCategory.last().id #}
      {% for entry in pageEntries %}

{{ entry.title }} ({{ entry.productCategory | join(', ') }})

      {% endfor %}

  {% if blogEntries|length > 9 %}
    {% include "_partials/pagination.twig" %}
  {% endif %}

I've managed to display the entries under the correct categories with the
if category.id == entry.productCategory.last().id on the for loop displaying all the entries, however this does not work with pagination.

My question is, is there a way to bake the conditional into the initial category params to avoid looping through all entries where the current category doesn't match the last category within the entry's array.

I hope this makes sense, please feel free to get in touch for any clarification.

Thanks,
Teegan

Found the solution, thanks to Aaron Berkowitz on How to get entries related to current category only (not children)

You need to exclude the entries related to the subcategories.

 {% if category is defined %}
 {% set dontInclude = [] %}
     {% for child in craft.categories.descendantOf(category) %}
        {% set dontInclude = dontInclude|merge(craft.entries.relatedTo(child).ids) %}
      {% endfor %}

      {% set str = dontInclude|join(', not ') %}

  {% if dontInclude|length > 0 %}
    {% set params = params | merge({
      relatedTo: category,
      order: 'order ASC',
      id: 'and, not '~str
    }) %}
  {% else %}
    {% set params = params | merge({
      relatedTo: category,
      order: 'order ASC'
    }) %}
  {% endif %}
    {% endif %}

    {% set blogEntries = craft.entries(params) %}

    {% paginate blogEntries.limit(2) as pageInfo, pageEntries %}

      {% for entry in pageEntries %}

{{ entry.title }} ({{ entry.productCategory|join(', ') }})

      {% endfor %}


404 message after following Craft installation instructions I'm installing Craft CMS on my domain which was formerly functional (previously used Wordpress). I removed all Wordpress files through FileZilla FTP and uploaded Craft files.
I put the /Craft folder in its entirety above the root.
I put the files in /Public in the Public_html folder.
I set up a new Database through my hosting provider and edited the db.php file with the credentials.
Now when I go to mydomain/admin I get an Apache 404: "Apache/2.4.10 (Debian) Server at chrislee.is Port 80"
I've triple checked the installation instructions given on the Craft site and can't see any mistakes. Any ideas about what may have gone wrong would be greatly appreciated!

How did you create the database?
Did you use phpMyAdmin or did you create it manually, or using other tools?

I've had a similar 404 error last week (db was created with phpMyAdmin) then I created database with Sequel Pro and that resolve the problem.


Variable "entry" does not exist This is very basic as I am new to Craft CMS, but I created a Plain Text field in the Homepage section labeled "Tagline". When I enter the Twig code {{ entry.tagline }} into the index.html template, I get the error that the variable "entry" does not exist.

My index.html is at the root of the public folder.

I would say that the index.html should be within your templates folder. Is it?
And make sure that you Homepage section is actually pointing to that template. Look at your sections part within Craft CMS.


Memory usage in sub tasks vs. regular tasks I'm currently implementing a task-based application, which pulls some data from an external API before creating a number of entries based on the payload.

After creating the entries, the app will need to download a fair amount of images, storing the files as Assets and adding them to an Assets fields on one of the entries (each entry has a set of ~30 related images on an external server, that needs to be pulled).

Currently, I'm running 1 task per entry, with a sub task for downloading all of the images related to each entry (1 step per image, so ~30 steps per sub task). The images are quite large – around 5MB each.

The sub task takes an entry ID and an array of image URLs and metadata as its settings. Each step of the sub task looks like this:

The entry the image will be related to is pulled from the entry ID.
The task attempts to pull any existing Asset for the image (criteria based on filename)
If Asset not found, the remote image is downloaded using Guzzle to a temporary folder, before the Asset is created using craft()->assets->insertFileByLocalPath.
Another criteria to pull the newly created Asset.
Asset is updated with the metadata (which could've changed, regardless of whether the Asset was previously saved)
The IDs for any Assets in the entries Asset field is pulled using $entry->assetField->ids().
The new Asset's ID is added to the ID array, the asset field is updated with $entry->getContent()->setAttribute('assetField', $ids); and the entry is resaved through craft()->entries->saveEntry.
The temporary image file is deleted using the IOHelper class.

This is running on a 2GB droplet, where PHP/Craft has access to the full 2GB RAM – which I assumed should be plenty, though the server is running out of memory, intermittently. At one point, MySQL even crashed and had to be restarted :/

The memory issues never appear when Craft is running one of the regular, parent tasks – it always happens when one of the image sub tasks is running, which is why I'm debating my current setup.

From Brad Bell's comment to this answer, I know that 1 task = 1 request, even if that task has multiple steps and/or sub tasks. What I take from that is that having loads of sub tasks is potentially more dangerous in terms of memory usage and possible timeout issues, than having loads of smaller regular tasks. Is this a correct assumption?

In closing, which of the following approaches would be the safest, in terms of memory usage (and/or other issues I might not have considered):

One regular task per image (~30 tasks)
One regular task per image set (~30 steps)
One sub task per image (~30 sub tasks)
One sub task per image set (~30 steps, my current implementation)

I should mention that in this case, it doesn't really matter if the parent task completes before the image tasks run/complete, so I don't actually need to use sub tasks for the downloads.

Also, devMode is currently false on the server and I'm still having issues.

I think this is difficult to answer properly because it depends almost entirely on what the tasks and subtasks are actually doing.

For example, the main task could do something that ate 400MB of memory and triggered 400 sub-tasks that did nothing but return null not using any memory.

Alternatively, the main task could do nothing but trigger subtasks (using very little memory itself) but each subtask could use 400MB of memory.

Obviously with subtasks you have to me more conscious of memory usage because usually there will be multiple subtasks and there is only ever one main task.


Scan of front end user uploads I wonder if we have a form allowing file uploads for front end users, does Craft or its plugins have certain feature to scan for virus / malicious content, before saving it? If not, what would be the best practice to handle front-end users' uploads? E.g. shall it be handled by the hosting server, or is there a 3rd party library / service that can help?

Craft will do some minimal cleansing of potentially malicious uploaded images by default by saving them back out to the file system and will try to sanitize SVG files as well.

It also has a relatively tame list of file extensions it allows on upload: https://docs.craftcms.com/v3/config/config-settings.html#allowedfileextensions

Anything outside of that, it'd be up to a Craft plugin or something on the server-side to do additional analysis and cleansing.


Changing Username On Front End To Another Account Email We have a front end form for a logged in user to change their Username (email). In our testing, it does not appear to check against and prevent selecting an email address that's already taken (like happens on a login form). However, our Create Account from - which is almost identical - works.

This Form (our create account form) works and catches duplicate emails and returns an error:

<form id="createForm" method="post" accept-charset="UTF-8">

    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="{{ siteUrl }}account/signup-sent">

        Email *
        <input id="signupEmail" name="email" placeholder="Email" value="" data-parsley-type="email">

        Confirm Email *
        <input id="confirmEmail" placeholder="Confirm Email" value="" data-parsley-type="email">

        Password *
        <input name="password" id="password" type="password" placeholder="Password" value="">

        Confirm Password *
        <input name="confirmPassword" id="confirmPassword" type="password" placeholder="Confirm Password" value="">

    <input type="hidden" name="fields[accountReceiveEmails]" value="">

        <input type="checkbox" name="fields[accountReceiveEmails][]" value="yes" id="emailOptin">
        Yes, I would also like to receive offers, discounts and news for Cadex products by email.

        <button>Create Account</button>

</form>

This is our form for users logged into their account. It does not return an error when a user tries changing their email to one that already exists in another account:

<form id="profileCredsForm" method="post" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="account/profile/saved">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">

        Current Password *
        <input id="currentPassword" name="password" placeholder="Current Password" value="" data-parsley-required="true">

        New Password
        <input name="newPassword" id="newPassword" type="password" placeholder="New Password" value="">

        Confirm New Password
        <input name="confirmNewPassword" id="confirmNewPassword" type="password" placeholder="Confirm New Password" value="">

        New Email
        <input id="email" name="email" placeholder="New Email" value="">

        Confirm New Email
        <input id="confirmNewEmail" placeholder="Confirm New Email" value="">

    <button type="submit">Update</button>
</form>

We've tested this repeatedly, changing an email to one for another existing account and no error is returned, the form submits and the email is sent to confirm the new email address.

Also, as an aside, the confirm link in the follow up email seens to ignore the activateAccountSuccessPath set in our config. Is that expected behaviour?

Thanks.

Just answering this for anyone else who sees this. The case above was confirmed by Brad Bell and was fixed in Craft 2.6.2984. So, going forward, the scenario described above should return an error to handle.


Upload file into Assets using URL? Is it possible in a front end entry form to pass the URL of a file to an assets field and have it upload that way?  Specifically, I'm trying to move an image from one assets field & upload folder to another in an edit entry form.

It’s not currently possible to upload assets via URL, but if we’re only talking about images that are already uploaded into Craft, you could have them selected by their existing asset IDs, rather than URLs, and it would work.

First, go into your Assets field settings and check the “Restrict uploads to a single folder” checkbox.

Then in your entry form, write a UI for selecting an existing asset. Something like this:

    {% for image in craft.assets.source('images') %}

                <input type="radio" name="fields[myAssetsField][]" value="{{ image.id }}">
                {% do image.setTransform({ width: 100, height: 100 }) -%}

    {% endfor %}


Correct behaviour for 'Login as user' when user cannot access CP? A client uses the 'Login as user' behaviour to be able to see what users of the site are seeing, useful as it's an e-learning site and each user can see different content based on their progress. The users however, are only allowed to view the public site and not anything in the CP which means when the 'Login as user' is invoked the client is presented with the 'Unauthorized You don’t have the proper credentials to access this page' message.

Is this right? Looking through the code it seems the function _handleSuccessfulLogin() is called and if the user cannot access the CP then they should be redirected to the postLoginRedirect which in the case of this site is not set, so the user should be redirected to the homepage if I understand correctly.

You're correct... it should be sending to postLoginRedirect, but there is actually a bug where after impersonating:

// Get the current user
$currentUser = craft()->userSession->getUser();

is returning a cached copy of the previous user (who had CP access).

Will get that fixed for the next release.

Update:

Fixed for the next post 2.2.2596 release!


Access Site Cookie From Email Message I want to add source tracking to my Craft CMS site.  Using Google Analytics I can track users through just about the entire process but can't see them as they go through account registration.

I want to simply add a query parameter to the {{ link }} from the activation email.

I can see that if I add {{ link }}&source=test that the additional query param shows up, however what I really want is something like this:

&source={{ craft.request.getCookie('traffic_src') }}

However the above solution returns the activation code and source= which leads me to believe that it is undefined

What is the best way to approach this problem of accessing a cookie for a user in one of Craft's email messages.

Assuming this is for Craft 2, there are a few cookie plugins that let you read and write cookie values from a Twig template.

https://github.com/nystudio107/cookies

https://github.com/lewisjenkins/craft-lj-cookies

https://straightupcraft.com/craft-plugins/?q=cookie


send e-mails via smtp without authentification I try to send e-mails via SMTP without authentification and I'm getting the following error:

  There was an error testing your email settings.

I checked my setup on https://www.smtper.net/. No problems!

I read through the troubleshooting-email-errors page but still found no solution for my problem.

Why can't I find a log under craft/storage/runtime/logs/craft.log. This file does not exist on my system. There is only craft/storage/logs/web.log.

When I use another SMTP server (with auth) everything works as expected. Any ideas on how to find out what's going on here?

My guess is that protection.outlook.com simply doesn't allow un-authenticated connections, because well... I'm sure they relay enough SPAM with authenticated connections, much less unauthenticated ones.


Landing Page with Same URL Structure as Category I have a category group called "Resource Categories" and categories within it have their own urls.

Category Url Formats:

top-level categories: resources/{slug}
nested categories: {parent.uri}/{slug}

Category Template:
resources/_category

There's also a category template which is here:
resources/_entry

What I want to do is add a Landing page at /resources.

This would be a standard entry page ideally created within my Pages channel using the pages/_entry template.

Failing that I could also create an index page inside the resources folder.

But I keep getting 403 forbidden when visiting site.com/resources.

I've tried creating a route but that doesn't help the issue.

'resources' => 'pages/_entry'

You've hit on most of the options — all of which should work fine.

Assuming you have a structure called 'pages', with the 'uri' set to {slug}, 'parent uri' set to {parent.uri}/{slug}, and template set to 'pages/_entry'; create a new entry 'resources' which should route to your template at 'pages/_entry.html', or
If you do not have a 'pages' structure you can also just create a template at 'templates/resources.html', or 'templates/resources/index.html', or
Create a route 'resources' => 'pages/_entry'

If those aren't working, then you might check that the template itself isn't creating any restrictions, and/or that you don't have any other routes defined (i.e. in your config file) that might be creating conflicts.


change the root directory references All, we have a website built by third party company and they gave us the pack which includes cms, craft and MySQL database. But our hosting server is hardcoded to run the website from public_html folder (can't change this). Could you tell me how can change cms references to public_html? Tried to copy everything under cms folder to public_html only to see misconfiguration errors. Let me know if you need more info.

The actual web root name doesn’t matter. Usually it’s “public_html” or something similar, and Craft’s “public” folder is only meant to represent that folder.

There are no references to the public/public_html folder within Craft itself; it’s the other way around: The index.php file within public/public_html is the one referencing Craft, via its $craftPath variable.

So here’s what you need to do:

Upload the craft/ folder to your web server, ideally on the same level as your public_html/ folder rather than inside it, but if you don’t have permission to do that, inside public_html/ is OK.
Upload the public/index.php file into your public_html/ folder
Upload the public/htaccess file into your public_html/ folder and rename it to .htaccess
Open up public_html/index.php and make sure the $craftPath variable is a valid path to the craft/ folder, wherever it is.


Template logic to address a third URL segment I'm using Craft 3, and I'm struggling to make sense of how to address the following. (I've not had need to venture into a third URL segment before.)

I have a url of the form:

stories/{slug}

served by a template:

stories/_entry

I'm aware that the 'entry' variable gets set automatically. So far so basic.

But I also want to address urls of the form:

stories/{slug}/{variable}

…where variable is used to fetch content from a specific Matrix row in the entry that matches slug.

It is important that variable forms a third segment addressable as its own page, and not just a URL query parameter.

I have tried 2 approaches:

Getting segment 3 and then using it in a conditional inside of stories/_entry:

{% set seg3 = craft.app.request.getSegment(3) %}
{% if seg3|length %}
    {% include 'partials/extract' %}
{% else %}
    {% include 'partials/story' %}
{% endif %}

…but when seg3 is not empty Craft says:

  Template not found

Setting a route to a different template:

stories/{slug}/{*}

…is processed by:

stories/_extract

…in which, as a basic test I have:

{% block meta %}
    <title>{{ entry.title }}</title>
{% endblock %}

…but Craft then reports a Twig runtime error, saying:

  Variable "entry" does not exist

So I tried using:

{% set seg2 = craft.app.request.getSegment(2) %}
{% for entry in craft.entries.section('stories').slug(seg2).all() %}
    {% block meta %}
        <title>{{ entry.title }}</title>
    {% endblock %}
{% endfor %}

…but that makes no difference.

Is my approach 2 definition of entry wrong?

Why does a non-empty value in segment 3 cause approach 1 to fail?

I'm obviously missing something fundamental here. Any pointers much appreciated.

I would suggest you look into using Craft's Advanced Routing functionality to accomplish this.

For instance, add the following to your config/routes.php:

'stories/<slug:\w+>/?<option:\w+>?' => ['template' => '_extract'],

This will then populate the _extract template with the twig variable {{ slug }} and also the {{ option }} variable, if it exists.

Then in your twig template you can grab the entry and check for the existence of the option variable thus:

    {% set entry = craft.entries.section('stories').slug(slug).one() %}

    {% if entry %}

Entry title is: {{ entry.title }}

    {% endif %}

Slug is: {{ slug }}

    {% if option is defined %}

Option is: {{ option }}

    {% endif %}

I'd recommend reading the docs on Advanced routing as it's quite a powerful feature: https://docs.craftcms.com/v3/routing.html#advanced-routing


What attribute type should I set in the record or model to create a TEXT type in the database? I am having a problem with record and model attribute types.

I have a frontend user form with some textfields which require a TEXT type field in the database to hold the data. So far I have tried setting the attribute type to String which creates a varchar(255) which isn't big enough to hold the data.

I've also tried Mixed which creates the TEXT type but does not populate the data when the form is submitted. Reading further and based on a previous problem I had I think this is due to the lack of validation on the Mixed attribute.

So my question is how do I get my form to submit this data if the attribute I create is causing the

$record->setAttributes($model->getAttributes());

to ignore the Mixed fields data. Or is there another attribute that would work better something like Text?

Also what would be useful to know is if there is any resource which describes the different attributes with examples of how to set them up for records and models as I can't seem to find anything that describes this process clearly.

Any help much appreciated.

Cheers

Ok worked out a solution to the attributes. You can set them like this:

array(AttributeType::String, 'column' => ColumnType::Text,  'required' => false)

By defining the column, so hopefully this will help someone else.


Craft 3 composer installation I have installed Craft with Composer and have run the set up command.

When I type in my database name I always get the error:

Testing database credentials... failed: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO)

I have tried with a Mamp Pro server set up (restarted as per another post) and with a different username (I can't seem to set a password in terminal during the setup?).  Any ideas how I can get past this final hurdle?

Have you tried to enter the database information in your .env file?

Your password is usually "root" in a MAMP environment.


Set Property within Eager Loading I'm looking to eager load and set another variable within the eager loading. But I can't seem to find out how on numerous guides/tutorials, and the query seems to be slowing the system down a bit.

  {% set entries = craft.entries ({
          section: 'events',
          order: 'postDate desc',
          with: ['eventMainImage'],[''],
          relatedTo: category
      }) %}

  {% for entry in entries %}
    --> {% set venue = entry.eventVenueId.one() %}

As you can see by the arrow, I'm wanting to set this property, is this possible within an eager load?

Eager-Loading is not like a hook or a callback. You wouldn't set variables within it. You'd want to use eager-loading to load your eventVenueId then in your loop you'd set the variable a little differently.

 {% set entries = craft.entries ({
          section: 'events',
          order: 'postDate desc',
          with: ['eventMainImage', 'eventVenueId'],
          relatedTo: category
  }) %}

 {% for entry in entries %}
    {% set venue = entry.eventVenueId[0] ?? null %}

Additionally you could look at eager-loading a Nested Set of Elements to further optimize your query if possible with the data you need off your eventVenueId elements.


Using Craft for publishing an online magazine I was wondering if Craft is suitable for publishing online magazines. I was thinking about using a new structure for every issue/release. And entries for the actual content of an issue.

Is this the way to go? And does it affect Craft's performance?

Thnx

I wouldn’t recommend creating a ton of Structure sections, because the administration workflows and UI are just not suited for having lots of identical sections.

Here’s a basic model of how you could organize this in Craft:

Create two Sections called Issues and Articles
Create an Entries field called Issue Articles, with the Articles section selected.
Edit your Issues section’s Entry Type, and add the Issue Articles field to its Field Layout.

Now, each issue will be represented by an entry within your Issues section, and each article will be represented by an entry within your Articles section.

Thanks to the new Inline Element Creation feature in Craft 2.5, you will easily be able to define new articles right from the Edit Entry page when creating/editing a new issue, via your Issue Articles field.


How can I iterate through an array of field handles for an entry? Background:

One of my templates has up to 6 fields that should each go into the same markup. Here's an example with a courseDesign field:

{% if entry.courseDesign|length %}

Course Design

    {{ entry.courseDesign }}

{% endif %}

This worked fine when I wrote each section out like this. However, once I also added a table of contents/nav, I decided to refactor.

I now have a courseFields array, and I'm adding each field to it if it exists:

{% set courseFields = {} %}
{% if entry.courseDesign %}
  {% set courseFields = courseFields|merge({ "courseDesign": { handle: "courseDesign", title: "Course Design" } }) %}
{% endif %}

My navigation macro works perfectly, because it's only interacting with the objects in the courseFields array.

My problem:

I can't figure out how to iterate through my fields and get the actual content from them using a macro.

If I use {{ entry.handle }} in my macro, even when handle is a valid field handle, I get the runtime error Variable "entry" does not exist.

I also tried:

{% set courseField = "entry." ~handle %}
{{ courseField }}

but that produces a string: "entry.courseDesign".

How do I access entry from my macro? Should I be going about this a different way?

I figured it out! I ditched the macro and just included the following in my template:

{% for field in courseFields %}

{{ field.title }}

    {{ entry[field.handle] }}

{% endfor %}


FastCGI error when accessing a local development site using MAMP Pro I'm running across a problem developing a site locally using OS X 10.10 and MAMP Pro 3.0.5 with PHP 5.5.10. Accessing both the site front-end and the back-end admin interface is  throwing an error 500 Internal Server Error.

The MAMP Apache log is showing multiple instances of the following error:

[Mon Nov 10 14:03:04 2014] [error] [client 127.0.0.1] FastCGI: comm with server "/Applications/MAMP/fcgi-bin/php5.5.10.fcgi" aborted: idle timeout (30 sec), referer: http://jtp.dev:8888/admin/entries/project
[Mon Nov 10 14:03:04 2014] [error] [client 127.0.0.1] FastCGI: incomplete headers (0 bytes) received from server "/Applications/MAMP/fcgi-bin/php5.5.10.fcgi", referer: http://jtp.dev:8888/admin/entries/project

Once this happens, I can't continue working until I restart my machine. Restarting my Mac and restarting MAMP fixes the error temporarily, but it eventually reappears and prevents me from being able to view the site locally.

Has anyone got any ideas about what may be causing this?

Following the answer in this issue https://stackoverflow.com/questions/15563217/apache2-fastcgi-comm-with-dynamic-server-aborted-first-read-idle-timeout/15565267#15565267 I was able to successfully run my script without this dreaded timeout and 500 error, like so:

Go to File > Edit Template > Apache > httpd.conf
Do a Find & Replace for MAMP_FastCgiServer_MAMP
Comment out the line MAMP_FastCgiServer_MAMP
Add a config line for your version of PHP, with the desired timeout limit at the end like so: FastCgiServer /Applications/MAMP/fcgi-bin/php5.6.2.fcgi -idle-timeout 3600

For your version of PHP the code block would look like this, with the two changes being the second and third last lines:

<IfModule mod_fastcgi.c>
    # URIs that begin with /fcgi-bin/, are found in /var/www/fcgi-bin/
    Alias /fcgi-bin/ "/Applications/MAMP/fcgi-bin/"

    # Anything in here is handled as a "dynamic" server if not defined as "static" or "external"
    <Directory "/Applications/MAMP/fcgi-bin/">
        SetHandler fastcgi-script
        Options +ExecCGI
    </Directory>

    # Anything with one of these extensions is handled as a "dynamic" server if not defined as
    # "static" or "external". Note: "dynamic" servers require ExecCGI to be on in their directory.
    AddHandler fastcgi-script .fcgi .fpl

    MAMP_ActionPhpCgi_MAMP

    #MAMP_FastCgiServer_MAMP
    FastCgiServer /Applications/MAMP/fcgi-bin/php5.5.10.fcgi -idle-timeout 3600
</IfModule>

Also reference this solution:  https://stackoverflow.com/questions/24715426/how-do-you-increase-the-apache-fastcgi-timeout-on-mamp-mamp-pro/24976009#24976009


"Quick Links" in control panel Is it possible to create a "Quick Link" in the control panel, similar to the way quick links function in ExpressionEngine?

If you have a Single that is frequently accessed by the client, it would be really helpful to save a link to the publish page right in the CP, rather than having the clients select Entries > Singles > Title every time they need to make an edit.

Not natively, but it would be pretty easy for a plugin to add a widget that does something like that.

I don't see anything currently on Straight Up Craft that would fit that bill, unfortunately.


When creating new assets what should we put in base Url and document root file? I am not able to figure out what to put in base url and document root url while making new assets in craft cms

You can use the aliases for that. @web and @webroot are aliases which are included in Craft by default, @web is pointing to the base website url and @webroot is pointing to the document root file path (absolute path) respectively.


Problem installing on MediaTemple I'm getting an error when I start the installation process, i.e., <domain>/admin.

Here's the error I'm getting:

CDbCommand failed to execute the SQL statement: SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected. The SQL statement executed was: SHOW TABLES LIKE 'craft_%'

Since I've enabled dev mode, you can see the full stack trace here:

http://onehanders.info/admin

I've done the following prior to starting the install:

set up db and identified server, db name, user, & password that are needed
put proper settings in db.php in the config folder
put the craft folder one level above web root
updated all 3 of the relevant folder permissions (including enclosed)
enabled dev mode in general.php

I even added a statement to craft/etc/behaviors/AppBehaviors.php. After line 852, at which point the db connection appears to be valid, I echo'd a "db connection is valid" line and got there. That line is now commented out.

I'd love to hear your thoughts on what I might try to fix this.

Contents of config/db.php:

<?php

/**
* Database Configuration
*
* All of your system's database configuration settings go in here.
* You can see a list of the default settings in craft/app/etc/config/defaults/db.php
*/

return array(

// The database server name or IP address. Usually this is 'localhost' or '127.0.0.1'.
'server' => 'internal-db.s<my acct #>.gridserver.com',

// The name of the database to select.
'd<my acct #>_onehanders_db' => '',

// The database username to connect with.
'user' => 'db<my acct #>',

// The database password to connect with.
'password' => '<my password>',

// The prefix to use when naming tables. This can be no more than 5 characters.
'tablePrefix' => 'craft',

);

This:

// The name of the database to select.
'd<my acct #>_onehanders_db' => '',

Needs to be this:

// The name of the database to select.
'database' => 'd<my acct #>_onehanders_db',


Efficient way to get all related entries assigned to matrix fields across a set of entries I have a scenario where level 1 structure entries each have several to tens of level 2 child entries, and several to tens of entries in a different channel which are also allowed to be related to the level 1 structure entry.
'events' structure
  - event entry 'e'
    - child 1
    - child n
'articles' channel
  - article 1
  - article n:
      could be related to event 'e'
'people' channel
  - person 1
  - person n:
      could be related to a child of 'e' via a Matrix field
      and/or an article entry related to 'e' via a Matrix field

For each of the child entries and the article entries, there are Matrix fields in which one or more people entries can be related.
Other than looping through the set of children of 'e' and the set of related articles, and then through each of their Matrix rows to fetch their corresponding people entries, is there a cleverly more efficient way to get all the people entries used for event 'e'?

Update (revised)
Thanks, Ben, for pointing the way. Initially I couldn't get this to work but then I spotted my error. Here’s what now works a treat for the following specifics…
I have my child pages as sessions where:

Each child session has a Matrix field called eventProgramme

There are two Entries fields defined in this Matrix, one called speakers and one called chairs.

This works:
{% set people = craft.entries.section('people').relatedTo({
    sourceElement: sessions,
    field: 'eventProgramme'
})
.all() %}

It's cool that sourceElement can be an array such as sessions.
If I want to target a specific field I can just use something like field: 'eventProgramme.speakers'

One thing I don't understand is the distinction between targetElement and sourceElement. Only the latter works in this context.
Update 2
Doh! The difference between source and target element is clearly explained in the Docs but I had missed it:

"The source has the relational field where other elements are chosen."
"The target element is the one selected by the source"

If you are trying to get all people entries related to the event entry itself (what you call event "e") then I would suggest going through matrix as follows.
{% set people = craft.entries.section('people').relatedTo([
    'or',
    { targetElement: event, field: 'matrixFieldHandle.relatedEvents' },
    { targetElement: event, field: 'matrixFieldHandle.relatedArticles' }
]) %}

If you need the target element to be all children of the event then this might do the trick.
{% set eventChildren = event.children %}

{% set people = craft.entries.section('people').relatedTo([
    'or',
    { targetElement: eventChildren, field: 'matrixFieldHandle.relatedEvents' },
    { targetElement: eventChildren, field: 'matrixFieldHandle.relatedArticles' }
]) %}

You can also combine the event with its children, if necessary, as follows.
{% set eventWithChildren = event.children|push(event) %}


How to make a code/settings for accessing the one database from 2 different html files with {slug} I create a code for TV show database, but I have a big problem.
Please see the image
I want to access one entry(post) with some data from some templates.
But I don't know how to create any code or settings in the sections area.

Any advice or give me the url if there is another topic?

image

This makes more sense :)

So basically, you want to have info from one entry on multiple pages and your problem is that in the section settings, you can only define 1 template for an entry.

One way to go about this is to create your own urls when clicking on an entry where you add the {slug} of your entry to the url, something like this: {siteUrl}/episode-guide/recap/{entry.slug}

You can create a dynamic route for this url that takes you to (for example) the recap.html template. Here you just get the last segment (being the slug) and retrieve the correct entry from your database and show only the recap info.

{% set entrySlug = craft.request.lastSegment() %}
{% set entry = craft.entries.section("sectionName").slug(entrySlug) %}


ElementCriteriaModel exclude list of ids I'm trying to exclude a list of ids from a query using an ElementCriteriaModel

This is what I have so far, but it's resulting in nothing coming back when I'm expecting at least 1 result. Is something wrong with my syntax or is my method way off?

$criteria->id = 'and';
for ($i = 0; $i < count($idList); ++$i)
    $criteria->id .= ', not' . $idList[$i];

Also, I've tried removing the $criteria->id = 'and'; to no avail

A nudge in the right direction would be much appreciated

Thanks

This should do the trick:

$idList = [1, 2, 3, 4];
$criteria->id = 'and, not ' . implode(', not ', $idList);

In plain text, the id property would then look like this:

'and, not 1, not 2, not 3, not 4'

The syntax may look a little odd, but it essentially makes Craft compile an SQL query with an AND (elements.id!=$elementId) statement for each ID you want to exclude.


Re-render Widget after column number changes Is it possible to automatically re-render a widget after the number of columns is changed? I have a widget that has to be re-rendered/re-executed after the widget columns change and I don't know how to realize it.

I can't just make a javascript event like $(window).resize() because I already have this function and check if the client client height changes there because otherwise it would trigger every second for no reason.

I found an answer that works for me at least..
Since I render my widget via Javascript and not via PHP/Twig I can use this

$(document).on("click", ".colspan-picker a", function(){
    var container = $(this).parent().parent().parent();
    widgetID = container.data("id");
    sRGoogleAnalyticsRerenderChart(widgetID);
});

.colspan-picker a is the element for columnchange and its parent().parent().parent() has a data-id of the widget container


Installing Moodle to a Craft CMS server I was wondering if anyone had any experience in installing Moodle to a server that already had a CraftCMS website installed onto it? I've followed the instructions on the Moodle Installation Guide (I put the Moodle files in the CraftCMS template folder) but when I get to the part where I go to http://domain/moodle to install it I get a 404 error. If I go to http://domain/moodle/install.php I get the install file but it doesn't work, I just get a string of text like the PHP isn't executing. I can't find any similar issue's on Moodle's forums so I think that this will have something to do with craft not allowing the PHP?

What Damon said is correct.  You'll need to modify Craft's public .htaccess file so that all requests to Moodle URIs go to it's public index.php file and requests to Craft URIs go to Craft's public index.php file.

Alternatively, you could keep them as two separate installations, which simplifies things.


How can I debug `craft\web\User::_validateUserAgentAndIp()` warnings On a production site, we're seeing a ton of the following warning in our web.log files for (seemingly) every request, creating a ton of noise in the logs and making it hard to spot "real" issues:

<DATE> [-][-][-][warning][craft\web\User::_validateUserAgentAndIp] Request didn’t meet the user agent and IP requirement for maintaining a user session.

Under the hood craft\web\User::_validateUserAgentAndIp() does the following

private function _validateUserAgentAndIp(): bool
{
    if (!Craft::$app->getConfig()->getGeneral()->requireUserAgentAndIpForSession) {
        return true;
    }
    $request = Craft::$app->getRequest();
    if ($request->getUserAgent() === null || $request->getUserIP() === null) {
        Craft::warning('Request didn’t meet the user agent and IP requirement for maintaining a user session.', __METHOD__);
        return false;
    }
    return true;
}

As far as I can see, (for front end templates at least) craft.app.request.userAgent and craft.app.request.userIP are correctly populated with the UA and IP respectively, so I'm not sure why/how Craft is throwing this warning.

We don't see the same issue in dev / staging environments, so I know this is likely to be a configuration issue, but I'm asking this question to try and understand what's going on so I have some idea of what to look for.

Question:

What should I look for / how can I debug what's causing this issue?

(Note: I know I could turn requireUserAgentAndIpForSession off in config/general.php, but I don't really want to do that from a security POV)

Notes:

This is on a site running Craft 3.3.13 (latest at time of writing)
It's in a load-balanced environment
We're using nginx as our webserver

Most likely since it's a production site, it's from bots/scripts hitting the site's login page probing for vulnerabilities.

I'd suggest changing the cpTrigger config setting and see if the occurrences go down.


Craft 3: White blank page when accessing website and Craft login page I'm getting white blank page when trying to access my website and Craft login page. I haven't updated the website for few months. So I assume no files has been changed.

I checked with the hosting provider, and they say everything is okay on their part.

I turned on dev mode, but still get a blank page.

What could possibly cause this? Is there anything I need to check? Thank you in advance. It's on Craft CMS 3.1.28. The url is https://vispaleis-oostende.be/.

Edit: as commented on a below answer: When I change the contents of Craft's index.php file to echo some text, this text does get shown on the website. Also, when I create such an echo php-file and include it from other folders using the variables CRAFT_BASE_PATH or CRAFT_VENDOR_PATH, it also shows that text. So the domain does point to the correct location, the index.php file gets loaded (also on any 'subpage' and the CMS-url, so not only the index page) and the include paths are found.

Edit 2: I just linked the domain name back to the beta-server, since everything was still working there. I also copied the database, to reflect the changes made in the CMS (small text changes). No files were changed since going online, so I didn't need to copy any files. Everything works as expected on the beta-server, so I think it's a problem on the 'live' server, even though the hosting provider claims it isn't. If anyone has an idea what this could be, please let me know so I can get back to the hosting provider...

Based on the response headers:

It doesn't look like the response is coming from Craft at all, so I think it's likely that you should contact your hosting provider again.

To me, it seems like the domain isn't pointing at the right place for your website hosting, because Craft isn't even fielding the request.