doumi1912 2014-08-29 18:27
浏览 55
已采纳

如何在简单的php mvc示例中包含模型/视图和调用类

My question is how to dynamically include and call the model and view classes in a simple MVC model? I have no problem calling the controller, I have found various ways to do that, but I can't find a good solution for calling and passing in the model and view.

I have setup a .htaccess file to read the url as "www.domain.com/controller/method/id".

I was previously trying to do a check if a file exists for the model and view the same way I am doing the controller using the $cont variable, and then trying to load the model and pass it into the controller, then the view. The issue I had is that all the includes are using the $cont variable to call instantiate their classes and could not tell each other apart. I tried adding a suffic $cont . 'Controller', but then I couldn't load the class at all, let alone pass in the model or view.

Here is my latest example without model or view.

    <?php

//===============================================
// Debug
//===============================================
ini_set('display_errors','On');
error_reporting(E_ALL);

//===============================================
// Includes
//===============================================
require('coremvc.php');

//===============================================
// Constants & Globals
//===============================================
define('BASE_PATH', dirname(realpath(__FILE__)));
$GLOBALS['var'] = "";

//===============================================
// Session
//===============================================
session_start();

//===============================================
// Router
//===============================================

if ($_SERVER['REQUEST_URI'] !== '/') {
  $uri = $_SERVER['REQUEST_URI'];
  $uri = ltrim($uri, '/');
  $request = explode('/', $uri);

  foreach ($request as $key => $val) {
    if(empty($request[$key])) {
      unset($request[$key]);
    }
  }

  $request = array_values($request);

  if (isset($request[0])) { 
    $cont = $request[0];
  }

  if (isset($request[1])) { 
    $action = $request[1];
  }

} else {
  $cont = "home";
}

if (FILE_EXISTS('/controllers/' . $cont . 'Controller.php')) {
  require '/controllers/' . $cont . 'Controller.php';
} else {
  $cont = "home";
  require '/controllers/homeController.php';
}

//===============================================
// Start the controller
//===============================================
$controller = new $cont;

I have made the following changes to the example above, posted it below, as well as my super easy bake oven simple controller.

<?php

if (FILE_EXISTS('/controllers/' . $cont . 'Controller.php')) {
  require '/controllers/' . $cont . 'Controller.php';
} else {
  $cont = "home";
  $cont = ucfirst($cont) . 'Controller';
  require '/controllers/homeController.php';
}

//===============================================
// Start the controller
//===============================================
$controller = new  $cont('World');
$controller->world();

Controller, it is just extending an empty class which I was thinking I could use if I wanted to extend a common method to every class. That is what the coremvc.php is in the index.php above.

<?php

Class HomeController extends Controller
{

  function __construct($world) {
    echo "Hello ";
    $this->world = $world;
  }

  function world() {
    echo $this->world;
  }
}
  • 写回答

2条回答 默认 最新

  • duan32342 2014-08-30 10:34
    关注

    As it is already say you can have a look to use the spl_autoload_register which will require all your files in the given path. You can change this function to improve the load.

    Concerning the Model with your current code you can implement it as follow:

    $controllerPath = "/controllers/{$cont}Controller.php";
    $modelPath = "/model/{$cont}Model.php";
    if (FILE_EXISTS($controllerPath)) {
      require $controllerPath;
      if (FILE_EXISTS($modelPath)) {
          require $modelPath;
      }
      else {
          throw new \LogicException(
              sprintf("Your controller must implement a model. No model found: %s", $modelPath)
          );
      }
    } else {
      $cont = "home";
      require "/controllers/{$cont}Controller.php";
      require "/model/{$cont}Model.php";
    }
    
    //===============================================
    // Start the controller
    //===============================================
    $controller = new $cont($cont);
    

    In this sample of code, $cont is the name of the page like home. Which require the homeController and homeModel. Then in your __construct($modelName) just set the model.

    However, I don't recommand you tu use this because your controller can load many Models. Then, your controller could look like this:

    <?php
    namespace \App\Controller; // If you use namespace
    
    use App\Model\homeModel, // If you use namespace
        App\Model\productModel; // If you use namespace
    
    Class HomeController extends Controller
    {
    
      private $model;
    
      /* If this function is common to all controllers just move it 
      in the parent Controller class( one more time, I don't recommend to set
      the model using this way). */
      public function __construct($model) {
        $this->model= $model;
      }
    
      public function login() {
        $homeModel = new homeModel(); // If you use namespace
    
        // Example to call the view
        $myValue = 'Hello world';
        $this->render(array("myVariableName" => $myValue))
      }
    }
    

    In this second example $this->render can be a method in your Controller class (which by the way should be an abstract class). I'll give a last sample of code for the logic of the abstract controller.

    <?php
    
    namespace \App\Controller;
    
    abstract class AbstractController {
    
        /* Common code for all controllers */
        public function __construct() {
    
        }
    
        /* View renderer */
        protected function render($parameters) {
          /* Call the view here maybe an another class which manage the View*/
        }
    }
    

    To conclude, you can implement this MVC in many way, this code is just a suggestion and maybe its not the best way. I advise you to have a look with the spl_autoload that I put at the beginning of my answer.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?