Page 1 of 1
MVC and PHP
Posted: Tue Jul 24, 2007 1:07 pm
by timclaason
In the past, when I've had big database applications in PHP, I've put pages together like this (kind of a crude example):
form1.php
Code: Select all
<FORM METHOD='POST' ACTION='somepage.php'>
<TABLE>
<TR>
<TD>Field 1</TD>
<TD><INPUT TYPE='TEXT' NAME='whatevername'></TD>
</TR>
</TABLE>
<INPUT TYPE='SUBMIT' VALUE='Submit'>
</FORM>
somepage.php
Code: Select all
$post1 = $_POST['whatevername'];
$obj->doSomethingWithPostVariables($post1);
However, if I have a form with a bunch of fields, any changes result in a lot of work.
If I'm understanding MVC concepts correctly (and I'm not claiming that I am), I would think a better way to build applications would be to:
1. Have a database table that links each page with what fields a particular page's form should have
2. On the form page, populate the form with data from table in step 1.
3. On the post page, have the page determine the referrer (or perhaps pass it through as a querystring
4. Then have a method for the post page to extract the fields the referring page should have posted
5. Then the post page can do what it needs to with the posted variables
If it were done like this, it seems like it would be a good way to separate view components, and be more MVC-compliant.
Am I understanding MVC correctly, here? Does doing it this way make sense?
Posted: Tue Jul 24, 2007 3:33 pm
by Begby
No, thats not really MVC.
MVC is about separation of concerns and splitting up what happens on pages.
The view is only concerned about displaying data. You pass the view some data, and it displays it with no logic involved. (although often a bit of logic is required).
The controller takes input, grabs your model and sends it data, gets data from the model based on the input, passes data to a view, then sends the view to the client to see.
The model is where the business or domain logic goes. This is usually a set of classes that interface with a database and has logic to filter the data, get the data, save data, etc.
If your site is written using MVC well, then the model and the view can function completely independently. You should be able to create a view and send it some data without calling your model, and you should be able to write a command line script that uses nothing but your model to retrieve and save data.
Anyways, read more about it or post back here with further questions.
Posted: Tue Jul 24, 2007 5:11 pm
by kyberfabrikken
Begby wrote:
The controller (...) gets data from the model based on the input, passes data to a view, then sends the view to the client to see.
In MVC, the controller shouldn't tell the view, which model to use. The controller isn't a mediator between model and view. Think of controller as write-interface to model, and view as read-interface to model.
I'm nitpicking here, but this is a very common misconception, so I can't help my self.
Posted: Tue Jul 24, 2007 6:41 pm
by Begby
In my code though I don't tell the view which model to use or anything like that. Instead the controller takes the input, like maybe an ID, then passes it to the model. The model uses that ID to look up some data and then return it to the controller. The controller then takes that data and passes it to the view.
Is this correct?
Posted: Tue Jul 24, 2007 6:46 pm
by alex.barylski
kyberfabrikken wrote:Begby wrote:
The controller (...) gets data from the model based on the input, passes data to a view, then sends the view to the client to see.
In MVC, the controller shouldn't tell the view, which model to use. The controller isn't a mediator between model and view. Think of controller as write-interface to model, and view as read-interface to model.
I'm nitpicking here, but this is a very common misconception, so I can't help my self.
How then is the View supposed to be aware of which data to use?
Posted: Tue Jul 24, 2007 8:23 pm
by timclaason
Consider the following crude example:
page1.php
Code: Select all
$id = $_SESSION['id'];
$name = $obj->getName($id); //getName() returns a value from a db
$address = $obj->getAddress($id);
$city = $obj->getCity($id);
Code: Select all
<FORM METHOD='POST' ACTION='page2.php'>
<TABLE>
<TR>
<TD>Name</TD><TD><INPUT TYPE='TEXT' NAME='uname' VALUE='[syntax=php]$name
'></TD>
</TR>
<TR>
<TD>Address</TD><TD><INPUT TYPE='TEXT' NAME='uaddress' VALUE='
'></TD>
</TR>
<TR>
<TD>City</TD><TD><INPUT TYPE='TEXT' NAME='ucity' VALUE='
'></TD>
</TR>
</TABLE>
<INPUT TYPE='HIDDEN' NAME='id' VALUE='
'>
<INPUT TYPE='SUBMIT' VALUE='SUBMIT'>
</FORM>
[/syntax]
page2.php
Code: Select all
$id = $_POST['id'];
$name = $_POST['name'];
$address = $_POST['address'];
$city = $_POST['city'];
if(isset($id, $name, $address, $city)) {
$obj->setName($id, $name); //Update DB, set name=posted name
$obj->setAddress($id, $address);
$obj->setCity($id, $city);
}
else {
print("Input error. All fields are required. <a href='page1.php'>Click Here</A> to try again");
}
All in all, I interpret each as the following:
View: page1.php: The form (including variable values), the print() from the "else" statement from page2.php
Controller: page1.php: getName(), getAddress(), getCity(); page2.php: setName(), setAddress() setCity()
Model: page2.php: if, else
Am I wrong in this interpretation
Posted: Tue Jul 24, 2007 9:01 pm
by Begby
Here is an example from a Zend Controller that I am working on right now, the URL for this is something like
https://mysite.com/users/edit/id/10
Code: Select all
// This object is the controller, it handles requests from the client to do stuff. In this case the user asked to edit a user, so the controller
// will call the edit action.
class UsersController extends zFCP_Controller_Action
{
public function editAction()
{
$id = $this->params()->requireInt('id') ; // Get input
$model = new FCP_User_Mapper($this->db()) ; // Get the model
$user = $model->findByID($id) ; // Use the model to fetch some data
if ($user === false) // Do a bit of error checking
{
throw new FCP_Exception('Invalid ID param specified') ;
}
// Pass the view some data, then render it using a template
$this->view->user = $user ;
$this->view->actionURL = $this->url()->get('update') ;
$this->view->render('default/users/edit_form.phtml') ;
}
}
Here is the view script
Code: Select all
<form name="user" method="POST" action="<?= $this->actionURL ?>">
<fieldset>
<legend>Edit User</legend>
<label for="username"><em>*</em>Username:</label>
<input type="text" name="username" id="username" value="<?= $user->getUsername() ?>" /><br />
<label for="password">Password:<br /></label>
<input type="password" name="password" id="password" /><br />
<sub>Only enter a password if you would like to change the existing one</sub><br />
<label for="password_match">Retype Password:</label>
<input type="password" name="password_match" id="password" /><br />
</fieldset>
<input type="submit" value="Save" />
</form>
Here is the method in the model that fetches a user
Code: Select all
public function findByID($id)
{
$sql = "SELECT
authID, authUsername
FROM
tblAuth
WHERE
authID = ?" ;
$row = $this->db()->fetchRow($sql, array($id)) ;
if (!$row) return false ;
$user = new FCP_User() ;
$user->setID($array['authID']);
$user->setUsername($array['authUsername']);
return $user
}
Posted: Tue Jul 24, 2007 9:11 pm
by Begby
Here is another example of a very simple MVC that doesn't completely adhere to the pattern nor has any security whatsoever. The url might look like
https://mysite.com/users.php?action=edit&id=10
users.php
Code: Select all
switch ($_GET['action'])
{
case 'edit' :
include('user_edit.php') ;
break ;
case 'delete' :
include('user_delete.php') ;
break ;
}
user_edit.php
Code: Select all
$sql = "SELECT * FROM users WHERE userID = $_GET['id']" ;
// run my query and fetch the results into $rows
foreach ($rows as $row)
{
echo $row['username'] . '<br />' ;
}
In this case users.php is the controller. It looks at the user request and loads the corresponding action script, in this case edit. The model here is the database which is accessed directly from the script, and the view is also in the same script which is the foreach.
Moving towards true MVC takes the above and breaks it up even more so that it is separated further into classes and functions. The above works ok because it is simple, but more complex code will begin to become a disaster if you have a ton of logic all over in the script and then have HTML mixed in everywhere.
Posted: Tue Jul 24, 2007 9:18 pm
by Begby
So in conclusion, you should dive in and start using an MVC framework. That will give you an idea of how it works.
A good one to start with is probably codeignitor. It has a lot of really good documentation and you can start out with just SQL right in the controller as your model until you get used to the whole controller/view thing.
Posted: Wed Jul 25, 2007 5:50 am
by kyberfabrikken
Hockey wrote:
How then is the View supposed to be aware of which data to use?
You program it that way.
Begby wrote:
In my code though I don't tell the view which model to use or anything like that. Instead the controller takes the input, like maybe an ID, then passes it to the model. The model uses that ID to look up some data and then return it to the controller. The controller then takes that data and passes it to the view.
Is this correct?
I'd rather not use the terms
correct and
wrong. MVC is often overkill, and you may be better off with a harder coupled V+C. A lot of self-proclaimed MVC-based frameworks/applications do in fact have a tightly coupled C+V (presentation layer). So they are more correctly explained as model-presentation than model-view-controller. (Eg. view and controller have merged into one entity)
timclaason wrote:
Consider the following crude example:
(...)
All in all, I interpret each as the following:
View: page1.php: The form (including variable values), the print() from the "else" statement from page2.php
Controller: page1.php: getName(), getAddress(), getCity(); page2.php: setName(), setAddress() setCity()
Model: page2.php: if, else
Am I wrong in this interpretation
The model is represented by $_SESSION, as well as $obj (Which it isn't clear where comes from).
page1.php is clearly part of the view. You use a template view pattern, so presumably the HTML is a template, and thus also part of the view.
page2.php is mostly controller code, although you have a bit of view code in there (The print statement), so it's not a completely clear-cut case.
Posted: Wed Aug 08, 2007 11:58 am
by thinsoldier
Begby wrote:Moving towards true MVC takes the above and breaks it up even more so that it is separated further into classes and functions. The above works ok because it is simple, but more complex code will begin to become a disaster if you have a ton of logic all over in the script and then have HTML mixed in everywhere.
What if stuff in my classes determines whether or not certain parts of the html get displayed or not (or have different classnames)?
that's why I still haven't used any of the templating systems. It just seems like an unnecessary layer that adds the unnecessary limitation of not allowing php to be used to make the markup react to certain things in the data.
Posted: Wed Aug 08, 2007 12:37 pm
by Christopher
Using PHP as a templating language is fine and sometimes the best choice. Using non-PHP templates can have the benefit of allowing non-programmers to modify the templates without the security or error creation risks.