<p>Twig's <code>|trim</code> filter is just a wrapper for PHP's <a href="https://secure.php.net/manual/en/function.trim.php" rel="nofollow noreferrer"><code>trim()</code></a> method, which says:</p>

<blockquote>
  <p>Strip whitespace (or other characters) from the beginning and end of a string</p>
</blockquote>

<p>So in your example, you're telling it to strip all <code>/</code> and <code>2</code> from the beginning and end of the given string, which explains the output you're seeing.</p>

<p>I think you'll be better off by installing something like the <a href="https://github.com/victor-in/Craft-TwigPCRE" rel="nofollow noreferrer">Twig PCRE</a> plugin, which gives Twig full access to the PHP <code>preg_</code> regex methods.</p>

<p>Then you'd just do a <code>preg_match</code> to target exactly what you're looking for and replacing it with new values as necessary.</p>

CC BY-SA 3.0
2017-11-28T14:31:58.610Z
Ahhh I see! Ok yeah, this isn't going to work then. The better solution obviously is to use the filter names/handles instead of ids in the url, but I didn't want to start doing larger changes like that if I didn't have to. But, it looks like that'll be the way to go. I'll mark this as accepted answer.
jkilp
CC BY-SA 3.0
2017-11-27T22:23:18.337Z
2017-11-27T22:23:18.337Z
Brad Bell
<p>Instead of doing complicated things with the result of <code>getLastSegment()</code>, can't you just get the 4th segment using <code>getSegment(4)</code>?</p>

<p>If the segment you’re interested in is not always in the same position, you could use <code>getSegments()</code> and conditionally grab a part depending on count of segments returned.</p>

<pre><code>{% set segments = craft.request.getSegments() %}
{% set filter = segments|length == 4 ? segments[3] : segments[1] %}
</code></pre>

CC BY-SA 3.0
2017-11-28T14:29:50.480Z
Unfortunately, no. The number of segments changes. The default url when you load the page (with filters applied) would be `example.com/month/1`  So it omits the date segments from the url. You don't see the date segments until you start changing the date on the calendar.
jkilp
CC BY-SA 3.0
2017-11-28T17:23:35.407Z
@jkilp updated my answer to account for that case
carlcs
CC BY-SA 3.0
2017-11-28T00:06:05.663Z
2017-11-28T17:25:42.057Z
2017-11-28T17:25:42.057Z
carlcs
<pre><code>{{ entry.url|split('/')[:-1]|join('/') }}
</code></pre>
<p>This splits the url string into an array, uses the syntactic sugar version of the <a href="https://twig.symfony.com/doc/3.x/filters/slice.html" rel="nofollow noreferrer">slice filter</a> to cut the last item off, then joins them back together as a string.</p>
<p>Could also do <code>/{{ craft.app.request.segments[:-1]|join('/') }}</code> depending on your use case.</p>

CC BY-SA 4.0
2023-10-23T21:44:02.833Z
2023-10-23T21:44:02.833Z
Brimby
<p>I am fairly new to twig and templating with Craft (and I have inherited this code, so that makes it even more fun).</p>

<p>I have a calendar page that lets you filter the events in the calendar based on a venti group (using the <a href="https://venticalendar.io/docs/groups.html" rel="nofollow noreferrer">Venti Calendar</a> plugin to create those groups).</p>

<p>How it currently works is that whatever group filter is selected, the url updates to have that group ID as the last segment. </p>

<p><strong>Filter Names and their IDs: Cinema = 1, Theatre = 2, Events = 3, Education = 4</strong></p>

<p>If a user is looking at the events for the month of December 2017 with no filters, the url looks like this:</p>

<p><code>example.com/month/2017/12</code></p>

<p>If a user is looking at the events for the same date, but has a filter applied (in this case, the "Cinema" filter), the url looks like this:</p>

<p><code>example.com/month/2017/12/1</code> Cinema has group ID of <code>1</code> so 1 is the last segment.</p>

<p>In order to change the applied filter without resetting the date, I want to trim the last segment from the url, and replace with the new ID as the last segment. Doing this works completely as expected unless the last segment and the last character of the previous segment are the same number (e.g., <code>example.com/month/2017/12/2</code>).</p>

<p>In this case, if I am currently on this URL, and I want to change to a different filter (in this example we change to use Cinema Filter = 1), the following happens.</p>

<p><code>example.com/month/2017/1/1</code> where it should actually be <code>example.com/month/2017/12/1</code></p>

<p>So what is happening is that it is trimming the <code>2</code> from the last segment and the segment before the last segment.</p>

<p>Here's the code for the filter buttons:</p>

<pre><code>    {% set groups = craft.venti.groups() %}
    {% for group in groups %}      
        &lt;a class="button" href="
            {% spaceless %}
            {% if craft.request.getLastSegment() in ['1','2','3','4'] %}       
                {{url(craft.request.path)|trim('/' ~ 
                craft.request.getLastSegment())}}/{{group.id}}
            {% else %}
                {{url(craft.request.path)}}/{{group.id}}
            {% endif %}
            {% endspaceless %}"&gt;
            {{ group }}
        &lt;/a&gt;
    {% endfor %}
</code></pre>

<p>If I remove <code>'/' ~</code> from this: 
<code>{{url(craft.request.path)|trim('/' ~ craft.request.getLastSegment())}}/{{group.id}}</code></p>

<p>It actually works perfectly, save for the fact that the new url looks like this: <code>example.com/month/2017/12//1</code> With the addition of that second backslash.</p>

<p>Can anyone see what I am doing wrong here, or provide any help? If you need more of my code, please let me know.</p>

<p>Thank you!</p>

<templating><filter><segments><calendar><plugin-ventievents>
Trimming lastSegment from a URI trims that PLUS the last number of the previous segment
# Trimming lastSegment from a URI trims that PLUS the last number of the previous segment

(Asked by: username_0 on 2017-11-27)

I am fairly new to twig and templating with Craft (and I have inherited this code, so that makes it even more fun).
I have a calendar page that lets you filter the events in the calendar based on a venti group (using the Venti Calendar plugin to create those groups).
How it currently works is that whatever group filter is selected, the url updates to have that group ID as the last segment. 
Filter Names and their IDs: Cinema = 1, Theatre = 2, Events = 3, Education = 4
If a user is looking at the events for the month of December 2017 with no filters, the url looks like this:
example.com/month/2017/12
If a user is looking at the events for the same date, but has a filter applied (in this case, the "Cinema" filter), the url looks like this:
example.com/month/2017/12/1 Cinema has group ID of 1 so 1 is the last segment.
In order to change the applied filter without resetting the date, I want to trim the last segment from the url, and replace with the new ID as the last segment. Doing this works completely as expected unless the last segment and the last character of the previous segment are the same number (e.g., example.com/month/2017/12/2).
In this case, if I am currently on this URL, and I want to change to a different filter (in this example we change to use Cinema Filter = 1), the following happens.
example.com/month/2017/1/1 where it should actually be example.com/month/2017/12/1
So what is happening is that it is trimming the 2 from the last segment and the segment before the last segment.
Here's the code for the filter buttons:
    {% set groups = craft.venti.groups() %}
    {% for group in groups %}      
        
            {{ group }}
        
    {% endfor %}

If I remove '/' ~ from this: 
{{url(craft.request.path)|trim('/' ~ craft.request.getLastSegment())}}/{{group.id}}
It actually works perfectly, save for the fact that the new url looks like this: example.com/month/2017/12//1 With the addition of that second backslash.
Can anyone see what I am doing wrong here, or provide any help? If you need more of my code, please let me know.
Thank you!

**Tags:** templating, filter, segments, calendar, plugin-ventievents


---

## 3 answers

### Answer by username_1 on 2017-11-27. Score: 2 | Accepted answer

Twig's `|trim` filter is just a wrapper for PHP's [`trim()`](https://secure.php.net/manual/en/function.trim.php) method, which says:

> Strip whitespace (or other characters) from the beginning and end of a string

So in your example, you're telling it to strip all `/` and `2` from the beginning and end of the given string, which explains the output you're seeing.

I think you'll be better off by installing something like the [Twig PCRE](https://github.com/victor-in/Craft-TwigPCRE) plugin, which gives Twig full access to the PHP `preg_` regex methods.

Then you'd just do a `preg_match` to target exactly what you're looking for and replacing it with new values as necessary.

> **Comments:**
> **username_0**: Ahhh I see! Ok yeah, this isn't going to work then. The better solution obviously is to use the filter names/handles instead of ids in the url, but I didn't want to start doing larger changes like that if I didn't have to. But, it looks like that'll be the way to go. I'll mark this as accepted answer.  

---

### Answer by username_2 on 2017-11-28. Score: 1

Instead of doing complicated things with the result of getLastSegment(), can't you just get the 4th segment using getSegment(4)?
If the segment you’re interested in is not always in the same position, you could use getSegments() and conditionally grab a part depending on count of segments returned.
{% set segments = craft.request.getSegments() %}
{% set filter = segments|length == 4 ? segments[3] : segments[1] %}

> **Comments:**
> **username_0**: Unfortunately, no. The number of segments changes. The default url when you load the page (with filters applied) would be `example.com/month/1`  So it omits the date segments from the url. You don't see the date segments until you start changing the date on the calendar.  
> **username_2**: @username_0 updated my answer to account for that case  

---

### Answer by username_3 on 2023-10-23. Score: 1

{{ entry.url|split('/')[:-1]|join('/') }}

This splits the url string into an array, uses the syntactic sugar version of the slice filter to cut the last item off, then joins them back together as a string.
Could also do /{{ craft.app.request.segments[:-1]|join('/') }} depending on your use case.


---

