# Redirect to new slug in Page.update:after?

**URL:** <https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982>\
**Category:** Questions\
**Created:** [March 2, 2024, 4:04pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982 "2024-03-02T16:04:00Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 2, 2024, 4:04pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/1 "2024-03-02T16:04:00Z")

</div>

**Question:**  
How do I redirect to a newly updated page slug after updating the page’s slug?

**Situation:**  
I have a page called Work with subpages called project - each project’s title and url appendix is generated from two fields; Client and project title.

On the project page I can update either client or project title which correctly set the new title and slug but I am unable to redirect to the new page.

**Project.yml blueprint:**

```auto
#
# Blueprint for Projects
#
# page title
title: Project
# options for when creating a new work projects
create:
  title: "{{ page.client }} – {{ page.project }}"
  fields:
    - client
    - project
  slug: "{{ page.client }}-{{ page.project }}"

# options for available status options
status:
  listed: Published
  draft: Draft
  unlisted: Unlisted

#
# Content
#
tabs:
  #
  # TAB 1 - content
  #
  content:
    label: Content
    icon: text
    columns:
      # layout
      media:
        width: 1/2
        fields:
          #
          # Project - media
          #
          mediaGallery:
            type: files
            layout: cards
            size: medium
            label: Project Media
            uploads: false
            help: select media, to upload see storage tab.
            sortable: true
            info: "{{ file.template }}"
      #
      # Project - information
      #
      information:
        width: 1/2
        fields:
          #
          # Project - client
          #
          client:
            label: Project client
            width: 1/2
            type: select
            required: true
            placeholder: select client
            help: Select client for project, or create new under Work > Settings
            options:
              type: query
              query: site.find("work").clients.toStructure
              text: "{{ item.clientname }}"
              value: "{{ item.clientname }}"
          #
          # Project - title
          #
          project:
            label: project title
            width: 1/2
            type: text
            help: Enter the project name
            required: true
          #
          # Project - url
          #
          project url:
            type: headline
            help: "{{ page.url }}"
          # break
          lineA:
            type: line
          #
          # Project - categories
          #
          tags:
            type: tags
            label: Categories
            min: 1
            accept: options
            help: Select one or more categories for the project, or create new under Work > Settings
            options:
              type: query
              query: site.find("work").categories.toStructure
              text: "{{ item.category }}"
              value: "{{ item.category }}"
          # break
          lineB:
            type: line
          #
          # Project - description
          #
          description:
            type: textarea
            size: small
            buttons: false
          toggleDisplayDescription:
            label: Hide description on project page?
            type: toggle
            help: Hide the description on the project page but will keep it for SEO.
            default: "no"
            options:
              - no
              - yes
          # break
          lineC:
            type: line
          #
          # Project - credit list
          #
          credits:
            label: Credit list
            type: structure
            fields:
              name:
                label: name
                type: text
              role:
                label: role
                type: text
              link:
                label: link
                type: url

  #
  # TAB 2 - media storage
  #
  storage:
    label: Media
    icon: import
    fields:
      #
      # Media - Image uploading section
      #
      imageMedia:
        label: Image upload
        help: Upload project images here.
        type: files
        layout: cards
        size: medium
        uploads: image
        info: "{{ file.template }}"
      # break
      lineD:
        type: line
      #
      # Media - Video uploading section
      #
      videoMedia:
        label: Video upload
        help: Upload project videos here.
        type: files
        layout: cards
        size: medium
        uploads: video
        info: "{{ file.template }}"
      # break
      lineF:
        type: line
      #
      # Media - Audio uploading section
      #
      audioMedia:
        label: Audio upload
        help: Upload project audio here.
        type: files
        layout: cards
        size: medium
        uploads: audio
        info: "{{ file.template }}"

```

**“Page.update:after” hook:**

```auto
"page.update:after" => function (
            Kirby\Cms\Page $newPage,
            Kirby\Cms\Page $oldPage
        ) {
            $client = $newPage->client()->value();
            $project = $newPage->project()->value();

            function convertText($inputText)
            {
                // Replace spaces with dashes
                $textWithDashes = str_replace(" ", "-", $inputText);

                // Convert non-English characters to Latin
                $latinText = iconv("UTF-8", "ASCII//TRANSLIT", $textWithDashes);

                return $latinText;
            }

            $cleanClient = convertText($client);
            $cleanProject = convertText($project);

            $newPage->changeTitle($client . " - " . $project);
            $newPage->changeSlug($client . " - " . $project);
        },

```

Any suggestions or hints would be greatly appreciated.

Kirby: 4.1.0  
PHP: 8.3.3  
Browser: Safari 17.3  
OS: Mac 14.3

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [March 2, 2024, 4:07pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/2 "2024-03-02T16:07:37Z")

</div>

The simple answer is: you can’t.

It’s better to overwrite the relevant methods in a page model, so Kirby can take care of the redirect.

---

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 2, 2024, 7:35pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/3 "2024-03-02T19:35:04Z")

</div>

argh right ok. I had a go at creating an update and it seems to work except it does not redirect correctly to the new page, it just shows a panel dialog with the old url and I’m not sure where I’m going wrong.

Do you have a suggestion?

```auto
public function update(
        ?array $input = null,
        ?string $languageCode = null,
        bool $validate = false
    ): static {
        parent::update($input, $languageCode, $validate); // Call parent update method

        if (isset($input["client"]) && isset($input["project"])) {
            $client = $input["client"];
            $projectTitle = $input["project"];

            $this->changeTitle($client . " - " . $projectTitle);
            $this->changeSlug($client . "-" . $projectTitle);

            // Get the URL of the updated page with the new slug
            $newUrl = $this->panel()->url("pages/" . $this->id());

            // Redirect to the updated page in the panel with the new slug
            Panel::go($newUrl);

            // Redirect to the updated page in the panel with the new slug
        }
        return $this; // Return an instance of ProjectPage
    }

```

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [March 2, 2024, 9:30pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/4 "2024-03-02T21:30:00Z")

</div>

Don’t redirect from there

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [March 2, 2024, 9:30pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/5 "2024-03-02T21:30:51Z")

</div>

Also, don’t call changeTitle/changeSlug from update

---

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 2, 2024, 10:16pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/6 "2024-03-02T22:16:02Z")

</div>

would it then be in the page.update:after hook?

---

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 2, 2024, 10:17pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/7 "2024-03-02T22:17:32Z")

</div>

I’m not following why that is not okay. Could you link to the docs on what I should use else?  
thank you

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [March 3, 2024, 9:31am UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/9 "2024-03-03T09:31:24Z")

</div>

Oh, sorry, I totally misread (and didn’t read your code properly). This is about the client and project being changed, and you want to change the title and slug accordingly.

---

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 3, 2024, 9:43am UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/10 "2024-03-03T09:43:31Z")

</div>

exactly yes 🙂

There are two fields on the blueprint ( client and project ) which is the ‘components’ for both the title and slug.

The title and slug format is always: Client name – Project name  
i.e. client could be _Kirby cms_ and project name could be _theme design_, Then the slug would be _kirby-cms-theme-design_

The client and project is set on the page creation dialogue but I also have it on the page it self and I would like to be able to change either client or project title and then the page title and slug update to match.

Do I need to create separate extensions to changeSlug and changeTitle, and then redirect to the new page through a page.update:after hook?

any help is much appreciated ! thank you

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [March 3, 2024, 10:15am UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/11 "2024-03-03T10:15:55Z")

</div>

As I said in one of the first post, you cannot redirect to the new pages from that hook. And in particular, you cannot call `go()` inside the update method, that method needs to return a page object.

However, updating the slug from the model doesn’t seem to be possible, it always results in an error.

So not sure if this is possible at all.

BTW: Unless you are using permalinks, changing the slug without having redirects in place is generally not such a good idea, I think, at least not once your pages are public and indexed by search engines.

---

<div class="post-metadata">

**Author:** ![studio](https://avatars.discourse-cdn.com/v4/letter/s/a8b319/32.png) [@studio](https://forum.getkirby.com/u/studio)\
**Post date:** [March 3, 2024, 12:18pm UTC](https://forum.getkirby.com/t/redirect-to-new-slug-in-page-update-after/30982/12 "2024-03-03T12:18:54Z")

</div>

Thank you for looking in to it for me!  
It’s not a deal breaker as I can just have it update the page title based on my fields and then manually have the slug change based on the title - that works as well.

As I mentioned when I create the page I will select client and project title and the likelihood of me having to change it later is slim, but it was just intended as a neat little helper feature 🙂

I’m familiar with the SEO-issues that can arise from changing the urls if indexed, but a good point 🙂
