How to Read/Render URLs Like Zend Framework

2019-03-03 14:24发布

问题:

I am working on creating my own framework in php.
Everything is going as planned except working the framework according to the URL.
I cannot understand this:
Normal URL loading from www.mydomain.com/folderone/foldertwo/index.php
Zend Framework URL loading from the same URL would be
www.mydomain.com/folderone(controller)/folder2(action)/variables

how can i create that logic?
What am i missing?
I am really dedicated to create this framework.

回答1:

I had the same task as I setup my framework. This is a solution work for me.

Create first your .htaccess file. Set up your rewrite conditions and exclude your template path. You can do it like that (just copy & paste):

RewriteEngine On

Options +Indexes
Options +FollowSymLinks

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/index\.php -f
RewriteCond %{DOCUMENT_ROOT}/template -d

RewriteRule ^(.*)$  index\.php?$1 [QSA]

Before I go ahead, we have to create five directories at least:

/var/www/models/
/var/www/controllers/
/var/www/classes/
/var/www/system/
/var/www/template/

Now, I added an auto loading in my index.php:

<?php
error_reporting(E_ALL ^ E_NOTICE);
session_start();

function autoload($class_name)
{
    $autoloadDirs = array('models', 'classes', 'controllers');

    foreach($autoloadDirs as $dir)
    {
        if(file_exists($dir.'/'.$class_name.'.php'))
        {
            require_once($dir.'/'.$class_name.'.php');
        }
    }
}

spl_autoload_register('autoload');

require_once('system/Calling.php');

Calling::Run();

?>

At the script above you'll see that require_once within Calling.php

class Calling
{
    public static function Run($querystring = null)
    {
        //1. Parameter = Contollername
        //2. Parameter = Action
        $qString = preg_replace('/(\/$|^\/)/','',$querystring === null ? $_SERVER['QUERY_STRING'] : $querystring);
        $callParam = !empty($qString) ? explode('/', $qString) : array();

        $controllerName = count($callParam) > 0 ?     (class_exists(ucfirst($callParam[0]).'Controller') ? ucfirst(array_shift($callParam)) : 'Error') : 'Main';
        //All controllers have suffix "Controller" -> NameController.php
        //and class name ike NameController
        //If no controller name given, use MainController.php
        $controllerClassName = $controllerName.'Controller';
        //All public methods have suffix "Action" -> myMethodAction
        //If there is no method named, use DefaultAction
        $actionName = count($callParam) > 0 && method_exists($controllerClassName, ucfirst($callParam[0]).'Action') ? ucfirst(array_shift($callParam)) : 'Default';
        $actionFunctionName = $actionName.'Action';

        //Fetch the params
        $param = new stdClass();
        for($i = 0; $i < count($callParam); $i += 2)
        {
            $param->{$callParam[$i]} = isset($callParam[$i + 1]) ? $callParam[$i+1] : null;
        }

        ////////////////////////////////////////////////////////////
        //Init the Controller
        $controller = new $controllerClassName($controllerName, $actionName);
        $controller->$actionFunctionName($param);
        ////////////////////////////////////////////////////////////
        //If you adapt this code: Is up to you to extends your controller  
        //from an internal controller which has the method Display(); 
        $controller->Display();
    }
}

Further, in your controller directory add your first controller namend MainController.php

//--> just better if you have also an internal controller with your global stuff 
//--> class MainController extends Controller
class MainController
{

    /** This is the default action
     * @param $params
     * @access public
     * @return
     */
    public function DefaultAction(stdClass $params)
    {
            //-> Do your staff here
    }

     /** This is the second action
     * @param $params
     * @access public
     * @return
     */
    public function SecondAction(stdClass $params)
    {
            //-> Do your staff here
    }

    /** This is the view handling method which has to run at least
     * and I recommend to set up an internal controller and to extend
     * all other controller from it and include this method in your
     * internal controller
     * @param
     * @access
     * @return
     */
    public function Display()
    {
        //-> Run your template here
    }
?>

Now, you can call the controller, methods and params like that:

//-> Load the main controller with default action
www.example.com/ 
//-> Load the main controller with default action
www.example.com/main/default/ 
//-> Load the main controller with second action
www.example.com/main/second/ 
//-> Load the main controller with second action and gives two params
www.example.com/main/second/key1/value1/key2/value2/ 

And now you'll have the following files and directories to start up your own framework.

/var/www/.htaccess
/var/www/index.php
/var/www/controllers/MainController.php
/var/www/system/Calling.php

/var/www/models/
/var/www/classes/
/var/www/template/

Enjoy your new basic framework kit



回答2:

Zend FrameWork and most MVC frameworks use a BootStrap.

It routes the URL (using .htaccess) to one file let's say (index.php) by using something like that:

RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php

Which loads the bootstrap and the routing class that takes whatever data it needs from the URL.

According to ZEND manual:

Routing is the process of taking a URI endpoint (that part of the URI which comes after the base URL) and decomposing it into parameters to determine which module, controller, and action of that controller should receive the request. This values of the module, controller, action and other parameters. Routing occurs only once: when the request is initially received and before the first controller is dispatched.

EDIT: Answer for your comment: Far away from ZEND FRAMEWORK, that's a code to test in a new PHP file:

<?php
    $url = 'http://test.com/test1/test2/news.php';
    $parse = parse_url($url);
    $tokens = explode("/", $parse[path]);
    print_r($tokens);
?>


回答3:

If you want to build a router, you could look at Glue PHP for giving you examples. It's a micro-framework that just do the routing part.