<p>So this is REAL ugly I think...and perhaps there's a better way to do it, but this is what I ended up with. Again, I've only been working with craft for a few weeks, so please tell me if there is a better way.</p>
<pre class="lang-php prettyprint-override"><code>{% set productSegment = craft.app.request.getSegment(2) %}
{% set productDetailSegment = craft.app.request.getSegment(4)  %}

{% if productDetailSegment is not null %}
    {% set parentProduct = craft.entries.section('products').level(2).slug(productSegment).one() %}
    {% set entry = craft.entries.section('products').level(3).descendantOf(parentProduct).slug(&quot;details&quot;).with(['flexibleContent','productDetails']).one() %}
{% endif %}
</code></pre>
<p>The <code>with</code> function was the key to getting my missing Matrix and Entries fields.</p>
<p>This successfully resets my <code>entry</code> var so that it exists in the correct context.</p>
<p>Again, if there's a better way to do this with routing (as I said initially -- someway of ignoring the final segment without losing the entry var -- PLEASE point me in the right direction, because this seems really kludgy).</p>

CC BY-SA 4.0
2022-02-11T19:56:10.337Z
2022-02-11T19:56:10.337Z
kevindeleon
<p>I have a Structure - <code>Products</code> - that contains multiple products, and each product contains different sub pages (details, pricing, etc).</p>
<p>One section of the Structure is <code>Details</code> which is under each product.</p>
<p>The url structure is <code>/products/{product}/details</code> where <code>{product}</code> is the various products in the Structure.</p>
<p><code>Details</code> entry has an Entries field in it called <code>Details</code> that contains entries from a Channel that I'm essentially using as a data silo called <code>Product Details</code> that stores details about the various products.</p>
<p>This all works fine and if I load an entry at <code>/products/x-product/details</code> I have access to the Details associated with the Details entry as expected.</p>
<p>As part of this particular template, I want to be able to have a fourth segment like:</p>
<p><code>/products/x-product/details/specific-detail</code> -- where <code>specific-detail</code> is the slug of a specific channel detail</p>
<p>I've setup a route like so in <code>config/routes.php</code>:</p>
<p><code>'products/&lt;entrySlug:{slug}&gt;/details/&lt;detailSlug&gt;' =&gt; ['template' =&gt; 'products/_types/details']</code></p>
<p>And it loads the the <code>details</code> template fine...however... the <code>details</code> template extends a main layout that is used across the entire site, and that layout uses the <code>entry</code> variable which it is saying doesn't exist.</p>
<p>I need the <code>Details</code> entry var from the Structure to load as the <code>entry</code>, and for the final route (<code>detailSlug</code>) to be passed through unchanged/ignored to the <code>details</code> template so that I can just grab it via <code>craft.app.request.getSegment()</code> function and process/use it accordingly inside the template.</p>
<p>I could obviously do this with a url param, but I want to be able to do it with an actual segment for various reasons (one being SEO).</p>
<p><strong>UPDATE:</strong> OK, so I think I'm getting close -- I can maybe reset the &quot;entry&quot; variable to the Details entry -- but is there a way to grab a specific child of an entry in a Structure if all I have is the slug of the Parent? So like <code>set entry = craft.entries.section('products').slug(&quot;product-x&quot;).child(&quot;details&quot;)</code> ?</p>
<p>I know that specifc query won't work...but is there something like that? Consider the structure looks like:</p>
<pre><code>Products
- Product 1
  -- Details
  -- Pricing
  -- etc
- Product 2
  -- Details
  -- Pricing
  -- etc
</code></pre>
<p><strong>UPDATE 2:</strong> I've figured out a way to grab the specific entry I need and reset the entry var -- but some of the fields are null -- I did a <code>dd</code> on it, and I can see it's the correct object (correct ID and all) -- but my matrix field and entries fields are null. My other custom fields (text fields) are there and have the correct info in them.</p>
<p>This is the queries I ended up with:</p>
<pre><code>{% set parentProduct = craft.entries.section('products').level(2).slug(productSegment).one() %}
{% set entry = craft.entries.section('products').level(3).descendantOf(parentProduct).slug(&quot;details&quot;).one() %}
</code></pre>

CC BY-SA 4.0
2022-02-12T18:38:57.260Z
Noting re: `null` values when dumping an Entry object—this is the expected behavior, and not a consequence of your approach. I believe it's just a limitation of the Query classes (the initial value for Relation and Matrix fields) and how PHP represents them as strings when debugging. Calling `entry.flexibleContent.all()`, will get the data you're looking for!
August Miller
CC BY-SA 4.0
2022-02-12T18:41:45.087Z
Also worth noting that you can do a generic sort of "protection" routine in your layout so that when `entry` is not defined on a particular template (like the 404 page), it will just exit silently—this could be at output time (`<meta name="description" content="{{ entry.shortDescription ?? 'My default description!' }}">`), or guarding an entire block of output (`{% if entry is defined %} ... {% endif %}`).
August Miller
<craft3><templating><routes>
How can I use the final URI segment as an argument without losing the entry variable?
# How can I use the final URI segment as an argument without losing the entry variable?

(Asked by: username_0 on 2022-02-11)

I have a Structure - Products - that contains multiple products, and each product contains different sub pages (details, pricing, etc).
One section of the Structure is Details which is under each product.
The url structure is /products/{product}/details where {product} is the various products in the Structure.
Details entry has an Entries field in it called Details that contains entries from a Channel that I'm essentially using as a data silo called Product Details that stores details about the various products.
This all works fine and if I load an entry at /products/x-product/details I have access to the Details associated with the Details entry as expected.
As part of this particular template, I want to be able to have a fourth segment like:
/products/x-product/details/specific-detail -- where specific-detail is the slug of a specific channel detail
I've setup a route like so in config/routes.php:
'products//details/' => ['template' => 'products/_types/details']
And it loads the the details template fine...however... the details template extends a main layout that is used across the entire site, and that layout uses the entry variable which it is saying doesn't exist.
I need the Details entry var from the Structure to load as the entry, and for the final route (detailSlug) to be passed through unchanged/ignored to the details template so that I can just grab it via craft.app.request.getSegment() function and process/use it accordingly inside the template.
I could obviously do this with a url param, but I want to be able to do it with an actual segment for various reasons (one being SEO).
UPDATE: OK, so I think I'm getting close -- I can maybe reset the "entry" variable to the Details entry -- but is there a way to grab a specific child of an entry in a Structure if all I have is the slug of the Parent? So like set entry = craft.entries.section('products').slug("product-x").child("details") ?
I know that specifc query won't work...but is there something like that? Consider the structure looks like:
Products
- Product 1
  -- Details
  -- Pricing
  -- etc
- Product 2
  -- Details
  -- Pricing
  -- etc

UPDATE 2: I've figured out a way to grab the specific entry I need and reset the entry var -- but some of the fields are null -- I did a dd on it, and I can see it's the correct object (correct ID and all) -- but my matrix field and entries fields are null. My other custom fields (text fields) are there and have the correct info in them.
This is the queries I ended up with:
{% set parentProduct = craft.entries.section('products').level(2).slug(productSegment).one() %}
{% set entry = craft.entries.section('products').level(3).descendantOf(parentProduct).slug("details").one() %}

**Tags:** craft3, templating, routes

> **Comments:**
> **username_1**: Noting re: `null` values when dumping an Entry object—this is the expected behavior, and not a consequence of your approach. I believe it's just a limitation of the Query classes (the initial value for Relation and Matrix fields) and how PHP represents them as strings when debugging. Calling `entry.flexibleContent.all()`, will get the data you're looking for!  
> **username_1**: Also worth noting that you can do a generic sort of "protection" routine in your layout so that when `entry` is not defined on a particular template (like the 404 page), it will just exit silently—this could be at output time (`<meta name="description" content="{{ entry.shortDescription ?? 'My default description!' }}">`), or guarding an entire block of output (`{% if entry is defined %} ... {% endif %}`).  

---

## 1 answers

### Answer by username_0 on 2022-02-11. Score: 1 | Accepted answer

So this is REAL ugly I think...and perhaps there's a better way to do it, but this is what I ended up with. Again, I've only been working with craft for a few weeks, so please tell me if there is a better way.
{% set productSegment = craft.app.request.getSegment(2) %}
{% set productDetailSegment = craft.app.request.getSegment(4)  %}

{% if productDetailSegment is not null %}
    {% set parentProduct = craft.entries.section('products').level(2).slug(productSegment).one() %}
    {% set entry = craft.entries.section('products').level(3).descendantOf(parentProduct).slug("details").with(['flexibleContent','productDetails']).one() %}
{% endif %}

The with function was the key to getting my missing Matrix and Entries fields.
This successfully resets my entry var so that it exists in the correct context.
Again, if there's a better way to do this with routing (as I said initially -- someway of ignoring the final segment without losing the entry var -- PLEASE point me in the right direction, because this seems really kludgy).


---

