Leftfield Posted September 16, 2019 Share Posted September 16, 2019 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 Link to comment Share on other sites More sharing options...
psy Posted September 16, 2019 Share Posted September 16, 2019 Maybe take a look at URL segments? https://processwire.com/docs/front-end/how-to-use-url-segments/ 3 Link to comment Share on other sites More sharing options...
Leftfield Posted September 17, 2019 Author Share Posted September 17, 2019 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". Link to comment Share on other sites More sharing options...
Zeka Posted September 17, 2019 Share Posted September 17, 2019 @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(); } 3 Link to comment Share on other sites More sharing options...
wbmnfktr Posted September 17, 2019 Share Posted September 17, 2019 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. 1 Link to comment Share on other sites More sharing options...
Leftfield Posted September 17, 2019 Author Share Posted September 17, 2019 @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) Link to comment Share on other sites More sharing options...
Leftfield Posted September 17, 2019 Author Share Posted September 17, 2019 @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) Link to comment Share on other sites More sharing options...
Zeka Posted September 17, 2019 Share Posted September 17, 2019 @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. 1 Link to comment Share on other sites More sharing options...
Leftfield Posted September 17, 2019 Author Share Posted September 17, 2019 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. Link to comment Share on other sites More sharing options...
Leftfield Posted September 17, 2019 Author Share Posted September 17, 2019 OK. I think I am resolving this. Will post everything Link to comment Share on other sites More sharing options...
Leftfield Posted September 18, 2019 Author Share Posted September 18, 2019 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 2 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now