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.)
Related
I have almost completed a PHP project, using MVC, jQuery and Ajax. It is pure PHP project. I don't use any frameworks in the code right know. I would like to change that.
Doing some research, I found, that Yii turns out to be one of the best frameworks out there.
Is it possible to somehow migrate pure PHP project to Yii?
If so, then how to do this? Which steps should I follow in order to reduce the workload and enjoy the benefits the Yii framework presents?
I'm a total Yii newbie, any insights appreciated.
TL;DR : Don't do it. It's a really horrible idea.
The Rant ..
"Framework" is not a magic sauce, that you add to a project, to make it better and shinier.
Doing some research i found Yii turns out to be one of the best frameworks out there.
What a strange research you have done .. I would love to see the materials. Especially, since I would rank it as 3rd worst PHP framework. Only surpassed in it's awfulness by CodeIgniter and CakePHP.
And the reason for it is the extremely bad quality of code, that this framework displays, combined with the bad practices, that it perpetuates.
Why avoid migration?
From your description is obvious, that you are NOT familiar with this framework and have no previous experience with it.
In management of projects there a subject: risk management. And in this case, adding a previously unused framework in final stages of project would constitute a high probability an high impact risk which also, due to the sage of project, is completely unmitigated.
It means that there is a really good chance that something will go wrong. And when it does, it most likely will sink the project. Or at least push back the release data by significant length of time.
In a perfect world frameworks are used to simplify the repetitive tasks of development, at the cost of some performance. Those are the tasks you do at the start of the project. You are not at the start of a project. This means that you will gain no benefits from this "maneuver".
Why not Yii?
As I noted before, there are also reasons not only for avoiding adding framework to an existing project, but also reasons why to avoid Yii in particular.
The inheritance nightmare
All your controller will extend class CController, which extends CBaseController, which extends CComponent
All your "models" will extend ether CActiveRecord or CFormModel, which extends CModel, which extends CComponent.
Both of there chains contain static variables and execute static methods on multitude of different other classes. Combination of these factors will make debugging extremely difficult and tedious.
Global state
There are several forms of global state. One that people in PHP usually know are global variables. But that is not the only form. Every time you have a class that contains a static variable, it also creates a global state, that can (and almost always - will) cause seemingly unrelated instance mysteriously interact.
Use of global state is a core mechanic. You will see static calls all over the codebase, and the Yii's configuration file would not function without global state.
And every time you call Yii::app() you are accessing and/or changing it.
This makes unittesting impossible for Yii applications. And debugging turns into exercise of using grep on your whole project.
Tight coupling
When you create an application in Yii. It becomes bound to it. You cannot execute parts of your application without launching the full framework. Mostly it is due to the static call, that you end up adding to your code.
Every time you add a static call in your own code, that piece of code becomes tied to the name of the class. That essentially is tight coupling.
As you might have noticed (hopefully), there is another way how to achieve the same effect - the use of new operator. That is another way of coupling some code of yours to a specific name of a class.
No interfaces .. none .. whatsoever
No matter how horrible the configuration of a Yii project is, the configuration file was a well intended gesture. The least harmful way to introduce external code and replace existing components in so messed up codebase.
But unfortunately it brings in the focus the problems caused by lack of interfaces and the existing coupling.
One of the component that developers will try to replace is the CUrlManager. Mostly due to way how you can pass additional parameters.
An interface in OOP specifies the contract between two instances. It lets you define the capabilities of an instance, the methods that can be used by others. When it's not there, in a large codebase, you are left guessing, which methods are required and which are not.
In case of Yii components the problem is compounded even further due to static call and deep inheritance. The above mentioned CUrlManager extends CApplicationComponent, which extends CComponent. Also the same file defines CUrlRule and CBaseUrlRule classes.
When you are writing a replacement, you have to write some code, plug it in the configuration and then test it by running your applications. That way you know which method (or parameter) next you need to add.
Basically, it's the "save-an-see-what-blows-up" method of development.
That's not MVC!
Yii does not implement MVC or any of MVC-inspired design patterns. What it calls "MVC" could be described as ActiveRecord-Template-Logic pattern.
Instead of having proper model layer (yes, it should be a layer), the creator(s) of Yii opted for collection of active record and form wrappers. This forces the application logic to be forced in the "controllers".
On the other hand you have glorified templates, instead of proper view instances for containing presentation logic. It is somewhat mitigated by use of widgets, but those instead suffer from SRP violations, because widgets are forced to contain bits of presentation logic and perform partial rendering. The rest of presentation logic ends up again in the controllers.
And to make it all worse, the "controllers" also have to deal with authorization. This usually will mean, that whenever you change the access scheme, you will have to go through every single instance of CController to check whether it needs to be changed too.
It's not MVC. It's a mess with names taken from MVC design pattern and slapped on some components.
All the small things ..
The framework also comes with few minor issue, that do not deserve a separate section:
Defining more then one class per file:
This will get annoying quite fast, because there will be classes that are shoehorned at the class files with completely unrelated filenames. This will mean, that debugging will quite often require use of search.
Slapped on "modules":
By the looks of it, the modules where added to the framework after the fact. Which is why, when you need to set default module, you will have to set it in the configuration files parameter, that is called 'defaultController'.
I actually recently converted a MVC pattern website I had built from the ground up into Yii. It did take some time to set it all up but in all honesty it was well worth it. I was able to throw away a lot of code because there were already Yii extensions doing what I needed. I would also suggest that you keep your database because you can create the controllers and Models using Gii which will save you a ton of time.
I don't know of any quick solutions to this. It depends upon how the code was written. You have the database and your views so it is not really a complete new project when you take into yii. Yii will generate the database models for you. You already have the views from the existing project. Write the controller and actions and modify the views if necessary.
try these links as they refer to the same problem.
How do you convert an old oop project into Yii
tips on migrating an existing site to Yii
Drupal to Yii Migration
Since you already have a code in mvc, things will be much easier for you to migrate. However, while migrating to Yii, since it can generate controller and model very easily using gii, you can take the advantage of it.
So, first generate controller and model using gii, then you can replace your existing code (by replace I mean, substitute your code to the specific function in the controller and model) to the built in controller and model so that the functionality of your site still works. You can modify your view accordingly. But that won't be much of a work.
You can simply register your script for ajax, jquery and css. Those will work as well.
And yes, Yii is the best framework out there so take as much benefit as you can.
Thanks,
Ujjwal
In this project you converted php to yii framework. Its really easy for you if you do following step.
Since you already have a code in mvc, things will be much easier for you to migrate. However, while migrating to Yii, since it can generate controller and model very easily using gii, you can take the advantage of it.
second, If your database is accurate then 50% work complete.when you create CRUD operation using gii then automatically model-view-controller create.if you create mvc in php then it benifit for you.
third,You can simply include your script for ajax, jquery and css. Those will work as well you create a folder in themes(CSS,JS,AZAX,BOOTSTRAP).
four-Protected->view->layout, where you can change your theme..thats all
you also help www.yiiframework.com/doc-2.0/guide-intro-yii.html
if you think my answer is help you then rating me...thank you.
I've been learning OOP programming for about a year and a half now and have developed a fairly standard framework to which I generally abide by. I'd love some feedback or input on how I might improve some functionality or if there are some things I'm overlooking.
VIEW MODE
1) Essentially everything starts at the Index.php page. The first thing I do is require my "packages.php" file that is basically a config file that imports all of the classes and function lists I'll be using.
2) I have no direct communication between my index.php file and my classes, what I've done is "pretty them up" with my viewfunctions.php file which is essentially just a conduit to the classes so that in my html I can write <?php get_title('page'); ?> instead of <?php echo $pageClass->get_title('page'); ?> Plus, I can run a couple small booleans and what not in the view function script that can better tailor the output of the class.
3) Any information brought in via the database is started from it's corresponding class that has direct communication with the database class, the only class that is allowed direct to communicate with the database (allowed in the sense that I run all of my queries with custom class code).
INPUT MODE
1) Any user input is sent to my userFunctions.php.
2) My security class is then instantiated where I send whatever user input that has been posted for verification and validation.
3) If the input passes my security check, I then pass it to my DB class for input into my Database.
php general model http://img139.imageshack.us/img139/3319/phpmodel.gif
FEEDBACK
I'm wondering if there are any glaringly obvious pitfalls to the general structure, or ways I can improve this.
Thank you in advance for your input. I know there is real no "right" answer for this, but I imagine a couple up votes would be in order for some strong advice regarding building frameworks.
-J
One thing I would recommend you do is to go ahead and separate your functions into classes. I understand the points you made about avoiding instantiations but consider this: any framework will, by necessity, begin to accumulate a large number of functions.
Instead of doing
<?php get_title('page'); ?>
you would be better served to create a Page class with all of its functions inside of said class which you call statically. Then, your code becomes
<?php Page::GetTitle('page'); ?>
a much more descriptive naming convention and will become critical later on when trying to avoid naming collisions (you only have to avoid name collisions on say, 50 classes, rather than two thousand functions).
I would study up on the Model-View-Controller design methodology (as ircmaxell hinted at in his post). A lot of very powerful and very well-written frameworks apply this principle, and not just PHP frameworks either. My suggestion - study Yii for how your application should be controlled - very slick and the creator makes excellent use of static variables to control class instantiation.
Good luck with your framework!
Well, the only issue that I can see (without seeing code), is that SQL will be everywhere. What I'd suggest is creating a "model" layer in front of the DB connection class. That way, all your sql is in one spot (break it off into multiple models, etc). It makes maintenance MUCH easier (if you want to add a column to a table, optimize a query, etc)...
Otherwise, it looks like a good start!
Nice presentation. I would definitely look under the hood at other popular frameworks for some insight.
At first glance, I would suggest to see if you can find a way to only load the classes you need per request. Loading them all for every request may become unfeasible if the class library grows large.
Are you using autoloaders? It seems that you will be using a lot of requires... maybe I am just misinterpreting. I think it is great that you are writing your own framework. I don't see it as "reinventing the wheel" either as you are writing it to accomplish the tasks you want to accomplish and can control the overall weight of your project as well as, since you are by most standards still moderately new to OOP, learning a ton I am sure from the experience. Creating your own frameworks, trying to improve other peoples code and learning how others do things and why is an amazing learning experience and in my opinion will drastically improve your programming skills and understanding.
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why should I use templating system in PHP?
I was just curious as to how many developers actually do this?
Up to this time I haven't and I was just curious to whether it really helps make things look cleaner and easier to follow. I've heard using template engines like Smarty help out, but I've also heard the opposite. That they just create unnecessary overhead and it's essentially like learning a new language.
Does anyone here have experience with templates? What are your feelings on them? Are the helpful on big projects or just a waste of time?
On a side note: The company I work for doesn't have a designer, there are just two developers working on this project charged with the re-design/upgrade. I also use a bit of AJAX, would this have issues with a template engine?
Not only does this practice make the code look cleaner, it also has many long term and short term benefits.
You can never go wrong with organizing code. First off it makes it much easier to maintain and easier to read if someone else has to pick up after you. I have worked with Smarty before and it is nice, it keeps the designers work from interfering with the program code.
Using template systems and frameworks would make it much easier to accomplish tasks. There is a rule of thumb you can follow which is DRY (Don't Repeat Yourself). Frameworks help you achieve this goal.
You may want to look into MVC, this is the model that these frameworks are based off of. But you could implement this design structure without necessarily using framework. Avoiding the learning curve. For frameworks like Zend, the learning curve is much greater than some other ones.
I have found that Code Igniter is fairly easy to use and they have some VERY helpful video tutorials on their website.
Best of Luck!!
Actually it's the business logic that needs to be separated from the views. You can use php as a "template language" inside the views.
You can use ajax on any template engine i think.
Edit
My original response addressed the question whether to use a template engine or not to generate your html.
I argued that php is good enough for template tasks, as long as you separate business logic from presentation logic.
It's worth doing this even for simple pages, because it enables you to:
isolate the code that is the brain of your application from the code that is the face, and so you can change the face, without messing with the brain, or you can enhance the brain without braking the looks
isolate 80% of bugs in 20% of your code
create reusable components: you could assign different presentation code to the same business code, and vice versa;
separate concerns of the feature requests (business code) from the concerns of the design requests (presentation code), which also usually are related to different people on the client side, and different people on the contractor side
use different people to write the business code and the presentation code; you can have the designer to handle directly the presentation code, with minimal php knoledge;
A simple solution, which mimics MVC and doesn't use objects could be:
use a single controller php file, which receives all requests via a .httpdaccess file;
the controller decides what business and presentation code to use, depending on the request
the controller then uses an include statement to include the business php file
the business code does it's magic, and then includes the presentation php file
PHP is a template engine (or if you prefer, a hypertext preprocessor). When HTML is mixed heavily with PHP logic, it does become very difficult to maintain, which is why you would have functions defined separately to build various parts and simply build the page from short function calls embedded in the HTML. Done like this, I don't see much of a difference between Smarty and raw PHP, other than the choice of delimiters.
Separation of concerns is a very important tenant to any type of software development, even on the web. Too many times I have found that people just throw everything into as few files as possible and call it a day. This is most certainly the wrong way to do it. As has been mentioned, it will help with maintainability of the code for others, but more than that, it helps you be able to read the code. When everything is separated out, you can think about easily.
Code Ignitor, I have found, has been the easiest to learn framework for working with PHP. I pretty much started my current job and was up and running with it within a few days, from never having heard of it, to using it pretty efficiently. I don't see it as another language at all, either. Basically, using the framework forces me to organize things in a manageable way, and the added functionality is anlagous to using plugins and such for jQuery, or importing packages in Java. The thought that it's like learning another language seems almost silly.
So, in short, organize organize organize. Keep in mind, though, that there is a level of abstraction that just becomes absurd. A rule of thumb is that a class (or file in our case) should do one thing very well. This doesn't mean it is a class that wraps around print, but takes a string, formats it using a complex algorithm and then prints it (this is just an example). Each class should do something specific, and you can do that without any framework. What makes MVC great, though, is that it lets you organize things further, not just on the single class level, but on the level of "packages", being Model, View, and Controller (at least in the case of these frameworks; there are other ways to package projects). So, now you have single classes that do things well, and then you have them grouped with similar classes that do other things well. This way, everything is kept very clean an manageable.
The last level to think about once you have things organized into classes, and then packages, is how these classes get accessed between packages. When using MVC, the access usually will go Model<->Controller<->View, thus separating the model (which is usually database stuff and "business" code in the PHP world), from the view (which usually takes information from the user, and passes it along to the controller, who will then get more information from the model, if necessary, or do something else with the input information). The controller kind of works like the switchboard between the two other packages usually. Again, there are other ways to go with packaging and such, but this is a common way.
I hope that helps.
Smarty and other php template frameworks really do nothing more than compile to PHP anyway, and they also cache their results in most cases to allow for faster processing. You can do this all on your own, but if you ever look at the compiled templates that Smarty generates, and compare to the original Smarty template you create, you can see that one is far more readable than the other.
I write mostly mod_perl these days and started using templates (HTML::Template) halfway through our ongoing project. If I had to make the decision again, I would use templates right from the start - rewriting later to use templates is kind of tedious, though rewarding because you get nicer and cleaner code. For anything bigger than 2-3 pages in php, I would also use some template engine.
One big advantage of a templating engine such as Smarty is that non-developers can use it to embed the necessary logic that is used on the front-end (one really can't separate logic and display on all but the simplest sites). However, if the developer is the one maintaining the pages then using PHP would be preferable in my opinion.
If you separate out large logic blocks and maintain a consistent patten for looping and for-each flow control statements (i.e. don't use print statements, or only use print statements for one-liners, etc.) Then that should be okay.
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.
All the popular PHP frameworks today use their own view layer implementation that is based on pure PHP templates and lots of helpers. I've tried some of them and always found that this approach introduced huge complications to quite simple things. For example, in Zend Framework forms and the pagination use their own solutions to customize the look of these items. The helpers re-invent loops, providing also quite slow solutions, and the whole view layer, in my opinion does not exist as a one part, but many of its functionality is delegated to other parts of the script. The same configuration problems occured in Symfony and admin generator, and in Kohana I was forced to duplicate the same code over all my forms. Is PHP really a good choice for the view layer? Do you also find these implementations inconvenient or maybe, why despite all these problems they are good and cannot be replaced, for example by a smart template engine (I don't mean Smarty :))?
Now I like PHP but ultimately, first and foremost, it is a templating language, not a general purpose programming language nor an object-oriented language. Don't fight it. Embrace it.
I've looked at a few different MVC frameworks like Symfony, CakePHP and Zend and I have a hard time getting past the examples. Typically they are "with these 17 files you can make a 'Hello world' program!" Huh?!?!
There is such a thing as complexity for sake of it and solving a problem before you have a problem and I'm yet to be convinced that these heavyweight (they are heavyweight) frameworks really adds value.
I'm more of a fan of the 'no framework' framework. This is really 'roll your own' but I think that it leads to the leanest, cleanest end result.
I feel similarly about Smarty. A lot of people on SO are big fans of Smarty but it's never made sense to me why you'd add a templating language to your... templating language.
Ultimately I end up writing this kind of PHP script most of the time
<?
require 'config.h'; // set up constants, DB connections and so on
page_header('My Page'); // page header, site menu and so on
deny_unregistered(); // security
if (/* user submitted page */) {
$valid = validate_form(/* validation rules */);
if ($valid === true) {
// do db changes
// redirect user ie POST+REDIRECT+GET
} else {
// output error messages
}
}
?>
// display page
<? page_footer(); ?>
With judicious use of helper functions (eg pagination links), the above is incredibly easy to read and debug. I also much prefer it to this model:
URL: /index.php?inc=blah
index.php:
<?
require "$inc.php"; // hopefully you sanitize this but so many don't
?>
I find this ugly, error-prone and even dangerous. I have a hierarchy of PHP files that mirrors the site structure (from a menu point of view) where each page is a PHP script. If they have common behaviour they both require it (not require_once, which is typically used as a hack for poor organisation).
Simple, easy, understandable, straightforward.
It seems a lot of programmers will throw a framework into the mix before there is really ever any need. I think this is a fairly lazy practice and one with a big cost: every decision made today is one that becomes harder to change later so put off making decisions like this as long as possible. Introducing something later is easier than introducing something now, finding out it doesn't really do what you want and then changing it later.
there are several other templating engines out there. however i've always found pure php to be the most convenient. i'm just more comfortable with it.
the thing i did not like about view helpers in ZF is that it usually made my code more bloated than cleaner. i'm specifically talking about the $this->url() helper :)