3

I have blog articles set up on the site i'm working on to be built using a matrix, much the same way as in the features video about the matrix field. So it is entirely possible for an article to start with an image or a video.

What i'd like to be able to do is find the first text entry in the matrix and pull the first 155 characters out of it, creating an excerpt. The point of this is to pass that into a meta og:description tag (and i guess meta description too!)

Is it possible to do that with matrix content?

5

You can filter by block type: http://buildwithcraft.com/docs/matrix-fields#filtering-by-block-type

In short:

{% set ogDescription = false %}

{% for block in entry.myMatrixField.type('richText').limit(1) %}
  {% set ogDescription = block.text | striptags | slice(0, 155) %}
{% endfor %}

{% if ogDescription %}
  ...
{% endif %}

Also, this was suggested in the comments:

{{ entry.myMatrixField.type('richText').first() | striptags | slice(0, 155) }}
| improve this answer | |
  • Very cool! I tried it before you made edits and it output to the screen just fine. However if i try it now i get Unexpected tag name "assign". I tried changing it to set and i get no error, but no output either (using {{ ogDescription }}) – Dan Owen Feb 20 '15 at 15:31
  • Opps, my mistake. I'll change assign to set. Are you sure the handle of the field you're trying to get is named "text"? I was just trying to make it a little less error prone haha. – Bill Criswell Feb 20 '15 at 15:37
  • It doesn't output anything for me if i use set. If i try removing the if defined and just put {{ ogDescription }} after the for loop, i get the error "Variable "ogDescription" does not exist". Yep my block is just called text. The code you posted worked fine when it was just straight up outputting the value (before you added the assign / set etc) so... when it was this "{{ block.text | striptags | slice(0, 155) }}" – Dan Owen Feb 20 '15 at 15:40
  • Ok, i discovered if i put the if is defined inside the for loop, it works! But that wont work for passing the variable to my _layout template. Not sure how to pass that variable outside of the for loop...! – Dan Owen Feb 20 '15 at 15:54
  • 2
    for loops are scoped in Twig. So you have to set it before the loop. But in this cause I'd rather use first() method to get the first block of this type. – carlcs Feb 20 '15 at 16:08
2

We've designed Sprout SEO to help you handle situations like these. Personally, I think it's the easiest path to take for dealing with this situation. So, my first answer would be to consider using it.

There is an example on how to assign meta values in included Matrix blocks in the Sprout SEO docs here Extending a Base Layout


But, this is a question on StackExchange so that answer alone is unsatisfying. If you'd like to dig into solving this issue yourself, to start, I'd recommend you try to get the best understanding you can of the Twig Processing Order. While part of the challenge your facing is how to grab the specific text you need from the field variable (Bill Chriswell's answer addresses that), another part of it may be where your variable exists in your templates.

For example, if you are managing your variables in a parent _layout template and trying to assign your excerpt within a block tag extending it, you're description variable is getting set after you are outputting your meta variables.

So, however you are assigning your meta variables you need to make sure that you are assigning the description variable in a way that it gets updated before you are actually outputting the meta values in your header.

I'll quote a couple paragraphs from the Twig Processing Order article linked above:

[T]he Twig processing order flows down the page. Variables are processed and become available farther down the page to be output. Sometimes however, we can only determine a value farther down the page, and the value itself needs to be output higher on the page.

Out of the box, some scenarios like this can be handled by Twig but things can get messy quick, and code that once felt dry can begin to feel harder to maintain. Other scenarios simply can't be solved without extending Twig or managing your variable with the help of a plugin.

Here are three methods mentioned in the article to consider if you want to get around this:

  1. Try to set your variables as high on the page as you can. Even arrays of data can be queried and set as variables higher on the page. Once a variable exists, it's much easier to refer to that variable anywhere below it's first instance in your templates.
  2. Create your page variables in a plugin. Craft allows you to set up routes to point to a Controller action instead of a page template.
  3. Consider building a plugin and and managing the variable of the content you need access to in a Twig Global or public variable in the service layer of your plugin.
| improve this answer | |
  • Wow! Pretty comprehensive Ben :^) The method Bill suggested above works for me though. I had to declare the variable as blank outside of the for loop first and then it all works. – Dan Owen Feb 20 '15 at 16:09
  • "[if you are] trying to assign your excerpt within a block tag extending [a parent _layout template]" – you can use the set tag outside of blocks to pass vars to the parent template. – carlcs Feb 20 '15 at 16:24
  • Good clarification @carlcs. Dan Owen, glad you have it working. Out of curiosity, are you extending a layout or is everything just in one template? – Ben Parizek Feb 20 '15 at 17:03
  • Extending a layout. So in my articles/_entry template i have Bill's code from above (before my {% block content %}) and before Bill's code i set the variable as blank. Then in _layout i'm calling ogDescription in my <head> – Dan Owen Feb 20 '15 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.