资源说明:A Modular MVC Framework
App/Www/Main/Views/Index/HelloWorld.html
# Voodoo 1.x.x #### A Simple, Easy, Intuitive PHP Framework for Those Who Keep It Simple --- Name: Voodoo License: MIT Design: Modular MVC Requirements: PHP 5.4 Compliance: PSR-2 Author: [Mardix](http://github.com/mardix) Copyright: This Year - Mardix [VoodooPHP.org](http://voodoophp.org) [Forums](https://groups.google.com/d/forum/voodoophp/) *This is an overview of Voodoo, please go to [VoodooPHP.org](http://voodoophp.org) for a complete documentation of the framework* --- ## About Voodoo! Voodoo is Modular MVC framework written in PHP. Its main goal is to ensure separation of concerns by keeping your code organized and avoid mixing database calls, HTML tags and business logic in the same script. Voodoo, first, organize your application into subset of MVC structure which are independent from other one. These subsets are called Modules. Modules can be an admin section, the main site, intranet, or can be used for A/B testing. Modules improve maintainability by enforcing logical boundaries between components. By being Modular, Voodoo allows developers/designers to work on individual module at the same time, thus making development of program faster. New features or new sections can be implemented quickly without changing other sections. And when it's no longer needed, the module can be deleted and everything is still gravy. --- ### Features Highlight - Slim - RESTful - API ready - MVC - Shared Application - Modular MVC - Namespaced - PSR compliant - Front Controller - Templates - Handlebars (templating system) - Smart Routing - [VoodOrm](https://github.com/mardix/VoodOrm) - Annotation - [Paginator](https://github.com/mardix/Paginator) - [Handlebars](https://github.com/mardix/Handlebars) - Bootstrap CSS/JS framework - HTTP Request - Voodooist (generate code on the fly) --- ## Install Voodoo with Composer To install Voodoo, create or edit the **composer.json** file, and add the code below in the 'require': "voodoophp/voodoo": "1.*" Your composer.json file should look something similar to this: { "name": "voodoophp/myapp", "description": "My awesome Voodoo App", "require": { "voodoophp/voodoo": "1.*" } } then run the command below to download Voodoo and its dependencies composer install Assuming that your composer installed the packages in your `/vendor` directory, you should see at least the following when you go inside of /vendor | +-- composer.json | +-- vendor/ | +-- composer/ | +-- voodoophp/ --- ## Setup & Filesystem Now the Voodoo is installed, it's time to set it up so it creates the directories for your applications. Assuming that composer installed packages in your `/vendor` directory, the Voodoo framework will be in: `/vendor/voodoophp/voodoo` Enter the command below cd vendor/voodoophp/voodoo/src/Voodoo/Voodooist php ./setup.php Once the setup is done, you should have a filesystem similar to this: | +-- App/ | +-- .htaccess | +-- _conf/ | +-- Www/ | +-- Config.conf.php | +-- Main/ | +-- Controller/ | +-- Model/ | +-- Views/ | +-- assets/ | +-- bootstrap/ | +-- css/ | +-- img/ | +-- js/ | +-- jquery/ | +-- vendor | +-- composer/ | +-- voodoophp/ | +-- composer.json | +-- .htaccess | +-- index.php | +-- robots.txt **/App** : Contains your application's Modular MVC **/App/_conf** : Contains the configurations, ie: DB.conf.php for database settings, System.conf.php for system wide settings, app.json your application schema to create your MVC files on the fly. **/App/Www**: That's your default application which contains your MVC files. When someone accesses your application that's where he/she will land, unless you change it to another application. You can also have */App/Site1*, */App/Site2*, */App/Api* and so on to create multi applications which share the same Voodoo code base. **/assets/**: That's your application shared assets. For your convenience, we added Bootstrap and JQuery. **/vendor/**: Where composer installed the packages **/composer.json**: The composer file **/index.php**: The front-controller file which redirect everything to Voodoo to do its magic! --- ## The Voodooist The Voodooist is our servant, it will help us create directories and files properly namespaced per PSR-0 in our Voodoo application. Once our application has been setup, Voodooist requires: /App/_conf/app.json and /App/voodooist.php. These files were created during the initial setup. #### - App/_conf/app.json **App/_conf/app.json** is a JSON file that contains the layout of your application, including modules, controllers, controller's action etc. It is ran by Voodooist to setup your application. Below is a basic **app.json** { "createPublicAssets" : true, "applications" : [ { "name" : "www", "modules" : [ { "name" : "Main", "template" : "Default", "isApi" : false, "omitViews" : false, "controllers" : [ { "name" : "Index", "actions" : ["index", "login", "logout", "about-us"] }, { "name" : "Account", "actions" : ["index", "info", "preferences"] } ], "models" : [ { "name" : "User", "dbAlias" : "MyDB", "table" : "user", "primaryKey" : "id", "foreignKey" : "%s_id" }, { "name" : "User/Preference", "dbAlias" : "MyDB", "table" : "user_preference", "primaryKey" : "id", "foreignKey" : "%s_id" } ] } ] } ] } #### - /App/Voodoist.php Once Voodoo is setup, you won't need to go the `/vendor/voodoophp/voodoo/src/Voodoo/Voodooist/setup.php` to create your application's files. Voodoo created `/App/voodooist.php` to serve the same purpose. You will need it to create your application's files on the fly based on your /App/_conf/app.json. All files will be properly namespaced per PSR-0, and placed inside of /App under their respective application. Running the code below, will execute the `/App/_conf/app.json` set above: cd /App php ./voodooist.php Upon execution of /App/voodooist.php you will should see a filesystem similar to this: | +-- App/ | +-- .htaccess | +-- Www | +-- Config.conf.php | +-- Main | +-- Controller/ | +-- BaseController.php (extends Voodoo\Core\Controller) | +-- Index.php (extends BaseController) ::actionIndex() ::actionLogin() ::actionLogout() ::actionAboutUs() | +-- Account.php (extends BaseController) ::actionIndex() ::actionInfo() ::actionPreferences() | +-- Model/ | +-- User.php | +-- User/Preference.php | +-- Views/ | +-- Index/ | +-- Index.html | +-- Login.html | +-- Logout.html | +-- AboutUs.html | +-- Account/ | +-- Index.html | +-- Info.html | +-- Preferences.html | +-- _assets/ | +-- js/ | +-- css/ | +-- img/ | +-- _components/ | +-- flash-message.html | +-- pagination.html | +-- _layouts/ | +-- default.html | +-- head-tag.html | +-- footer.html | +-- header.html | +-- assets/ [+] | +-- vendor/ [+] | +-- index.php | +-- .htaccess ### Application (Multi-Applications) Application is the upper level of your program. Everything must be in an application. An application can be another site sharing the same Voodoo code base of other application. Hence making Voodoo multi-sites , multi-applications ready. You can have *Site1.com*, *Site2.com*, *SiteX.com* all under the same environment sharing the same front controller, same Voodoo code base. And since your application is namespaced PSR-0, it's easy to re-use code from other applications. Inside of each applications are the applications modules. By default Voodoo creates the **WWW** which is the default entry point of your site. In large, Applications are sets of Modules. A more advance app.json looks like that with three applications: *Www, AnotherApp, Api* /App/_conf/app.json { "createPublicAssets" : true, "applications" : [ { "name" : "www", "modules" : [ { "name" : "Main", "template" : "Default", "isApi" : false, "omitViews" : false, "controllers" : [ { "name" : "Index", "actions" : ["index", "login", "logout", "about-us"] }, { "name" : "Account", "actions" : ["index", "info", "preferences"] } ], "models" : [ { "name" : "User", "dbAlias" : "MyDB", "table" : "user", "primaryKey" : "id", "foreignKey" : "%s_id" }, { "name" : "User/Preference", "dbAlias" : "MyDB", "table" : "user_preference", "primaryKey" : "id", "foreignKey" : "%s_id" } ] } ] }, { "name" : "AnotherApp", "modules" : [ { "name" : "Main", "template" : "Default", "isApi" : false, "omitViews" : false, "controllers" : [ { "name" : "Index", "actions" : ["index", "info"] } ] }, { "name" : "Admin", "template" : "Default", "isApi" : false, "omitViews" : false, "controllers" : [ { "name" : "Index", "actions" : ["index", "login"] } ] } ] }, { "name" : "Api", "modules" : [ { "name" : "Main", "template" : "", "isApi" : true, "omitViews" : true, "controllers" : [ { "name" : "Index", "actions" : ["index", "status"] } ] } ] } ] } After running /App/voodooist.php you will get the following structure | +-- App/ | +-- .htaccess | +-- Www | +-- Config.conf.php | +-- Main | +-- Controller/ | +-- BaseController.php (extends Voodoo\Core\Controller) | +-- Index.php (extends BaseController) ::actionIndex() ::actionLogin() ::actionLogout() ::actionAboutUs() | +-- Account.php (extends BaseController) ::actionIndex() ::actionInfo() ::actionPreferences() | +-- Model/ | +-- User.php | +-- User/Preference.php | +-- Views/ | +-- Index/ | +-- Index.html | +-- Login.html | +-- Logout.html | +-- AboutUs.html | +-- Account/ | +-- Index.html | +-- Info.html | +-- Preferences.html | +-- _assets/ | +-- js/ | +-- css/ | +-- img/ | +-- _components/ | +-- flash-message.html | +-- pagination.html | +-- _layouts/ | +-- default.html | +-- head-tag.html | +-- footer.html | +-- header.html | +-- AnotherApp | +-- Config.conf.php | +-- Main | +-- Controller/ | +-- BaseController.php (extends Voodoo\Core\Controller) | +-- Index.php (extends BaseController) ::actionIndex() ::actionInfo() | +-- Views/ | +-- Index/ | +-- Index.html | +-- Info.html | +-- _assets/[+] | +-- _components/ [+] | +-- _layouts/ [+] | +-- Admin | +-- Controller/ | +-- BaseController.php (extends Voodoo\Core\Controller) | +-- Index.php (extends BaseController) ::actionIndex() ::actionLogin() | +-- Views/ | +-- Index/ | +-- Index.html | +-- Login.html | +-- _assets/[+] | +-- _components/ [+] | +-- _layouts/ [+] | +-- Api | +-- Config.conf.php | +-- Main | +-- Controller/ | +-- BaseController.php (extends Voodoo\Core\Controller\Api) | +-- Index.php (extends BaseController) ::actionIndex() ::actionStatus() | +-- assets/ [+] | +-- vendor/ [+] | +-- index.php | +-- .htaccess ### Modules Modules are the second level of your application. Application are sets of Modules and Modules are set of MVC application. Each module contains one set of MVC. By default Voodoo will fall back to `Main` module if a module is not specified. That's how the module **Main** looks like in the **Www** application. | +-- App/ | +-- .htaccess | +-- Www | +-- Config.conf.php | +-- Main | +-- Controller/ | +-- Index.php ::actionIndex() ::actionAbout() | +-- Model/ | +-- MySampleModel.php | +-- View/ | +-- Index/ | +-- Index.html | +-- About.html | +-- _assets/ | +-- js/ | +-- css/ | +-- img/ | +-- _components/ | +-- flash-message.html | +-- pagination.html | +-- _layouts/ | +-- default.html | +-- head-tag.html | +-- footer.html | +-- header.html | +-- assets/ [+] | +-- vendor/ [+] | +-- index.php | +-- .htaccess All classes are namespaced per PSR-0. So the main namespace for Www/Main are as follow: App\Www\Main App\Www\Main\Controller App\Www\Main\Controller\Index App\Www\Main\Model App\Www\Main\Model\MySampleModel Substitute `Www` for any other application name you would have the same structure. #### What can modules be used for? Modules can be other sections of your site separated from the main site, let's say `App\Www\Admin` for an admin section or `App\Www\Api` to serve an API. It can be anything you want it. It can be used for A/B testing... etc... --- Now you understand how Voodoo is structured let's get to know about how everything works --- ## Front-Controller: /index.php At the root of your application there is the **index.php**. Its job, as a front-controller, is to encapsulate the typical request/route/dispatch/response for the Voodoo application, by invoking `Voodoo\Core\Application` /index.php doVoodoo(); Everythings comes here first then go to where they need to be ### Front-Controller serving multiple application based on URL The example below illustrates how you can have multi-sites using the same code base. Based on the hostname, each site will use a different application directory. You will have to point all the domains to the same IP address for it to work. Let's use the /App/_conf/app.json above for our multi-sites /index.php doVoodoo(); So now you have a multi-sites application. Ayibobo! --- ## Smart Routing & Application Execution Voodoo cleverly routes to the right module of the application by using the URL schema site.com/Module/Controller/Action/Segments/?paramName=paramValue * Module: The container of the MVC application * Controller: A class accepting the user request * Action: A method of the controller's class * Segments: extra parameters that are passed in the action * ParamName/ParamValue : Parameters from the query url ### How does Voodoo excute your application? The very first thing Voodoo requires is an App name. The app name contains all the modules for the application. This is set in the front-controller. Then it checks for the **Module**, if found, it accesses the directory Then checks the **Controller**, which is a class, if exists it loads it Then checks the **Action**, a method in the Controller. If exists it executed the method But if the Action doesn't exist, it will fall back to the *Controller::actionIndex()* method If Controller doesn't exist, it will fall back to the *Index.php* controller If Module doesn't exist, it will fall back to *Main* module ### Application Routes (Customed Routes) Sometimes, you may want to change the way the URL is displayed. Maybe because of SEO purposes, or something has changed, or whatever... you will have to alter the routes in the application config fille at: /App/$AppName/Routes.conf.php Each application contains a `Routes.conf.php` file. It is loaded by `Voodoo\Core\Application` upon initialization, and contains the necessary settings such as which controller to load by default, the views settings etc. It also contains your application's routes. If you open /App/Www/Routes.conf.php, look for the routes key, and you should fine something that looks like this: /App/Www/Routes.conf.php path["(:any)"] = "$1" It, by default, uses the basic route schema site.com/Module/Controller/Action/Segments/?paramName=paramValue Let's say you have this url path: site.com/users/profile/info/mardix - users = module - profile = controller - info = action - mardix = segment But you want to short it to: `site.com/profile/mardix` You can create a new route path in your Config.conf.php file like this path["/profile/(:any)"] = "/Users/Profile/Info/$1" path["(:any)"] = "$1" Now when someoneone enters `site.com/profile/mardix` , the application will be re-routed to `/Users/Profile/Info/mardix`. You can add as many routes as you want. Also, the routes can have as many directives as you want and they support regex for more advanced matching. path["/profile/(:any)"] = "/Users/Profile/Info/$1" path["/music/([rap|techno|compas]+)/(:num)"] = "/Music/Selection/genre/$1/song/$2" path["/blog/(:alnum)/(:num)/(:any)"] = "Main/Blog/Category/$1/post/$2/$3/" path["(:any)"] = "$1" The /music route: site.com/music/rap/1526 -> /Music/Selection/genre/{rap}/song/{1526} Music = module Selection = controller genre = action rap = segement #1, accessed in the controller $this->getSegment(1) song = segement #2, accessed in the controller $this->getSegment(2) 1526 = segement #3, accessed in the controller $this->getSegment(3) #### Stuff to understand about routes: - To reduce overhead, Application's routes are run before the call to any MVC application - Re-routing is not a redirect. It routes a path to a new path without changing the URL in the address bar - Voodoo routes are case incensitive. So accessing */Profile/info/mardix* and */pRofile/inFo/mardix* will result to the same place - Only alphanumeric [AZ-09] characters are accepted. All the other one will be ignored when routing. So */pro-file/info/mardix* will still result to */Profile/Info/mardix/*. Same as */about-us/* which result to */aboutus/*. So you can cleverly write your SEO friendly url and still keep your application running with no headache. *It is important to understand that routes are matched in the order they are added, and as soon as a URL matches a route, routing is essentially "stopped" and the remaining routes are never tried. Because the default route matches almost anything, including an empty url, new routes must be place before it.* path[/article/(:num)] = "/Blog/Article/Read/$1" path["/profile/(:any)"] = "/Main/Profile/Info/$1" path["(:any)"] = "$1" --- Now you see how Voodoo works with Front-Controller and Routes, let's get in the sauce of the meat. Ayibobo! --- ## Model-View-Controller As you already notice above, your MVC application will reside under an $AppName and a $ModuleName. - Models: `App\$AppName\$ModuleName\Model` - Controllers: `App\$AppName\$ModuleName\Controller` - Views: `App/$AppName/$ModuleName/Views` Let's say we are using the `Www` application and the `Main` module. **Controller** All controllers will reside under the namespace: `App\Www\Main\Controller` App/Www/Main/Controller/Index.php view()->setTitle("Hello World"); } public function actionAboutUs() { } //... } All controllers are extended by `BaseController` which is extended by `Voodoo\Core\Controller` which contains the methods needed to get params, load views, get models, etc... BaseController is set so you can share functionnalities with other controllers **Views** All views a placed at: `App/Www/Main/Views` Views, by default, are HTML template files. Based on the separation of concerns principle, the views role are to display data. No logic whatsoevet. To accomplish that, Voodoo uses *[Mustache.php](https://github.com/bobthecow/mustache.php/tree/cd6bfaefd30e13082780b3711c2aa4b92d146b1e)* as the template engine to render HTML. Other engines, such as Twig can be used instead of Mustache. But if you are thinking about using PHP as template system itself, like `= $this->title; ?> ` , well my friend, I'm not sure Voodoo is the right tool for you. Anyway... That's how a template file looks like with mustache template:{{_app.title}}
-
{{#each articles}}
- {title} {{/each articles}}
Welcome to my site
Blah blah blahHello World
Blah blah blahLatest Articles
-
{{#each articles}}
- {{title}} {{/each}}
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。