Пример контроллера MVC

Я много читал о том, как и почему использовать подход MVC в приложении. Я видел и понимаю примеры модели, я видел и понимаю примеры View...., но я все еще неясен на контроллере. Мне бы очень хотелось увидеть достаточно подробный пример контроллера (ов). (в PHP, если это возможно, но любой язык поможет)

Спасибо.

PS: Было бы замечательно, если бы я мог увидеть пример страницы index.php, которая решает, какой контроллер использовать и как.

EDIT: Я знаю, какая задача контроллера, я просто не понимаю, как это сделать в ООП.

Ответ 1

Пример запроса

Поместите что-то вроде этого в index.php:

<?php

// Holds data like $baseUrl etc.
include 'config.php';

$requestUrl = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$requestString = substr($requestUrl, strlen($baseUrl));

$urlParams = explode('/', $requestString);

// TODO: Consider security (see comments)
$controllerName = ucfirst(array_shift($urlParams)).'Controller';
$actionName = strtolower(array_shift($urlParams)).'Action';

// Here you should probably gather the rest as params

// Call the action
$controller = new $controllerName;
$controller->$actionName();

На самом деле базовый, но вы получаете идею... (Я также не заботился о загрузке класса контроллера, но я думаю, что это можно сделать либо с помощью автоматической загрузки, либо вы знаете, как это сделать.)

Пример простого контроллера (контроллеры/login.php):

<?php    

class LoginController
{
    function loginAction()
    {
        $username = $this->request->get('username');
        $password = $this->request->get('password');

        $this->loadModel('users');
        if ($this->users->validate($username, $password))
        {
            $userData = $this->users->fetch($username);
            AuthStorage::save($username, $userData);
            $this->redirect('secret_area');
        }
        else
        {
            $this->view->message = 'Invalid login';
            $this->view->render('error');
        }
    }

    function logoutAction()
    {
        if (AuthStorage::logged())
        {
            AuthStorage::remove();
            $this->redirect('index');
        }
        else
        {
            $this->view->message = 'You are not logged in.';
            $this->view->render('error');
        }
    }
}

Как вы видите, контроллер заботится о "потоке" приложения - так называемой прикладной логике. Он не заботится о хранении и представлении данных. Он скорее собирает все необходимые данные (в зависимости от текущего запроса) и присваивает его представлению...

Обратите внимание, что это не сработает ни с какой структурой, которую я знаю, но я уверен, что вы знаете, какие функции должны выполнять.

Ответ 2

Здесь хорошая статья Джо Стампа (бывший ведущий архитектор digg.com). Эта статья является частью серии по внедрению MVC в PHP. Ссылка

Ответ 3

Представьте себе три экрана в пользовательском интерфейсе: экран, на котором пользователь вводит некоторые критерии поиска, экран, на котором отображается список сводок соответствующих записей, и экран, на котором после выбора записи она отображается для редактирования. Будет некоторая логика, связанная с начальным поиском в строках

if search criteria are matched by no records
    redisplay criteria screen, with message saying "none found"
else if search criteria are matched by exactly one record
    display edit screen with chosen record
else (we have lots of records)
    display list screen with matching records

Куда должна идти эта логика? Не в виде или модели наверняка? Следовательно, это работа контроллера. Контроллер также будет нести ответственность за принятие критериев и вызов метода Model для поиска.

Ответ 4

<?php
class Router {

    protected $uri;

    protected $controller;

    protected $action;

    protected $params;

    protected $route;

    protected $method_prefix;

    /**
     * 
     * @return mixed
     */
    function getUri() {
        return $this->uri;
    }

    /**
     * 
     * @return mixed
     */
    function getController() {
        return $this->controller;
    }

    /**
     * 
     * @return mixed
     */
    function getAction() {
        return $this->action;
    }

    /**
     * 
     * @return mixed
     */
    function getParams() {
        return $this->params;
    }

    function getRoute() {
        return $this->route;
    }

    function getMethodPrefix() {
        return $this->method_prefix;
    }

        public function __construct($uri) {
            $this->uri = urldecode(trim($uri, "/"));
            //defaults
            $routes = Config::get("routes");
            $this->route = Config::get("default_route");
            $this->controller = Config::get("default_controller");
            $this->action = Config::get("default_action");
            $this->method_prefix= isset($routes[$this->route]) ? $routes[$this->route] : '';


            //get uri params
            $uri_parts = explode("?", $this->uri);
            $path = $uri_parts[0];
            $path_parts = explode("/", $path);

            if(count($path_parts)){
                //get route
                if(in_array(strtolower(current($path_parts)), array_keys($routes))){
                    $this->route = strtolower(current($path_parts));
                    $this->method_prefix = isset($routes[$this->route]) ? $routes[$this->route] : '';
                    array_shift($path_parts);
                }

                //get controller
                if(current($path_parts)){
                    $this->controller = strtolower(current($path_parts));
                    array_shift($path_parts);
                }

                //get action
                if(current($path_parts)){
                    $this->action = strtolower(current($path_parts));
                    array_shift($path_parts);
                }

                //reset is for parameters
                //$this->params = $path_parts;
                //processing params from url to array
                $aParams = array();
                if(current($path_parts)){ 
                    for($i=0; $i<count($path_parts); $i++){
                        $aParams[$path_parts[$i]] = isset($path_parts[$i+1]) ? $path_parts[$i+1] : null;
                        $i++;
                    }
                }

                $this->params = (object)$aParams;
            }

    }
}

Ответ 5

<?php

class App {
    protected static $router;

    public static function getRouter() {
        return self::$router;
    }

    public static function run($uri) {
        self::$router = new Router($uri);

        //get controller class
        $controller_class = ucfirst(self::$router->getController()) . 'Controller';
        //get method
        $controller_method = strtolower((self::$router->getMethodPrefix() != "" ? self::$router->getMethodPrefix() . '_' : '') . self::$router->getAction());

        if(method_exists($controller_class, $controller_method)){
            $controller_obj = new $controller_class();
            $view_path = $controller_obj->$controller_method();

            $view_obj = new View($controller_obj->getData(), $view_path);
            $content = $view_obj->render();
        }else{
            throw new Exception("Called method does not exists!");
        }

        //layout
        $route_path = self::getRouter()->getRoute();
        $layout = ROOT . '/views/layout/' . $route_path . '.phtml';
        $layout_view_obj = new View(compact('content'), $layout);
        echo $layout_view_obj->render();
    }

    public static function redirect($uri){
        print("<script>window.location.href='{$uri}'</script>");
        exit();
    }
}

Ответ 6

  • Создание структуры папок
  • Настройка .htaccess и виртуальных хостов
  • Создать конфигурационный класс для сборки конфигурационного массива

Controller

  1. Создайте класс маршрутизатора с защищенным нестационарным, с геттерами
  2. Создать init.php с конфигурацией include и autoload и включить пути (lib, controlelrs, models)
  3. Создать файл конфигурации с маршрутами, значениями по умолчанию (маршрут, контроллеры, действие)
  4. Установить значения в маршрутизаторе - по умолчанию
  5. Задайте пути uri, взорвите uri и задайте маршрут, контроллер, действие, параметры, параметры процесса.
  6. Создать класс приложения для запуска приложения путем передачи uri - (защищенный маршрутизатор obj, запустить func)
  7. Создайте родительский класс контроллера для наследования всех других контроллеров (защищенные данные, модель, параметры - не статические) установить данные, параметры в конструкторе.
  8. Создайте контроллер и расширьте его выше родительского класса и добавьте метод по умолчанию.
  9. Вызовите класс и метод контроллера в функции запуска. метод должен иметь префикс.
  10. Вызов метода, если exisist

представления

  • Создайте класс родительского представления для создания представлений. (данные, путь) по умолчанию, установить контроллер, верните полный путь tempalte (не статический)
  • Создайте функцию рендеринга с ob_start(), ob_get_clean, чтобы вернуть и отправить содержимое в браузер.
  • Измените класс приложения для анализа данных для просмотра класса. если путь возвращен, перейдите также к классу просмотра.
  • Макеты.. layout зависит от маршрутизатора. повторно проанализируйте макет html для просмотра и рендеринга

Ответ 7

Пожалуйста, проверьте это:

    <?php
    global $conn;

    require_once("../config/database.php");

    require_once("../config/model.php");

    $conn= new Db;

    $event = isset($_GET['event']) ? $_GET['event'] : '';

    if ($event == 'save') {
        if($conn->insert("employee", $_POST)){
            $data = array(
                'success' => true,
                'message' => 'Saving Successful!',
            );
        }

        echo json_encode($data);
    }

    if ($event == 'update') {
        if($conn->update("employee", $_POST, "id=" . $_POST['id'])){
            $data = array(
                'success' => true,
                'message' => 'Update Successful!',
            );
        }

        echo json_encode($data);
    }

    if ($event == 'delete') {
        if($conn->delete("employee", "id=" . $_POST['id'])){
            $data = array(
                'success' => true,
                'message' => 'Delete Successful!',
            );
        }

        echo json_encode($data);
    }

    if ($event == 'edit') {
        $data = $conn->get("select * from employee where id={$_POST['id']};")[0];
        echo json_encode($data);
    }
?>