In the last couple of websites I made, I implemented a kind of MVC-style controller, I think.
I used mod_rewrite to send everything through index.php, so the url became a querystring.
It worked, but I'm wondering if it's a bit hacky, or just the accepted way of doing things. Is there a better way? I don't want a framework, I want to learn to do it myself.
Try my smallest framework in the world.
<?php
$g=$_GET;$c=#$g['c']?$g['c']:'Home';
if(!#include"c/$c.php")die('fail');
$m=method_exists($c,$m=#$g['m'])?$m:'index';
$o=new$c();$o->$m($g);
That goes in index.php and your controlls are Blog.php in ./c/Blog.php.
class Blog {
function index()
{
echo "Hello world";
}
function otherpage()
{
echo "ZOMG!";
}
Made mainly as a joke, as I wanted to make a framework that could fit in a tweet, but the basic logic is there ;-)
Passing everything through a single point of entry, e.g. index.php is not MVC, it is the FrontController Pattern. This goes well with MVC though. See my related answer here.
Apart from that, why not check out some of the frameworks around to learn how they do it. Doesn't mean you have to use them, just look at their code and adapt for your own framework.
That's the way I accomplished it. I then created a dispatch table that new, based on URL, which controller to instantiate and which dispatch to run.
How about learning to do it yourself, but still use a framework ? Either way, take a look at an open source framework like Symfony or CMS apps like Wordpress, Jommla! etc, and you will find that they all use mod_rewrite to set things off.
Most PHP frameworks make use of mod_rewrite do accomplish the same objective, and it's the only way to suppress index.php and make the urls more friendly, in a segmented way.
I'd say you're in the right path.
That method you used is called FrontController Pattern, and it's used by those frameworks as well, to go along with the MVC pattern.
If you care for a suggestion, I'd recommend you to make every request pass through each page controller, extending a base controller, since every site has some base data structures that you will probably need to use in every page, such as templates and session control.
Related
Is it bad to use index.php as loader for other scripts or does it make a difference?
i.e. requesting index.php with different query strings and inside it, selecting and including the matching script.
e.g.
www.example.com/?sign-in insteade of www.example.com/sign-in.php
www.example.com/?new-post insteade of www.example.com/new-post.php
In this way you can use index.php to do the common inclusions and processes, like, setting timezone, mb encoding, DB connection, auth, etc..
Best practice is to let apache rewrite all urls to an index.php or some other file which you can use as bootstrap. This bootstrap runs all the basic code and then this bootstrap can figure out which other actions to take based on the url.
Every framework works like this.
several things you might want to do in the bootstrap:
setup, autoloading classes
setup mysql connection
check if user is authenticated for a certain action
There are many tutorials on rewriting urls with apache: http://www.workingwith.me.uk/articles/scripting/mod_rewrite
If you really want to learn about best practices i would suggest looking at existing frameworks, at how they implement certain things. eg: Zend or Symfony
Yes and No
The problem is that by doing it you will lose any SEO value, eg: domain.com/index.php?post=story will rank very poorly against domain.com/post/story . Also your index.php is going to get messy very quickly.
That being said MVC's usually use a index.php, so my url would be domain.com/users/edit/123 which is a very logical url, but what actually gets called is domain.com/index.php , it then looks at the first paramater, "users" and instantiates the user controller and then looks for the function edit inside that and passes the "123" (user id) as the first parameter in the function. If you are not familiar with MVC's I would advise codeigniter as a starting one, more on codeigniter.
In the end you will just be re-inventing the wheel by building it from scratch, rather use a MVC make development much easier.
This is the best approach. You can take control of your website.
Create index.php and include other files on demand.
(Define a constant and use it in included files and so on)
But keep in mind to minimize index.php as much as possible.
Also you can use Apache mod_rewrite to generate SEO friendly URL.
Instead of routing all your requests (through htaccess) to index.php you can also split the routes to map to other files:
/blog/hello-there mapping to blog.php?title=hello-there
/sign/in mapping to login.php?login
etc, thus you create your own simple routing based on the request URL; easy to read and easy to maintain.
This solution is suitable in small projects, for bigger project I advise to use a complete framework like Yii or Symfony.
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 have some (basic perhaps) knowledge of the Model-View-Controller pattern and I want to create a site using this. But I find it a bit confusing how to actually implement this. I get stuck in the details.
Say that I have a site where each user keeps some todo lists. How would you approach this?
What classes would you create? Which class would output the HTML, which class would server as the controller and how would it communicate with the view to produce the output? etc.
Sorry if it seems silly and I guess it must be somewhat easy but I am stuck.
For the record:
It is not as hard to do a MVC in PHP, its more related with to be disciplined rather to be a difficulty task.
a) Model(s) (optional, you can use an array in PHP)
<?php
class MyModel() {
}
?>
b) Route (index.php?)
<?php
include "...";
// here we collects all the information, such post,get and path values
$action=...;
$param=....;
switch($controller) {
case "my": // www.myweb.com/my/action
include "controller\MyController.php"; // open the right controller.
break;
}
?>
c) Controller
<?php
include "model\MyModel.php";
switch($action) {
case "add":
// here live the logic, information, call for services and such.
$model=....;
// and finally...
include "view\MyView.php";
break;
}
?>
d) View
<html>
<body>
<?=$model->field;?>
</body>
<html>
As a note:
a) The view should be clean as possible. Think that the view could be created by a web designer that doesn't care about php.
b) The view is always the last step of the process. The view web always returns nothing.
It is very possible to do this without an existing framework, and just create your own. Its not a very difficult task anyway.
Not being application-specific, your MVC framework would have to do the following:
Redirect all trafic to a central page, so that every request gets
handled correctly.
Extract the controller and action from the request url. (for example, a request to http://yoursite.com/Task/Add, you have to translate that to the Add method on the TaskController)
Load the controller class (in our example TaskController). Perhaps using Autoload.
Call the Add method on the Controller
Show the result
There are multiple ways to implement views, you could emulate ASPMVC and have each Controller's action return an ActionResult, which has one method Execute. Then an overload of that, ViewResult would take care of loading the correct view and including it with the proper ModelData.
Here's the precise answer to your question from RASMUS LERDORF himself.
Read through.
Read the following intro to Symphony network:
http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html
Although your question is a little too broad, I think I can provide some help.
The number one question I had when starting out with frameworks was: Which framework, if any, should I use? In your case, I would not try to build a MVC website without a premade framework. Most of the architecture you will end up writing has already been done dozens of times over.
Things like DB abstraction, login systems, etc. are boring to write. Might as well use a framework that already has these things.
I would highly suggest this book: http://www.amazon.com/Building-Applications-Symfony-CakePHP-Framework/dp/0470887346/ref=sr_1_2?ie=UTF8&qid=1315227178&sr=8-2. It will walk you through building a simple MVC website using three different PHP MVC frameworks. By the end of the book, you will have enough experience with each framework so that you can choose which one you like best.
Alternatively, if you'd like to write your own framework so that you can learn how it's done, I'd recommend TJHeuvel's answer. Another option is to read the source code of an existing framework so you can see how others have implemented it.
The comment by Kheldar makes perfect sense. The tutorial actually covers making a micro framework using the MVC pattern.
Although you'd need to add to it - in terms of adding custom routes and some sort of routing engine but apart from that it is a very good baby step into developing your own MVC framework..
I'm new to Zend Framework MVC. I love a lot of things about working with an MVC environment, but find myself confused about it structurally sometimes.
I have a simple task, I'd like to flag certain users on our site to track their movements. For this I've set up a simple table in the database, and started to code in my _initTracking() function into the bootstrap. I then realized I was approaching this from the wrong direction - I'd like this to be one of the last functions that fires, to avoid mucking up my tracking entries with header redirects, and to ensure all autoloaded classes are present. How do I do this? Is there an "onBeforeRender" type of function? If there is I couldn't find it.
Thanks
I would suggest using a ZF plugin. You could track user's actions in plugin's postDispatch() or dispatchLoopShutdown() method, depending on how granular your tracking needs to be.
Some reading about ZF plugins - http://framework.zend.com/manual/en/zend.controller.plugins.html
Also a really neat article about request lifecycle in Zend Framework - http://www.eschrade.com/page/zend-framework-request-lifecycle-4b9a4288.
Ended up putting this in the layout scripts. There's probably a better way of doing this, but in my case (having all views I wanted the code to run in under 2 layouts) it was the easiest, and accomplished my goal.
I think the best place for this would be in a postDispatch() hook in your controller.
Have a look at http://framework.zend.com/manual/en/zend.controller.action.html, specifically the section on Pre- and Post-Dispatch Hooks.
This would suit placing your tracking code in a base controller - which your action controllers would extend, keeping the tracking code in one location.
how do you trigger a MVC application.
im only used to use procedural coding. since everything are classes, how do i trigger the first method, where should this method be put, and what should the class holding this starter method be called?
thanks
This is too general of a question. The answer will be subjective, because it can be done in many different ways. Your best bet is to look at a simple, lightweight MVC framework, see how they did it, and use that as a guide. I recommend checking out LightVC.
Generally all requests are routed through an index.php file. The request url is inspected to figure out what class file to include. For example, a request to /users/login would fire up Users_Controller, and then it would execute the login() method on the Users_Controller class. This is how most frameworks do it, but like I said, you should look at their source to get a better feel.
MVC applications have routers which based on the URL will call the appropriate controller and function inside.
Take a look at the flowchart of CodeIgniter for example -
http://codeigniter.com/user_guide/overview/appflow.html
Remember an MVC application is like a website, so when the user visits a page in their browser, it will call the methods automatically associated with that page, in the Controller.