How to create manually an Entry from command line I would like to migrate content from external source to my Section model. So I have to create Entries manually. Is there any better way to do this beside this snippet from the documentation:

$entry = new Entry();
$entry->sectionId = 10;
$entry->typeId = 1;
$entry->fieldLayoutId = $entry->getType()->fieldLayoutId;
$entry->authorId = 5;
$entry->enabled = true;
$entry->title = "Hello World!";
$entry->setFieldValues([
    'body' => "
I can’t believe I literally just called this “Hello World!”.
",
]);
$success = Craft::$app->elements->saveElement($entry);
if (!$success) {
    Craft::error('Couldn’t save the entry "'.$entry->title.'"', __METHOD__);
}

reference: https://docs.craftcms.com/api/v3/craft-services-elements.html#saveElement()-detail

I am looking for a factory method, or a Builder to properly create the object. Using EntityController is not an option, because I would like to use it from CommandLine interface.

This is the best answer so far. Basically the easiest way is to use array, and map everything there. The saveElement function will the the rest. You can update fields, tags, categories, matrixTables etc. The given example is matrix-data only, but again the same logic could be used everywhere.

How to save Matrix data programmatically in Craft 3

The only missing point is the "merge" functionality but I guess it has to be done manually after using the toArray() function first


Where should an encryption key be stored? I'm working on a plugin that needs to encrypt some user data. I'm setting an encryption key for SecurityService, but am trying to decide where to store that encryption key so it can be used on subsequent requests to decrypt the data. A few options are coming to mind:

StatePersister: this is where Craft keeps its cookie validation key, but is likely to be ignored by .gitignore, so probably wouldn't be persistent for long.
Plugin Settings Table: this is the approach being used by the SecureField Plugin. It's very straightforward, but also minimally secure as pretty much any SQL injection attack would compromise the key and its encrypted data. The upside is that the key's persistence is practically guaranteed.
Extend CStatePersister: This could be used to persist state in a writable location of my plugin's folder. It's more likely that this would be preserved in version control, but not very likely that the location will be writable on a production server.

As it stands, storing the key in the database is the most likely to work on a wide variety of servers, but probably has the poorest level of security. Am I missing any other options?

I'm hardly a security expert but if someone can get to your filesystem or your db, you'd be screwed either way—so what you're really doing is technically obfuscation and not really encryption. Ideally you'd do the crypto on a different server or have a hardware module that does the encryption and sends the result back but that solution probably won't work here.

Like you mentioned, if you're storing data in the database, don't keep your key in the db. That would be like taping the combination to the outside of a safe. If someone got a dump of the database, they'd be able to use the key to decrypt the data, obviously.

Keep it simple. I'd probably opt for somewhere in the filesystem, like in your plugin's config for example. Leave the key blank until you're ready to use the plugin for production and then have the user fill in the value... maybe with something like WordPress's Secret key generator... that way, nobody has the same key even if someone were to get a copy of your plugin's source code.


htaccess query (not Craft per se) I'm using locales to drive several sites/domains from one build.
I have set up a bunch of 301 redirects in the .htaccess to capture and redirect previous URLs. I've used RewriteCond to target the rules for the individual sites but these aren't working as I'd expect.

RewriteCond %{HTTP_HOST} ^site1\.com [NC]
RewriteRule ^news.asp /news/news-listings? [R=301,L]

RewriteCond %{HTTP_HOST} ^site2\.com [NC]
RewriteRule ^news.asp /news-galleries/news-listings? [R=301,L]

If I enter site2.com/news.asp I am redirected to the Rule stated for site1 so the user is redirected to site2.com/news/news-listings which (obviously) returns a 404 error message. Any thoughts on how should be doing the above properly?

As per your comments, I've gleaned that the problem is really because of an incorrect assumption about how RewriteConds apply to RewriteRules.

So I'm guessing your .htaccess looks more like this:

RewriteCond %{HTTP_HOST} ^site1\.com [NC]
RewriteRule ^someurl.asp /folder/page? [R=301,L]
RewriteRule ^news.asp /news/news-listings? [R=301,L]

RewriteCond %{HTTP_HOST} ^site2\.com [NC]
RewriteRule ^someurl.asp /folder/page? [R=301,L]
RewriteRule ^news.asp /news-galleries/news-listings? [R=301,L]

So there are multiple RewriteRules to some of the RewriteCond statements. You're expecting site2.com/news.asp to go to site2.com/news-galleries/news-listings?, but instead it's going to site2.com/news/news-listings? because it's strictly obeying the mod_rewrite rules.

This is because RewriteCond statements only apply to the RewriteRule that immediately follows them. So your site2.com/news.asp request is actually matching the second RewriteRule in the above example.

RewriteMap to the rescue

If you have a lot of URLs you're needing to manually rewrite under multiple condition scenarios, this can get complicated because you would have to define the same RewriteCond statements for each RewriteRule.

Here's a better way - use RewriteMap (not yet tested):

RewriteMap "site1.com" "txt:/path/to/file/site1.com.txt"
RewriteMap "site2.com" "txt:/path/to/file/site2.com.txt"

RewriteCond %{HTTP_HOST} ^site1\.com [NC]
RewriteRule ^(.*)$ "${site1.com:$1}" [R=301,L]

RewriteCond %{HTTP_HOST} ^site2\.com [NC]
RewriteRule ^(.*)$ "${site2.com:$1}" [R=301,L]

That would be it. One RewriteMap, RewriteCond and RewriteRule per domain. Then your site2.com domain rewrite-map file would look like this, for example (simple space-seaparted, key-value pairs):

news.asp /news-galleries/news-listings?

Hope that helps provide a more flexible, manageable solution :)


How to redirect site root to preferred language in multi-language site? I followed the Craft directions for setting up a localized site. In the fifth step I followed the first example for setting up my folder structure. In my case the languages I'm working with are French and Arabic.

craft/
public_html/
   fr/                 --> example.com/fr/ (french)
      .htaccess
      index.php
   ar/                 --> example.com/ar/ (arabic)
      .htaccess
      index.php

The primary language for the site is French, what is the best way to redirect so that if a visitor comes to the root of the site www.example.com they will be redirected to the French version at www.example.com/fr/ ?

Should I use a .htaccess file in main public_html directory of the site, should I use the dynamic routes in Craft, or is there some other, better, way?

I would put a .htaccess file in the public HTML folder and let Apache deal with it, that way you don't have the overhead of PHP/Craft having to deal with that request.


How to detect the current report in settings.twig I have several reports to create but their settings are going to be very similar.  So I want to use one settings.twig for all of them and detect which report is the current one to show any extra settings.
Something like this pseudo code:

{% set current_report = craft.barrelstrength.sproutreports.current %}
{% if current_report == 'fourth_quarter_payments' %}

{% elseif current_report == 'payments_above_100' %}

{% endif %}

Is it possible to know what the current report is so conditionals can be used in the settings template?

At the time of this post, the only variable available to the settings template that might help you out is the settings object: {{ dump(settings) }}.
As this is the Twig Template report, you might be able to use the settings.resultsTemplate value to identify the active report in a shared settings file.

I've opened a ticket for adding improved support for this scenario and will look into making the dataSource object available to the settings template in a coming release.


Set site locale to display correct date format in date/time field The date field is displaying dates in US format (mm/dd/yyyy) but I need the UK (dd/mm/yyyy) format. According to the docs:

  Dates and times are both formatted for the user’s preferred locale. They are displayed in the site’s timezone, however they get stored in UTC like all other dates in Craft.

How does one set this? The timezone is set correctly in the site config.

Dates and times are both formatted for the user’s preferred locale.

You have to select your "preferred locale" when installing Craft. If you chose the wrong one  you (currently) can't undo it from the CP, but have to change it directly in the database (--> "craft_locales" table).

Another way would be to install a second locale (even if you don't need it at all). Because if your Craft site is multilingual you can switch between installed locales from the user settings in the CP though.


Global override specific field templates in Sprout Forms Plugin I want to restructure the output of the way Sprout Forms generates checkboxes and radio buttons from that of the input.html in templates/_components. I need the label to appear after the radio/checkbox input for styling/accessibility purposes.

But I'm not seeing the documentation to override  without editing the plugin (obviously not a sustainable plan). Can I just put them in the designated Global custom form templates folder and have SproutForms look for form_overrides/radiobutton/input.html first?

Example of what I need to do:

<input type="radio"
  {%- if id %} id="{{ id }}-{{ loop.index }}"{% endif %}
  {%- if name %} name="{{ name }}"{% endif %}
  {%- if value %} value="{{ value }}"{% endif %}
  {%- if checked is defined and checked %} checked{% endif %}
  {{- required -}}
  {{- dataAttributes|raw -}}
>
    <label {%- if id %} for="{{ id }}-{{ loop.index }}"{% endif %}>
        {%- if label is defined %}{{ label|raw }}{% endif -%}
    </label>

The HTML of the input fields are managed by the Custom Field, not within Sprout Forms, so Sprout Forms does not have easy access to that code to give you control over it. There are a few input types where we have to make assumptions about the HTML and the checkboxes field is one of them.

We're looking into ways to give better control here. Right now, the best option if you want an upgrade-safe way to modify that HTML would be to create a [Custom Front-end Field integration](https://sprout.barrelstrengthdesign.com/craft-plugins/forms/docs/customization/custom-front-end-fields
) for the fields you wish to update the input.

Using this approach, you would create a separate plugin and add front-end support for whatever fields you need to modify the input HTML for and your new field would display in the field dropdown when creating a form. As a starting point, you could copy just about everything from the Sprout Forms checkboxes integration which is located in sproutforms/integrations/sproutforms/fields/SproutFormsCheckboxesField.php. Aside from wrapping the Custom Front-end Field in a new plugin, the main things you will need to change is the name of the field so you can identify it in your dropdown and the input HTML in the front-end field template file.


An SEO software tool says 'keywords' meta tag is obsolete Can anyone tell me where on the Craft dashboard I can correct this and upload new keywords?

So this isn't a simple answer, because we don't know how the SEO has been implemented on your particular site. It could have been done manually, or they could have used my SEOmatic plugin or it could have been another plugin. You also don't mention what version of Craft CMS you're using.

In any event, what that SEO tool is telling you is that the <meta name="keywords"> tag is largely ignored by Google. I say largely, because if you stuff it with all sorts of keywords that look "spamy" it can be a negative ranking signal for your site.

Other search engines such as Bing, Yandex, etc. do look at the meta keywords tag, though, and as long as you're not "keyword stuffing", there's no harm in leaving that tag in there.


Let admin create price offers/quotes for customers in Commerce Does anyone know of a plugin (or coming functionality in Commerce 3 or 4) that allows admin to create price offers/quotes for a customer and then send it to the customer's email for review?
Scenario
I am talking to a customer on the phone. He wants a price on a specific product/configuration. I add the desired products to the customer's basket, save it as a price offer/quote. I am allowed to adjust prices. I send the quote to the user. The user can access the quote and easily accept or reject it.
Feature request
I added this as a feature request here: https://github.com/craftcms/commerce/issues/1156

I would advise raising this as a feature request on Github (i.e. issue).

https://github.com/craftcms/commerce/issues

Commerce 3 has back end order entry (i.e. admins can enter orders on behalf of customers), but extending this to quotes etc. would be super useful and that would be  a good place to get the conversation happening.


Can I disable languages from the General Config Settings? I started to develop my new Craft site in two languages (French & German). Once done here, I have to put the website online temporarily in one of these two languages (French).

So I turned off all sections and entries to disable the language (German) but:

This was tedious and time consuming to do this manually via the CP
domain.com/de/ now redirects to the homepage with empty content instead of redirect to the 404 page

Questions :

Is there a faster and safer way to temporarily disable a website language with the General Config Settings?
Is it possible to disable some website languages depending on the environment and / or if devMode is enabled?

How about hiding the language switcher on the front-end?


Writing a plugin that triggers on a Control Panel Template Hook? I want to do something similar to this answer but for Craft 3 (eg. render some custom HTML in the Entry editing screen). I can't work out how to do this with the changed Craft 3 hooks.

Should this be registered as an event now? What class/event ID should I be using to add code to cp.entries.edit.details?

(I'm new to Craft plugin dev so a little unclear how to proceed here)

Figured it out after browsing some existing plugins' source:

Craft::$app->getView()->hook('cp.entries.edit.details', function(array &$context) {
    return 'My Button!';
});


Content Security Policy CSP On Craft 2.x, is it a known limitation that we must allow unsafe-inline for script-src in the Content-Security-Policy? My admin dashboard fails to load when I don't allow it.

...Trying to get a high grade on Mozilla Observatory :)

I implemented this recently and what I ended up doing is return the content security headers using PHP. Depending on the request path (is it a CP URL or not?), we send CSP headers with unsafe-inline and unsafe-eval or not.

Of course, the CP is still unsecured, but what you can do is to specify a custom domain for the CP in your configuration (using the "baseCpUrl" key). Something like "admin.yourwebsite.com" that only certain users can access (using IP filtering for example).

It is still not a perfect solution, but we cannot do anything at the CP level unfortunately. I hope this will not be an issue anymore in Craft 3.


createCommand sql query not working in plugin Hi I have a plugin which I am running an sql statement from.

$users = craft()->db->createCommand("SELECT craft_users.id as userId, craft_users.firstName, craft_users.lastName, craft_users.email FROM craft_users INNER JOIN craft_content on craft_users.id = craft_content.elementId WHERE craft_content.field_interests LIKE '%\"8948\"%'");

The query is not returning the expected results from the createCommand function in fact it returns an empty array. But if I run it directly in the database it works perfectly and returns the entries.

I also tried building this with the query builder but it was throwing errors and not finding the user table.

Thanks to @carlcs for pointers managed to get this working with the following:

$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->limit = NULL;

$query = craft()->elements->buildElementsQuery($criteria);
$params = array(
    ':interest' => '%"8948"%',
);
$query->andWhere("field_interests LIKE :interest", $params);
$result = $query->queryAll() ;


Is there a logarithm function in Craft or Twig? I searched the Craft and Twig documentation, although I did not find any information about a logarithm function (http://php.net/manual/en/function.log.php ). I am trying to calculate the loan amortization formula below in Craft / Twig:

{% set payoffTime  = -(ln(1 - ((128000 * '.05') / 1260)) / ln(1 + '.05')) %}

The numbers will be replaced with field handles once I can get the 'ln' function working. I'm not even sure if the formula is 'exactly' the way it should be yet - just trying to find a way to get logarithms working in Craft, and then go from there with testing, etc. :)

To give some background on the goal of this: it will calculate the amount of time it will take to pay off an amoritized loan, (mortgage, etc) based on the amounts the user has already submitted (loan amount, interest rate, extra payments, etc.) Also, this can't be done in Javascript - it needs to be in Craft since it's calculated from user data.

Thank you in advance for any info you can give about the logarithm function in Craft / Twig.

Thanks!

The short answer is no... because Twig is a templating language, and Craft doesn't otherwise have a general need for a log type of function.

The longer answer is you can very easily build this yourself!

Grab the Business Logic Template.
Delete the services and controllers folders... you won't need them.
In the BusinessLogicVariable.php file, change exampleVariable to payoffTime. Whatever parameters you assign to this function will correspond to the parameters you'll use when calling this variable from Twig.
Set whatever logic you want within the function, and return the resulting value.
Enable the plugin from your Control Panel.
Call that variable from your Twig template!

{% set payoffTime = craft.businessLogic.payoffTime(foo, bar) %}

UPDATE

Here's an example based on the use case you outlined in the comments below...

Twig:

{% set payoffTime = craft.businessLogic.payoffTime(entry.loanAmount, entry.loanPayment) %}

PHP:

public function payoffTime($loanAmount, $loanPayment)

Alternatively, if you wanted to, you could even pass the whole entry object in as a single parameter, and just use its field values once you're on the PHP side of things...

Twig:

{% set payoffTime = craft.businessLogic.payoffTime(entry) %}

PHP:

public function payoffTime($entry)
{
    // $entry->loanAmount
    // $entry->loanPayment
}


Entries Overview: Add Field Columns Does anyone have an idea how I can add columns in the entries overview? Columns with the title of the fields that exist in the page and are filled with content.
Thank you

You can configure the columns to display using the little cogwheel icon at the bottom (below the list of sections):

This will open a modal window allowing you to select the fields you want to display in the table for each section. You can also rearrange the fields using drag-and-drop with the little handle icon to the left of the field name.
As a sidenote, this modal also allows you to reorder the sections in the sidebar, and use your own headings instead of the default headings for channels and structures.


Find one section in a for loop based on url I am new at Craft CMS so have patience with me (and my English).

I don't know if I am doing this right, but I have a link (URL) from my index.html, and I want to display the specific content on the _entry.html.

Index.html

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

{{ entry.title }}

{% endfor %}

And when I click on that link I want only to display the content related to that entry.url.

If I click the link now, all my entries will show in _entry.html.

_entry.html

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

{{ entry.title }}

{% endfor %}

I just want to show the specific content for that section.

Update:

I tested this and it worked:

{% for entry in craft.entries.section('news').type('news').slug(craft.request.getSegment(2)) %}

But I don't know why?

Just use {{ entry.title }} on your dynamic _entry template to output that specific title. You were looping through all the news entries again on the dynamic _entry template and listing each one. Any other custom fields on that page/section can be accessed simply by {{ entry.myCustomFieldName }}.


Where can I find the robots.txt file in Craft 3? I can't find it in the web folder or anywhere else, but its there when I visit the file in the browser.

Ok, so my hosting provider Hyperlane overwrites the robots.txt as long as you visit the file on their address. The file should be in the web/ folder and will show up when you visit it with your domain.


Utilizing/ Converting another database with craft (First off, I apologize for the really long question, but any help I can get would be appreciated!)

Hello!
I am taking over a bunch of sites that a developer had created for a company (I am not a developer, but I have some coding knowledge and wordpress experience).  Anyway, I want to switch over the site from just php and sql to a CMS and I feel like Craft might be the one.  However, I feel like it might just be over my head.

Basically the cms needs to manage an event (or if 1 instance of Craft can handle multiple events, each with its own website, even better!)
Each event visits up to 40 cities a year and has up to 3500 attendees at each one.  And all information regarding attendees, venue, host hotel, faculty, schedule, etc. is all stored in a data base.  And all that information is displayed on the site on pages that are created dynamically by the cities name, year, etc..

My question is: How would I transfer all of that into Craft and organize it appropriately?  And would this be possible for someone with limited knowledge of coding?

I am willing to do all the research necessary, or if its way out of my league, hire a developer to do it for me.  I just need a nudge in the right direction.

Thanks for your time!
-Alex

Welcome to Craft! Craft does not require coding experience to set up fields and relationships (attendees to events, for example). All of that is handled from the control panel.

Displaying the fields on the frontend requires some knowledge of Twig, the templating engine Craft uses.

Transferring the data may require some pretty heavy coding, depending on how the data is currently structured. There are a few importing plugins (here's a popular one) that might be able to help. From your numbers above, migrating by hand may not be an option, so you might need to invest in some research or hire a developer to help with that phase.

Craft has a lot to offer out of the box in terms of organizing content. I could see you making use out of singles and structures to manage events, hotels, attendees, etc. I recommend reading through the introduction documentation to get a hold on how Craft is set up.


Eager-loading of matrix field with getPage Can anyone provide a working example to extend the following code (add support for matrix block named "copy") and allow getPage usage:

{% set entries = craft.entries({
   section: ['news'],
   order: 'postDate desc',
   limit: 5,
   with: [
     ['assets', { kind: 'image' }]
   ]
}) %}

{% for content in entry.contentBuilder.type('copy').limit(1) %}
   {{ content.copy.getPage(1) }}
{% endfor %}

Update after Brad's comment since the with part seems to be ok - by the way thank you, it is another good example that you never stop learning.

I never saw that with attribute in a ElementCriteriaModel and after several searches I could not find any use of that attribute in craft (Please correct me if I'm wrong) the rest should be fine.

Instead of the .limit(1) you could do the following

{% set content = entry.contentBuilder.type('copy').first() %}

The getPage() function only exists in the class RichTextData maybe you have a different fieldType? Otherwise you could just do {{ content.copy }} as well to display the text in that field.

All in all it would be a good idea to tell us a little bit more about your goal, your fields and your errors. Your description is a little bit insufficient in my opinion


How to query entries written in a specific locale? (Craft 3) In Craft 2 you used to be able to do something like {% set entries = craft.entries.section('something').locale('de') %} but .locale() has been removed and there's nothing similar in the docs that I see.

I'm aware that the locale automatically gets included based on the url, and I'm aware that "Locales" have been replaced by "Sites", but I want to force a query of entries from a specific locale on the one and only site I have regardless of what's in the URL. How can this be done?

In Craft 3, you can't really have locales. If in Craft 2 you had multiple locales, that should have been automatically migrated to multiple sites (as now the site is always single locale)

Having said that, you now need to use site or siteId parameter https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#site


Template for event archive I've hacked this together to create an event archive listing, and although it works, I'm wondering if it's 'correct' or could be done more succinctly?

{% set pastEvents = craft.entries.section('eventsEntry').orderBy('eventDate') %}
   {% for date, entries in pastEvents | group("pastEvents.eventDate|date('Y')") %}

{{ date }}

                {% for event in pastEvents.all() if event.eventDate <= now %}

                    {{ event.eventDate|date('d/m/y') }}
                    {{ event.title }}

                {% endfor %}

   {% endfor %}

Instead of grabbing all entries in the eventsEntry section, then filtering by the current date/time, you could do the filtering on the database side first, so you're returning only the entries you're interested in.

Something like this:

{% set pastEvents = craft.entries.section('eventsEntry').eventdate('<= ' ~ now|atom) %}

{% for date, entries in pastEvents | group("pastEvents.eventdate|date('Y')") %}

{{ date }}

        {% for event in pastEvents.all() %}

                {{ event.eventdate|date('d/m/y') }}
                {{ event.title }}

        {% endfor %}

{% endfor %}


How can retrieve users custom fields only? I have created fields for users and also entry type.
I want to get only users fields. I have retrieved custom fields but that returns all the fields.

$users = \craft\elements\User::find()->id(USERID)->one();
print_r($users->getbehaviors()['customFields']);

I know how to get user custom fields with field Handle.
I need only users fields (whole users fields not single) that admin assign in the CP. ( settings/users/fields ).

You can do this by going via the element's field layout:

$user = \craft\elements\User::find()->id(1)->one();

$fields = $user->getFieldLayout()->getFields();

This will return you an array of all the fields (fields, not values) attached to your user.


saving user field type custom field - Failed to set unsafe attribute I have tried to save a custom field of "user field" type which resulted in this error.

  "Failed to set unsafe attribute"

code:

$order->setAttributes(array(
    'operatorUid' => Craft::$app->user->id
));

Has anyone encountered a similar issue or can you let me know how to save a custom userType field to an order?

In order to set field values there is setFieldValue function

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

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


craft.entryRevisions.getDraftsByEntryId(entry.id) is returning an empty array I'm trying to get the drafts for the entry on the front end to populate my plugin on the sidebar but cannot get the drafts returned with this code in a Twig template.

entry is an EntryModel here.

The entry ID is {{entry.id}}

{% set drafts = craft.entryRevisions.getDraftsByEntryId(entry.id) %}

{{ dump(drafts) }}

drafts is an array of 0 elements

Even trying it in a PHP plugin class and hard-coding the entry ID like

$drafts = craft()->entryRevisions->getDraftsByEntryId(995);

$drafts is empty.

Everywhere I've looked says to do like the above; however, this doesn't return any drafts that belong to the entry as expected.

In the dropdown by the entry name, it has the 2 Drafts' names and when clicking them it takes me to the draft, so it seems like the drafts are correctly mapped to this entry.

What am I missing?

Specify the locale when getting the drafts, or else it will fetch drafts for the default locale. In my case, there was only drafts for a particular locale but not the default.

{% set drafts = craft.entryRevisions.getDraftsByEntryId(entry.id, 'localeId') %}


Exclude category from channel entries (with pagination) I'm trying to paginate a channel of entries but I also need to exclude any entries that relate to a specific category.

This is what I have so far...

{% set insightCategory = craft.categories({"slug": "insights"}).first() %}
{% set insightsEntryIds = craft.entries.section('blogChannel').relatedTo({targetElement: insightCategory}).limit(null).ids() %}

{% paginate craft.entries.section('blogChannel')|without(insightsEntryIds) as entries %}
    {% for blogEntry in entries %}
        <p>{{ blogEntry.title }} ({{ blogEntry.id }})</p>
    {% endfor %}
{% endpaginate %}

Unfortunately the pagination doesn't seem to work with the |without filter. How can I achieve this?

Thanks

The without filter converts your ElementCriteriaModel into an array of entry models (the same as find() does). But that array won't work with paginate, as explained in the docs:

  This parameter needs to be an actual ElementCriteriaModel object; not an array of elements. So don’t call find() on the object.

So you need to query for the entries you're after directly with an ElementCriteriaModel. The workaround to get there would be to pass an array of entry IDs into the id() parameter.

{% set categoriesToExclude = craft.categories({slug: 'berlin'}) %}
{% set entriesToExcludeIds = craft.entries.section('news').relatedTo(categoriesToExclude).limit(null).ids() %}
{% set entryIds = craft.entries.section('news').limit(null).ids()|without(entriesToExcludeIds) %}

{% set entries = craft.entries.id(entryIds) %}

{% paginate entries as entriesOnPage %}
    ...
{% endpaginate %}

It's not recommended to use the without filter with objects anyways (→ see Brad's answer to a related question)!


How to list all Matrix Blocks from anywhere, using a slug? I came across a specific situation where I needed to list out all the values within a collection of Matrix fields on a single entry page.

More specifically, I had a single entry that needed multiple team groups, each with the name, role, and description of various people. I then wanted to list them all out anywhere on the site (single or entry pages).

Hope this solution helps people out. Feel free to critique.

{% cache %}
  {% set entry = craft.entries.slug('team').last() %}
  {% for field in entry.getFieldLayout().getFields() %}
    {% if field.getField().type == "Matrix" %}
      {% set fieldHandle = field.getField().handle %}
      {% set matrixBlocks = entry.__get(fieldHandle).find() %}
      {% for block in matrixBlocks %}
        {{ block.team_name }}
      {% endfor %}
    {% endif %}
  {% endfor %}
{% endcache %}


PHP warning on Guzzle failed to open stream: No such file or directory We just deployed Craft to Elastic Beanstalk running on a docker container.
When we revisit the site hours later at random it gives us a warning:

PHP warning

include(/var/www/craft/app/vendor/guzzle/guzzle/src/Guzzle/Http/Client.php): failed to open stream: No such file or directory

Refreshing helps and load the application properly.
Has anybody stumbled with this and so yes would be great if you have some tips!

Thanks

Files were not added to the deployment branch!


Craft 3: Image transformation - grayscale Are there any image manipulation options in Craft 3?

Like grayscale or so?
(what imager does for Craft 2: https://imager.vaersaagod.no/?img=5&demo=basic-image-adjustments)

Craft 3 currently doesn't have image filter support, but it is on the list and you can track the Github issue here: https://github.com/craftcms/cms/issues/1492


Why is the parent slug showing up in the child slug in a structure? Basic info

I have a structure with a handle about.
The Entry URI format is about/{slug}. EDIT: also tried it with just {{ slug }}
I created a child page called "Privacy Policy" with the slug privacy-policy. It has a parent of the page "About SAFS" (slug about-safs).
I can only access the page at mysite.com/about/about-safsprivacy-policy. If I go to mysite.com/about/privacy-policy, I get a 404.
If I include {{ entry.slug }} in the template, it prints privacy-policy.

Edit: This is my Settings > Sections > About after changing slug to just { slug }

My question

Why is the parent's slug being inserted into the URI, and how do I change that?

Possibly relevant info

All the top-level pages in the About structure display on a single page, using this template for the entries:

{% if entry.level == 1 %}
  {% redirect siteUrl|trim ~ 'about#' ~ entry.slug %}
{% else %}

  {# normal template #}

For the About index template, I include:

{% set link = siteUrl ~ "/about" %}

EDIT: I also tried removing the redirect from the template, and I'm getting the same routing issue for the privacy-policy entry.

Pretty sure that the ResaveElements task just hadn't run yet - my queue was stuck. Once I cleared the stuck items, the issue resolved on its own!


Craft CMS 3 error in Windows installation process I was tried to run Craft 3 on a Windows machine, it has shown the multiple errors.

An Error occurred while handling another error:
yii\base\InvalidConfigException: craft\web\Request::cookieValidationKey must be configured with a secret key. in D:\xampp\htdocs\craft\vendor\yiisoft\yii2\web\Request.php:1554
Stack trace:
#0 D:\xampp\htdocs\craft\vendor\yiisoft\yii2\web\Request.php(1536): yii\web\Request->loadCookies()

You'll get that error (regardless of OS) if the SECURITY_KEY variable isn't set in your .env file: https://github.com/craftcms/craft/blob/master/.env.example#L5

See this step in the install docs: https://docs.craftcms.com/v3/installation.html#step-3-set-a-security-key

If you run the craft setup terminal command, it will generate that key for you, but depending on how you install Craft, you can also manually set it.


How to hide the assets section of the control panel to specific user groups? I need to hide the assets section of the control panel to a given user group.
Changing the group permissions to prevent them from viewing all asset volumes also prevents them from uploading assets in entries, which is not what I want.
I want them to be able to upload new assets but prevent them from snooping around in the asset library.
Is there a way to achieve this?

Using a custom module it's easy to simply hide the Assets section of the CP.
Users would still be able to access the assets library by entering manually the URL but this is good enough for my use case.
Here's the (simplified) code:
<?php

namespace modules\appModule;

use Craft;
use craft\events\RegisterCpNavItemsEvent;
use craft\web\twig\variables\Cp;
use yii\base\Module;

class AppModule extends Module
{
    public function init()
    {
        $user = Craft::$app->getUser();
        if (
            Craft::$app->getRequest()->isCpRequest
            && !$user->isGuest
            && $user->getIdentity()->isInGroup('editors')
        ) {
            Event::on(Cp::class, Cp::EVENT_REGISTER_CP_NAV_ITEMS, function(RegisterCpNavItemsEvent $event) {
                $event->navItems = array_filter($event->navItems, static fn ($item) => $item['url'] !== 'assets');
            });
        }
    }
}


Installing Craft 3 RC on MAMP Pro - Pointing to the file directory After a successful install I point the (MAMP PRO 4+) Document Root to the Craft /web folder, which allows the final setup process. (via www/admin) However pointing at the site root (www) triggers this error; HTTP 404 – Not Found – yii\web\NotFoundHttpException

I am missing a final step?

Craft 3 does not come up with templates or default entries like Craft 2 so your templates directory is probably empty. As soon as you create some files there and link them to your entries you won't see the error when you enter your home url


How can I embed an iframe on my site? How can I embed an iframe on my site? I tried pasting the iframe code in the HTML section and it didn't appear.

Use a text field (not rich text).  Then in the output, add "raw" to avoid it stripping any HTML tags.

{{ entry.field | raw }}


Setting system email address and sender name in multi config Is there a way to set the system email address and sender name from within the config file?

This would be useful when using multi environment configurations. For instance, during development or on my staging server I wish emails to be sent to me (the developer). While for production they would go to the site owner.

I can see the values in serialised data within the database but was hoping I could override them within the config file. I've tried the  keys "emailAddress" and "senderName" to no avail.

The testToEmailAddress config setting which

  Configures Craft to send all system emails to a single email address (or multiple email addresses), for testing purposes.

sounds like the one you are looking for.


How do I pull categories from another category group for members of another category? `I will try this again.

I have an index page for each category within category group 1 (markets).

I loop through the descendants of the given category to create filter buttons.

How do i pull all the categories from a 2nd category group (country) assigned to each market from markets  - listing them only once

For the market from category group-1 (markets), I am using:

{% set segments = craft.categories.descendantOf(category) %}
{% for category in segments %}
button html using {{ category.title }}
``{% endfor %}

For the countries from category group-2 (country), I tried using:

{% set name = craft.categories.group('country').relatedTo(category) %}
{% for nation in name %} button html with {{ nation.countryName }}
{% endear %}

Where countryName is the field name for the country group.

I did not get a template error.  But nothing printed.

I forgot about the related entries.  So, I actually want to pull the related countries from the **entries** related to the market.

Here is the solution.  The key was the answer to this related question about related tags.

{% set entries = craft.entries.relatedTo(category).find() %}
{% set nation = craft.categories.group('country').relatedTo(entries).find()%}


Add localised tracking codes for production environments I have a localised site. I want to add in kiss metric and google analytic tracking codes for each locale, however, I don't want the tracking codes to output in staging and dev environments.

I considered using globals, but then I'd need a way to print the global in the template if the environment is production.
I have also considered using environment variables for in general.php file for the production environment and print the environment variable in the template.

Does anyone have advice on best practice for this.

If people don't need to change these through the control panel, I would put them in the general.php config file.

Here's how I would do it:

return array(
  '*' => array (
    // default to not doing analytics
    'doAnalytics' => false,
    // all the analytics codes, by locale
    'gaCodes' => array(
      'fr_fr' => 'UAxxx',
      'en_us' => 'UAxxy'
    ),
  ),
  // CRAFT_ENVIRONMENT is set to one of 'LOCAL', 'STAGING', or 'PRODUCTION' in index.php
  'LOCAL' => array (
  ),
  'STAGING' => array (
  ),
  'PRODUCTION' => array (
    'doAnalytics' => true,
  ),
);

Then in your template:

{% if craft.config.doAnalytics %}
  ...{{ craft.config.gaCodes[craft.locale] }}...
{% endif %}

Here {% if ... %} tests if we want to do analytics, and {{ craft.config.gaCodes[craft.locale] }} pulls out the gaCode for the current locale.


Images of Matrix not loading First time working with matrix fields. In this case to load images. But somehow I can't manage to fetch the url of the Images. I can get the title and id but not the url. Can someone point me to the mistake am am making? Thanks!

{% set allProjects = craft.entries.section(['sectionHandle']) %}

    {% for projects in allProjects.all() %}

        {% for block in projects.matrixFieldHandle.all() %}

           {% if block.type == "image" %}

             {% set image = block.image.one() %}
             {% if image %}
              {{ image.url }}
             {% endif %}

           {% endif %}

       {% endfor %}

    {% endfor %}

during this process :
{% set image = block.image.one() %}
please make sure the name of handle of image is image.
For example in this matrix the type is 'image' but to get image url you should call it. item.imageAssets.one().url


Matrix Gallery, with every image having it's own unique URL? As of right now I have nine or so structures created, each including it's own Image Gallery created in a Matrix.

Is it possible to give each image inside that matrix a unique URL?

What I'm trying to accomplish is to be able to create multiple galleries, each gallery when clicked will just pull up into a Fancybox. The problem with this, is there also needs to be social media sharing (Facebook, Twitter, Pinterest, and Google+) for each item in the gallery. After a bit of research the Facebook og:image tag only shares what is in that URL being shared. So I will need to be able to create pages for each item in the gallery. Would this be possible?

You can do this by creating a "single image" template, and point to that template with a URL GET variable containing the Asset ID, for example:

http://yoursite.com/gallery/single?assetId=234

First, create a template for your "single" image – e.g /templates/gallery/single.twig (I like to use the twig extension rather than .html, but its not important).

Add the following Twig code to your template – it will look at the current request query string for the assetId variable, and try to pull the relevant Asset:

{% set assetId = craft.request.getParam( 'assetId' ) %}
{% if assetId %}
{% set asset = craft.assets.id( assetId ).first() %}
{% endif %}

Then, you can easily output the image in whatever way you want, here's an example:

{% extends 'layouts/myGalleryTemplate' %}
{% block single %}
    {% if asset is defined %}

    {% else %}

The specified image could not be found

    {% endif %}
{% endblock %}


Can I get an entry by Matrix Block ID? For a url like domain.com/example/123 where 123 is a Matrix Block ID (not an Entry ID), can I get the associated entry for given block ID in a template?

Or, for a more general approach, what would be the best way to get that Matrix Block element and its Entry element when you only have a block ID?

Edit: so ideally:

{% set block = craft.matrixBlocks.id(craft.request.segment(2)).first() %}
{% set entry = block.getOwner() %}

...which isn't possible now.

At the time of this writing, the ideal solution isn't possible. But, as jpea suggested, creating a plugin was dead easy, so here it is:

Low Blocks

...which lets me use syntax like this:

{% set block = craft.lowBlocks.id(craft.request.segment(2)) %}
{% set entry = block.owner %}


Twig Runtime Error on settings/general (value: system.name) When I go to settings/general in the CP i get this Twig Runtime Error.  Does anoyone here know what to do to fix it?

You might need to fix this manually.
Open your config/project/project.yaml and make sure that the system object has all the following keys in there (you seem to be missing name):
system:
  edition: pro
  live: true
  name: Site Name
  retryDuration: null
  schemaVersion: 3.6.6
  timeZone: Europe/Paris

Once you have done that, run ./craft project-config/apply and the error should go.
Note that the schemaVersion is for Craft 3.6.11.1.


Calling an Asset field from a Global I can't, for the life of me, find an answer to this question.

I have a global called work.  It has three Asset fields.  One is called mediakit, which is an upload of a PDF.  I am trying to get the file name of that asset and add it into the template but cannot find anything giving me the proper way to do this in the template

Based on the documentation I thought:

 {{ work.mediakit }}

would output something at least but nothing shows and so whittling away from there to get it to call the correct path has eluded me.

Can anyone give me the correct way to call that?

The path is:

  "/assets/medikit/{{ the filename of the pdf uploaded}}"

Assets fields always return ElementCriteriaModel’s in templates. To get the actual related asset, do this:

{% set asset = work.mediakit.first() %}

You can’t be sure that there’s actually a related asset, so it’s worth making sure work.mediakit.first() actually returned something before accessing its properties:

{% if asset %}
    {{ asset.url }}
{% endif %}


Filter entries by Field value using a variable How do I filter a list of entries by the value of a field using the value of a variable?

e.g.

{% set location = block.locationVacancies %}
{% set entries = craft.entries.section('careers').search('locationVacancies:"{{location}}"')

doesn't work for me. But if I replace {{location}} with the value of the string location by hand then it works

{% set entries = craft.entries.section('careers').search('locationVacancies:"uk"')

Twig has an interpolation syntax (using #{} inside a double-quoted string) to accomplish this:

{% set location = block.locationVacancies %}
{% set entries = craft
    .entries
    .section('careers')
    .search("locationVacancies:#{location}")
    .all() %}

In addition, you can be more explicit about the values you’re searching for (and avoid any kind of sneaky search capabilities/side-effects exposed by using raw query input):

{% set location = block.locationVacancies %}
{% set entries = craft
    .entries
    .section('careers')
    .locationVacancies("*#{location}*")
    .all() %}

…or even using Twig object syntax…

{% set location = block.locationVacancies %}
{% set entries = craft.entries({
    section: 'careers',
    locationVacancies: "*#{location}*"
}).all() %}

(locationVacancies: location will also work, but disables partial matching)

  It should be noted: if you're looking to associate multiple explicit entries, you can also make the field within your (presumed) Matrix Block an Entries field, which establishes actual relationships in the database—accessing such a field (myBlock.myLocationEntriesField.all()) will return that list of Entries, exactly as set in the admin) If you just need a dynamic search param, what you have is a fine solution!


Noob here. Can I buy a license without installing the software? I'm not the developer. I have no need for the software on my workstation. I just want to buy the license. Can I buy a license without installing?

It's not possible to do this by yourself... reach out to Pixel & Tonic directly:

  support@craftcms.com

If this software already is installed somewhere public, you can simply log in and pay for it directly.


Protecting public assets I'd like to manage access to assets with public URLs.
Is there a way to set permissions for anonymous users?

This answer is a bit self-serving, but I'm the author of the Digital Download plugin. It allows you to control how and when assets are downloaded.
You can restrict downloads by a time period, maximum number of downloads, or tie them to a logged-in user.


Flexible content requirements for Matrix I’m attempting to setup a site with only a couple of templates and having a LOT of Matrix fields so the client can build content out of component based content, making it super flexible (hopefully).

I'm using Matrix Table Field Types for various items but what I really need to do is have the ability to have other types of content within the Table, other than just 'single-line text', 'multi-line text', 'number' or 'checkbox'.

Does anyone know any way to do this or of there are maybe any plugins which would solve this issue?

If these Matrix fields are going to have a lot of fields then I'd recommend taking a look Pimp my Matrix to keep them well organised.

If you're wanting to make your Tables more powerful and have more field types check out SuperTable.


P&T Contact Form not submitting Craft 2 I'm working on a site that I did not build.

The first party contact form stopped submitting so I updated Craft and all plugins. All went smoothly but the form is still not  submitting.

Checked the templates and compared to the docs and it appears that it should work (was previously). Any recommendations on how to better troubleshoot?

  {% from _self import errorList %}

  <form id="contact-form" method="post" action="" accept-charset="UTF-8" enctype="multipart/form-data">
      {{ getCsrfInput() }}
      <input type="hidden" name="action" value="contactForm/sendMessage">
      <input type="hidden" name="redirect" value="/careers/apply-now#form-thanks">

        Name
        <input id="fromName" type="text" name="message[fromName]" placeholder="Your Name" value="">
        {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

        Email
        <input id="fromEmail" type="text" name="fromEmail" placeholder="Your Email" value="">
        {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

        Phone
        <input id="phoneNumber" type="text" name="message[phoneNumber]" placeholder="Your Phone Number" value="">
        {{ message is defined and message ? errorList(message.getErrors('phoneNumber')) }}

      Position
      <input id="position" type="text" name="message[position]" placeholder="Position of Interest" value="" />

      Attach Resume
      <input type="file" id="attachment" name="attachment" />

    <input type="hidden" name="subject" value="Career Form Submission" />
    <input type="hidden" name="nothanks" id="nothanks" value="" />

        <input type="submit" value="Send">

  </form>

This sounds like a problem with your email configuration, not the form plugin.

Check your site wide email settings, specifically check the "Protocol". If you are using "PHP Mail", you're gonna have a lot of problems. The best option is "SMTP".

There are several SMTP services to choose from. We've been using Mailgun for several years, and are very happy with them.


How would I create unique fields for different user groups programmatically? I understand this isn't possible from the Control Panel, I'm developing a custom plugin for this specific client project. Essentially these user groups won't need access to the Control Panelat all, but will have unique permissions within the site and will have a few custom fields.

Can I create custom fields per user group? Or do I just need to create relationships between these fields and the users when they create their profile? Trying to figure out the proper way to go about this.

EDIT:
After watching the Element Type hangout as suggested, they explain why this isn't possible with the current implementation of User Groups, if you are curious.
https://youtu.be/hU_wduMEimY?t=27m44s

You could control which fields a user has access to based on their group from a front end edit profile page, but there is no way to do this in the admin outside of creating a plugin with a custom table and screens.


Loop index inside a switch content builder How would one construct this? I have built a little content builder and wish now to change the layout HTML on the fly when there are more than one matrix block.

In the example below, this is just one section of the builder and the one I would like to change.

Basically 'move' the block.text part above the image every 2nd time in the loop. I have looked at batch and loopindex but having trouble for the last few hours. Can someone please help with this?

Builder code:

{% case "splitImageAndText" %}

        {% set images = block.imagePart %}

        {% if images and images|length %}
            {% set image = block.imagePart.all() %}

            {# Loop through the images #}
            {% for image in images.all() %}

            {% endfor %}
        {% endif %}

            {{ block.textPart }}

I belive you can use {% if loop.index is even %} or {% if loop.index is odd %}


Why is Live Preview scrolling to the top of page after every change? Having an issue with Live Preview scrolling to the top of the page in the preview area on every update made (even title field). Narrowed it down to it not being a browser issue as it works plum good on another site. Here’s the error I’m seeing in console with the site giving me the issues. Can anyone point me in the right direction? Please and thanks]1

Figured it out. The issue was related to Font Awesome 5's SVG replacement with JS method but specifically Asynchronous Loading Indicators. Once I stopped using this async stuff all is peachy again.


Page currently being edited by another user notification? Any thoughts on how I could let  users know when they go to a page in the backend that/if another user is currently editing that page? I don't need it to lock editing, just to present a notice that it's being looked at/edited by someone else

It would definitely have to be a plugin, but I'm not sure the right events are available for a plugin to pull it off right now.

Seems like there would need to be at least two that need to be created.  Some onDisplayEntry event that gets fired as soon as an entry page is viewed and another onEditEntry event that gets fired over AJAX as soon as any field value changes.


Craft Commerce: Frontend Validation on Address Fields Yes I know there is this post
But how do you do address validation in the frontend of Commerce 3?
The problem is the way Billing Address & Shipping Address are set up.
Billing Address are the same form fields duplicated via js and it is next to impossible to differentiate the two.
If I add required to any field this will also apply to the hidden field in the billing address form. Therefore, the html5 validation will always fail.
Has anybody a solution to this?

Would removing required via JS be an option?


Adding Categories navigation to show certain entries I'm abit lost as to how to structure my FAQ page.
I have a single FAQ page that pulls in every FAQ post, these posts come from the FAQ Entries channel.
But
On the single FAQ page, how do I add a navigation that only shows certain FAQ Entries using categories?

If I understand properly, you want to show related FAQ based on categories.
On your entry template, you could do something like this:
{# Fetch the categories of the current entry #}
{% set entryCategories = entry.yourCategoriesFieldHandle.all() %}

{# Find related entries #}
{% set relatedFaqs = craft.entries()
    .section('faqs')
    .relatedTo(entryCategories)
    .all() %}

{# Display related FAQs #}

{% for entry in relatedFaqs %}

{{ entry.title }}

{% endfor %}

Change yourCategoriesFieldHandle to what your field handle is and .section('faqs') to the correct section handle for your FAQ's section.


Contact Form Plugin - Not sending/receiving emails? I'm developing my first website on Craft 3 and I'm essentially a front-end designer so my PHP/MySQL/AJAX knowledge is extremely limited.

I installed the Contact Form plugin as explained here https://github.com/craftcms/contact-form and used the code example on the page (minus the redirectInput).

        {% macro errorList(errors) %}
        {% if errors %}

                {% for error in errors %}

{{ error }}

                {% endfor %}

        {% endif %}
    {% endmacro %}

    {% from _self import errorList %}

    <form method="post" action="" accept-charset="UTF-8">
        {{ csrfInput() }}
        <input type="hidden" name="action" value="contact-form/send">
        {{ redirectInput('contact/thanks') }}

Your Name

        <input id="from-name" type="text" name="fromName" value="{{ message.fromName ?? '' }}">
        {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

Your Email

        <input id="from-email" type="email" name="fromEmail" value="{{ message.fromEmail ?? '' }}">
        {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

Subject

        <input id="subject" type="text" name="subject" value="{{ message.subject ?? '' }}">
        {{ message is defined and message ? errorList(message.getErrors('subject')) }}

Message

        <textarea rows="10" cols="40" id="message" name="message">{{ message.message ?? '' }}</textarea>
        {{ message is defined and message ? errorList(message.getErrors('message')) }}

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

But when I submit my form, the page reloads then zwoooosh, nothing happens! I can't tell if I'm not receiving the email or if it's not even being sent. I checked pretty much everywhere for similar issues but can't tell what's happening or not happening.

I didn't install any mail server on Ubuntu, I don't even know if that is necessary. I checked my Spam folder... I'm a bit lost at this point!

Any help would... help!

Welcome to Craft!

You mention you haven't configured any kind of mail server—this is almost certainly the issue.

There are a few mailer adapters for Craft, the availability of which will depend on whether you're using Craft 2 or Craft 3.

That said, the easiest route will probably be to use the built-in SMTP method, configured in the Settings -> Email screen of the Admin.

I'd recommend checking out Mailgun or Sendgrid as third-party services that handle mail delivery—this way, you're not responsible for maintaining your own mail server. Both offer generous free tiers that should cover most use cases.

Each should provide you with some SMTP credentials you can drop into Craft's settings.

Be aware: some ISPs will block SMTP traffic over the standard port. If you still have trouble sending mail, look at the docs for your chosen provider and see if they support sending over an alternate port.

Good luck!


Is Craft Suitable for Large Public Body website I have used craft for a few medium sites sites and I love it.
Would Craft be capable of running a large public body website which would be updated with news regularly and have a wealth of information on the wide range of services provided - and likely to be a large number of documents needing accessed.
On a rough estimate there could be 7-8 structures and maybe 10 channels.
There will be a small eCommerce requirement on the site.

Will Craft handle this all ok?
Is there any limitations?

Don't want to be running into the problem of developing the site then at launch it and it not being able to cope.

One of the biggest Craft projects I've worked on has around 25 sections, 10+ global sets,  250+ fields, and 12,000+ elements across 16 locales (although only 1 locale has launched atm). Craft itself (the CP) has not had any problems I can remember handling it so far, especially with the element index updates that have been introduced over the last few months. I know there must be people running sites much bigger than that too.

On the front-end, we definitely had some slow templates where we are looping over a lot of related elements and outputting assets that were generating hundreds of queries per page, but careful planning, template caching, and in some cases using plugin code to pre-fetch data outside of the craft.entries etc calls in templates helped a lot. You can suffer from N+1 problems with relations and images - as you can with any CMS/website.

I wrote a small plugin for storing template caches in Craft's data cache (in our case Redis), which I'll see if I can release; we stuck Varnish in front of everything except CP requests; use S3 & CloudFront for serving assets; and while there's still room for improvement, we're now getting straight A's on webpagetest.org, so Craft certainly isn't just for small hobby-projects.


Changing the frontend sorting according to different fields I am creating a site that has a list of events that I need to be able to sort by different fields. I know how to do it statically in my templates but I want to enable it in the front end.

For the example, each event will have three different sorting fields - 'Teacher', 'Country' and 'Event Date'. The initial order will be according to date but I want that the user will be able to choose from an option button a specific value (with all the available options of this field) and to see only events from a specific teacher or specific country.

I would appreciate any help on how to start such a thing. Again, I know how to create static sorting in the templates but not live one being done in the front-end...

Use Categories for Teacher & Country.  Add inputs for those categories to your Section.

To create your select inputs:

{% set entryIds = craft.entries.section('events').ids() %}
{% set teachers = craft.categories.relatedTo({ sourceElement: entryIds }).group('teacher').find() %}
{% set countries = craft.categories.relatedTo({ sourceElement: entryIds }).group('country').find() %}
<select>
  {% for item in teachers %}
       <option value='{{ item.title }}'>{{ item.title }}</option>
  {% endfor %}
</select>
<select>
  {% for item in countries %}
       <option value='{{ item.title }}'>{{ item.title }}</option>
  {% endfor %}
</select>

Then when you submit these as a form or via javascript on your filtered page you would do something like this.

{% set filterId = craft.request.getParam('id') %}
{% set events = craft.entries.section('events').relatedTo({targetElement:filterId}).startDate('and', '>= ' ~ now) %}

If you needed to filter for more than one category group:

{% set entries = craft.entries({
    section: 'events',
    relatedTo: [
        'and',
        { targetElement: craft.request.getParam('teacherId') },
        { targetElement: craft.request.getParam('countryId') }
    ]
}) %}


Feed Me: Feed inside the feed I have just started using Feed me to import a festival schedule, and I have run into an issue with how their API is set up. The URL I have to use for the feed (with the token) outputs only a <link>URL.xml</link> to a temporary XML-file with a unique filename each time. So there's pretty much a feed inside the feed. Any way of getting Feed Me to look at the linked XML-file, or any other suggestions on how to solve this?

There's no current way for Feed Me to handle this I'm afraid. My best suggestion would be to write a module to fetch the XML from your first URL, parse that, find the <link> note, fetch and parse that, and output the XML. You'd then point Feed Me to that URL, with the actual content of the feed that's required.
It could be a Craft module, a standalone PHP script, or even JS - whatever you're comfortable work.
It's a bit of extra work, but custom development would be the only option for the moment.
EDIT: The other option you could create a template (let's say my-feed.xml) in your templates directory with:
{% header "Content-Type: application/xml;" %}

{% set params = {
    url: 'http://path.to/feed/',
    type: 'xml',
} %}

{% set feed = craft.feedme.feed(params) %}

{% for node in feed %}
    {# Find the node that contains the link #}
    {% set link = node.myLinkNode %}

    {# Get the raw data and output it #}
    {% set xml = craft.feedme.getDataTypes().getRawData(link) %}

    {{ xml }}


Access Default User Photo I'm calling user photo's from my template, but it error's out when trying to obviously call a user photo which is empty. What I'm trying to achieve is

  if there is no user photo, use the default placeholder image craft supplies

The problem I'm having trouble getting to the bottom of is, how to access the default user photo?

    <img class="img-fluid rounded-circle" src="{{ entry.author.getPhoto().url }}" width="100" height="100" alt="{{ entry.author }} Picture">

Any help would be great

You want to use the default blank user SVG from the Control Panel on the front-end of the site when there is no photo selected?

If so, it's probably easiest just to copy it from vendor/craftcms/cms/web/assets/cp/dist/images/user.svg to a place in your public HTML folder and reference it there.

Something like:

{% if entry.author.getPhoto() %}
    {{ entry.author.getPhoto().url }}
{% else %}
    {{ url('path/to/user.svg') }}
{% endif %}


Save Continue Editing Is it possible to configure "Save & Continue Editing" as default mode?
I know there is option to select it when adding entry but I want to configure so that always is the case for one of the channel.

It's currently not a configuration option, but there is a Control-S (Windows) / Command-S (OSX) shortcut that should work on every page in the Control Panel that basically says "save and stay on the same page".


Import body field into a matrix text block I'm working on importing a database and I was looking at some of the available import plugins. However I am unable to figure out how to import a body field (just a string) into a Matrix block.

Old database entry structure (non-Crafty)

title
description
body

New database entry structure (Crafty)

title
description
matrix [body, image, gallery, etc]

Does anyone have experience with this? Any advice?

Nevermind. Clearbold's Craft Import plugin has the starting code for it.

// new entry
$entry = new EntryModel();
$entry->sectionId = 1;
$entry->typeId    = 12;
$entry->authorId  = 123;
$entry->enabled   = true;
$entry->getContent()->title = "Here goes my title!";

// new matrix and matrix block
$block = array();
$block['new1'] = array(
    'type' => 'body',
    'enabled' => true,
    'fields' => array(
        'text' => 'Here goes my article.'
    )
);

// add content to entry including created matrix
$entry->setContentFromPost(array(
    'description' => "And of course the description...",
    'matriz' => $block,
));

// save entry
$success = craft()->entries->saveEntry($entry);


Generate pdf with form submission data I'm using amforms for a client and need to create a user confirmation email that has a pdf attached containing the submitted form data, like a receipt.

After a little google searching, I believe I'd have to hook into amforms' onEmailSubmission method and generate the pdf using the mPDF library, is this correct?

How do I add the mPDF library to Craft?
After creating a nice pdf template design, how can I populate a 2 column table in the pdf with form names/values submission data from all the fields?
And then finally attach that pdf to the user confirmation email?

Does anybody have experience with this whether using amforms or not?

Note: I've never used amforms nor mPDF, so I'm on a bit thin ice with this answer – hopefully it'll prove semi-useful, though.

  How do I add the mPDF library to Craft?

To include any third-party PHP library in Craft, you'll need to build a custom plugin, since that's the only real way to write (or include) PHP inside a Craft CMS app.

Craft plugins are just plain ol' PHP, so to actually include the library, you can use a regular require statement:

public function init()
{
    ...
    require_once('/path/to/mpdf.php');
}

...however, the recommended way to include a third party package is to use Composer (which mPDF supports) and autoload your dependencies from your plugin's main class' init method:

public function init()
{
    ...
    require_once(__DIR__ . '/vendor/autoload.php');
}

One thing to pay attention to when using third party libraries inside a Craft plugin, is that Craft has it's \Craft namespace for the core and all plugins, and your third party library's code won't be found under that namespace. To account for this, you can use the use statement (add it to the top of any file where you want to use the mPDF library:

use \Mpdf\Mpdf as Mpdf;

...
$mpdf = new Mpdf();

...or you can skip the use statement, in which case you'll have to type out the namespace path for the third party library every time you use it:

$mpdf = new \Mpdf\Mpdf();

  After creating a nice pdf template design, how can I populate a 2 column table in the pdf with form names/values submission data from all the fields?

In order to generate a PDF based on the fields submitted via amforms, you'll probably need to hook into the onEmailSubmission event (as you mention), and render a Twig template to HTML before using mPDF to generate a PDF from that HTML output.

Here's a very basic example – this would also go into your plugin's main class' init method:

public function init()
{
    // Require your Composer dependencies (mPDF, possibly others)
    require_once(__DIR__ . '/vendor/autoload.php');

    // Hook into amforms' onEmailSubmission event
    craft()->on('amForms_submissions.onEmailSubmission', function (Event $event) {

        $params = $event->params();

        // Use whatever's in $params to generate a PDF via mPDF
        // One way to do it is to compile a Twig template from your site's /templates folder via Craft's [TemplatesService][5], and then feed the HTML output to mPDF:
        $html = craft()->templates->render('/path/to/template', $params);

        // Create a mPDF instance, and generate a PDF file from the HTML
        $mpdf = new Mpdf();
        $mpdf->WriteHTML($html);

        // Have mPDF save the PDF file to some location
        $mpdf->Output('/path/to/your/pdf.pdf');

        // Some code that will attach the PDF to the email amforms will send
        ...
    });
}

Note: As I've never used amforms, I'm not totally sure about the syntax for the actual event listener here – the plugin's documentation is lacking in terms of its custom events; briefly looking at the source code makes me believe that amForms_submissions is the correct prefix for the event, but a minor disclaimer here.

Beyond the simple example above, for details on how to generate the actual PDF, I'll have to refer to the official mPDF documentation: https://mpdf.github.io/.

  And then finally attach that pdf to the user confirmation email?

I've no idea how to attach the PDF to the actual confirmation email amforms sends, and the documentation doesn't mention a use case like that – hopefully someone familiar with amforms can help you out with that part.

Finally – this is probably not helpful to your specific use case, but still – here's how you could send the PDF using Craft's EmailService:

$email = new EmailModel();
$email->toEmail = 'hello@example.com';
$email->subject = 'Your PDF is ready, boss';
$email->body    = 'How you doin, {{ user.name }}?';
$email->attachments = [[
   'path' => '/path/to/your/pdf.pdf',
   'name' => 'An awesome PDF',
   'encoding' => 'UTF-8',
   'type' => 'application/pdf',
]];

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

(If amforms doesn't offer a way to include the PDF attachment, you might be able to solve it by a) using the onBeforeEmailSubmission event instead and setting $event->performAction to false inside the event handler, to prevent amforms from actually sending the email confirmation; then compile an EmailModel yourself (like in the example above), and sending that instead – just an idea)


Solspace Calendar Event Editing I'm using Solspace Calendar for Craft and I'm currently trying to implement the edit event form. Once a user selects an event on the calendar they are taken to the event page. On this page I have the edit event form.

The fields in this form will be added to the event entry once submitted. The issue I'm having is getting the form to submit.

<form method="post">
                    {{ csrfInput() }}
                    <input type="hidden" name="action" value="calendar/events/save-event" />
                    <input type="hidden" name="redirect" value="{{ (siteUrl~"availability/event/{id}")|hash }}" />
                    <input type="hidden" name="eventId" value="{{ event.id }}" />
                    <input type="hidden" name="slug" value="{{ event.slug }}" />

Looking at the demo documentation, the two fields I'm not too sure about is the 'action' and 'redirect' fields. I have changed the redirect field to match the current event page. But I don't know what needs to go into the 'action' field.

Currently as you can see, it's 'calendar/events/save-event'. Is this a demo template I have missed. Does this need to be changed to something more specific. Any help much appreciated.

You'll want to make sure you include all of the Calendar field inputs in order for this to work. If you're trying to hide them for your workflow, you can set the fields to hidden, or wrap them in a div and hide them with CSS. :)


Does Craft have a server-side queuing system? I am wondering if Craft/Yii has some sort of built in queuing system for apps that need to do additional processing that could hang up the UI or make the user wait unnecessarily. I am looking for something similar to Laravel Queues. Does Craft have something similar built in? If not, I think queues would make a great addition to the API.

http://laravel.com/docs/queues

Not so much true queues, but Craft does have the (completely undocumented) concept of Tasks, which are meant to be used for potentially long running tasks that don't need to execute immediately.  Plugins can create and register tasks to run.

Here are some questions discussing them:

My tasks don't seem to be running as a background process

How to add a subTask to an already running Task?

Triggering the start of a task from a CRON job

You can view the TaskService in craft/app/services/TaskService.php and you can see examples of Craft's own tasks in craft/app/tasks.

Also worth noting that proper support for queues at the framework level looks like it's on the roadmap for Yii 2.1.


Filter syntax for Dimensions & Weight? Is there comparable syntax to display dimension and weight filter settings from Commerce similar to those for currency eg: {{ variant.price|currency('CAD') }}? Couldn't see any info on this in the docs.

There is currently no filter but you can access the units of measurement from your settings, and display the measurement:

{% set weightUnits = craft.commerce.settings.weightUnits %}
{% set dimensionUnits = craft.commerce.settings.dimensionUnits %}

{{ variant.weight }} {{ weightUnits }} // 10 mm


locale loop doesn't get correct path I'm trying to loop on locales to get the path to the current entry, but for the other locales (for a language switcher).

Here is my code:

{% set locales = craft.i18n.getSiteLocales() %}
{% for locale in locales %}

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

        {{dump(localeEntry.locale)}}
        {{dump(localeEntry.getUrl()) }}

{% endfor %}

Results:

"en"
"http://website.dev/en/page"

"en_gb"
"http://website.dev/en/page"

"en_us"
"http://website.dev/en/page"

"de"
"http://website.dev/de/page"

The language only versions are fine en and de, though the language-location versions are incorrect. These are all set correctly in my config.

What am I doing wrong here?

Turns out the issue was my config set incorrectly. I was doing this:

'siteUrl' => array(
    'en' => 'http://website.dev/en',
    'en-gb' => 'http://website.dev/en-gb',
    'en-us' => 'http://website.dev/en-us',
    'en-au' => 'http://website.dev/en-au',
    'en-nz' => 'http://website.dev/en-nz'
),

When the array keys need to match the way they are set in craft with underscores (and your public/locale/index.php file)

'siteUrl' => array(
    'en' => 'http://website.dev/en',
    'en_gb' => 'http://website.dev/en-gb',
    'en_us' => 'http://website.dev/en-us',
    'en_au' => 'http://website.dev/en-au',
    'en_nz' => 'http://website.dev/en-nz'
),


Redirect Manager 301 results in "Entry DNE" error This is my old URL. No entry exists here:

/post/234234234234/happy-fourth-of-july

This entry exists:

/news/happy-fourth-of-july

I have the Redirect Manager plugin setup as follows:

However when I visit the old URL (above) the URL remains unchanged and I receive a Variable "entry" does not exist template error.

I must be missing something really obvious, so if I can provide more infomation, let me know.

Turns out that I was right on the money with my plugin configurations, however earlier I had incorrectly tried to solve the problem using the route below, which was still in place and scuppering my subsequent good work!


How to retrieve the mode of an image transformation from its name? I work on a portfolio with a large number of images with very high sizes and a lot of images transforms. The server on which this site is hosted reach these limits (images generations process are generally blocked), so I would like to experiment with imgix in order to move the transformations of images in the cloud.

I need to tell imgix how to crop images and I prefer to define my transformation types in the Control Panel rather than in the templates. How can I retrieve the mode of an image transformation from its his name?

Is there something like {{ craft.assets.getMode('myTransformName') }} ? I haven't found a method for this in the documentation.

Not possible out of the box, unfortunately. Asset transforms can be pulled by using the AssetsTransformService, but Craft doesn't expose that service to Twig (unlike the AssetsService, which is what you're working with when you're using craft.assets).

What you could do is to create a simple, custom plugin exposing the AssetsTransformsService to Twig by adding the following to a Variable class in your plugin:

public function assetTransforms()
{
    return craft()->assetTransforms;
}

Then, you'd be able to do something like this in your templates:

{% set transform = craft.myPluginHandle.assetTransforms.getTransformByHandle('myTransformName') %}

The mode is {{ transform.mode }}


Detect if a language is translated or not For entries where the content isn't translated yet I'd like to add a "Sorry not translated yet" message.

Since all the content is synced is there a way to check if the synced content is the same as in the other locales?

You could try adding something like the following to the end of your template. This is assuming you only have 2 locales.

{# test for the current entry locale (i.e. spanish) #}
{% if entry.locale = 'es' %}

    {# retrieve the same entry in the original locale #}
    {% set localizedEntry = craft.entries.id(entry.id).locale('en') %}

    {# compare the body content, and append additional content #}
    {% if localizedEntry[0].body == entry.body %}
        Sorry, not translated yet.
    {% endif %}

{% endif %}


Craft 3 Plugin: Saved image asset has no width / height In my Craft 3 Plugin I am saving an image (YouTube poster) to an asset volume like this:

$asset = new Asset();
$asset->title = $url;
$asset->tempFilePath = $tmpPath; // temp path for image in /storage/runtime/temp/
$asset->volumeId = $volumeId; // ID of my Asset Volume
$asset->filename = $filename; // filename like youtube_<youTubeKey>.jpg
$asset->newFolderId = $folder->id; // root folder id of the volume
$asset->avoidFilenameConflicts = true;
$asset->setScenario(Asset::SCENARIO_CREATE);
clearstatcache();
list ($w, $h) = Image::imageSize($tmpPath);
$asset->setWidth($w);
$asset->setHeight($h);
$result = Craft::$app->getElements()->saveElement($asset);

The image saved does not have width or height (so it's there while saving), so if I later output its width like this in TWIG: {{ dump(img.width) }} it will be NULL.

Any hints what I need to call so that craft persists the image width / height?

As Andris Sevcenko pointed out, the problem is Craft 3 Beta 22 and a Multisite Configuration. Fixed in Beta 23.


How to call Controller in Module? I'm very new to craft and I'm having trouble finding an answer to my question (I've scoured the questions on here - but the only answers appear to be for plugins).

Basically, I want to submit a form to an action in a controller - which will be inside a Module.

I have this form in a template:

<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="site/say">
    <input class="btn submit" type="submit" value="submit me">
</form>

I'm trying to get it to go to this controller (which is in modules/controllers/SiteController):

<?php

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    // ...existing code...

    public function actionSay($message = 'Hello')
    {
        die('in say action');
    }
}

I'm constantly getting a 404 - I've tried different variations for the value of action, e.g. actions/site/say.
Do I need to add a route somewhere like in Laravel?
Really, really stuck on this, any help would be appreciated.

You need to include your module handle to the route

module-handle/site/say

You also should use the correct namespace instead of app/controllers I suggest you to read the documentation

You can as well define a route if you like


Figuring out why my image is not working in the template Possibly a very easy question. Let me explain my flow:

I created an asset folder (images)
I added the folder in the assets
I created in image transforms 'square' which is an image of 500 by 500px.
I added a custom field to my homepage called 'hoofdafbeelding' and added an image to it.

I call the image like so:

{{ entry.hoofdafbeelding.getUrl('square') }}

I get the following error:

Object of class Craft\ElementCriteriaModel could not be converted to string

What am I missing?! How can it be so hard to show an image?

You can have more than one Asset in any Assets field, so it always returns to you an array of assets. So you just need:

{{ entry.hoofdafbeelding.first().getUrl('square') }}

...assuming you want the first asset.


Use utf8mb4 for database operations the plugin I'm currently working on has to store user inputs which might contain 4 byte unicode characters like emojis. MySQL is not able to handle this with a utf-8 charset. It works if the charset of my tables is set to utf8mb4 and if I add 'charset' => 'utf8mb4' to config/db.php. Since the file config/db.php does not belong to my plugin, but to the installation of Craft itself, I'd like to not modify it.

Alternatively, I can convert the inputs with StringHelper::encodeMb4() but then I would have to do that at every place where something from the outside enters my tables.

Is there any pragmatic way of handling this?

Greetings Jus

Crafts ActiveRecord has a function beforeSave

/**
 * @inheritdoc
 */
public function beforeSave($insert)
{
    foreach ($this->fields() as $attribute) {
        $this->$attribute = Db::prepareValueForDb($this->$attribute);
    }

    // Prepare the values
    $now = Db::prepareDateForDb(new \DateTime());

    if ($this->getIsNewRecord()) {
        if ($this->hasAttribute('dateCreated')) {
            $this->dateCreated = $now;
        }

        if ($this->hasAttribute('uid')) {
            $this->uid = StringHelper::UUID();
        }
    }

    if ($this->hasAttribute('dateUpdated')) {
        $this->dateUpdated = $now;
    }

    return parent::beforeSave($insert);
}

You can overwrite this method and include your StringHelper::encodeMb4() into it so every time $record->save() is executed your string will be converted


Why am I getting only one result with "craft()->db->createCommand()"? Why am I getting only one result with the following query?

$query = craft()->db->createCommand();
$entryRecord = $query->select('craft_content.field_releaseDate, craft_content.title, craft_entries.id, craft_entries.dateCreated')->from('content')->join('entries', 'craft_content.elementId = craft_entries.id')->where('craft_entries.sectionId=2')->queryRow();

Also the documentation says that the table prefix isn't required, but this doesn't work most of the time, weird.

Completely untested but it looks like you're just querying a row instead of all.

Update queryRow() to queryAll()


Mapping plugin settings to checkboxes I'm struggling to figure out how to map an array of values in a plugins settings to a group of checkboxes:

protected function defineSettings()
{
    return array(
        'createGlobals' => array(
            AttributeType::Mixed, 'default' => array(
                "twitter" => true,
                "facebook" => true,
                "linkedIn" => true
                )
            )
        );
}

Here's one checkbox in my plugins template:

{{  forms.checkboxField({
  label: "Twitter"|t,
  name: '???',
  value: 'on',
  checked: settings.createGlobals.twitter
}) }}

As you can see, I've omitted the name value. Is there any way of mapping this name to the settings.createGlobals object?

Sure:

{{  forms.checkboxField({
      label: "Twitter"|t,
      name: 'createGlobals[twitter]',
      value : 'on',
      checked: settings.createGlobals.twitter
}) }}


Error With ContactForm Plugin - Internal Server Error Using,
https://github.com/pixelandtonic/ContactForm

I recently migrated the server to a new server and now i get:

2015/12/03 19:21:27 [error] [exception.phpmailerException] exception 'phpmailerException' with message 'SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting' in C:\inetpub\wwwroot\craft\app\vendor\phpmailer\phpmailer\class.phpmailer.php:1256 Stack trace:
#0 C:\inetpub\wwwroot\craft\app\vendor\phpmailer\phpmailer\class.phpmailer.php(1100): PHPMailer->smtpSend('Date: Thu, 3 De...', 'This is a multi...')
#1 C:\inetpub\wwwroot\craft\app\vendor\phpmailer\phpmailer\class.phpmailer.php(1004): PHPMailer->postSend()
#2 C:\inetpub\wwwroot\craft\app\services\EmailService.php(435): PHPMailer->send()
#3 C:\inetpub\wwwroot\craft\app\services\EmailService.php(77): Craft\EmailService->_sendEmail(Object(Craft\UserModel), Object(Craft\EmailModel), Array)
#4 C:\inetpub\wwwroot\craft\plugins\contactform\services\ContactFormService.php(54): Craft\EmailService->sendEmail(Object(Craft\EmailModel))
#5 C:\inetpub\wwwroot\craft\plugins\contactform\controllers\ContactFormController.php(100): Craft\ContactFormService->sendMessage(Object(Craft\ContactFormModel))
#6 C:\inetpub\wwwroot\craft\app\framework\web\actions\CInlineAction.php(49): Craft\ContactFormController->actionSendMessage()
#7 C:\inetpub\wwwroot\craft\app\framework\web\CController.php(308): CInlineAction->runWithParams(Array)
#8 C:\inetpub\wwwroot\craft\app\framework\web\CController.php(286): CController->runAction(Object(CInlineAction))
#9 C:\inetpub\wwwroot\craft\app\framework\web\CController.php(265): CController->runActionWithFilters(Object(CInlineAction), Array)
#10 C:\inetpub\wwwroot\craft\app\framework\web\CWebApplication.php(282): CController->run('sendMessage')
#11 C:\inetpub\wwwroot\craft\app\etc\web\WebApp.php(805): CWebApplication->runController('contactForm/sen...')
#12 C:\inetpub\wwwroot\craft\app\etc\web\WebApp.php(275): Craft\WebApp->_processActionRequest()
#13 C:\inetpub\wwwroot\craft\app\framework\base\CApplication.php(184): Craft\WebApp->processRequest()
#14 C:\inetpub\wwwroot\craft\app\index.php(62): CApplication->run()
#15 C:\inetpub\wwwroot\public\index.php(14): require_once('C:\inetpub\wwwr...')
#16 {main} REQUEST_URI=/contact HTTP_REFERER=https://soho.infor.com/contact
--- 2015/12/03 19:21:27 [error] [application] SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

Is, Some application not installed? Or something not configured? Or could it be a matter that this site requires authentication now to hit it in the browser (https redirects)?

Additionally where is the SMTP server configured?

-Tim

Craft's email SMTP settings are configured under Settings->Email in the control panel.

The error message you're getting:

2015/12/03 19:21:27 [error] [exception.phpmailerException] exception 'phpmailerException' with message 'SMTP connect() failed.

Simply means that PHP/Craft can't connect (for whatever reason) to the server you specified with whatever SMTP settings you've entered in Settings->Email.

Chances are the credentials are invalid or the settings are incorrect, but it can also happen is something (firewall, router, etc.) is blocking output SMTP access as well.


How to calculate average age members We are building a family community website with 600+ members.

One of the gimmicks will be some stats, like average age all members.

Is there a smart way to calculate this?

I don't think this will exactly answer your question, but I think it will help get you going in the right direction.

Within my application, I am grabbing entries that belong to the currently logged in user - finding the fields and then displaying an average distance.

If you'll notice I am setting a level': 2 in my parameters. That's because I am working with a structure and the first level is the "parent" entry that does not have any of the data I am attempting to average.

{# Get all of the entries entered by the user. #}
{% set entries = craft.entries({
    'section': 'mySection',
    'level': 2,
    'descendantOf': user.id
}) %}

{% if entries|length %}

    ...

    {% set value = 0 %}
    {% set count = 0 %}

    {% for entry in entires %}
        {% set value = value + entry.distance %}
        {% set count = loop.index %}
    {% endfor %}

    {% set averageDistance = (value / count)|round(1, 'floor') %}

Avg: {{ averageDistance }}

    ...

{% else %}
    {# Could not find any entries. #}
{% endif %}

So in a nutshell, you'll want to:

grab the entries from the appropriate section
find the field(s) you want to average ex: distance
do math
return the result

For you (this is a stab in the dark) you would want to get all users, get the value of the age field. Then loop over to get your count and divide that by the ages.

Hope this helps!


How can I use multi-environment configuration to set each root URL? I'm building www.mynewcraftsite.com.au, but I also wanna create www.mynewcraftsite.dev which is a testing server to preview to my clients. I've heard that I can set this up with Craft without going through the drudgery of downloading/uploading databases and updating urls in the db, users ... etc.

I've been reading the Craft CMS documentation for "Multi-Environment Configs".  So far I've got this in my db.php file;

return array(
    //All environments
    '*' => array(
        'omitScriptNameInUrls' => true,
        'localhost' or '127.0.0.1'.
        'server' => 'localhost',
        'user' => 'dashing-print',
        'password' => 'f#$njEwFRn3&2',
        'database' => 'dashing-print',
        'tablePrefix' => 'craft'
    ),

    //Testing environment
    'www.mynewcraftsite.dev' => array(
        'siteUrl' => 'www.dashingprint.dev'
    ),

    //Live environment
    'www.mynewcraftsite.com.au' => array(
        'siteUrl' => 'www.dashingprint.com.au'
    )
);

It works EXCEPT when I go to www.mynewcraftsite.dev and then click on the links, I end up back on www.mynewcraftsite.com.au (eg. Instead of going to www.mynewcraftsite.dev/services, I go to www.mynewcraftsite.com.au/services. In order to get to the correct page I gotta write up the whole url www.mynewcraftsite.dev/service into the google chrome url bar.)

The siteURL property isn't doing anything, there's gotta be something else that I gotta stick in there in order to rewrite the urls.

Make sure to change the "Site URL" setting to {siteUrl} in your control panel settings...

  Control Panel > Settings > General > "Site URL"

Within your config file, you'll also want to put your siteUrl value inside of an Environment-Specific Variables sub-array:

'mynewcraftsite.dev' => array(
    'devMode' => true,
    'environmentVariables' => array(
        'siteUrl' => 'http://www.mynewcraftsite.dev/'
    )
),
'mynewcraftsite.com.au' => array(
    'environmentVariables' => array(
        'siteUrl' => 'http://www.mynewcraftsite.com.au/'
    )
)

Here's how Craft is compiling all of that...

Within each of your environment configurations, there are many config settings that you can apply to that specific environment. Additionally, each environment can have a sub-array called environmentVariables, which allows you to set whatever unique variables you want. The most common examples are siteUrl and fileSystemPath (great for setting up assets sources), but you can truly set whatever environment variables you want.

Once you've set the siteUrl value in your environment variables array, you now need to use that value... This is where the control panel settings page comes into play. Changing "Site URL" to simply {siteUrl} tells Craft to pull that value from your environment variables.

IMPORTANT: Notice the single set of curly braces, and the lack of spacing between the variable name and the braces. This is the syntax difference between environment variables and Twig variables.

That's it! When you create a path, Craft will use whatever is in the "Site URL" setting. And since that's pulling in your environment variable, that's what you'll get.

Lastly, allow me to point out a few things in your example which may also be stopping this from working for you (feel free to update the example in your question to fix these issues)...

Most importantly: You're combining data that should be stored in two separate files... craft/config/db.php and craft/config/general.php. While the multi-environment format is the same, you'll need to separate the data shown in your example. Put most of your settings into general.php, only the following belong in db.php:

server
user
password
database
tablePrefix

You also have an errant line of code in your example... This line should definitely be removed:

'localhost' or '127.0.0.1'.

Finally, you've left some crucial security information in your example... All of your database connection info is exposed (as well as your true domain names in your siteUrl examples).

Hope that helps... If you fix the bugs in your example code, I'll remove my corresponding notes from this answer. :)


How would I allow guests to add comments and ratings to existent entries? I have a page with a bunch of images that I'd like people to rate and comment on.  The rating would be a select custom field, and the comment would be a simple textarea custom field.

I'd like to allow guests to submit their ratings and comments, but the Guest Entries plugin doesn't seem to handle editing.

Any ideas how to get this to work?

Using the Guest Entries plugin, it is not possible. Using a custom plugin is possible though. The trick is that each guest needs to be identifiable in some way. Otherwise every guest would be able to edit every comment, and you would have chaos (or a wiki).

So if you want them to be able to edit a comment and still not have to log in, you can create a custom plugin that replicates much of the functionality of the Guest Entries plugin. Adding on to that, you could create a unique string stored in a separate table linked to that entry. This string would be used to give the anonymous user a unique edit link. This would keep the comment reasonably safe.

Though in all honesty, you would be better served by having users log in or using an external commenting service (if you are avoiding buying a higher Craft version).


How can I set the isCompleted status of an order from within a custom module? The default behaviour for commerce is to mark the isCompleted flag on an order to true once the order has been paid for.

I have need to alter this behaviour and only want to mark an order as Complete via manual intervention of a site admin - or after a predefined date has passed.

Is it possible to set the isCompleted flag from within a custom module?
Right now, I'm listening to the EVENT_AFTER_ORDER_PAID then attempting to set the isCompleted flag and save the order.

What I can't figure out is how to save the order!

Code so far, for what it's worth:

Event::on(
            Order::class,
            Order::EVENT_AFTER_ORDER_PAID,
            function(Event $e) {
                $order = $e->sender;

                $order->isCompleted = false; // no idea if this is correct

                $order->saveOrder(); // this doesn't work
            }
        );

This can be achieved with

Event::on(
            Order::class,
            Order::EVENT_AFTER_COMPLETE_ORDER,
            function(Event $e) {

                $order = $e->sender;

                $order->isCompleted = false;
                Craft::$app->getElements()->saveElement($order, false);

            }
        );

But I'm not sure it's actually a good idea anyway.


net::ERR_CONTENT_LENGTH_MISMATCH for CP after enabling compression Also: https://plus.google.com/111272585078935192473/posts/5qNuffv3SKp which seems to be a similar problem.

I’m with a hoster where compression for PHP scripts must be enabled in php.ini adding zlib.output_compression = On to it.

After restarting the front end gets compressed as exprected, but the CP breaks, throwing net::ERR_CONTENT_LENGTH_MISMATCH for all resources (css, js etc.) which causes them not to be loaded. I have spoken with the hoster but they are unsure about this.

What is to do?
How can i get compression for my website without breaking the Control Panel?

Is there something i can do on my end?

I think we've just found a workaround for this in the upcoming 2.3 release. :)


Output specific entry from entries field based on position I have an entries field in a section, I am looking to output a certain selected entry from this field based on its position.

For example I want to out the 2nd or 3rd entry only from this entry field, what is the best way to do this without calling all the entries and looping through them all?

{% set allEntries = entry.entriesSelector.all() %}

First: {{ allEntries[0].title }}

Second: {{ allEntries[1].title }}

Fourth: {{ allEntries[3].title }}

Last: {{ allEntries|reverse[0].title }}