Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento - Best way to handle forms in blocks?

I'm coming from different MVC frameworks (e.g. Symfony) to Magento. I read a lot about Magento best practices and I can see Magento doesn't use the typical MVC style. Alan Storm wrote the followings:

it's not the responsibility of the controller to set variables for the view [...] controller's job is to do certain things to Models, and then tell the system it's layout rendering time.

I think I understand this approach as this can provide a kind of flexibility for blocks.

Right. But what about forms?

In a typical MVC framework you will get the request parameters in the controller, validate form data in the controller, make model operations (save, load, etc) or redirections if necessary there, and when everything is clean and tidy, you will provide the freshly baked output pieces for the view.

In Magento these all should happen inside a block and the (thin) controller is only supposed to prepare the layout and then render it. (If I understand.)

I tried to find an article (manual, forum topic, anything), which describes a creation steps of a separate module with an own new model, which can be editable via a form in the frontend by the user. I would like to see how a custom form should work in the frontend. I've found only general articles about blocks, forms, modifying or creating adminhtml forms or customising contact or newsletter signup forms.

I made it. It works now, but I'm not satisfied. So then, I checked the source code of the Contact form in the core module, and those messed up the entire picture for me. The built-in Contact form uses the IndexController to most of the above mentioned operations, (almost) like a standard MVC.

Could anyone suggest to me a best practice, how to manage a simple flow like the following? (I've got a solution for these below, but I'm not sure, is that the "right Magento way"):

  • When the page loads, show a form in a block, which is included in the separate page
  • Load a model object from the DB by a request parameter
  • Populate object data into the form
  • When user submits the form, process form data, validate them
  • If validation error, show the form again, and pop up error message
  • If OK, store the data into the DB, show a thank you page

My confusion is mainly around:

  • Where should I get and manage the request parameter? (I did it in the block class file)
  • And load an object from the DB, based on it? (Also, and then passed to the phtml)
  • How to pass it to the view, if I wouldn't load it there? (I would know a way, but I don't know the best way.)
  • Where should be the (POST) form data processed, validated and stored? (Block?)
  • How can I use properly redirections in a block? Do I need redirection, as the thank you page should be a different block / page? Or just an alternativ (conditional) look of the same block?
like image 526
Adam Solymos Avatar asked Nov 28 '12 13:11

Adam Solymos


1 Answers

You can just look into the Customer/AccountController and see how the loginPost, createPostmethods are handling the incoming form data.

I would never add the CRUD logic to the block. You need to validate and process your POST data in your Controller. Block should contain only view-related logic: like format url, or prepare Collection.

Also the form preparation lays on Controllers shoulders as well. You need to load your object and validate it inside the Controller action. Then there are few ways to pass it to the block:

  • Mage::register (Registry)
  • $this->getLayout->getBlock('your_form_block')->setEntity($object) (directly set variable to block)

Any redirection should be done in Controller only.

UPDATE Few words about why load model inside the controller.

  1. If you fail to load your object, it means that the url User is using (with object id) is outdated and it's possible you'll need to redirect the Customer to some convenient page with error.
  2. As I said above, all redirects should be done in Controller only. why is that? Because at the moment block is processes, huge amount of bootstrapping work has been already done by Magento - like loadLayout and create all Blocks. You don't want to make user wait for all that time just to redirect him afterwards.
  3. Also putting redirects anywhere not in the Controller makes application not maintainable. Of course there are exceptions, but you should know what you're doing very well.

Also you've forgotten about one more valuable part. If the validation fails inside your controller, you need to fill the form with the values User has sent. In Zend_Form that is done pretty, but with Magento forms you'll need to use session (like it's done in AccountController) - save all key-value parts in session and then in block check for those session variables existence. Again, you should do this only if your POST validation has failed and you're redirecting user back to your form. In successful case clear the session variables connected to the form.

As a general piece of advice: if you want to follow Magento style, read less forums and more core code.

like image 200
Slayer Birden Avatar answered Oct 19 '22 03:10

Slayer Birden