Jump to content

Ok to change page name / path after save ?


john
 Share

Recommended Posts

I'm building a dealership website and have several vehicles of the same make-model.

I'd like to have the make, model name in the URL.

I'd like to add a link to create the page with a unique name using the api, then before it is saved, change the name to reflect the make-mode and unique id.

I know I can create a hook before the save event and add the make / model info. How can I add a link ( process ? ) to the admin to skip the manual entry of a page title / name when adding inventory?

Thanks.

Link to comment
Share on other sites

The name/title screen is something that can't be skipped because a page can't exist without at least having a name. That screen is what creates and initializes the page as something that can be populated by your fields. One example would be a files or images field, which can't be populated until the page exists and has an ID.

I'm not sure that I understand the full context of your need, so forgive my answer if it's not relevant…

But if you really want to skip the PageAdd screen, you could create a bunch of ready-to-go but unpublished pages:

for($n = 0; $n < 100; $n++) {
 $p = new Page();
 $p->template = 'vehicle';
 $p->parent = '/vehicles/';
 $p->status = Page::statusUnpublished;
 $p->title = "Unused vehicle page $n";
 $p->save();
}

Regardless of whether you do something like the above… on another subject would be how your hook knows when to populate an automatically generated 'name' field to your page (If I understand correctly what you were trying to do). I'm thinking you could add a hidden integer or checkbox field to your page (one set to be 'hidden' from it's input tab). Then populate that field after you've set your automatically defined page name. That way your hook would know which pages to setup the name for and which pages to skip.

Link to comment
Share on other sites

The problem: I have multiple inventory with the same name / model. I want the name / model in the title and URL ( name ) fields but can't create multiple pages with the same URL.

The simplest solution I can think of, would be to use the stock number for the title / name fields and then add the make / model to the name before the page is published the first time via a hook. So the published URL would be make-model-stocknum, which would be unique.

This shouldn't affect any images attached to the page correct?

Is it possible to change the "Title" label to "Stock Number" for the inventory template?

P.S. I don't want to add the make / model info in the title manually because many manufacture / model names are easily miss-spelled. It's easier to select this information from a list in the template.

Thanks for PW and your help.

Link to comment
Share on other sites

It won't affect images or files attached to the page if you change the title or name fields - it's all tied together using a unique ID so you can rename things as much as you like.

You would need a custom module to auto-generate a URL concatenated from the fields in question and it would depend on how you have certain things set up. I would suspect Make and Model would be Page fieldtypes (see this video, but you'd want to set it up as a Select or Autocomplete rather than a multiple select).

The title field itself would be best left as a stock number I think as this can easily be outputted as something like "Stocknum - Make Model" in the <title> tag in your template (which I'm guessing you've already worked out), it's just the URL you'll need a module for and you'll be happy to know that even that shouldn't be too hard.

The module would be something like this:

<?php
class BuildUrl extends WireData implements Module {

   /**
   * Basic information about module
   */
   public static function getModuleInfo() {
    return array(
	   'title' => 'Build URL',
	   'summary' => 'Builds a URL on page save based on specific fields.',
	   'href' => '',
	   'version' => 001,
	   'permanent' => false,
	   'autoload' => true,
	   'singular' => true,
    );
   }

   /**
   * Populate the default config data
   *
   */
   public function __construct() {

   }

   /**
   * Initialize the module and setup hooks
   */
   public function init() {
   $this->pages->addHookBefore('save', $this, 'buildUrl');
   }

   /**
   * Checks if we're in maintenance mode and performs any neccessary redirects
   *
   * @param HookEvent $event
   */
   public function buildUrl(HookEvent $event) {
   // Accesses the $page object
   $page = $event->object;

   // We only want this to apply to a certain template
   if ($page->template->name == 'yourtemplatename') {
	   $page->name = $page->make->name . '-' . $page->model->name. '-' .$page->stocknum;
   }
   }
}

The code above is untested but should give you a bit of a head start.

The code only wants to run before save on a page using a certain template - it then gets the name from the "make" field (so it checks the make and fetches the name value from that associated page) and the same for the "model" field, then attaches the stocknum field (just a plain text field I guess) to the end, concatenated with hyphens.

Because it runs before page save there's also no need to call save, but some extra checking would be advantageous as some of those fields won't be populated when the page is first saved (i.e. brand new).

To install the module, whack that code in a file called BuildUrl.module and place it in your site/modules directory. Then go to the modules section of the admin and check for new modules, then install it (after making changes to suit your fields and template name).

EDIT: Some of the settings at the top (autoload, singular) might not be right as I was doing this in a hurry and don't have more time tonight, and I'm not sure the empty __construct function is required, but left it in in case it broke without it. I'm sure someone else who's around later will improve on it with other suggestions :)

  • Like 2
Link to comment
Share on other sites

It's not particularly relevant here as something like the above should be fine for a one-off URL, but it might well be possible to create a configurable module in future if this sort of scenario arises again. I can see a simple textares config field with this being able to work for multiple templates, one per line followed by fieldnames to concatenate:

template1name,field1name,field2name,field3name
template2name,field3name,field1name,field7name

That's the easiest way I can think of to do it for multiple templates in the same site and have it configurable with no code edits. Of course the module code above would have to become more complicated to support that, so for a one-off stick with the code above - I'm just thinking out loud and once again being pleasantly surprised by the fact that anything seems possible with ProcessWire.

Link to comment
Share on other sites

The simplest solution I can think of, would be to use the stock number for the title / name fields and then add the make / model to the name before the page is published the first time via a hook. So the published URL would be make-model-stocknum, which would be unique.

Pete's module code he posted seems to be a good way to do this. You might also want to add a little check to the buildUrl function/hook, just in case they haven't selected a make or model yet.

// make sure a make and model are already selected
if($page->make && $page->model) {
 // make sure $page->name isn't already in a "make-model-stocknum" format
 if(!preg_match('/^\w+-\w+-\w+$/', $page->name)) {
   $page->name = $page->make->name . '-' . $page->model->name . '-' . $page->stocknum; 
 }
} 
Is it possible to change the "Title" label to "Stock Number" for the inventory template?

You can change the label that appears with the field by editing your template and clicking on the "title" field in the list. It'll pop-open a model dialog box where you can change the settings of that field specific to the context of that template. In your case, you would just change the "Title" label to be "Stock Number". And of course, you'd update the code examples above to refer to $page->title rather than $page->stocknum.

Link to comment
Share on other sites

  • 10 months later...

i tried Pete's code but it wasn't working; i made some changes based on seeing similar things on other modules, so here is a version that is working for me on latest stable:

<?php
class BuildUrl extends WireData implements Module {

    /**
    * Basic information about module
    */
    public static function getModuleInfo() {
	    return array(
		   'title' => 'Build URL',
		   'summary' => 'Builds a URL on page save based on specific fields.',
		   'href' => '',
		   'version' => 001,
		   'permanent' => false,
		   'autoload' => true,
		   'singular' => true,
	    );
    }

    /**
    * Initialize the module and setup hooks
    */
    public function init() {
	   $this->pages->addHookAfter('saveReady', $this, 'buildUrl');
    }

    /**
    *
    * @param HookEvent $event
    */
    public function buildUrl($event) {
	   // Accesses the $page object

	   $page = $event->arguments[0];
	   
	   if($page->template != 'product-child') return;

		   $page->name = $page->title;
		   
		   $this->message("slug changed to " . $page->name);

    }
}
  • Like 4
Link to comment
Share on other sites

My code would only work for the OP as he had those specific fields that he wanted concatenating into the page name ;)

Your code looks like the default behaviour for PW anyway - it makes the name from the page title already so not sure what that will achieve? I suspect you are wanting the name (slug) to change if the page title ever changes, but beware as if you do something like this on a page that has been on your site for a while then you could break links from external sites and search engines.

I would suggest installing ryan's page path history module as well as this will automatically redirect links from the old URLs to the new ones.

Link to comment
Share on other sites

Hi Pete - thanks for the clarification - so your code is different because it is meant to only set the URL on the first page save?

I had taken your code and then made changes to the template and fields (in my case i didn't need the concatenation) but it wouldn't change the URL after save;

I'm not super clear on why your module uses the save hook, as opposed to my example (which was taken from a different similar module) which uses the saveReady hook;

what i posted is sort of a utility for a specific need that is mostly happening during development, where the title field is holding a product # and we want to keep those in sync with the page name; but i can think of a lot of other uses where having the ability to build the page name on save based on one or more fields is going to be really useful; so i would like to get a better understanding and further improve the code i posted; i'll probably add checks similar to what Ryan posted.

Link to comment
Share on other sites

Ah, no, I thought you'd just copied my example without changing any field names :)

I've never used saveReady, but ryan explains it a bit here: http://processwire.com/talk/topic/1705-need-to-send-email-notification-after-a-page-has-been-published/?p=15786

I should probably use that instead from now on :)

I'm not sure why the code you posted doesn't work though unfortunately - I don't have time to test it right now either so hopefully someone else will be able to help.

Link to comment
Share on other sites

  • 11 months later...

I also have a need to shange the name after the page is saved. For me it is because i need to re-transliterate titles from russian language. I am coming from using Joomla. In that CMS you could delete the old alias (name in PW) and save the page. Then the alias would regenerated from the title field. In PW admin interfase if you delete the old name field you just cannot save the page. Is there an easy solution? Maybe a module adding a "regenerate from title" capability? It is a little thing but it annoys me, because i can't just type in a name like all you latin-writing people.

Link to comment
Share on other sites

@ivan see Macrura's post that Module is doing exactly that. ( and you should remove the if template statement ) 

I am coming from using Joomla. In that CMS you could delete the old alias (name in PW) and save the page. Then the alias would regenerated from the title field.

The URL get indexed with search engines and are shared on social media & mail etc. Then changing the title will result in a 301 or in worse case a 404. There are situations where it is desirable that the url changes and thus trowing a 404, but to make this the default behaviour is bad practise in my opinion.

  • Like 3
Link to comment
Share on other sites

This is very rough, but if it does what you want, I can clean things up.

Basically it will regenerate the name of the page if the title changes. It works on page save, so you won't see the updated name until after you save.

Of course you need to consider the impact this can have on broken links and search engine indexing of your site. You might want instead to change the module so it only updates the name if it is empty at page save.

EDIT: I didn't see Macrura's code above.

I also agree with Martijn that in general this isn't a good idea, but one great tool in PW that can help with this is a core module that is disabled by default, but if you turn on the "Page Path History" module, PW will take care of redirecting pages to their new name/url automatically.

UPDATE: For those interested in this functionality, check out this module, instead of the attached one:

https://processwire.com/talk/topic/7724-page-rename-options/

RegenerateName.zip

Edited by adrian
Link to new module
  • Like 1
Link to comment
Share on other sites

Thank you! Two pieces of code is much more than i could expect. I will try them out.

I am aware of the importance of consistent urls. I want to use that function mostly while developing. The pages get renamed and i want urls to change accordingly. Simply renaming default "about" page requires that.

  • Like 1
Link to comment
Share on other sites

I actually really agree with you on this being enabled during development - I often change page titles at this time and it can become painful to remember to change the names as well. 

  • Like 1
Link to comment
Share on other sites

yeah, i always need to nag the clients during development to keep their page names consistent with the titles..

maybe a module where you could enable a "development mode" which would prompt the user when changing title if they also want to rename (update slug)...

some might even want to leave it on and then rely on the page path history to redirect..

  • Like 3
Link to comment
Share on other sites

This is very rough, but if it does what you want, I can clean things up.

Basically it will regenerate the name of the page if the title changes. It works on page save, so you won't see the updated name until after you save.

Of course you need to consider the impact this can have on broken links and search engine indexing of your site. You might want instead to change the module so it only updates the name if it is empty of page save.

EDIT: I didn't see Macrura's code above.

I also agree with Martijn that in general this isn't a good idea, but one great tool in PW that can help with this is a core module that is disabled by default, but if you turn on the "Page Path History" module, PW will take care of redirecting pages to their new name/url automatically.

Thanx, Adrian. I tried it out. It works perfectly with latin titles, but fails with cyrillic. Could you please check it if you have time.

Link to comment
Share on other sites

Ivan,

Is this just an issue with this module, or does it happen when creating pages in PW in general? I don't know much about this stuff. Just found this post:

https://processwire.com/talk/topic/5278-error-in-transliteration/

but before I look into it more, I just want to confirm that it works as expected for you when creating a page normally in PW.

Link to comment
Share on other sites

When i create a new page the name gets transliterated from the cyrillic title. So it works in PW in general.

But when i change the name and try to save with your module on only latin titles get converted to names. Cyrillic titles (i guess all UTF chars) are not converted. If i mix latin and cyrillic letters in title only latin get their way to name - all cyrillic get stripped.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...