Jump to content

[SOLVED] - Blog Post Path Format Query


ridgedale
 Share

Recommended Posts

22 hours ago, dragan said:

It just seems like this never really worked as intended, or maybe stopped working as expected.

However, I just installed kixe's module mentioned earlier, and when I tried this children name format, it works:

date(Y-m-d) title id

gives me

2018-01-20-here-we-go-again-1043

 

Hi dragan,

Thank you for your reply. However, I really would like to avoid deploying modules where possible particularly as it should be completely unnecessary in this case.

I'm sure it should just be a case of changing a setting or adding some code.

What I simply cannot understand is why $id generates a random number. There must be a reason for that, but I cannot find an explanation. In all my experience with database development ids have always been generated as auto-incrementing sequential numbers.

If anyone can shed some light on why $id generates a random number, it would be very much appreciated.

Link to comment
Share on other sites

21 hours ago, Robin S said:

Nothing extra is needed to achieve this. If you create a page that has the same title as another page under the same parent then by default PW will automatically add a digit to the end of the page name to make it unique. Unless you have a need for something different it's best to just leave it at that.

But if you want to prepend the page id to the page name you can do it with a hook in /site/ready.php:


$pages->addHookAfter('saveReady', function (HookEvent $event) {
    $page = $event->arguments(0);
    if($page->template != 'blog-post') return; // Only for the blog-post template
    if(!$page->id) return; // Skip pages that are brand new and aren't yet populated with data
    // If the page name doesn't start with the page id
    if(strpos($page->name, $page->id) !== 0) {
        // Prepend the page id to the page name
        $page->name = $page->id . '-' . $page->name;
    }
});

Hi Robin S,

Thank you for the feedback. However, the issue remains that $id generates a random number instead of an auto-incrementing sequential number. This forum's posts do appear to have ids being created that are auto-incrementing sequential numbers. The only thing I can think of is to add a custom separate id field in the backend database that produces auto-incrementing sequential numbers to be used for the blog posts only. However, my concern with that is it might completely break the site.

Any input on how the auto-incrementing sequential ids for the forum posts are achieved would be appreciated.

Link to comment
Share on other sites

7 minutes ago, ridgedale said:

However, the issue remains that $id generates a random number instead of an auto-incrementing sequential number.

Page IDs are not random, and they do auto-increment. If you check the "pages" table in phpMyAdmin you will see that the ID column is an auto-incrementing INT type. You'll also notice that rows (pages) in the table have sequential IDs. But the IDs increment site-wide for all pages, not separately or specifically for your blog post pages. So if you add some non-blog pages in between blog posts then the IDs for your blog posts will not be sequential. Deleting pages will also create gaps in the ID sequence.

But all of this is completely normal on a system like this, and I can't see how it affects anything you might need to do with a blog post. Perhaps you could explain what the specific problem is that you are trying to overcome by inserting IDs in the page names.

Link to comment
Share on other sites

Hi Robin S,

11 minutes ago, Robin S said:

Page IDs are not random, and they do auto-increment. If you check the "pages" table in phpMyAdmin you will see that the ID column is an auto-incrementing INT type. You'll also notice that rows (pages) in the table have sequential IDs. But the IDs increment site-wide for all pages, not separately or specifically for your blog post pages. So if you add some non-blog pages in between blog posts then the IDs for your blog posts will not be sequential. Deleting pages will also create gaps in the ID sequence.

Thanks for the update. The confusion has arisen because when id or $id is entered into the Name format for children field it does not return the Page id!

  • /blog/0919/
  • /blog/2619/

These appear to be randomly generated Names using id or $id!

 

Link to comment
Share on other sites

23 minutes ago, ridgedale said:

The confusion has arisen because when id or $id is entered into the Name format for children field it does not return the Page id!

Nowhere does the documentation say that "Name format for children" supports the string "id". The (unfortunately very brief) documentation for the feature says that it supports the string "title", or a date format string. When you insert "id" in the setting field PW attempts to interpret it as a date format.

If you need something beyond what the feature provides you could try kixe's module, or use a hook.

Link to comment
Share on other sites

28 minutes ago, dragan said:

Maybe @ryan can share some light on this. Meanwhile, why not open an issue @ https://github.com/processwire/processwire-issues/issues ?

 

1 hour ago, Robin S said:

Nowhere does the documentation say that "Name format for children" supports the string "id". The (unfortunately very brief) documentation for the feature says that it supports the string "title", or a date format string. When you insert "id" in the setting field PW attempts to interpret it as a date format.

If you need something beyond what the feature provides you could try kixe's module, or use a hook.

@dragan,

Thanks for your reply. I'll do that.

@Robin S,

That is probably where I have been going wrong.

I've tried your hook method. When I created _ready.php under site > templates, added the code you provided, updated the blog_post template prepending _ready.php and refreshed the webpage, the path /blog/<id - title> did not not get prersented as expected. In addition, when I clicked on the browser back button the code from the _ready.php file ended up being displayed on the page behind the navbar.

The documentation is a little confusing as the document you linked to suggests /site/ready.php:

1 hour ago, ridgedale said:

... a hook in /site/ready.php

but the templates suggest the file should be placed under /site/templates/.

I'm assuming the /site/ready.php file is just an example file. Is that correct?

Edited by ridgedale
Robin S explanation explains the id confusion
Link to comment
Share on other sites

@Robin S,

I can see that /site/ready.php is called by uncommenting:

/** @var ProcessWire $wire */


but when that line is uncommented and the file includes the code provided I'm still only getting the page title returned.

Any thoughts on where I'm going wrong?

Link to comment
Share on other sites

22 hours ago, ridgedale said:

When I created _ready.php under site > templates

The path must be /site/ready.php

Create a new PHP file "ready.php" in the "site" directory. Save the following as the contents of this file:

<?php
$pages->addHookAfter('saveReady', function (HookEvent $event) {
    $page = $event->arguments(0);
    if($page->template != 'blog-post') return; // Only for the blog-post template
    if(!$page->id) return; // Skip pages that are brand new and aren't yet populated with data
    // If the page name doesn't start with the page id
    if(strpos($page->name, (string) $page->id) !== 0) {
        // Prepend the page id to the page name
        $page->name = $page->id . '-' . $page->name;
    }
});

Adjust the name of the blog post template within the hook if needed.

Link to comment
Share on other sites

@Robin S,

Thanks for you help. For some reason the page names are now working. There appears to have been some delay before the post names were updated. Plus I needed to review and amend the database entries for the posts where the post names were scrambled/junked during testing.

Many thaks to everyone for all their input. :)

Link to comment
Share on other sites

...updated the blog_post template prepending _ready.php ....

You shouldn't need to prepend the file.  I believe site/ready.php gets picked up automatically.

To fix your other blog posts, just re-save them and the hook should execute and correct the page name with the correct format.

If there's a bunch of posts to go through, you could use Adrian's admin actions module http://modules.processwire.com/modules/process-admin-actions/ or the process wire API to loop through and re-save the pages.

Link to comment
Share on other sites

Here's where it talks about the site/ready.php file https://processwire.com/blog/posts/processwire-2.6.7-core-updates-and-more/

I think I remember why I chose not to use id based urls.  I was worried it might be hard to import/export pages because the ids on the other site/system you are migrating to might be different.  I think that's why I chose to use the built in behavior of Processwire.  In my case duplicate page names don't happen very often.

I would like to hear other people's opinion on urls that contain a page id.

Link to comment
Share on other sites

Hmm... @Robin S I tried your hook in my site/ready.php, but it doesn't appear to do anything.  The page name/url stays the same.  I do see the hook displayed in the Tracy Debugger.

Any thoughts as to why it might not be working?

I also tried changing:

$page = $event->arguments(0); to $page = $event->arguments[0];

but it didn't seem to make a difference.

Link to comment
Share on other sites

10 hours ago, gmclelland said:

Hmm... @Robin S I tried your hook in my site/ready.php, but it doesn't appear to do anything.

I think ridgedale has the hook working now. Or are you asking because you want to use this hook yourself?

10 hours ago, gmclelland said:

I do see the hook displayed in the Tracy Debugger.

If you have Tracy you can do some simple debugging to find out why the hook might not be working in your case.

$pages->addHookAfter('saveReady', function (HookEvent $event) {
    bd('saveReady hook fired');
    $page = $event->arguments(0);
    if($page->template != 'blog-post') return; // Only for the blog-post template
    bd('$page has template blog-post');
    if(!$page->id) return; // Skip pages that are brand new and aren't yet populated with data
    bd('$page has a non-zero ID');
    // If the page name doesn't start with the page id
    if(strpos($page->name, (string) $page->id) !== 0) {
        bd('$page name does not already start with its ID');
        // Prepend the page id to the page name
        $page->name = $page->id . '-' . $page->name;
    }
});

Based on what is dumped you can find out where things are going wrong.

Link to comment
Share on other sites

For some reason it doesn't fire if I include the following in the hook:

if($page->template != 'calendar-posting' || $page->template != 'community-event') return;

or 

if(($page->template != 'calendar-posting') || ($page->template != 'community-event')) return;

It does work for:

if($page->template != 'calendar-posting') return;

Any idea why that is?
 

Link to comment
Share on other sites

@Robin S

Just come across an issue with the hook code. If a post needs to be updated, an additional id is added to the name for example after one change and save the name becomes: <id>-<id>-<post-title> and after four changes it becomes <id>-<id>-<id>-<id>-<post-title>. Is there any way to avoid this other than resolving the issue by directly editing the database to remove the unwanted additional ids? Or removing the id from the name before saving the edited post?

Edited by ridgedale
Additional information
Link to comment
Share on other sites

@ridgedale, sorry, I should have tested that hook better. It seems that PHP's strpos() function will not work with an integer (page ID) as a parameter. So the page ID needs to be cast to a string. I'll add the revised code below and edit my earlier replies.

To fix your posts, first remove the hook in /site/ready.php.

Next you will need to execute some API code. Not sure how experienced you are with that, so a couple of ways you can do it...
1. If you have Tracy Debugger installed you can use the Console panel.
2. Assuming your site is a dev site and you are the only person with access to it, you can put the code in a template file (e.g. home) and then load a page using that template on the front-end.

Code is:

$items = $pages->find("template=blog-post, include=all");
foreach($items as $item) {
    $item->of(false);
    $item->name = $item->id . '-' . $sanitizer->pageName($item->title, true);
    $item->save();
}

When you have executed that and checked that your blog post names are okay you can remove the API code above from your template file (if you executed it that way) and add the revised hook back to /site/ready.php:

$pages->addHookAfter('saveReady', function (HookEvent $event) {
    $page = $event->arguments(0);
    if($page->template != 'blog-post') return; // Only for the blog-post template
    if(!$page->id) return; // Skip pages that are brand new and aren't yet populated with data
    // If the page name doesn't start with the page id
    if(strpos($page->name, (string) $page->id) !== 0) {
        // Prepend the page id to the page name
        $page->name = $page->id . '-' . $page->name;
    }
});

 

  • Like 2
Link to comment
Share on other sites

On 22/01/2018 at 8:23 AM, Robin S said:

sorry, I should have tested that hook better. It seems that PHP's strpos() function will not work with an integer (page ID) as a parameter. So the page ID needs to be cast to a string. I'll add the revised code below and edit my earlier replies.

@Robin S Please don't apologise. Your assistance has been extremely helpful. I didn't need to execute the API code as I had already gone through all the posts and manually corrected them. The solution was to remove <page id> - from the name field, make any changes and then save them. However, the updated code you have kindly provided resolves the issue and avoids having to do that in future.

Many thanks again for all your help.

  • Like 1
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

×
×
  • Create New...