Spec-Zone.ru › Phalcon 2

MVC-приложения

Вся сложная работа по организации работы MVC в Phalcon обычно выполняется компонентом Phalcon\Mvc\Application. Этот компонент инкапсулирует все сложные операции, необходимые в фоновом режиме, инициализирует каждый необходимый компонент и интегрирует его в проект, чтобы шаблон MVC работал как и ожидается.

Одномодульные или многомодульные приложения

С помощью этого компонента вы можете запускать различные типы MVC-структур:

Одномодульное приложение

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

single/
    app/
        controllers/
        models/
        views/
    public/
        css/
        img/
        js/

Если пространства имен не используются, для организации потока MVC можно использовать следующий файл загрузки:

use Phalcon\Loader,
    Phalcon\DI\FactoryDefault,
    Phalcon\Mvc\Application,
    Phalcon\Mvc\View;

$loader = new Loader();

$loader->registerDirs(
    array(
        '../apps/controllers/',
        '../apps/models/'
    )
)->register();

$di = new FactoryDefault();

// Registering the view component
$di->set('view', function() {
    $view = new View();
    $view->setViewsDir('../apps/views/');
    return $view;
});

try {

    $application = new Application($di);

    echo $application->handle()->getContent();

} catch (\Exception $e) {
    echo $e->getMessage();
}

Если используются пространства имен, можно использовать следующий файл загрузки:

use Phalcon\Loader,
    Phalcon\Mvc\View,
    Phalcon\DI\FactoryDefault,
    Phalcon\Mvc\Dispatcher,
    Phalcon\Mvc\Application;

$loader = new Loader();

// Use autoloading with namespaces prefixes
$loader->registerNamespaces(
    array(
        'Single\Controllers' => '../apps/controllers/',
        'Single\Models'      => '../apps/models/',
    )
)->register();

$di = new FactoryDefault();

// Register the dispatcher setting a Namespace for controllers
$di->set('dispatcher', function() {
    $dispatcher = new Dispatcher();
    $dispatcher->setDefaultNamespace('Single\Controllers');
    return $dispatcher;
});

// Registering the view component
$di->set('view', function() {
    $view = new View();
    $view->setViewsDir('../apps/views/');
    return $view;
});

try {

    $application = new Application($di);

    echo $application->handle()->getContent();

} catch(\Exception $e){
    echo $e->getMessage();
}

Многомодульное приложение

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

multiple/
  apps/
    frontend/
       controllers/
       models/
       views/
       Module.php
    backend/
       controllers/
       models/
       views/
       Module.php
  public/
    css/
    img/
    js/

В каждом каталоге в apps/ есть своя собственная MVC-структура. Файл Module.php используется для настройки специфических параметров каждого модуля, таких как автозагрузчики или пользовательские сервисы:

namespace Multiple\Backend;

use Phalcon\Loader,
    Phalcon\Mvc\Dispatcher,
    Phalcon\Mvc\View,
    Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{

    /**
     * Register a specific autoloader for the module
     */
    public function registerAutoloaders()
    {

        $loader = new Loader();

        $loader->registerNamespaces(
            array(
                'Multiple\Backend\Controllers' => '../apps/backend/controllers/',
                'Multiple\Backend\Models'      => '../apps/backend/models/',
            )
        );

        $loader->register();
    }

    /**
     * Register specific services for the module
     */
    public function registerServices($di)
    {

        //Registering a dispatcher
        $di->set('dispatcher', function() {
            $dispatcher = new Dispatcher();
            $dispatcher->setDefaultNamespace("Multiple\Backend\Controllers");
            return $dispatcher;
        });

        //Registering the view component
        $di->set('view', function() {
            $view = new View();
            $view->setViewsDir('../apps/backend/views/');
            return $view;
        });
    }

}

Для загрузки многомодульной MVC-архитектуры требуется специальный файл загрузки:

use Phalcon\Mvc\Router,
    Phalcon\Mvc\Application,
    Phalcon\DI\FactoryDefault;

$di = new FactoryDefault();

//Specify routes for modules
$di->set('router', function () {

    $router = new Router();

    $router->setDefaultModule("frontend");

    $router->add("/login", array(
        'module'     => 'backend',
        'controller' => 'login',
        'action'     => 'index',
    ));

    $router->add("/admin/products/:action", array(
        'module'     => 'backend',
        'controller' => 'products',
        'action'     => 1,
    ));

    $router->add("/products/:action", array(
        'controller' => 'products',
        'action'     => 1,
    ));

    return $router;
});

try {

    //Create an application
    $application = new Application($di);

    // Register the installed modules
    $application->registerModules(
        array(
            'frontend' => array(
                'className' => 'Multiple\Frontend\Module',
                'path'      => '../apps/frontend/Module.php',
            ),
            'backend'  => array(
                'className' => 'Multiple\Backend\Module',
                'path'      => '../apps/backend/Module.php',
            )
        )
    );

    //Handle the request
    echo $application->handle()->getContent();

} catch(\Exception $e){
    echo $e->getMessage();
}

Если вы хотите сохранить конфигурацию модуля в файле загрузки, вы можете использовать анонимную функцию для регистрации модуля:

//Creating a view component
$view = new \Phalcon\Mvc\View();

//Set options to view component
//...

// Register the installed modules
$application->registerModules(
    array(
        'frontend' => function($di) use ($view) {
            $di->setShared('view', function() use ($view) {
                $view->setViewsDir('../apps/frontend/views/');
                return $view;
            });
        },
        'backend' => function($di) use ($view) {
            $di->setShared('view', function() use ($view) {
                $view->setViewsDir('../apps/backend/views/');
                return $view;
            });
        }
    )
);

Когда в Phalcon\Mvc\Application зарегистрированы модули, всегда необходимо, чтобы каждый соответствующий маршрут возвращал действительный модуль. Каждый зарегистрированный модуль имеет связанный класс, предлагающий функции для настройки самого модуля. Каждое определение класса модуля должно реализовывать два метода: registerAutoloaders() и registerServices(), которые будут вызываться Phalcon\Mvc\Application в соответствии с выполняемым модулем.

Понимание стандартного поведения

Если вы следовали учебнику или сгенерировали код с помощью Phalcon Devtools, вы можете узнать следующий файл загрузки:

try {

    // Register autoloaders
    //...

    // Register services
    //...

    // Handle the request
    $application = new \Phalcon\Mvc\Application($di);

    echo $application->handle()->getContent();

} catch (\Exception $e) {
    echo "Exception: ", $e->getMessage();
}

Ядро всей работы контроллера происходит при вызове handle():

echo $application->handle()->getContent();

Ручная загрузка

Если вы не хотите использовать Phalcon\Mvc\Application, код выше можно изменить следующим образом:

// Get the 'router' service
$router = $di['router'];

$router->handle();

$view = $di['view'];

$dispatcher = $di['dispatcher'];

// Pass the processed router parameters to the dispatcher
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());

// Start the view
$view->start();

// Dispatch the request
$dispatcher->dispatch();

// Render the related views
$view->render(
    $dispatcher->getControllerName(),
    $dispatcher->getActionName(),
    $dispatcher->getParams()
);

// Finish the view
$view->finish();

$response = $di['response'];

// Pass the output of the view to the response
$response->setContent($view->getContent());

// Send the request headers
$response->sendHeaders();

// Print the response
echo $response->getContent();

Следующая замена Phalcon\Mvc\Application не содержит компонента представления, что делает её подходящей для REST API:

// Get the 'router' service
$router = $di['router'];

$router->handle();

$dispatcher = $di['dispatcher'];

// Pass the processed router parameters to the dispatcher
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());

// Dispatch the request
$dispatcher->dispatch();

//Get the returned value by the latest executed action
$response = $dispatcher->getReturnedValue();

//Check if the action returned is a 'response' object
if ($response instanceof Phalcon\Http\ResponseInterface) {

    //Send the request
    $response->send();
}

Ещё один вариант, который перехватывает исключения, сгенерированные в диспетчере, и перенаправляет их на другие действия:

// Get the 'router' service
$router = $di['router'];

$router->handle();

$dispatcher = $di['dispatcher'];

// Pass the processed router parameters to the dispatcher
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());

try {

    // Dispatch the request
    $dispatcher->dispatch();

} catch (Exception $e) {

    //An exception has occurred, dispatch some controller/action aimed for that

    // Pass the processed router parameters to the dispatcher
    $dispatcher->setControllerName('errors');
    $dispatcher->setActionName('action503');

    // Dispatch the request
    $dispatcher->dispatch();

}

//Get the returned value by the latest executed action
$response = $dispatcher->getReturnedValue();

//Check if the action returned is a 'response' object
if ($response instanceof Phalcon\Http\ResponseInterface) {

    //Send the request
    $response->send();
}

Хотя вышеприведённые реализации намного более громоздки, чем код, необходимый при использовании Phalcon\Mvc\Application, они предлагают альтернативу при загрузке вашего приложения. В зависимости от ваших потребностей, вы можете захотеть иметь полный контроль над тем, что должно быть инициализировано, или заменить определённые компоненты своими собственными для расширения стандартной функциональности.

События приложения

Phalcon\Mvc\Application может отправлять события в EventsManager (если он присутствует). События генерируются с типом «application». Поддерживаются следующие события:

Название события Срабатывание
boot Выполняется при обработке первого запроса приложением
beforeStartModule Перед инициализацией модуля, только при наличии зарегистрированных модулей
afterStartModule После инициализации модуля, только при наличии зарегистрированных модулей
beforeHandleRequest Перед выполнением цикла диспетчеризации
afterHandleRequest После выполнения цикла диспетчеризации

Следующий пример демонстрирует, как подключить слушатели к этому компоненту:

use Phalcon\Events\Manager as EventsManager;

$eventsManager = new EventsManager();

$application->setEventsManager($eventsManager);

$eventsManager->attach(
    "application",
    function($event, $application) {
        // ...
    }
);

Внешние ресурсы

  • Примеры MVC на Github

© 2011–2016 Phalcon Framework Team
Licensed under the Creative Commons Attribution License 3.0.
https://docs.phalconphp.com/en/2.0.0/reference/applications.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API