Jump to content

Framework/MVC/Design Patterns Learning Curve


Recommended Posts

Okay, I have a slight problem.  I've got PHP down pretty well, I've got the basics of OOP down, and I'm fairly well at programming. However, I have a slight problem. I've been wanting to move my site over to a OOP/MVC code, but it is giving me problems. It shames me slightly to admit it, but admitting ones problems is the first step to solving them, but I can't seem to learn how to use a Framework, wrap my head around MVC, nor do I see the point/know the first thing of a Design Pattern.

 

I've read all the topics in this board with similar questions, went to the websites, went through tutorials and explanations, etc. but I can't seem to get my head wrapped around it.  Is there anyone here that can tell me something that might help?  I'm like the old dog that you can't teach new tricks to, but I want to learn the new tricks.  :'(

Link to comment
Share on other sites

Design patterns are common solutions to common problems. They are something that you just try to implement because you can, which is the outlook that many people try. Patterns tend to reduce complexity and make code more reusable by breaking components down into parts.

 

It's a good idea to separate OOP and MVC in your mind, while the two generally go together they don't necessarily have to. The point of the MVC (Model-View-Controller) system is to separate data, logic, and display from each other, much like separating the PHP logic files from the PHP template files, though on a larger scale.

 

Frameworks generally use a URI based system to find which controller and view to use. They simply look at the controller specified, then the action specified, and call the action method of the controller object.

Link to comment
Share on other sites

That went way over my head.  :(

Which part? Or all of it?

 

The most simple way to break down MVC is in 3 groups (not necessarily classes).

 

The model represents the layer that interacts with the database. It uses queries to select, update, create, and delete from the database.

 

The controller represents programming logic. This is the stuff that handles the actual action of a page. It calls on the model to do any querying. Generally, the controller will then call upon the view associated with the action.

 

In most cases the view is just a file that has bits of PHP by which variables can be plugged in. If you have any experience with a templating engine then this is similar, though it doesn't necessarily use a templating engine either.

Link to comment
Share on other sites

Hmm...okay, that borke it down a bit easier than the rest of the sites.  Let me see:

 

If i created a page to view something from the database I would need to have the controller to call on the model to access the database.  Else, i will only need to call on the controller and echo the raw data to the view page?  That sort of makes sense, but i feel like this doesn't even begin to scrape the surface of MVC or any of the others. :-\

Link to comment
Share on other sites

(off topic: not sure what happened, but the word 'model' was being blanked out...I filled in the gaps, which was like doing a newspaper puzzle :) )

 

anyway...this is no disrespect to Eric_Ryk for his explaination or Ronald for not getting it, but sometimes I think half the problem with MVC and frameworks (and patterns, for that matter) is the way they're explained. Personally, I remember asking these same questions and scratching my head at the same answers. So I guess it might be easier to explain the benefits I've found...

 

I'm sure we all remember our first scripts. You'd have a HTML page and above the doctype, you'd throw most of your PHP code, and in between the HTML you'd throw more PHP code to display whatever. After a while, you got bored of the site and wanted to give it a nice new lick of paint. Only - the problem was, all the HTML is mixed up with your PHP. Whilst copy and pasting is all good and well, it takes a good chunk of time. So then you discover templating (be it Smarty or a pure PHP version) and realise that you can seperate your main code from your templates. If you need to change the functionality then, all you need to deal with is PHP. Wanna change the look? no worries - just change a template without worrying about buggering up your code :) What you've essentially just done is seperated your logic (M+C) from your presentation (V).

 

The next step I guess is just clearly defining two areas - the Model and the Controller. If for example you want to move your database to MSSQL or PostGreSQL or even text, or even change the table structures (just the same way as you might change your sites style), then you need to sift through all your code thats responsible picking out that code concerned with DB access and change it to suit. Seperating this from the off means if you want to change the way your database is accessed or handled or even the database system altogether, you're just dealing with the Model without breaking your actual code.

 

So to me, the seperation means:

- everything is very organised

- I can change the look of the site without breaking the site itself

- I can change the way the database is handled or even restructure/rename my tables without breaking my site

- I can change the operation of the site without worrying if i'm breaking my database or the HTML

 

The CakePHP way of handling databases is fantastic. To kit out my database table with all the methods I need, all I need to do is set up a model file only a handful of lines long that extends a base class, and I'm set to go. Even table joins, etc - you might just do:

 

$post = $this->Post->read(null, $post_id);

and your $post var will not only have the blog post in question, but all of the comments belonging to that post, too. Ok, it's a lame and cliched example, but how many times to you deal with table joins, etc and then format the results afterwards to get them in the right way and how much code does it take? or how many times do you set up little functions that will, for example, turn a user_id into a username?

the list goes on, but essentially all that has just taken one line. Odds are, you'll probably use exactly the same structure for your Posts or Users tables etc in another site - no problem. Just copy the model over, and you probably wont even have to make changes to it either - it'll just work :)

Since I wrote my first site using my framework, I've not had to write either a login system or article system since. I just use the same one :)

 

As for patterns - if I'm honest, I dont have a bloody clue other than MVC, though in using a framework, I'm probably using them without either knowing or knowing what they're called...Personally, I don't think it's important to have a full knowledge of design patterns to be able to benefit/enjoy working with MVC frameworks.

 

In summary, MVC = nice way of organising and making changes to parts of site without breaking other parts. Framework = nice way of ridiculously speeding development up by allowing you to concentrate on site specific code rather than mundane tasks that you do each and every time.

Link to comment
Share on other sites

Hmm...okay, that borke it down a bit easier than the rest of the sites.  Let me see:

 

If i created a page to view something from the database I would need to have the controller to call on the model to access the database.  Else, i will only need to call on the controller and echo the raw data to the view page?  That sort of makes sense, but i feel like this doesn't even begin to scrape the surface of MVC or any of the others. :-\

Yeah, that is essentially what the pattern is. You have it right there, the only thing that complicates the pattern is that the framworks that use MVC couple in many other patterns and features that don't necessarily go with MVC itself. Other patterns can be used to strengthen the MVC relation, but are not actually required.

 

A good way of working out the MVC pattern is to define three classes, Model, View, and Controller.

 

Then from these three classes you extend actual classes (except for view). So say you have some pages that are used to view and interact with the "users" table, you would load the Users_Controller, and then call the action of the page. The Users_Controller would load any necessary models that it needs, chances are the Users model will be included, though you may want others such as a messages table by which they could access private messages.

Link to comment
Share on other sites

wow.  I mean a lot of it makes sense, but I still think it is going to be a bugger trying to figure out.  I'm going to grab a framework, I guess CakePHP, and see what I can do.  But, i don't get something. If a framework is a bunch of pre-packaged scripts, what if it doesn't have a script I want?  How do I go about creating a script? Like say I download a framework and it can do a user system and a news system, but I wanted to create a shopping cart.  Do I have to go in and edit all the source and add to the source files so I can create a shopping cart?

Link to comment
Share on other sites

with frameworks like Cake, you'll find many scripts on their site to simply download a plug in - whether there's a shopping cart, i don't know but otherwise, it wouldnt be that different to any other type of integration. If you need to break the MVC pattern sitewide to integrate something, then so be it.

CakePHP and CodeIgniter keep plugins/extensions seperate - so adding a new one is pretty much a case of throwing it into the plugins/components directory and then it's available to use.

 

You could do worse than setting up Cake and playing with it, even if just following through the blog tutorial that's on there. I'd say take an hour or two to learn/suss out how to install, and about the same again to fully complete and understand the blog example. Look at the RubyonRails screencast too - Cake is based heavily on Rails, so the priciples are almost identical. Seriously, I know what position you're in - only not so long ago, I was exactly the same as you but then it just kinda clicks and you just get it. Hold on in there - the benefits are HUGE :)

Link to comment
Share on other sites

Frameworks aren't prepackaged scripts so much as they a way to speed up development (at least when you get the hang of it). I used CakePHP for a while, and I'd agree with going for that one. The one problem that you may find is there is a lot of "magic" which you might have to dig through the source to figure out.

 

Overview of building a shopping cart in CakePHP:

To create a shopping cart you'd first set up the database structure that you want. Then set up a model for each additional table that you added (instructions are given on the CakePHP website). Now you could create a controller for each table itself, but I'd recommend creating a "Shopping_Cart_Controller" in which you set the $uses variable to all the models you just created (in other words you make them available for use in the controller's methods). Then you create a folder in the views that is titled Shopping_Cart, and you can add .thtml files in there that will match any methods/actions in the controller.

Link to comment
Share on other sites

wow!  Eric it sounds like you know what your talking about, but that all just went way over my head. Plus, i was just using a shopping cart as an example. My main point of the post was to ask what happens when you want to create something that isn't prepackaged in CakePHP. Do you add to their source files or do you create your own or what?  But I think you answered some in your post, and redbullmarky answered it in his too.

Link to comment
Share on other sites

I'm still a big fan of ZF. In fact, I think it is now so good and extensible that I stopped development of my own framework core. I still use my own View package though, as well as some adaptors for specific components. As time passes, I'm sure I'll extend some more of the functionality ZF provides: Zend framework is VERY extensible.

 

If you follow Zend (PEAR) naming conventions you can even use Zend_Loader to load your own components (alternatively you could use spl_autoload_register - I don't really recommend it):

 

dir.gif

 

index.php is basically only a bootstrap for the frontcontroller (and I use it to define __autoload):

 

<?php

Bib_Settings::init();
include 'Zend'.DIRECTORY_SEPARATOR.'Loader.php';

function __autoload($name){
Zend_Loader::loadClass($name);	
}
Zend_Controller_Front::run(Bib_Settings::APP_CONTROL_DIR); 
?>

 

Zend uses what they call 'ActionControllers', which is where the communication with the View and Model takes place. These user defined controller classes update the Model, and decide what View to display. Something like www.mysite.com/user/login would be dispatched to the class UserController, method loginAction.

 

A simplified UserController may then look something like this:

 

<?php
class UserController extends Zend_Controller_Action {

//Override Zend_Controller_Action::init. Normally you would subclass this.
public function init(){
	if(!Zend_Registry::isRegistered('view')){
		Zend_Registry::set('view', new Zend_View);
	}
	$this->view = Zend_Registry::get('view');
	$this->view->setBasePath(Bib_Settings::VIEW_DIR);
	$this->getResponse()->setHeader('Content-Type', 'text/html');
}
public function indexAxtion(){
	//Display default view		
	$this->render('index.php');
}
public function loginAction(){

	$user = new Bib_User($req->getPost('user'), $req->getPost('pass'));

	if($user->login()){
		//Login succesfull
		$this->view->title = 'MySite - Member area';
		$this->view->member = $user->username;
		//Display member specific view
		$this->render('member.php');
	}
		//Login unsuccesfull
		else {
		//This isn't right:
		$this->view->errorMsg = Bib_Message::format(User::LOGIN_FAILED);
		//Back to user index
		$this->_forward('/user/index');
	}

}
//Override Zend_Controller_Action::render. Normally you would subclass this.
public function render($contentScript){
	$this->view->contentView = Bib_Settings::VIEW_CONTENT_DIR.DIRECTORY_SEPARATOR.$contentScript;
	$this->getResponse()->appendBody($this->view->render('index.php'));
}
}
?>

 

Note that for this example I used the standard Zend_View (and I don't do input filtering). The index.php view represents the base XHTML you use on every request. $view->contentView refers to the variable part of the view. In index.php you can do something as basic as:

 

</div>
     <?php include $this->contentView ?>
</div>

 

Zend_View uses magic methods to accept updates, but in strict MVC terms, the View should get it's updates directly from the Model, instead of the ActionController telling the View what exactly to update. In the later approach, the Controller acts as mediator between the View and the Model, which (temptingly easy as it may look) is not the way MVC is supposed to work. You may end up with multiple Controllers doing the same formatting if they use the same View. A better approach would be to simply provide the View with a reference to the Model, and fetch data itself:

 

<?php
public function loginAction(){

$this->user = new Bib_User($req->getPost('user'), $req->getPost('pass'));
$this->view->user = $this->user;

if($this->user->login()){
	//Login succesfull
	$this->view->contentView = 'member.php';
	$this->render();
}
	//Login unsuccesfull
	else {
	//Back to user index
	$this->_forward('/user/index');
}	
}
?>

 

The conditional if($this->user->login()) acts as both a control condition and the initiation of domain logic. Achieving full separation between the MVC triad members is a constant struggle, and arguably impossible (depending on your interpretation).

 

Note that a reference to the Model (only User in this case) is made available to both the controller and the View. This is how the MVC is supposed to work: View and Controller have equal opportunity to access the data in the model (even though it is the Controller that initializes the Model status - you could say the View has "read-only" access to the Model).

 

Example fragment of View:

 

<div id="msgContainer" class="subnavselected">
     <?php echo Bib_Message::format($user->getStatus()) ?>
</div>

 

Domain Model class (basically meaning representation of an application specific entity, incorporating data and behavior) User can use a Data Mapper or DAO (Data Access Object) - those are almost the same - to fetch data, achieving an extra degree of decoupling of the Domain Model and the data handling layer:

 

<?php
public function login(){
	if($this->dao->fetch($this->username, $this->password)){
		$this->setStatus(User::LOGGED_IN);
		return true;
	}
		else {
		$this->setStatus(User::LOGIN_FAILED);
		return false;	
	}
}?>

 

Please note that I've simplified this a whole bit, and you may want to look into the terms I've used.

 

All in all I recommend you just try out something basic like this first. If you run in to any problems I'm available through PM to help you out.

 

I also recommend you pick up a book. Matt Zandstra's Objects, Patterns and Practice is pretty good, and all the examples are in PHP (5), which is a rarity.

Link to comment
Share on other sites

After noticing a comment in one of the previous replies, I feel compelled to add the following clarification:

 

The Domain Model does NOT strictly interact with the a data handling layer like a database layer. In fact, Domain Model objects can interact with various aspects of the data handling layer, like a session handling class. The Domain Model provides a level of abstraction between the data handling layer (sessions, database, xml, pretty much anything that handles 'external' data) and the two MVC triad member that are not part of the Model: the View and Controller. The Domain Model classes define most of the specific behavior of your application. I.e. how a user login affects the database (possibly the login attempt - failed or succesful - is stored). Interaction between various Domain objects is usually required; Maybe you want the ip involved in a failed login attempt logged: employ the Observer pattern and notify a Logger class of a failed login attempt. Both are Domain Model objects. Logger may interact with the data handling layer (possibly simply represented by PHP's standard stream layer - e.g. file functions) to write a log file.

Link to comment
Share on other sites

You know Nike's slogan? Just do it. Try something basic like a user login. Then you have a frame of reference and things will start to make sense.

 

Like with any pattern, you need some frame of reference to grasp how it works and what problem it solves. As for frameworks; Cake and such is nice and all, but ZF is far more extensible. ZF is one of those things that makes life easier, without trying to do too much for you.

 

Just try it, I'm pretty sure your head won't explode (I think).  ;)

 

Don't be put off too much by the terms used, most of them are simply handles for things you've been doing all along in some form on another (or will be doing).

 

You never really learn unless you apply.

Link to comment
Share on other sites

John - take a little step back a minute dude. I consider you very knowledgable in this field and I kinda understand half of what you're on about - but skip back up to Ronalds original post and you'll see that - absolutely no offence to Ronald - things need to be put into a bit more simplistic terms - even for my own benefit :)

 

Consider the fact that not everyone cares much how extensible/fast something is - as long as it does the job nicely and comfortably and enables them to learn, that's all that's required. Be honest - Zend Framework is not for the feint hearted or the learner, as it's very advanced and hugely easy to get very very lost indeed. Learn to walk before running, etc, etc.

 

For me, heavy OOP and best practices are the deep end of the swimming pool. At the other end is something simple like a templating engine, a bit further on you have code igniter, a bit deeper you have cake then maybe symfony. Diving into unknown territory without picking up some of the basics and terminology first is one surefire way to get pissed off and give up altogether.

 

At college when I was dabbling in C++ and trying to make a simple graphical game, one of my fellow students suggested I started writing certain routines in Assembly language "because you'll save several ticks of the clock cycle hence fully optimising the routine making things run about 9000 nanoseconds quicker". If i'd have jumped into assembly there and then, I'd probably have gotten out of coding altogether....

Link to comment
Share on other sites

I'll do my best to try and talk 'monkey' (thanks CV)...  :P

 

I disagree that ZF is not for the learner, I believe you're better off learning things the right way from square one. As far as the terminology goes, like I said before, most of it concerns concepts you've already used. I agree that you should have some reference, even when using something like Cake. Which is why I HIGHLY recommend some reading before diving into MVC in general.

 

At the risk of 'talking to the wall' I'll still include some simplified explanation on how to create a proper model:

 

First off, a framework doesn't provide you with a finished Model. It'll probably provide data handling layer classes, but a Database class doesn't make a Model. This is where the Domain Model pattern steps in. The Domain Model is a very basic concept, that might remind you of when you first learned OOP. The Domain Objects are things that do stuff. Where in many other parts of an application the focus is on a responsibility (i.e. Controller: controls, Logger: logs - sorry that was a bad example in my previous post), Domain Objects focus on subjects. The Domain Model is at the very core of an application. Hence the popularity of Domain Driven Design (DDD).

 

(Note about '* Driven Design' paradigms: they aren't exclusive. )

 

If you (i.e.) have an Article class, a User class, etc, you are close to having a Domain Model. When you decouple these classes from the data handling layer, for example using Data Access Objects, they become highly reusable and you probably have what could be considered a Domain Model. A DAO will be dependent on the database schema; by encapsulating (hiding) this dependency, you are able to reuse your Domain classes regardless of the database schema.

 

I would've extended a little and gone into OOAD, but lets try and keep it simple...  :)

 

Link to comment
Share on other sites

A final note about extensiblity and reusability: to not care about those is like not caring about having to make dough for a cake (pardon the pun) twice. Or ten, thirty, maybe a hundred times. Baking a cake is more fun when you can skip the tedious repetitional parts of the process. Extensibility is usually also an indicator of reusability.

 

So: avoid boredom AND develop with lighting fast speed (getting faster which each project). It can hardly get any better.  :P

Link to comment
Share on other sites

haha!  wow, i feel so overwhelmed.  Against what I'm sure most people say, I grabbed CakePHP.  I had me a PDF of the manual, I've spent all day reading the manual and doing no coding.  It is a lot to learn, but I needed to learn the basics and it is pretty good at laying it out for you.  So, I'm working with CakePHP. It is pretty complex, but I think I might survive. It is just so overwhelming learning all this new stuff.

Link to comment
Share on other sites

this is why new coders seem to find Ruby on Rails "easy" - they're learning the whole thing, including the framework/MVC and the actual language all from the off. As you said from the start, "teaching an old dog new tricks" is pretty tricky but definitely possible - and yet it depends on how you're doing things already.

 

What I like about some of these MVC frameworks (Cake included) is the way they deal with the view. Some people are used to the whole [pre]include('header.php')[/pre] and [pre]include('footer.php')[/pre] style of coding - what Cake does is to have a sitewide standard "outer" template (called a 'layout') that contain all your doctypes and basic structure, etc and the inner changing templates that hold your page content (views). The 'view' is automatically chosen based on the 'action' name within the controller - so calling the login action within the users controller (uri: mysite.com/users/login) would look for the file called '/app/views/users/login.thtml' or something like that automatically. All that said, it's generally a totally new method to lots of people that's hard to grasp at first.

 

As we all like to "see" things happening, you can safely sod the model for now. From the way I picked it up and went through the confusion, I'd suggest getting to grips with everything on the Controllers page as it pretty much covers EVERYTHING you need to get a working site (including interracting with views). In many ways, even if you decided to ignore the rest of the whole framework, you could still put together a fully fledged site knowing everything on that page. Once you're up to speed with that, then the Model and other areas will make LOTS of sense

 

Good luck!

Link to comment
Share on other sites

I'm very new to programming, but I am attempting to at least understand MVC. I'm going to lay out a basic idea for what I understand.

 

This is the frame(file structure) I would start everything in.

 

Model-      This will contain all of the data base(sql) retrieving functions.

Controller-  This will have objects that will be referenced to from my index.php in order to perform actions.

        Actions-Uses the Model folder to retrieve, send, update, delete data from the database; and reference to the correct 'template' in the View folder.

View-        This folder will have the css files, graphics files, and html files that the index.php will access to output the view according to the situation.

 

I don't know if this is just a simplistic view  of it or a wrong view, but this is what I have seemed to gleen from my reading this far.

 

I would also have another folder for javascript and possibly also for larger php scripts with specific functions(shopping cart) etc.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.