Jump to content
Leftfield

Dismantling and rewritting URL [SOLVED]

Recommended Posts

Hi @All 🙂

I have template product in category products
And have URLs like this: example.com
/pr/salomon-gtx-3d-1930649707/
The last numbers, the hash, is added by a module before save page.

What I need is this: example.com/salomon-gtx-3d/pr/1930649707

Is there a way to do this on the fly in the backend and record URL to database? A hint please

Share this post


Link to post
Share on other sites

Thank you @psy, I think don't need that. To explain my problem a little bit better:

1rst: I need to build URL before page save and add hash after forward slash. IT doesn't matter is it JS or PHP:

$new_name = $page->title . '/' . $hash;

The problem is: The core is converting forward slash "/" to "-". Probably something with $sanitizer->pageName but I am stuck here.

2nd problem is to move parent name after the child's name or to remove it completely - probably easiest way "Name format for children".

Share this post


Link to post
Share on other sites

@Leftfield I think that URL segmetns is the way to go.

wire()->addHook("Page(template=product)::path", function($e) {
		$page = $e->object;
		$e->return = "/{$page->name}/pr/{$page->hash_field}/";
	});

Then you have to enable URL segments for your home template.

And in template file 

if (input()->urlSegment(1)) {
	$pagename = input()->urlSegment(1);
	$hash = $input()->urlSegment(3);
	$match = pages()->findOne("template=product, name={$pagename}, hash_field={$hash}");
	if (!$match->id) throw new Wire404Exception();
	echo $match->render();
	return $this->halt();
}

 

  • Like 3

Share this post


Link to post
Share on other sites

There are some threads with similar topics discussing your need. You may find some ideas on how to achieve it.

But just for me to understand this better... why do you want/need such a weird URL? That doesn't make sense - generally speaking. 

 

 

 

 

 

 

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

@Zeka Thank You! I will try and give feedback what I have done. I need the URL to be recorded in the database on Page Save, not alternated on the fly.

@wbmnfktr I am making website similar to yellow pages and I need SEO. Main reason - hash will be kind of ID of the page. I am not alternating real ID because of pagination (I am OK with PW but not that good)

Share this post


Link to post
Share on other sites

@Zeka First part of the code I placed in ready.php file.
The second part is in template product.php
URL segmentation is enabled in backend.
When saving article, I got message with desired URL.

But still get 404. I am using latest PW and WAMP.

$input->urlSegment1 is empty (var_dump):

  (length=0)

 

Share this post


Link to post
Share on other sites

@Leftfield  The path hook should be in ready.php and all logic should be in home.php or in the template file that you are using for root page. 

if (input()->urlSegment(1) && input()->urlSegment(2) == 'pr' && input()->urlSegment(3)) {
	$pagename = input()->urlSegment(1);
	$hash = $input()->urlSegment(3);
	$match = pages()->findOne("template=product, name={$pagename}, hash_field={$hash}");
	if (!$match->id) throw new Wire404Exception();
	echo $match->render();
	return $this->halt();
}

Also you should enable URL segment for root ( home ) page.

Generate hash and save it to hash field you can by hooking in Pages::saveReady. You can find a lot of exaples in the forum. 

  • Thanks 1

Share this post


Link to post
Share on other sites

I placed the URL segmentation code in _main.php.
While natural PW URL is still working, I am getting error:

Fatal error: Uncaught Error: Maximum function nesting level of '50' reached, aborting!

I have turned off xdebug, tried with ini_set('xdebug.max_nesting_level', 10000); in config.php but it loads forever.

Share this post


Link to post
Share on other sites

OK. Here it is.
ProcessWire 3.0.123
PHP 7.2.18

1. In "product" template turned on "Allow URL segments".
2. Made text field: "hash_field" and added it to product.php template. Set visibility to: Open when populated + closed when blanked + Locked (not editable)

In site/ready.php

<?php namespace ProcessWire;

    //* conf segments of URL of template product *//
    wire()->addHook("Page(template=product)::path", function($e) {
            $page = $e->object;
            $e->return = "/{$page->name}/pr/{$page->hash_field}/";
        });

Made a module "AddHashField" with simple hash CRC32 to populate "hash_field" so the URL will be as short as possible.

<?php namespace ProcessWire;

class AddHashField extends WireData implements Module {

    public static function getModuleInfo() {
	    return array(
		   'title' => 'Add Hash Field',
		   'summary' => 'Populate hash field of product template',
		   'href' => '',
		   'version' => 001,
		   'permanent' => false,
		   'autoload' => true,
		   'singular' => true,
	    );
    }

    public function init() {
	   $this->pages->addHookBefore('saveReady', $this, 'AddHashField');
    }

   public function AddHashField($event) {
	    $page = $event->arguments[0];  

        if($page->template != 'product') return;
            
        if(!$page->hash_field){        
            date_default_timezone_set('Europe/Podgorica');
            $new_date = new \DateTime(date('Y/m/d 00:00'));
            $formated_date = $new_date->format(YmdHi);

            $hash = hash('CRC32', $formated_date);
            $page->set('hash_field', $hash);
            $this->message("Hesh is set " . $page->hash_field);
        }
	}

}

Now, I am using 'views/' folder for templating so, instead of using home.php I am placing this on the top of the _main.php file.

<?php namespace ProcessWire;

    if ($input->urlSegment1 && $input->urlSegment2 == 'pr' && $input->urlSegment3) :
        $pagename = $input->urlSegment1;
        $hash = $input->urlSegment3;
        $match = $page->findOne("template=product, name={$pagename}, hash_field={$hash}");
        if (!$match->id || !$match->hash_field) throw new Wire404Exception();
            include("./head.inc");
            include('./nav.php');
                include('views/' . $match->template->name . '.php');
            include("./foot.inc");
        // echo $match->render(); // problem with looping page endlessly + fatal error
        return $this->halt();
    endif;

NOTE: echo $match->render is causing massive looping until Fatal Error. I don't have idea what is causing that. Tried to turn off xdebug etc.

Special THANKS to @Zeka

  • Like 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...