joshuag

Routes and rewriting URLS

45 posts in this topic

I wanted to have a similar short link as mods.pw/XXX and wanted to store them directly in the page in a field.

Created a unique text field "shortlink"

This is my module code for creating a random key (in this case 6 digits) and assign it to the shortlink field

<?php class ShortLink extends WireData implements Module {

    /** getModuleInfo is a module required by all modules to tell ProcessWire about them
     * @return array
     */
    public static function getModuleInfo() {

        return array(
            'title' => 'ShortLink',
            'version' => 100,
            'summary' => 'Pre-populate $field->shortlink with random 6 digit string',
            'singular' => true,
            'autoload' => "template=admin"
            );
    }

    public function init() {
        // add before-hook to the inputfield render method
        $this->addHooKBefore("Inputfield::render", $this, "renderField");
    }

    /**
     * If not empty, create unique value for textfield 'shortlink'
     *
     */
    public function renderField(HookEvent $event) {
        $field = $event->object;
        if($field->name == 'shortlink' && $field->value == '' ) {
          // $id is unique, as page id is unique
		  $shortlink = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@-_"), 0, 6);
          $field->set('value', $shortlink);
        }
    }
}

and then I activated URL Segments on my home template

and added this at the very top of my head.inc

if($input->urlSegment1) {
  // URL has /category-name/post-name/
  $shortLink = $sanitizer->pageName($input->urlSegment1);
  $post = $pages->get("shortlink=$shortLink"); 
  if(!$post->shortlink) {
	$session->redirect("/search/"); 
  } 
  $session->redirect($post->url); 
} 

It´s customized option 2 from Ryan (post #21)

At the moment it seems to work as expected. But as I´m not really a programmer I don´t know if it´s really safe etc..

Maybe the code for the head.inc could come in the module?

What do you guys think about this?

Cheers Can

EDIT:

Added canonical metatag to the header

I like that I´m able to override the generated key.

The module is not really needed but it´s nice to have when I´m to lazy to think about an own shortlink

When using for a customer I maybe set the field to read only, but because it´s unique text field it will throw an error anyway so shouldn´t be possible to mess with the field value

Ah there is one thing I´m not sure about.

The shortlink field is type of TextUnique, but what if the str_shuffle generates a duplicate (don´t think it´s impossible?!)

I guess the field wouldn´t get populated right? Of course I could save the page for a second time but I´m sure there is a way of doing this directly while populating it for the first time in the module but I don´t know how?

It´s currently not working with Markup Sitemap XML module, could extend the if in my header.inc to check for /sitemap.xml

Ah just figured out that Markup Sitemap XML is not working with URL Segments turned on at all.

Edited by Can
2 people like this

Share this post


Link to post
Share on other sites

Hi @Can,

Here is another option for automatic shortlinks:

http://modules.processwire.com/modules/process-redirect-ids/

It uses the ID of the page, so a link can be as simple as: mysite.com/1034

but as long as the page id is in the url somewhere, it will work, so you can structure the link to be whatever you want really.

Not sure if it suits your needs or not, but thought I'd mention it just in case.

Share this post


Link to post
Share on other sites

Thank you Adrian should´ve mentioned that I knew this module but thanks anyway..maybe someone else would prefer the id solution ;-)

I wanted to have the possibility to have readable shortlinks like example.com/tpls or /templates which would redirect to example.com/articles/templates for example

Because the core module "Markup RSS Feed" works fine with my redirection stuff I don´t care about Markup Sitemap XML at the moment.

Share this post


Link to post
Share on other sites

Yes thanks again  ;)

It even provides a API function so it should be possible to automate it.

But I wanted to have it even simpler with short links within the page

And at the moment I don´t need to have external redirects

1 person likes this

Share this post


Link to post
Share on other sites

Add a template redirect, add page select and in template file redirect to the selected page.

1 person likes this

Share this post


Link to post
Share on other sites

Needed to change the rewrite code a little to get it work beside the shopping checkout from apeisa

The second line (after <?php) looks now like this

$get = $input->urlSegment1;
if($get && $get !== "confirmation" && $get !== "payment" && $get !== "completed") {

Share this post


Link to post
Share on other sites

How about adding in virtual URL segments like /year/month/ appending the parent page name and prepending the name of the active page? without having to actually separate them? Anybody know of a way to do this?

Share this post


Link to post
Share on other sites

what do you mean by "without having to actually separate them?"

Don't really get what you're trying to achieve

Share this post


Link to post
Share on other sites

I think hellomoto is trying to get a url structure like in wordpress (/2014/07/page-title), without creating folders for 2014 and 07.

That would work, if you deligate all posts from the homepage template with three url segments. 

Share this post


Link to post
Share on other sites

A question about urlsegments and site structure:
In my professional life I mostly replicate private real estate databases to public web databases and develop websites on top of the latter.

Now I want to incorporate the real estate data (and my set of classes) into Processwire (as a test).  The real estate tables will reside next to the Processwire tables (for now).
I plan to make a template immo.php and use it as a controller for all the real estate output.

Would it be safe to say that using urlsegments - assuming I allow url segments in the immo template - is the way to go to obtain something like:

url.com/immo/sales/p1/welcome-to-the-sales-page
or
url.com/immo/estate-detail/123/some-friendly-url-of-the-estate-title 

Share this post


Link to post
Share on other sites

It's definitely one possible way to go, sure.

the url names are received from the db or you define them in the template? If the first is the case make sure to sanitize them e.g. $sanitizer->pageName($url)

2 people like this

Share this post


Link to post
Share on other sites

Good point, Can.  Everything in immo.php would be communicating with the db, more specifically with the real estate tables.

1 person likes this

Share this post


Link to post
Share on other sites
On 13.9.2012 at 3:25 PM, ryan said:

But the reason you don't see things like this outlined in the documentation is because I don't think it's a best practice, whether in ProcessWire or on the web in general. So if someone uses multiple routes, I would suggest it only to solve a specific need after a site is produced… not as something to build around from the start.

Having multiple routes to a given page is certainly not a good idea. And I like the idea of the page tree as a kind of file system.

But I also sometimes like to use pages as kind of “folders” in my page tree, but do not necessarily want them as part of my URL structure. TYPO3 has a nice checkbox giving me the option to omit a page’s URL section from the URLs of its children. This way you can use pages as “folders” to structure your page tree, but they can be invisible in the URLs if they are not required there.

Would this be an idea for ProcessWire?

Share this post


Link to post
Share on other sites
7 hours ago, Michael van Laar said:

But I also sometimes like to use pages as kind of “folders” in my page tree, but do not necessarily want them as part of my URL structure. TYPO3 has a nice checkbox giving me the option to omit a page’s URL section from the URLs of its children. This way you can use pages as “folders” to structure your page tree, but they can be invisible in the URLs if they are not required there.

Would this be an idea for ProcessWire?

i think using this sort of structure is going to be inevitable on a lot of projects, especially where you don't need/want the users to even interact with the page tree - for example a shop or product catalog; in those situations, you may use a bucket approach, putting all of the products into a 'folder' and then when the user creates a new product they need to set it up from the editing screen - meaning they may need to specify a product type, family, category, or even a combination of those things. Product categories may be just options that need to render lists of items in those categories. In Ryan's CMS critic case study, he demonstrated a hook to rewrite the path of any page based on it's template.

I use that method, but depending on how complex the setup is, it may have a series of cascading implications that need to be accounted for system-wide, such as page title, section, breadcrumbs, and the actual page that is supposed to be rendered.

I setup a WireData container ($config->segmentData) where i can set those items so that the system can work with whatever virtual page needs to get rendered based on the request.

So in the end i was able to get a complete URL routing system by

1) adding the page paths in a hook in ready.php for the relevant templates
2) adding a custom WireData() ($this->wire("config")->segmentData = new WireData();) in ready.php
3) setting up some blank vars in that $config->segmentData in the template init, like $config->segmentData->page = '';
4) setting up a router template which handles the segment requests, and setting a page in the tree to use that template.
5) i also use a getVirtualPage function that simplifies the code in the router

there are a couple of other concerns depending on how you render the content, but nothing that difficult...

1 person likes this

Share this post


Link to post
Share on other sites

I know this is possible. And I also considered using a similar solution in such cases. But …

17 hours ago, Macrura said:

… So in the end i was able to get a complete URL routing system …

That’s exactly what I don’t want. I don’t want to sort of reinvent the whole URL handling in ProcessWire – which is basically what any of the mentioned solutions is, even if it is only for a certain part of the page tree. As a front end developer I simply don’t want to have to take care of URL handling. That’s the CMS’ job. And ProcessWire does this job very well. I don’t want to completely separate the page tree structure from the URL creation. I’d just like to have an intuitive and easy to use way to skip one page tree level in the URLs if required.

But probably this is no good idea at all. In most cases I can ether live with the extra level in the URL path, or I can structure my page tree using some “folder” pages and the multi-sort module, so that the most of the URLs are as short as I want them to be, while the page tree is still quite neatly arranged.

1 person likes this

Share this post


Link to post
Share on other sites

Hello guys,

Although I have already built a web-site with ProcessWire, I'm still feeling new at ProcessWire developing. So, I have one question regarding this topic. I want to shorten my urls. I did what WillyC told in the first post. And I get my link shortened successfully. However, the page content does not display, shows only header content. What I'm doing wrong? Should I do something additionally?

My code in the top of _head.php file:

<?php
$pages->addHookAfter('Page::path', null, 'hookPagePath');
function hookPagePath(HookEvent $e) {
    $page = $e->object;
    if ($page->template == 'services') $e->return = "/$page->name/";
}
?>

Thanks!

Share this post


Link to post
Share on other sites

you still have to tell processwire what content to show, either by redirecting or rendering for redirection check out my post at the top of this page https://processwire.com/talk/topic/1799-routes-and-rewriting-urls/?do=findComment&comment=60856

for rendering you go a similar way by checking if there's a urlSegment present, if so render the requested page by urlSegment (shortlink) instead of the home page or blog page..depending on how you structure your shortlinks
so if you shortlinks will look like domain.com/shorty then you're rendering instead of home page, if you url looks like domain.com/blog/shorty then rendering will replace blog template..

and where / how to place the code depends on how you set up your template files, are you using the delayed output using _init.php -> template file -> _main.php or are you including the head and foot in each template file? (could even be a totally different set up..)  

 

 

1 person likes this

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.