Jump to content

Proper way to handle post request


pneumatig
 Share

Recommended Posts

Ok, now a simple (?) and basic question:

What is the proper way of handling post request in a module. Currently I add hook before page render, and then check if specific post variables are defined. However I'm not sure if its the best solution.

Any suggestions?

Link to comment
Share on other sites

I'm aware of that.

I want to know how should I "handle" the process of receiving data from post in terms of what url form should point to?

At the moment I do request to current page, and in each "page render" i check if its maybe the post request I'm interested in.

Usually (other frameworks) this is done by some kind of controller logic which can be connected to certain urls - so i some controller action I'm pretty sure that I should expect certain post request, because it shouldn't be accessed otherwise. 

In my current scenario I have to check if post variables exists and even if not I have to process request normally since its some "page render" (some other page for example, without form).

Can I somehow map my module action to certain url??? Is there an hook for this?

Link to comment
Share on other sites

You'll probably want to make this module (if it's not already) a Process module. ProcessHello is an example of this module type; they're essentially modules that add a page of their own, usually under admin, and use that to handle incoming requests, whether GET or POST (and respond to those accordingly).

Depending on your use case it might make sense to bundle "regular" hooking module and Process module together, so that the module attaching hooks doesn't need a page of it's own and the Process module isn't loaded unnecessarily before it's really needed. Not a huge difference, but just wanted to mention this option. In some cases this can also make the module "architecture" more sensible, separating different types of features.

As a concept this is very close to controller actions, really; in Zend Framework I'd have IndexController with methods indexAction and actionNameAction, in ProcessWire I've got ProcessMyModuleName.module with methods execute (requests to the initial URL of that page, same as indexAction in Zend Framework) and executeActionName :)

  • Like 2
Link to comment
Share on other sites

You could hook into page render and based on $page->name or $page->url or alike handle your post data

public function init() {
    $this->addHookBefore('Page::render', $this, 'myRenderPage');
}

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

    if ($page->url == '/') {
        // handle post for home page
    }
    elseif ($page->url == '/contact/') {
        // handle post for contact page
    }
}
Link to comment
Share on other sites

Ok, now a simple (?) and basic question:

What is the proper way of handling post request in a module. Currently I add hook before page render, and then check if specific post variables are defined. However I'm not sure if its the best solution.

Any suggestions?

I'm not very convident the other responses are really what you need. What module are you talking about, and what POST are you talking about? 

I'm assuming from your posts you talking about front-end forms and you ask how to handle the form processing?

Link to comment
Share on other sites

Solution with processing module didn't work since processing module works with admin page only, and login is required for admin pages. 

I'm working on simple module for user register/login/logout, very basic one, and I wanted to have common url for all module related stuff. Like at least: www.example.com/user (not to mention /user/login, /user/register, /user/logout). I don't really like the idea of placing business logic in template files, and I would like to avoid it. 

At the moment I'm going back to where i started and i will prepare some in-between solution - I will create a hidden page (accessed by /user/), and I will hook to on before render, and check if I'm on that page, and then process any proper requests, and finally I'll do redirection (so /user/ page won't be rendered). 

And I could really form question otherwise since I also wanted to know how to connect module with specific url (so it can be used as form action for post requests).

Link to comment
Share on other sites

There's no single or recommended way to what you're after. You can build anything any system with your templates and or modules. So I guess there's no general answer and one right way to do it.

Modules extending Process are meant for admin pages and only work for logged in users. They have a url mapping to method.

/processwire/myadminpage/ -> execute()

/processwire/myadminpage/edit/ -> executeEdit()

etc

But as far as I understand it's not for what you're after.

ProcessWire doesn't work like other frameworks. There's no routing and mapping to controllers and methods.

ProcessWire's template are not "views" in the traditional MVC sense, but rather can be what you make out of it. I see them also as controllers, or can be used as such.

Further ProcessWire has url segments (enabled on template setting) that can be used to extend a page's url with url segments, which then can be used to control actions.

If /user/ is a real page with a template

/users/edit can be catched with something like:

if($input->urlSegment1 == "edit"){
    ....
}

Modules (WireData) are usually used for hooks or similar stuff in front-end or backend. They can be autoload so they get loaded and init()'d on reach request. 

The init() method in such a module could be used to catch what's the current page or any request or url segment is set, you don't even need to hook into Page::render.

public function init(){
   if($input->post->userlogin) {
       $this->userLogin();
   }
}

or also the ready() method is called when ALL the API with the current page going to render is ready.

What I don't see is how you deal with the connection of your module with the template, how would the processing of a form in a template be done and return the populated form with error messages. Remember it's not like you think of other system with MVC, your module isn't a controller and your template a view. But certainly possible to make a setup that works that way.

I for example simply use templates for each page of /user /user/login user/profile user/profile/edit etc containing all code to deal with them. So every url maps to a "template" or "controller". The output is done by another template that is simply included at the end. But it would still be possible to put all this code and the generation of the form via API in a module but the code stays the same and I don't see much benefit.

What you could try is having a front-end-user module that has methods to do stuff, it doesn't have to be autoload. And use that in your template. So in your template you could do

// just some pseudocode 
// load module
$usersModule = $modules->get("UsersModule");
$urlSegment = $input->urlSegment1;

if(!count($input->urlSegments)) {
      $out = $usersModule->renderLogin():
} else {
    if($urlSegment  == "profile") {
          $out = $usersModule->renderProfile();
    }
}

echo $out;

Or have that logic in your module or whatever. Since you load the module on demand, there's no need for a hook or anything, and use urlsSegments to add urls

// user template that is a real page
$usersModule = $modules->get("UsersModule");
echo $usersModule->render();

And in the init() of you module test for url segments or requests. And the render() just outputs your result. 

By no means this is THE only way to go and just something to show there's nothing set in stone.

  • Like 5
Link to comment
Share on other sites

Just wanted to add that in a autoload module the init() method doesn't yet know the current page.

But instead there's ready() where the current requested page is set.

public function ready(){
    $page = wire("page");
    if($page->id == 1002){
         ....
    }
}

This can also be handy.

  • Like 2
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...