MVC, Forms, and JavaScript

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

MVC, Forms, and JavaScript

Post by VirtuosiMedia »

At the risk of spawning a debate, I have a question. I've read in one of the threads here that 'forms are a special case' in MVC-style architectures. I can see why because you are required to process the forms and true MVC separation isn't always practical for doing so. I like the idea of separating the model, view, and controller for the most part, or at the very least separating the view from everything else, but is there a good solution for forms being as they constitute a large part of almost any web app you'll make? I'm not wedded to MVC for MVC's sake...I'm just looking for something practical.

Also, I was reading DZone today and I saw this article about writing two layers of MVC, one for the server and one for the browser (a combination of JavaScript, CSS, and HTML). I thought I would point it out and see what everyone thought about it.

Could perhaps a browser MVC pattern be something like:

HTML = Model
CSS = View
Javascript = Controller
User avatar
ghurtado
Forum Contributor
Posts: 334
Joined: Wed Jul 23, 2008 12:19 pm

Re: MVC, Forms, and JavaScript

Post by ghurtado »

I very much agree with the thought that forms don't fit well within classic, strict MVC. I think this is so because there are always two parts in any form based page: the HTML form itself and the processing behind it. Both these parts are naturally coupled together so tightly that it hardly makes sense to divide them just to fit some ideal of 'cleanliness' within MVC. In this sense, the pseudo-MVC style that .net uses, with their code-behind pages and their tight coupling of view and controller, actually makes a lot more sense to fit the form processing problem. Much of common form processing and validation is actually cleaner and more explicit when described in a declarative way (ie: via XML in your view), and this is actually how a number of pragmatic frameworks handle it.

As far as the browser MVC, I have heard that comparison before and it seems a little bit far fetched to me, except for the most complicated, client-heavy ajax applications. I don't really see the benefit of seeing the client layer as an "MVC within an MVC"
At the risk of spawning a debate...
Spawning a debate is a noble goal, in my opinion, never a risk :)
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Re: MVC, Forms, and JavaScript

Post by Luke »

I completely agree that forms don't fit well with MVC. A number of us here on the forums are working on a validation / filter chain method that goes something like this:

in the controller:

Code: Select all

$filters = new A_Filter_Set();
$filters->addFilter(new A_Rule_Trim()); // no specific form element specified, so apply to all
 
$rules = new A_Rule_Set();
$rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
        ->addRule(new A_Rule_Email('email', 'Please enter a valid email'));
 
if (is_post()) {
    $data = $filters->filter($_POST);
    if (!$rules->isValid($data)) {
        $view->errors = $rules->getErrorMsg();
    }
}
 
$view->render('account.phtml'); // view is a made-up view object
in the view (uses some form of helper to render form elements):

Code: Select all

<form method="post" action="<?php $this->url('/account') ?>">
    <dl>
        <dt><?php echo $this->formLabel('phone') ?></dt>
        <dd><?php echo $this->formText('phone'); echo $this->errorMsg('phone', $this->errors) ?></dd>
        <dt><?php echo $this->formLabel('email') ?></dt>
        <dd><?php echo $this->formText('email'); echo $this->errorMsg('email', $this->errors) ?></dd>
    </dl>
</form>
I've found that this method allows the most freedom in advanced form creation (most forms are not this repetitive and simple) as well as uses the least code possible to get the job done. But... that's just me. :)
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: MVC, Forms, and JavaScript

Post by matthijs »

Wether you need or want a separation depends on the situation I think. Maybe the reason that the MVC separation is not always followed with forms is because forms have so many "connections" between the layers.

But I think using your view/template layer like this will give a quite clean V separation and complete freedom in styling everything

Code: Select all

 
        <form action="/login/" method="post">
            <fieldset>
                <div>
                    <label>Username</label>
                    <input type="text" name="username" value="<?php echo htmlentities($username, ENT_QUOTES, 'UTF-8'); ?>" size="20" class="text" />
                    <td><span class="error"><?php echo $unerrmsg; ?></span>
                </div>
                <div>
                    <label>Password</label>
                    <input type="text" name="password" value="" size="20" class="text" />
                    <span class="error"><?php echo $pwerrmsg ?></span>
                </div>
                <div>
                    <input type="submit" name="submit" value="Log in"/>
                </div>    
            </fieldset>
        </form>
 
And then when you manage to separate the form processing logic from the underlying models you've separated the M and C.

[edit] Ninja's example is nice
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: MVC, Forms, and JavaScript

Post by Christopher »

VirtuosiMedia wrote:At the risk of spawning a debate, I have a question. I've read in one of the threads here that 'forms are a special case' in MVC-style architectures. I can see why because you are required to process the forms and true MVC separation isn't always practical for doing so.
I would be interested in knowing where someone said that forms are a special case in MVC. I don't think they are. What makes them a special case or not doable in MVC?
VirtuosiMedia wrote:I like the idea of separating the model, view, and controller for the most part, or at the very least separating the view from everything else, but is there a good solution for forms being as they constitute a large part of almost any web app you'll make? I'm not wedded to MVC for MVC's sake...I'm just looking for something practical.
The problem with forms is mainly that they are not fun so programmers want to take shortcuts to avoid the pain. Nothing wrong with that, but what makes forms a 'special case' to me is that every shortcut leads to even more pain as the problem changes or gets more complex. Usually a programmer can take a shortcut and maintain that style -- but not forms.

The main question with forms is whether you consider the form data to be in the Presentation layer or the Domain layer -- meaning in the Controller or the Model. I should note that all the shortcuts involve making the form part of the Controller. That provides the most immediate pain relief, but causes the most problems later. Also there is the question of whether the form itself is a Model separate from the Model in the domain where it loads/saves its data from/to.
VirtuosiMedia wrote:Also, I was reading DZone today and I saw this article about writing two layers of MVC, one for the server and one for the browser (a combination of JavaScript, CSS, and HTML). I thought I would point it out and see what everyone thought about it.
I don't think you have your M, V and C quite right. They will all be some Javascript probably. And adding a MVC layer in the client really does not change the design and responsibilities of the server side form code.

The next step past Ninja's example is to combine things like this (but you should be able to do it both ways):

Code: Select all

$form = new A_Model_Form();
$form->addFilter(new A_Rule_Trim())   // no specific form element specified, so apply to all
     ->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
     ->addRule(new A_Rule_Email('email', 'Please enter a valid email'));
 
if ($request->isPost()) {
    if (! $form->isValid($request)) {
        $view->errors = $form->getErrorMsg();
    }
}
 
$view->render('account.phtml'); // view is a made-up view object
(#10850)
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Re: MVC, Forms, and JavaScript

Post by Luke »

I forgot to mention in my example that (like arborint pointed out) sometimes validation data might need to come from the model, or more often, some needs to come from the model and some needs to be added or removed on an action-by-action basis. That's why I like to add a getRules() and getFilters() method to my model so that it can add any bit of filtering / validation it needs to before you actually validate, for example:

Code: Select all

$myModel = new MyModel(); // made-up model object
 
 $filters = new A_Filter_Set();
 $filters->addFilter(new A_Rule_Trim()) // no specific form element specified, so apply to all
          ->addFilter($myModel->getFilters()); // getFilters() returns an A_Filter_Set() object which can be added just like a regular filter to addFilter()
 
 $rules = new A_Rule_Set();
 $rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
         ->addRule(new A_Rule_Email('email', 'Please enter a valid email'))
         ->addRule($myModel->getRules()); // getRules() returns an A_Rule_Set() object which can be added just like a regular rule to addRule()
  
 if (is_post()) {
     $data = $filters->filter($_POST);
     if (!$rules->isValid($data)) {
         $view->errors = $rules->getErrorMsg();
     }
 }
I like this because it allows me to pull validation from any source I want. A good example is when you have an "edit user" and a "my account" page. I usually don't allow users to change their own username, but the admin can. So I would do this:

In the model

Code: Select all

class myModel {
    public function getRules($admin = false) {
        $rules = new A_Rule_Set();
        $rules->addRule(new A_Rule_Phone('phone', 'Please enter a valid phone number')) // this will validate the "phone" element
              ->addRule(new A_Rule_Email('email', 'Please enter a valid email'))
        return $rules;
    }
}
 
in the controller's "edit user" action for admin:

Code: Select all

$myModel = new MyModel();
 
$rules = new A_Rule_Set();
// special rules for this action
$rules->addRule(new A_Rule_UsernameAvailable('username', $this->getPk(), 'The username you requested has already been taken. Please try another one.'));
      ->addRule(new A_Rule_UsernameWellFormed('username', 5 'Please provide a username at least 5 characters in length with at least one capital letter and at least one number.'));
      // standard rules all myModel actions use
      ->addRule($myModel->getRules());
 
See how that works?
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: MVC, Forms, and JavaScript

Post by VirtuosiMedia »

arborint wrote:I would be interested in knowing where someone said that forms are a special case in MVC. I don't think they are. What makes them a special case or not doable in MVC?
Here is where I got the 'forms being a special case in MVC' quote from.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: MVC, Forms, and JavaScript

Post by Christopher »

VirtuosiMedia wrote:Here is where I got the 'forms being a special case in MVC' quote from.
I don't think Kieran meant 'special case' in the sense I of 'unique' if you read the rest of his post. When you add a data element to a Model, you usually have to change the View to reflect that data. If a new element gets added to an XML feed then you will will need change your Model to hold that new element.

Forms are certainly make the connection between the Model and View more obvious and immediate that other things. I think maybe that is what Kieran meant (but I try not to second guess Mr. FTW ;)))

Back to what I think was you initial question, I do think there are some very interesting possibilities with doing more in the client. The simplest would be to get out of the business of generating HTML on the server side. A Javascript library independent way for the server side to provide form information so it could initialize and render the form as needed would be really nice. Next would be doing client side validation would decrease load on the server -- another win.

If you are interested in this stuff, I know a project looking for someone to work on a client side forms solution. ;)
(#10850)
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: MVC, Forms, and JavaScript

Post by VirtuosiMedia »

arborint wrote:A Javascript library independent way for the server side to provide form information so it could initialize and render the form as needed would be really nice. Next would be doing client side validation would decrease load on the server -- another win.

If you are interested in this stuff, I know a project looking for someone to work on a client side forms solution. ;)
I'm actually pretty close to having a clientside validation script done using MooTools. There are few issues that still need to be worked out across browsers. I've been working on another project, but I should finish that up this week hopefully and I'll be able to get back to it. Once I get the issues solved, I'll opensource it. You guys are welcome to make use of it if you want. There aren't any onclick, onsubmit, or onblur events that you have to put into the form elements...those are all handled by the script. It will allow you to specify whether or not the error messages are above or below the input, the label and the input both have error and success states that are controllable by CSS, you can choose to disable the submit button if an error occurs, you can specify customized error messages for each validation check, and you will be able to choose from a few preset validations or enter your own regex. The syntax will be similar to the following:

Code: Select all

 
<script type="text/javascript">
        window.addEvent('domready', function(){
                var form = new Validator('form');
                form.empty('firstName', 'You must enter a first name');
                form.alpha('firstName', 'Name must be alphabetic'); 
                form.empty('email', 'You must enter an email'); 
                form.email('email', 'The email address you entered is not valid'); 
                form.validateRegEx('hello', 'helloInput', 'You must type hello'); 
         });
</script>
 
My goal is to be able to generate the above to use with a server side validation class that uses the same filters and error messages.
User avatar
inghamn
Forum Contributor
Posts: 174
Joined: Mon Apr 16, 2007 10:33 am
Location: Bloomington, IN, USA

Re: MVC, Forms, and JavaScript

Post by inghamn »

I don't see forms as a special case of MVC at all. In my stuff I treat forms like any other HTML markup. I think of forms as a way to tell the user where to send their data, and what data the server accepts. It is very much a web application as a service.

The view has the form markup no different from any other view in the system. You still have to escape any data you display.

The controller creates the view and tells it to render itself. But also looks for and handles user input coming from GET and POST. By handle, I mean that it makes sure the user is allowed to send the data they;re sending. It then instantiates the model and passes all the data to the model. It may also tell the model to save itself.

The model handles all the data validation.

As far as the controllers are concerned, they don't care whether the data came from the user interacting with an HTML form and hitting submit, or if the user used some AJAXy thing to send data. It is only concerned with reading the incoming data and passing it along to the model.

The same controller becomes a service. One that can read and respond to HTML as well SOAP, JSON, XML-RPC, or plain text. It's always just reading the input a view and telling the view to render.
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: MVC, Forms, and JavaScript

Post by Eran »

I very much agree with inghamn. In addition, when using an MVC structure form reuse becomes much easier. Some actions use essentially the same form (such as an add / edit action for a content item, or registration form / editing user profile), so reusing the same template with different controller actions / model methods can save much time on development and increase consistency all around.
User avatar
VirtuosiMedia
Forum Contributor
Posts: 133
Joined: Thu Jun 12, 2008 6:16 pm

Re: MVC, Forms, and JavaScript

Post by VirtuosiMedia »

So should the actual form itself be generated by the class or should it be written out in full HTML with snippets of PHP to generate values, errors, and such? I think that may be my root question more than anything else in regards to forms and MVC. I might be wrong in my definition, but the way I understood it, using MVC you are usually trying to separate the view so it contains as little PHP as possible so that it basically serves as an HTML template, which is much easier to edit by more people than having it generated by a class.
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: MVC, Forms, and JavaScript

Post by matthijs »

I would say that if you want a clean separation you would write the form in full HTML with little snippets of PHP, only echoing out the values and error messages. See the short example I gave earlier in the thread.

The point is not to remove all PHP (although it's possible with template systems as smarty), but to remove controller and/or model logic and only keep small presentation code.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: MVC, Forms, and JavaScript

Post by Christopher »

VirtuosiMedia wrote:So should the actual form itself be generated by the class or should it be written out in full HTML with snippets of PHP to generate values, errors, and such? I think that may be my root question more than anything else in regards to forms and MVC.
It can be either. The decision is dictated by the problem being solved and your personal taste.
VirtuosiMedia wrote:I might be wrong in my definition, but the way I understood it, using MVC you are usually trying to separate the view so it contains as little PHP as possible so that it basically serves as an HTML template, which is much easier to edit by more people than having it generated by a class.
This is one of the major misconceptions about MVC. The View is the part of the Presentation Layer that is responsible for rendering the Model is a specific way. There can be may Views for a Model. The View often has much more code than the Model does in fact, because the output is often more complex than the Model's data and logic. You are free to put as much PHP code into your Views as necessary. Think if all the code in modern template libraries -- that is all View code. All the code that uses a template library in your app is View code as well. People often put that code in the Controller (which is also in the Presentation Layer) so the View code is in a Controller action.
(#10850)
acidHL
Forum Commoner
Posts: 41
Joined: Wed Dec 07, 2005 7:38 am

Re: MVC, Forms, and JavaScript

Post by acidHL »

To echo what some of the folks have already said... I don't think forms are particularly a special case, you just need a flexible helper for outputting validation errors. I tend to write form-heavy applications on CodeIgniter and don't really have a problem with code separation.

If you wanted to be pedantic about no PHP in your view then you could surely solve the problem with clever use of a template engine?
Post Reply