Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-28T14:31:58.610Z
Answers.Text: 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.
Answers.UserDisplayName: jkilp
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-27T22:23:18.337Z
Answers.LastActivityDate: 2017-11-27T22:23:18.337Z
Answers.UserDisplayName: Brad Bell
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-28T14:29:50.480Z
Answers.Text: 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.
Answers.UserDisplayName: jkilp
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-28T17:23:35.407Z
Answers.Text: @jkilp updated my answer to account for that case
Answers.UserDisplayName: carlcs
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-11-28T00:06:05.663Z
Answers.LastActivityDate: 2017-11-28T17:25:42.057Z
Answers.LastEditDate: 2017-11-28T17:25:42.057Z
Answers.UserDisplayName: carlcs
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-10-23T21:44:02.833Z
Answers.LastActivityDate: 2023-10-23T21:44:02.833Z
Answers.UserDisplayName: Brimby
Body: <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>
  
Tags: <templating><filter><segments><calendar><plugin-ventievents>
Title: Trimming lastSegment from a URI trims that PLUS the last number of the previous segment
ThreadText: # 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](https://venticalendar.io/docs/groups.html) 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 %}      
          <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 %}">
              {{ group }}
          </a>
      {% 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](https://twig.symfony.com/doc/3.x/filters/slice.html) 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.
  
  
  ---
  
  