Can Posted April 25, 2014 Share Posted April 25, 2014 (edited) 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 April 25, 2014 by Can 2 Link to comment Share on other sites More sharing options...
adrian Posted April 25, 2014 Share Posted April 25, 2014 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. Link to comment Share on other sites More sharing options...
Can Posted April 25, 2014 Share Posted April 25, 2014 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. Link to comment Share on other sites More sharing options...
adrian Posted April 25, 2014 Share Posted April 25, 2014 I am guessing you have also seen this module then? http://modules.processwire.com/modules/link-shortener/ Of course this requires manual creation of each shortlink, but thought I'd post it here just in case someone else finds it useful. 1 Link to comment Share on other sites More sharing options...
Can Posted April 25, 2014 Share Posted April 25, 2014 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 Link to comment Share on other sites More sharing options...
Soma Posted April 25, 2014 Share Posted April 25, 2014 Add a template redirect, add page select and in template file redirect to the selected page. 1 Link to comment Share on other sites More sharing options...
Can Posted April 26, 2014 Share Posted April 26, 2014 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") { Link to comment Share on other sites More sharing options...
hellomoto Posted July 15, 2014 Share Posted July 15, 2014 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? Link to comment Share on other sites More sharing options...
Can Posted July 15, 2014 Share Posted July 15, 2014 what do you mean by "without having to actually separate them?" Don't really get what you're trying to achieve Link to comment Share on other sites More sharing options...
LostKobrakai Posted July 16, 2014 Share Posted July 16, 2014 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. Link to comment Share on other sites More sharing options...
KarlvonKarton Posted August 15, 2016 Share Posted August 15, 2016 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 Link to comment Share on other sites More sharing options...
Can Posted August 15, 2016 Share Posted August 15, 2016 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 Link to comment Share on other sites More sharing options...
KarlvonKarton Posted August 15, 2016 Share Posted August 15, 2016 Good point, Can. Everything in immo.php would be communicating with the db, more specifically with the real estate tables. 1 Link to comment Share on other sites More sharing options...
Can Posted August 15, 2016 Share Posted August 15, 2016 Just let us know if you got another question Link to comment Share on other sites More sharing options...
Michael van Laar Posted October 22, 2016 Share Posted October 22, 2016 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? Link to comment Share on other sites More sharing options...
Macrura Posted October 22, 2016 Share Posted October 22, 2016 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 Link to comment Share on other sites More sharing options...
Michael van Laar Posted October 23, 2016 Share Posted October 23, 2016 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 Link to comment Share on other sites More sharing options...
TomasDev Posted November 14, 2016 Share Posted November 14, 2016 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! Link to comment Share on other sites More sharing options...
Can Posted November 14, 2016 Share Posted November 14, 2016 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 Link to comment Share on other sites More sharing options...
benbyf Posted April 27, 2017 Share Posted April 27, 2017 I've created a quick module implementation of @Can's work. https://github.com/benbyford/PostProcessUrl Hard Truncates any page name / url to a max length if exceeded. 3 Link to comment Share on other sites More sharing options...
gebeer Posted November 25, 2021 Share Posted November 25, 2021 On 9/13/2012 at 12:20 AM, WillyC said: i.am first you can puut this in your head.inc tamplate or some includeded file before.u are doing $page->url $pages->addHookAfter('Page::path', null, 'hookPagePath'); function hookPagePath(HookEvent $e) { $page = $e->object; if($page->template == 'article') $e->return = "/blog/$page->name/"; } I just implemented this inside a autoload module and discovered that this hook only works in application ready state. So if you are utilizing this inside a module, you need to call the hook inside ready() method like this public function init() { // handle render of correct page from urlSegements $this->addHookAfter('ProcessPageView::execute', $this, 'hookPageView'); } public function ready() { // need to call this in ready. Not working in init() $this->pages->addHookAfter('Page::path', $this, 'hookPagePath'); } public function hookPagePath(HookEvent $event) { $page = $event->object; // page ROW and all children recursively if ($page->id == 1043 || $page->rootParent->id != 1043) return; $orgPath = $event->return; $pathSegments = explode('/', trim($orgPath, '/')); // $pathSegments[0] is language segment // get rid of $pathSegments[1] 'row' unset($pathSegments[1]); $newPath = '/' . implode('/', $pathSegments) . '/'; $event->return = str_replace('//', '/', $newPath); } public function hookPageView(HookEvent $event) { $page = $event->page; // only act on homepage if ($page->id != 1) return; // get last urlSegment to retieve page with that name if (count(input()->urlSegments())) { $wantedName = sanitizer()->pageName(input()->urlSegmentLast); $wantedPage = pages()->get("name={$wantedName}"); if ($wantedPage && $wantedPage->id) { $event->return = $wantedPage->render(); } else { throw new Wire404Exception(); } } } If knew this earlier it would have saved me some time and frustration... 1 Link to comment Share on other sites More sharing options...
artfulrobot Posted April 13, 2023 Share Posted April 13, 2023 There's these URL/path hooks from ProcessWire 3.0.173 : https://processwire.com/blog/posts/pw-3.0.173/ which seem very promising for the sorts of problems encountered in this discussion. 1 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