I want to build a small ORM (Object Relational Mapping) framework in PHP. I want to do a mixture of an MVC approach, with the same controller/method/variable approach used by CodeIgniter.
There are a few frameworks out there already which do this, but things like
Form validation
Pagination
CRUD
And AJAX
are very difficult to do in these frameworks. My main goal, other than to have the entire functioning of the system be done using objects, is to use the DRY principle as much as possible. This mainly means very little repetitive code for form validation and CRUD etc.
I'm looking for ideas on how such a framework would be organized, what the architecture would be, and how a typical request such as a signup form and how to validate it, would be handled by this framework.
Please share your thoughts/ideas. This will be released as an open source framework, free of charge, when its finished.
I would probably suggest that rather than building your validation rules around forms (ala Zend Framework), you should build the validation within your domain objects. Then submit your form data directly to the domain object for validation. I am using Zend Framework, but I use this basic structure for my validation needs:
/**
* Contains the domain object properties.
* #var array
*/
protected $_data = null;
/**
* #var array
*/
protected $_filters = null;
/**
* #var array
*/
protected $_validators = null;
public function validate($data = null)
{
if(!$data) {
$data = (array) $this->_data;
} else {
$data = array_merge((array) $this->_data, $data);
}
$this->_input = new Zend_Filter_Input($this->_filters, $this->_validators, $data, $options);
$this->_input->addValidatorPrefixPath('LP_Validate_', 'LP/Validate/');
$this->_input->addFilterPrefixPath('LP_Filter_', 'LP/Filter/');
if($this->_input->isValid()) {
$this->_data = (object) $this->_input->getEscaped();
return true;
} else {
$this->_data = (object) $data;
return false;
}
}
Some of the limitations with my current approach with validation is that I can't call any necessary custom setters on the object properties and the fact that I need to figure out a way to keep the original data for the object available after running the validate function. But otherwise it has worked well so far.
As far as CRUD is concerned, the answer depends in part on the complexity of the problems you want to address and in part on what patterns you are familiar with and do/don't like and do/don't want to try to implement.
Obviously the most robust design to implement is to use Data Mapper with separate Domain Objects sitting on top. However, in most cases this is overkill and so you could just use the much (inappropriately) maligned Active Record pattern. This is basically what CodeIgniter and Zend Framework have done with what they have provided.
I ended up having to construct a custom ORM layer that uses the Data Mapper pattern because I needed to handle cases of Inheritance Mapping in my design and its worked pretty slick but I do regret losing the metadata mapping functionality that came with the Table and Row Gateway implementations in Zend Framework. (If you could find a way to effectively create metadata mapping using data mappers I want you to show me how you did it. :P). Even though you are trying to build your own, you might consider looking at Zend Framework as it has some of the finest PHP code I've seen and follows standard design patterns very closely.
One thing that would be nice to see in a Pagination class would be the ability to tie directly to a database object in such a way that the limit clause can be applied to the query based on what range of values the page should display. Otherwise, the key components with pagination are to keep track of current page, number of records to display per page, and some sort of collection object that contains the values to be iterated over.
At the very least though, you want to make certain that you don't preload the entire collection and then only display a certain range of records as this will provide a huge performance hit.
As far as Ajax requests are concerned, I would suggest building in some sort of context helper that can check for whether an HTTP Request is an XHR or not and then handling it specifically based on that context.
There are a lot of good open source frameworks out there that accomplish what you are looking to do much more easily and quickly than writing one from scratch! Having said that, I had an MVC framework that I developed that taught me a lot about framework development and object-oriented design. It is recommended if you have a lot of time and want to do it as a learning experiment (which may end with a pretty good framework).
As far as your idea of an ORM framework ... I think there may be some confusion about what ORM is. ORM is a technique that maps your objects to your relational database, handling retrieval and storage of data. It is usually one component in a larger framework, and does not necessarily characterize the framework itself. Most people throw around MVC framework, for the basic Model-View-Controller architecture on which an application can be built.
Some PHP frameworks provide more out-of-the box functionality, such as what you are interested in doing.
So, there are other threads on this, but I would say, build your own framework if you have time and want to learn. Use one of the many existing frameworks if you want to do something as easily as possible and in the shortest amount of time.
Great post by gabriel1836 but one neat technique you could use is pointed out by Matthew Weier O'Phinney where he shows a technique to "attach" the form to the model and use it for input filtering and validation. Very ZF specific but might come in handy.
Go with Zend, you can make so that each model object is "linked" to each of your tables, it does cover everything you said you need quite good.
Take a look at http://www.zendframeworkinaction.com/ its a good book for starting up with this. Even if you dont go with zend, it will teach you a lot of how it is build(if you decide you want to learn a lot about wheels by crafting your own, its a great starting point too!)
I would encourage you to take a look at http://www.qcodo.com. It's CRUD through the "Code Generator" is incredibly powerful, and seems to satisfy the requirements you've outlined.
As OT said, AJAX and Pagination is very difficult to implement in a flexible enough manner. It requires framework to be aware of what is on your screen, but most of the frameworks only produce HTML and don't concern themselves about client-side presentation.
There is a clear need for Web User Interface Framework.
That's why I'm suggesting to look into Agile Toolkit. Probably the following example will make it simple to see the power of integrated AJAX:
$b=$page->add('Button')->setLabel(rand(1,100));
$b->js('click')->reload();
This will produce a Button on the page with a random number as a label. Clicking the button will use AJAX request to reload button content showing you a new number.
With the foundation like that imagining how to built a paginator in a very AJAX-friendly way is a snap. Too bad paginator is already implemented and comes with the toolkit.
To cover other topics. CRUD is also a class/object.
$page->add('CRUD')->setModel('User');
And Form validation is done server-side but the errors are nicely displayed. All forms are submitted using AJAX requests.
Related
My problem is actually not the ajax loading itself, more the capability to load it without javascript. I mean, I cope easily when I code my whole project just based on ajax-availability OR just without the use of ajax.
//EDIT: Although Arend already had a more or less valid answer, at the same time 'there is no direct answer to this question'. However, I'd like to see some other approaches of developers for scenarios like mine though! Even just a few links can help!
Basically I just get frustrated, coding everything twice on the same page to make sure that both users without and with Javascript enabled have the same experience. It's annoying and I was always wondering how others solve this problem.
When I update for example two divs with dependency on the same variables, it gets messy. Here's an example:
non-js-version
require 'classobject.class.php';
$another_var = 'something';
$class = new classobject($_POST['variable']); // just an example to show that this is dynamic - I'm aware of injection!
$function = $class->returnsth(); // returns 1
if(isset($_POST)) {
echo '<div id="one">Module 1 says:'; $require 'module_one.php'; echo '</div>';
echo '<br /><br />';
echo '<div id="two">Module 2 says:'; $require 'module_two.php'; echo '</div>';
}
Now in module_two.php and module_two.php I have code that executes differently depending on the return variable of $function.
Like:
if($function >= 1 && another_var != 'something') {
// do stuff
}
else {
// do other stuff
}
Now as this works easily with a reload, when I want to load the two modules on keyUp/enter/submit or whatever, I have basically a few problems:
I have to send the $_POST variables manually to the modules to use them
I have to re-execute the class & it's methods and make a link (require_once) to them in each of the module-files.
As $another_var is not existent in the modules, I'd have to send this variable to each modules, too (with post for example) and then before it can be used, I'd have to 'change' it like $another_var = $_POST['another_var'];
I find this mildly annoying and I wonder how you guys do that. I hope my way of coding is not too silly, but I can't think of another way. It's probably hard to relate to my very basic example, but to bring a whole project with the code would be too much. To sum it up, I'm looking for a better way to code and clean this mess up - there must be a way! I thought about sessions, but for compatability I don't want to rely on them either (if someone doesn't allow cookies).
In case you can't relate to what I'm trying to accomplish with that way of having my code assembled, I'll explain a scenario I'm facing quite a lot (not important if you already understand my misery):
Basically I have my index.php page where everything gets executed, with the html body and css styling and so on. This page expects some variables, that get set from the page that requires the index (like $another_var in my example).
Now other variables can get set too (from a form for example). Depending on that different classes and methods load new variables (arrays) that get used in while-loops in my modules to echo everything out.
Hope that's not too abstract. Think of a booking system where some variables are set from the page you are coming from (the event you want to book) and then a few more things get set by the user (a timespan, some preferences,...). In the end it's supposed to show results from the database all the way to the end-result - you can say the user narrows the results from step to step.
There is no direct answer to your question, but there is some food for thought.
Seperation of concerns
You can think about if you can perhaps seperate your buisness logic and layout logic. Often the use of a template engine can help greatly with that. I've had positive experiences with for example Twig or Smarty (was some time ago, not sure how they measure up right now). It requires you to write your code in a (less linear) way, but more logical.
A typical example of an OOP like seperation of concerns might be something like this:
$this->setParam('Myparam','myvalue');
if ($this->isAjax())
{
$this->setTemplate('ajax.php');
$this->setLayout(false);
} else {
$this->setTemplate('normal.php');
$this->setLayout('Mylayout');
}
return $this->render();
It is an imaginative situation, which can be found in many MVC like applications and frameworks. The main idea is that you should have the possibility to seperate your layout from your data. I would suggest looking at some of the modern frameworks for inspiration (like symfony, codeigniter, zend framework).
Glossary / Often applied concepts in a decoupled PHP application
Here is a quick list of concepts that can be used.
Example mvc in php: http://www.phpro.org/tutorials/Model-View-Controller-MVC.html
Note: I don't really like the implementation. I much more prefer the existing frameworks. I do like the explanation in total of this tutorial. E.g. for me this link is for learning, not for implementing.
Silex
For a simple decoupled php micro-framework I would really recommend silex, by the makes of symfony2. It's easy to implement, and to learn, but contains mainy of the concepts described here; and uses all the php 5.3+ goodies such as namespacing and closures.
see: http://silex.sensiolabs.org/
Frontcontroller Pattern
Only have one, and one only point of entry for your code. I usually only have one, and one only point in your application. Usually a frontcontroller 'dispatches' the request to the rest of the application
http://en.wikipedia.org/wiki/Front_Controller_pattern
Routing
A routing system is often used in combination with the frontcontroller pattern. It basically describes which URL is connected to which module / controller. This allows you to change the way people access your app without changing the urls.
See: https://stackoverflow.com/questions/115629/simplest-php-routing-framework
Controller
A controller is the place where buisness logic is applied. Getting the data from the database, checking privileges, setting the template, setting the layout, etc. (although this is also moved outside the controller if it becomes too big of a seperate concern).
Model
The model basically is the layer in which use manage your database. This can be a simple class where you move all your mysql_* functions, or it can be a full-featured ORM. The main philosphy is that all the logic related to fetching and placing information in the database is seperated.
One step up: ORM
An often used method in applications are Object Relational Models, these 'map' SQL records to PHP objects. Doctrine and Propel are two of these well worked out libraries. I heavily rely on these systems in my development. In this sense, the doctrine or propel part will represent the model layer.
Doctrine: http://www.doctrine-project.org/
Propel: http://www.propelorm.org/
Other ORMS: Good PHP ORM Library?
PHP ORMs: Doctrine vs. Propel
View:
The view usually consists of a templating engine. Some use plain PHP as a template, others, such as symfony create a seperate scope in which variables are placed. There are many discussions and opinions about what is best, one is right here on stackoverflow:
Why should I use templating system in PHP?
PHP vs template engine
Ones I like:
- Twig: http://twig.sensiolabs.org/
- sfTemplate: http://components.symfony-project.org/templating/
- Smarty: http://components.symfony-project.org/templating/
Decoupling mechanisms:
Event based systems
Using events in your can help to seperate the code. For example if you want to send an email after a record has been saved, events are a good solution to do that; in general the model should not have to know about email. Thus events are a way to connect them: you can let your -email-send-class listen to certain records in order for them to send the right email. (Perhaps you'd rather want your e-mails send from your controller, this is probably a matter of taste).
Dependency injection
When using OOP code in PHP many relied on having singleton classes running around (configuration, etc). From an OOP point of view, this can be considered bad, because it's hard to test it, and it's not considered very elegant to have dependencies running around like that. Dependency Injection is a pattern that came form Java and is now used in the newer frameworks to get around this. It might be a bit difficult to wrap your head around, but you will see it coming back in several new frameworks.
Dependency injection in php: Dependency Injection in PHP 5.3
Frameworks:
A lot of these methods are difficult, or a lot of work to implement yourself. Many will reside to a framework for this. You may or may not need a framework. You may, or may not want to you a framework, it's your choice. But it's still useful to learn how the frameworks do it, and not try to reinvent the wheel yourself.
The no-framework php frameworks: https://stackoverflow.com/questions/694929/whats-your-no-framework-php-framework
Good habits: https://stackoverflow.com/questions/694246/how-is-php-done-the-right-way
Frameworks worth looking at (imho): CodeIgniter, Kahona, CakePHP, Symfony (1.4/2.0), Silex, Zend Franework, Yii. There are many many more, each with their dedicated fans and haters.
I wrote something like this with PHP. I already had abstracted the rendering of every page such that I define a $content variable and then require('layout.php'). The $content variable is just a big HTML string.
I wrote a PHP function to determine if request was AJAX or not.
The non-AJAX responses render the layout with $content in the middle, b/t header and footer layout content.
AJAX requests basically get this: json_encode(Array("content"=>$content)). And I use jQuery to get the HTML out of the JSON response and modify the DOM. Using json_encode() will handle escaping the string for javascript.
In the end, I effectively have AJAXified every page w/o over-engineering a complex solution.
Any browser that supports AJAX can also open a link in a new tab/window to simulate the non-AJAX request. (Or bookmark/share a link, too.)
I'm very new to PHP so far and have been trying to learn it. A big difficulty I face though is I just can't bend my head around to think about how is a PHP website structured with classes, objects, namespaces.
I'm not entirely new to OOP as I do have a little experience in Python and Java but PHP OOP just got me stumped. Many of the newbie PHP books I saw were on procedural PHP. I followed them made 1--2 small website but when I got to OOP, I'm just stuck and any tips on how you made the transition from procedural to OO PHP would be appreciated. In particular these are the questions on my mind at this moment
What are the type of classes one would usually creates? I thought of giving a class for each table in my database (User, Book) as well as maybe a form class, are there any other type of candidates that could be turned into classes too?
Any other way to reduce html code duplication other than the old usual require() and include()?
Any recommended ways to structure a typical PHP website? I currently only knows of having a folder for includes file. But I would like to know more.
Thanks.
You have questions, here are my answers!
The classes you make in PHP can be related to objects like User, Book as you would do in a persistent program. If you look at a framework like Code Igniter you can make a class as specific as constructing database queries to a class that uses an MVC architecture consisting of multiple classes to render your entire website.
To reduce code duplication, you can, for example, write a class to construct a table (or if you are really fancy a div table maker.). Then you can write methods like makeRow(), makeDivision(), etc... get really fancy and then you can write clean PHP code that can generate really large powerful pages.
EDIT:
If you were talking about reducing about the amount of include you'd have to do for classes then yes, Autoloading Classes on the PHP website is something you will want to look at!
Structure of your website can be based on the model you want to use. Right now it seems that MVC models are popular with frameworks, but it is up to you how your want your web app to be made. I'm sure you can take any architecture model and base your website around it.
With all that said, if you don't feel like start from absolute scratch on your project there are a plethora of PHP frameworks to choose from:
Comparison of Web application frameworks: PHP via Wikipedia
A very interesting question that brings us back to the age-old debate of procedural vs. OO programming. Why pick one or the other? The answer is..nobody has one. The whole purpose of designing software is to get something done. Does it matter how you get there? Well, it depends. If you get there very sloppily and a lot of updates are required, that's a big waste of time. Does OO programming prevent this? Absolutely not.
It seems like your real question is how to integrate OO into a website. This is really not something that you should do for the heck of it. What are you trying to achieve with this website? Does it contain many different application states with user interaction in a FSM or is it just a bunch of static pages. How much information do these pages share?
Let's tackle your specific questions first:
What type of classes does one usually create? Whatever type of classes they want! Before you type one character of code, you should sit down and write out a design for your application. No one can tell you how to do this: write up some documentation, pseudo-code (even in php if you like), draw up a UML diagram, etc. Figure out how your application can be compartmentalized. Do not make the mistake of dividing up object based on their logical separation in the real world (User, Book) unless it makes sense to. Why do you need a Book object? How does it interact with a user?
You could build a very simple class to display your standard webpage:
class anypage {
public function header() {
return '<head></head>';
}
public function footer() {
return '<br />Copyright © ' . date('Y');
}
public function render($body) {
return '<html>' . $this->header() . "<body>$body{$this->footer()}</body></html>";
}
}
Then on any page call:
$page = anypage;
echo $page->render("My Page Content");
Anyway, I'm talking more about general OO principles than just PHP, but this is a question that can't be answered. You design classes that your application needs to get the job done. A good example of using an object in PHP is PHPTAL, a template language. Your webpage may look like this:
$page = new PHPTAL('mytemplate.xhtml');
echo $page->execute();
The PHPTAL class takes care of building the html from your template file. That's an example of what an object might be used for.
Of course, PHPTAL is huge, and it's broken down into a lot of compartments. Taking a look at the source code, we see the classes Attr, Element, Node .. these are all pieces of an xml document and they have a class representing them.
An important part of OOP is having objects work together. Each object should serve a purpose and do what it is good at. I don't like objects that are models for nouns like "User" or "Book," unless they do something. PHPTAL does a great job of rendering a view for your page, but how do you know which page to render? You can use an object to handle that:
class controller {
public function __call($_, $_) { return $this->hello(); }
public function hello() {
session_start();
$view = new PHPTAL('hello.xhtml');
return $view->execute();
}
public function goodbye() {
session_destroy();
$_SESSION = array();
$view = new PHPTAL('goodbye.xhtml');
return $view->execute();
}
}
On you main page, you would have:
$c = new controller;
echo $c->$_REQUEST['action']();
If the 'action' is set by the request, the controller responds accordingly by calling that action. hello is used by default thanks to magical __call().
Similar to the other OO languages you are familiar with, you can even have events in PHP:
class controller {
private $models = array();
private $_listeners = array();
public function __construct() {
$model = new model;
$this->models[] = $model;
$this->_listeners[] = $model;
}
public function action($action = 'hello', $events = array()) {
$this->$action();
foreach ($events as $type => $data) {
foreach ($this->_listeners as $listener) {
$event = "fire_" . $type;
$listener->$event($data);
}
}
}
}
class model {
public function fire_hello($name) {
echo 'hello ' . $name;
}
}
As other answers have suggested, a good start is to take a look at a PHP framework. I recommend Kohana, since it is a good OO framework. I'm not necessarily suggesting you build a website from it, but take a look at the documentation and code to get a better understanding of OO development for PHP.
2 PHPTAL or another templating engine is an awesome way to reduce html duplication. Even my miniature anypage class above is an example. You don't necessarily have to have an html file and then use require() include() or virtual() to pass it into your code for reuse. Instead, you can have a wrapper that stores and builds common template html. I cannot stress enough how much I love PHPTAL for this purpose. XSLT is an alternative.
3 There is no set way to do this. Others are suggesting "Use a framework." I don't necessarily disagree. Using a framework helps out a lot in taking care of some of the annoying business of setting things up. It's not a magic problem-solving placebo, but it is nice for some things. If you are just trying to learn and there is no constraint on time, I say write your own framework. That will definitely teach you about OO programming in PHP. If time is a concern, use one of the 500,000 frameworks out there that others are suggesting. As for how to structure your website, I tend to have a _js folder for javascript and a _stylesheets folder for stylesheets. All of the php and xhtml template files I use are just placed in the folders they belong to logically. It's not rocket science, it's software engineering!
The MVC pattern is essentially the de facto pattern for web apps, regardless of language. Several frameworks utilize this pattern, including Zend Framework, CodeIgniter, and Kohana.
Like the others have said, __autoload() or spl_autoload_register() is the way to go when it comes to eliminating the need to follow includes/requires.
Remember that the currency of OOP is objects. You're not gaining much if you simply turn some back end data into OO models and calling it a day. I suggest you look at Matt Zandstra's book PHP 5: Objects, Patterns, and Practice as well as the Gang of Four's Design Patterns: Elements of Reusable Object-Oriented Software to really see how to use objects throughout a project.
You might find that working within a framework means that you're only creating some of the components yourself and that there are plenty of examples of best practice.
I moved from procedural stuff to Zend Framework which is a great framework and includes a full MVC model which helps to clearly define what your different objects should do and how they all fit together.
It's likely to be a bit of a learning curve but after a while it makes so much more sense than procedural stuff!
Use an object-oriented MVC framework like CodeIgniter (which is very easy), Yii (bit harder), or CakePHP or Symfony (much harder). You can see how the different objects link to each other, and the benefits from using them.
A good example of classes is the interaction between 'Form', 'Validation' and 'Schema'. You can instantiate a form by passing it a schema, and then use methods in 'Form' to generate HTML without writing it over and over again. When a user submits the form, you validate each field using an instantiation of the 'Validation' class, and then write it to the database using a 'Model'. Each table in your database has a 'Model' which defines how data is written to and retrieved from the database (CRUD).
You can avoid using lots of requires and includes using '__autoload()'.
It depends on what you want to accomplish. In a relatively complex web application you could follow a typical MVC approach. In that scenario you can create at least two classes, one for the model and one for the controller. And then have several templates (plain PHP files) whose content are filled/completed by the controller. You can create more classes (forms, utilities, code-generators,..) as needed, but be careful to keep your code compact and easy to mantain.
Many frameworks rely on the __autoload() magic method. Another alternative is to build your mechanism to handle all this stuff, probably using an AutoLoader class.
Use a framework. Seriously. Or at least take a framework as an example. I recommend CakePHP or CodeIgniter due to their fil structure simplicity.
I'm not a troll and my goal isn't to start a flame war; neither do I mean to disrespect the authors of the Zend Framework: there is a lot of fine work in it. But... I have a job to get done and I'm having a hard time reconciling the popularity of ZF against the reality of building apps with it. I would really like to know from others why they use Zend Framework.
I am fairly new to the PHP world but I've done a lot of programming in many languages. After reading many tutorials and building a couple of apps in it, some core Zend Framework facilities feel like alpha code to me. For me the following fundamental weaknesses, among others, would seem too overwhelming to consider deploying apps with it - but over and over again ZF is suggested as one of the, if not the leading framework.
First let me say I find the much of ZF to be workable. Routing works pretty much as it should, the Layout facility is serviceable (though very different from templating systems such as JSP/ASP), as is the cache facility, etc. There seems to be a tendency in the community to stuff a lot of modeling (e.g. validation) and view logic (e.g. $this->headScript() - why should my controller have to care which js file my view requires?) into controllers but could be a matter of usage and not necessarily the framework's fault.
Now for a couple of really serious (IMO) weaknesses I've experienced in my short time with it. I shudder to imagine the other areas I will discover in the future if I continue to build with it.
1. Form Layout
Many people seem to be unhappy with the lack of control over form layout. How can you have a popular framework where constructing a simple form requires so much discussion?
Question 1 and question 2.
2. Authentication/Authorization
No one really seems to understand how to simply perform routine authentication/authorization. People [including yours truly] struggle with implementing simple access control. Further, the approach seems to lean on serialization for persistence, rather than traditional database storage of users and permissions.
A confusing example, a proposal to enhance the facility, a tutorial - part I,
and part II. This is too much work guys!
Are my perceived weaknesses not real or somehow not a problem? Why or why not? Why did you choose Zend Framework (or not)? Are there other areas that you've found to be so painful that you want to dump ZF for a different approach? Thanks for your opinions.
Because they are good at Marketing
Zend's founders Andi Gutmans and Zeev
Suraski are key contributors to PHP
And they have one of the most complete framework for php.
When you think about it; it's like saying:
"Our language isn't as performant as it could be, so we made a framework with caching that makes it faster"
Most of what Zend offer, can be done
without Zend.
But Zend's package is a very good
"All in one" distribution.
They offer certifications and trainings.
One of the main benefits of ZF is that you can take any one of it's components and easily tie them in with your own (or a third party) framework with minimal modification.
Forms: The decorator approach is complicated, but bulletproof and priceless for applications with many forms. You don't care if you have 10 or 25 items in your form, the style is always the same. Saves you a great deal of work when you know how to use it.
For users with simplier minds and goals there is always the viewScript decorator ;)
Auth/Acl: Never had any problems with these.
Zend_Auth::getInstance()->hasIdentity() //logged in
and
Zend_Auth::getInstance()->getIdentity()->role; //returns admin
For Acl:
$acl->isAllowed($who, $where, $what);
$acl->isAllowed('roleAdmin', 'resourcePosts', 'create'); //returns true
Can be easily modified to match MVC:
$acl->isAllowed('roleAdmin', $module.ucfirst($controller), $action); //returns true
$acl->isAllowed('roleAdmin', 'adminPosts', 'create'); //returns true
Color me UNIMPRESSED with ZendFramework. Using Zend Framework is like welding a set of training wheels to your code. Anything you can do in Zend Framework is something you can do in raw PHP. (Remember ZF itself was written in raw PHP.) And you can usually do it with the same number of lines of code - written in a consistent style with the rest of your application. And, by using native PHP code, you're not locked into a niche tool that only a minority of PHP developers use. And you don't have to worry about compatibility with changes in ZF versions.
In my applications, I do all the same things that the ZF tools do, mostly by using simple PHP functions that have been around for years:
validate form data
cleanse form input
handle files uploaded through forms
manipulate and compare dates
handle authentication
send emails
write to log files
read from configuration files
read external HTTP pages
exchange in JSON and SOAP formats
work with third-party APIs
I can't find much of anything in Zend Framework that is worth my time. And don't get me started on overbearing "scaffolding" frameworks like CodeCoffin, AppShackler, or Ruby in Chains.
ZF is a good starting point. I used zend_tool to generate a MVC skeleton of my middle-size application and used many other components (Zend_Cache, e-mail, translate, forms, session).
And I agree that form layout is complicated if you are trying to do it as Zend says - with decorators. There are ways to use just Zend_Form elements with validation and in your custom layout - without decorators.
I had a bad experience with Zend Cookies - I just could not set a cookie for my entire domain. Old good setcookie did the trick right.
About Acl - again, examples in Zend documentation and Zend_Acl do not work well sometimes. I used Controller plugin approach and my own "role based resource management" to control permissions.
I did not even try Zend Data Gateway - used Doctrine instead (I guess that is because I like nHibernate :) ) And connecting Doctrine was really easy.
I think ZF is good because you can use it as you like. I think it would be harder with some other frameworks.
Simplicity to build medium size applications.
Until ZF you had to build your own "framework" to do medium size applications. Now is much more simpler.
I don't think decoupling and simple elements that can be used independently is the key to success. Is a nice feature, but is not the regular use.
Support and community size are relevant in the balance with other frameworks.
In terms of speed they are NOT better then other frameworks.
Wel, we are developers because we are supposed to be able to write "some" of our own code, arn't we? Frameworks not supposed to be wizards, just an added assistance.
I did not choose Zend Framework because at the time when I was evaluating PHP frameworks it was not a complete and integrated enough solution for building web apps. I chose symfony and since then I have never had a need to switch to anything else.
I'm not sure if it's the same nowadays, but I always thought of ZF as a component library rather than a framework. A framework has a somewhat more strict rules of doing things and often has better integrated support tools to help people do them. A component library is more loose in this regard. When the framework rules correspond to the requirements of most applications in the framework's domain, I myself clearly prefer this solution. This has been the case with symfony for me. I do use certain ZF components as needed, but never base my projects on ZF itself.
I use ZF for a few reasons:
The host of nifty classes, lazy loading of classes, stand-alone usage of classes, and clean clear source. The first time I used it I needed to build an ACL system - a very big complex one. Zend_Acl helped tremendously.
I think ZF needs to work on it's docs and db classes. The db classes problems have a lot to do with PHP itself. So maybe it's some thing Zend wants to look into.
The OP is new to PHP. I agree PHP has it's flaws such as the arbitrary naming of functions, but generally it does make sense for HTTP and doesn't hide reality from you.
Form layout:
It's really easy. Decorators are a pain in the butt during your first contact with them, they're just black magic. Then you realise how useful they are and that you can do almost anything with them. When you finally hit a point where decorators are just not enough, you can just render separate form elements in your view or even write your own form HTML. Consider this example:
form
$text = new Zend_Form_Element_Text('text');
$text->addValidator('NotEmpty')->setRequired();
$submit = new Zend_Form_Element_Submit('submit');
view
<form>
<input type="text" id="text" name="text" />
<input type="submit" id="submit" name="submit" value="Send" />
</form>
controller:
$form = new Form_Whatever();
if ($this->_request->isPost()) {
if ($form->isValid($this->_request->getPost()) {
// code
}
}
There you go. You have a form, you wrote its HTML manually, but you still benefit from ZF's inbuilt validation. Why? Because you still create the form object in the controller and feed it the data sent via POST. You still get your filters, validators, anything you want. With any HTML you want. And you can also plug an external view to the form if you want to go extreme :).
Oh, by the way, did you know that your forms are reuseable? Yeah, you can write one form and use it in multiple places. No hassle. That's what I personally like about forms in ZF (and dislike in CodeIgniter - which is a great framework too, by the way).
Authentication:
Zend Framework: Login password hash, email validator?
Yes, it's only a small piece of code. You basically copy and paste it in your projects.
As for ACL, you just create your rules and then check them whenever you need them. A one liner. Can't be simpler.
Personally, I think ZF is popular because it simply saves your money. If you put me in front of a project, I can guarantee you that I'll finish it twice faster if you let me use ZF instead of another framework I know. And probably a fraction of the time I'd need to do everything in baseline PHP. So that's about it: saving time = saving money. Or earning you extra money - but either of the two rules, right?
There is no need to use Zend_Form or Decorators themselves. You can just use plain HTML Forms and then inside Controller=Actions use Zend_Filter_Input like this. So you have best of both Worlds.
public function indexAction()
{
$this->view->title = 'Search Results';
$filters = array('q' => array('StringTrim' , 'StripTags'));
$validators = array('q' => array('presence' => 'required'));
$input = new Zend_Filter_Input($filters, $validators, $_GET);
if ($input->isValid()) {
$this->view->messages = '';
$q = $input->getEscaped('q');
$this->view->q = $q;
// do search
try {
$index = News_Search_Lucene::open(
SearchIndexer::getIndexDirectory());
$results = $index->find($q);
} catch (Exception $e) {
$results = array();
}
$this->view->results = $results;
} else {
$this->view->messages = $input->getMessages();
}
}
I'm not sure if ZF is really the most popular PHP framework. I chose it after comparing it with other frameworks that do more stuff "magically" because they all seemed to hard to customize.
I think ZF is a good object oriented PHP MVC framework, but I don't agree with some ZF approaches. For example, I only use Zend_Form for filtering and validate data. All the HTML and presentation stuff are done at view scripts. The CSS is the responsible for the layout. If we need some changes most of the time changing only the CSS is enough. If I need to make the same form appear in many pages, I use it as a partial view script.
I don't like to have to write a Mapper for each Model and to create a Zend_Db_Table subclass for each database table. Instead I'm researching how to use other patterns for data access, or maybe Doctrine.
What I don't like about Zend_Acl is that stores the ACL information in the ACL file. I would like to store that information in the database.
The good thing about this framework is that is easy make things your way.
In addition to the previous answers, it is worth mentioning that in a recent pool at DZone titled Which PHP framework would you use today for a brand new application?, Zend Framework was selected to be the most preferable for new projects.
I work in a web shop as a PHP programmer. Most of the time we use good coding practices but not much structure to the site as a whole.
I have now entered my phase of being bored with some of our practices and want to branch out and simplify and generate some things in a helpful way not just for me, but the hybrid-programmer web developers in the office.
One employee left us with a MVC site written in PHP, and I have had to maintain it a bit, and I get how it works but have my complaints, my main complaint is that it is tightly coupled with each piece dependent on another. I see the advantage of the seperation of concerns, but this would be confusing to anyone but me looking at the code.
So for example, if I need to add a new page to the site, I have to go add a view, and then add a model, then update the controller. The ad-hoc method of making a new page is way simpler than this and doesn't require a programmer.
My judgement was this was a much better method to build, rather then maintain, a website.
Still, it would be nice if I had some design patterns where I could reuse code effectively without it being dependent on a multiple places in the site.
So my question is, is there a design pattern for building and maintaining websites that is much more loosely-coupled? I'm not looking for slight variations on MVC, I need something quite different to look at, maybe some type of plugin approach.
EDIT:
Thanks for the answers so far! A different way of putting it is I want the code to be done better in my office. Do I A) Push for MVC or B) find/build an alternative not as confusing to the half-programmers. We already use classes for things like DB connectivity and Form helping. The point of this question was to explore B.
There's always a compromise between the code being confusing because it's highly deconstructionist, and the code being confusing because absolutely everything needed to do X is randomly scattered around a single file.
The problem with the latter is that exactly what is an "intuitive" way to split things up into monolithic modules differs between people. Highly decomposed and factored code is nearly always more difficult to wrap your head around, but once you do that, maintenance becomes both easy to do. I disagree that it would be confusing to anyone else but the author looking at it. Large-scope patterns like MVC are used because it becomes easier to spot them and work on projects structured around them over time.
Another advantage of using MVC is that you generally won't make the application more difficult to maintain for someone who comes after you if you don't stick to the layering. This is because now you have a predetermined place where to place any aspect of implementing a new feature.
As far as the tight coupling is considered, you can't really implement a feature without there being some connection between the layers. Loose coupling doesn't mean that the layers are ignorant of each other completely - it means that a layer should be unaware of how the other layers are implemented. E.g.: the controller layer doesn't care whether you're using a SQL database or just writing binary files to persist data at the data access layer, just that there is a data access layer that can get and store model objects for it. It also doesn't care about whether you use raw PHP or Smarty at the view layer, just that it should make some object available under some predetermined names for it. All the while the view layer doesn't even need to know there is a controller layer - only that it gets called with the data to display ready under the abovementioned names provided by /something/.
As frameworks templates go, I find the MVC pattern to be one of the most "loosely coupled" ways of building an application.
Think of the relationships like interfaces, or contracts between the parts of the application. The Model promises to make this data available to the View and the Controller. No one cares exactly how the Model does that. It can read and write from a typical DBMS, like MySQL, from flat files, from external data sources like ActiveResource, as long as it fulfills its end of the deal.
The Controller promises to make certain data available to the View, and relies on the Model to fulfill its promises. The view doesn't care how the Controller does it.
The View assumes that the Models and the Controllers will keep their promises, and can then be developed in a vacuum. The Model and Controller don't care if the view is generating XML, XHTML, JSON, YAML, plaintext, etc. They are holding up their end of the contracts.
And, of course, the View and the Controller need to agree that certain things exist. A View without some corresponding Controller activity might work fine, but could never be used. Even if the Controller doesn't do anything, as might be the case in static pages:
<?php
class StaticController extends ApplicationController
{
/**
* Displays our "about" page.
*/
public function about ()
{
$this->title = 'About Our Organization';
}
}
Then the associated View can just contain static text. (Yes, I have implemented things like this before. It's nice to hand a static View to someone else and say "Just write on this.")
If you look at the relationships between the M, V, and C as contracts or interfaces, MVC suddenly looks very "loosely coupled." Be wary of the lure of stand-alone PHP files. Once you start including and requiring a half-dozen .inc files, or mixing your application logic with your display (usually HTML) you may have coupled the individual pages more loosely, but in the process made a mess of the important aspects.
<?php
/**
* Display a user's profile
*/
require_once 'db.php';
$id = $db->real_escape_string($_GET['id']);
$user_res = $db->query("SELECT name,age FROM users WHERE id = $id;");
$user = $user_res->fetch_assoc();
include 'header.php';
?>
<h1><?php echo $user['name']; ?>'s Profile</h1>
<p><?php echo $user['name']; ?> is <?php echo $user['age']; ?> years old!</p>
<?php
include 'footer.php';
?>
Yeah, "profile.php" and "index.php" are completely unrelated, but at what cost?
Edit: In response to your edit: Push for MVC. You say you have "half-programmers," and I'm not sure which half (do you have front-end people who are good at HTML and CSS but not at server-side? writers with some programming experience?) but with an MVC framework, you can hand them just the views, and say "work on this part."
I have to say that I don't really see your problem with MVC, since your already using templates anyway. I kind of think of it as the pattern that evolves naturally when you try to add structure to an application.
When people first start developing PHP application, the code is usually one big mess. Presentation logic is mixed with business logic which is mixed with database logic. The next step that people usually take is to start using some kind of templating approach. Whether this involves a specialized template language such as smarty or just separating out the presentation markup into a separate file isn't really important.
After this most of us discovers that it's a good idea to use dedicated functions or classes for the database access logic. This really doesn't have to be any more advanced than creating specialized functions for each commonly executed query and placing all those functions in a common include file.
This all seems very natural to me, and I don't believe that it's very controversial. But, at this point you're basicly already using an MVC approach. Everything beyond this is just more or less sophisticated attempts to eliminate the need to rewrite commonly used code.
I understand that this might not be what to you wanted to hear, but I think you should re-evaluate MVC. There's a countless number of implementations, and if it's really the case that none of them suits your needs, then you could always write your own and more basic implementation.
Look at it this way: Since you're already using a template language you'll typically need to create first a regular PHP file, and then a templare file each time you create a new page. MVC doesn't have to be any more advanced than this, and in many cases it isn't. It might even be that all you really need to do is to investigate more sophisticated approaches for handeling data access and add it to your current system.
The fact that you have to create a new Model and Controller Action when you need a new page I don't think means that your M, V, and C layers are tightly coupled. This is just the separation of concerns and contributes to a decoupled system.
That said, it is quite possible to royally screw up the intent of MVC (and I've worked on an app like this) and make it make the components tightly coupled. For instance, a site might put the 'rendering engine' directly in the Controller layer. This would obviously add more coupling. Instead a good MVC will be designed so that the controller is only aware of the name of the view to use and then pass that name to the separate rendering engine.
Another example of bad design in an MVC is when the views have URLs hard-coded into them. This is the job of the Routing engine. The view should only be aware of the action that needs to be called and the parameter that action needs. The Routing engine will then provide the correct URL.
Zend framework is very loosely coupled and is very good. Check it out:
http://framework.zend.com
This article might be of use too:
http://blog.fedecarg.com/2009/02/22/zend-framework-the-cost-of-flexibility-is-complexity/
You can try code Igniter. Its very easy to learn and does not strictly adopt MVC whilst giving your code good structure.
Code Igniter and Kohana (a CI descendent) are OK, but also loosely MVC. I like the simple php framework. It doesn't get in your way and it provides the important stuff, without forcing a structure or complicated conventions on you.
Ah... good old MVC arguments.
I have to maintain a multi-faceted PHP application, pieces of which are written "MVC" style, but not all. Worse, different parts have different ways of doing MVC, all of which are homegrown. And some pages just do it all themselves.
The main problem is not that there is a diversity in framework code, but that the coders clearly did not understand how to abstract APIs. IMO, ths is the biggest problem with MVC frameworks. Almost all of the code I have to work with uses "models" as places to put functions. It is a nightmare to maintain.
To make this maintainable, IME you need a few things:
A distinct and well-defined data-access layer, the API boundary of which looks after retrieving and storing persistent storage and very little else.
I don't like to use the term "model" for that because that is contentious. Whatever calls that layer should not care how the data is stored, should not even be worrying about things like database handles: that is all the job of the data-access layer.
A dispatcher that is very light and doesn't do any magic outside of just dispatching.
Now you can put everything else in one place that accepts requests and parameters, probably normalised and error checked from the dispatcher, fetches the data (usually as objects) it needs, makes the changes it needs to do, saves the data it needs to, hands the data is needs to display to the view. Two hundred lines of code plodding through the task works for this step. You don't need to hive off bits into functions in another file that are called from nowhere else. You can even put the view on the end of this file! Idealism is nice to aspire to but pragmatism needs a look-in because this is maintainable.
(Okay, rant over... )
PHP's lack of enforcing a framework means that the best frameworks do what PHP does: they stay out of the way. Some of the most maintainable code I've worked on had a single require() statement at the top, did all the data-manipulation with data objects (no SQL in sight), then output HTML surrounded by template functions, with form control being done by a consistent function API.
Can someone please derive a concrete example from the following:
http://www.urdalen.com/blog/?p=210
..that shows how to deal with one-to-many and many-to-many relationships?
I've emailed the author some time ago but received no reply. I like his idea, but can't figure out how to implement it beyond simple single table relations.
Note: I don't want to use a full-blown ORM. I like doing my SQL by hand. I would like to improve the design of my app code though. Right now each domain object has its own class full of queries wrapped in static methods. They just return scalar, 1d-array (record) or 2d-array (recordset) depending on the query.
The problem of ORM's (The impedance mismatch, as it's called) is precisely with relations. In an object graph (In-memory objects), relationships are pointers to other objects. In a relational database, relationships are reversed; This makes it impossible to do a simple mapping between the two models, and that is why ORM's are so complex.
If you want to stay close to the database (avoiding an ORM), then you shouldn't try to abstract relationships away. The way I write datamappers is something like the following:
$car42 = $car_gateway->fetch(42);
$wheels = $wheel_gateway->selectByCar($car42);
In contrast to the ORM way:
$car42 = $car_gateway->fetch(42);
$wheels = $car42->selectWheels();
This does mean that the gateways end up in your client-code, but it also keeps things very transparent and close to the database.
If you're looking for a simple and portable DataMapper ORM, have a look at phpDataMapper. It's only dependencies are PHP5 and PDO, and it's very small and lightweight. It supports table relations and some other very nice features as well.
Given your response to Tom's answer, I would recommend that you look at something like Zend Framework. Its ORM has a take it or leave it architecture that can be implemented in stages.
When I came to my present employer, they had an application that had just been completed months previously but had been through one or two prior versions and the current version had been in development six months longer than it was supposed to have been. However, the code base was mess. For example there was no abstraction between the database access logic and the business logic. And, they wanted me to move the site forward building new functionality, extending existing features, and fixing existing bugs in the code. To further complicate things they weren't using any form of sanitation on data inputs or outputs.
As I started to wade into the problem, I realized that I would need a solution to abstract concerns that could be implemented in steps because they obviously weren't going to go for a complete rewrite. My initial approach was to write a custom ORM and DAL that would do the heavy lifting for me. It worked great because it didn't intrude on the existing code base, and so it allowed me to move entire portions of the application to the new architecture in an unobtrusive manner.
However, after having ported a large portion of the user's area of our site to this new structure and having built an entire application on my custom framework (which has come to also include a custom front-end controller and mvc implementation), I am switching to Zend Framework (this is my choice though I am certain that some of the other frameworks would also work in this situation).
In switching to the Zend Framework I have absolutely no concerns about the legacy code base because:
I can build new models and refactor
old models (built on my custom
framework) unobtrusively.
I can refactor the existing
controllers (such as they are) to be
wrapped within a class that behaves
in a manner consistent with Zend's
MVC framework so that it becomes a
minor issue to actually begin using
Zend's Front-End Controller.
Our views are already built in
Smarty so I don't have to worry
about separating controller and view
logic, but I will be able to extend
the Zend Framework so that I can
render existing templates in Smarty
while building new templates in
straight PHP.
Basically, Zend Framework has a take it or leave architecture that makes its a joy to use within existing projects because new code and refactored code doesn't need to intrude on existing code.