Jump to content

Routing system, aka. "Where to put page actions in ProcessWire"


MrSnoozles
 Share

Recommended Posts

Hello,

this feature wish came up while I was working on my first bigger project with ProcessWire. While almost all of the CMS is very well thought out there was one thing that always kept me thinking "where should I put this?": simple page actions.

What I mean is code snippets that belong to a page and should be run when a certain action is taken. E.g. when a user submits the form on my contact page (that has the contact template) I somewhere have to validate the form and then send it somewhere. So far I see two options to do that.

  1. Write a module that hooks into some methods and checks if the post data is set and if the page is my contact page
    This aproach is clean but it's usually a lot of overhead to write a module just for that
  2. Write the code in my contact.php template
    This aproach is fast but feels really dirty. It does not help to separate the logic from the design which I fear in a long term could lead to some Wordpressish code structure

 

Now since I don't have so much experience with ProcessWire there might be a chance I missed something, but then it's probably not documented obvious enough. So I thought how you improve on this problem and came to a solution, that's again really close to the syntax that jQuery provides. If we had some kind of routing system we could register those actions in any file, for example the templates _func.php

<?php
// execute this action when a post request is sent to /contact
// the parameters given to the callback function probably should be different
wire('request')->on('post', '/contact', function($request, $input) {
	// do an action
}

// do the action for any post request                    
wire('request')->on('post', function($request, $input) {
	// do an action
}

// do the action for get requests on contact pages                    
wire('request')->on('get', 'template=contact', function($request, $input) {
	// do an action
}

// do the action on ajax-GET requests                     
wire('request')->on('get.ajax', '/contact', function($request, $input) {
	// do an action
}                    

 

Is that something that could improve the work with ProcessWire? What's your honest opinion about it? If that's a useful suggestion I would like to help with the implementation.

 

Regards

Alex

Link to comment
Share on other sites

@MrSnoozles Why not put the code in _func.php and use if statements?

if($page->name == "page-name" && $input->post->submit) {
	// code to run on a specific page when form is submited
}

if($page->template->name == "template-name" && $input->post->submit) {
	// code to run on a specific template when form is submited
}

if($page->template->name == "template-name") {
	// code to run on a specific template
}

 

  • Like 3
Link to comment
Share on other sites

ProcessWire does have an router, even though it does look vastly different to what you're talking about. It's routing requests by the page template to the corresponding template.php file. What you proposed does not correspond very well with that core routing strategy, because neither urls nor the http methods are the identifying factor here. It's the pages template and the existence in the page tree.

If you're looking for a more traditional mvc routing layer, you can set an alternative template file for your templates (by hook or in the backend). Just point all of them to e.g. a router.php file and use whatever router package your like to route requests to wherever the action should be handled. 

And about the core routing of processwire. Always keep in mind that mvc frameworks do not have something like the page tree, which is why they need a router to work on the url of the request. ProcessWire does not need that with it's approach.

  • Like 10
Link to comment
Share on other sites

Hello MrSnoozles,

in Processwire template files are not actually templates and You can actually use them as controllers (see the "delayed approach" in pw tutorials). In template files You can manage the request ($input), build forms (InputfieldForm module instances) and assign variables which are later used in the included view file(s). (btw, I use the ".phtml" extension for my views/partials  to distinguish them from template/controller files ".php").

If you ever worked with Silverstripe you can actually think of template files code as Silverstripe's Page_Controller classes ' method code. You can leverage pw's urlSegment feature to add sub-routes for the current page/template. If you have a contact-page template (/contact-us/) You can use a "submit" segment ($input->urlSegment(1)) and use "/contact-us/submit" as the form action, the same way You can add any route segment in a Silverstripe (Page_)Controller class. 

I don't find it useful to add code used only by the "contact-page" template in a global function inside (_func.php).

As in Silverstripe cmf the segment approach has the advantage that it continues to work even if you change the url (name) of the page using that template.

Think of template files as controllers: while in other frameworks you have to assign controllers to routes, in PW  a route (Page path/url) is automatically linked to a peculiar controller (template) by the fact that the Page with that route is using that template.

kind regards,

maks feltrin

  • Like 5
Link to comment
Share on other sites

Agreed - you can take the MVC approach using template-files. If you really wanted to use a router like that, you could always create a Process module to use as a fallback to non-existing routes. Jumplinks 2 will use this methodology on the 404 event, where it collects routes from the database and applies a single action. You could do something similar where the module sets up the router (in the case of Jumplinks 2, it is FastRoute), and then have it include a routing file. From there, you'd have access to the global scope and do pretty much whatever you want to do.

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...