СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Введение в Silex в черновиках Перевод Tutorial

PHP
Silex — это микро PHP-фреймворк основанный на компонентах от Symfony.
В этой статье мы начнем с основ и попытаемся понять, для чего же нужен этот фреймворк.



Установка


Проще всего установить его через composer:
{
    "require": {
        "silex/silex": "1.3.*@dev",
        "twig/twig": "1.17.*@dev"
    },
    "require-dev": {
        "symfony/var-dumper": "dev-master"
    }
}

Или можете скачать архив.

Чтобы установить зависимости и сгенерировать файл автозагрузки запустите:
$ composer update


Мы установим шаблонизатор twig и дебаг-инструмент var dumper которые используются в Symfony.

Создаем структуру проекта


Одна из причин, по которой мне нравится Silex — это то, что вы можете организовать структуру как вы захотите.
|-app/
|----config/
|-resources/
|----views/
|----logs/
|-src/
|----MyApp/
|-public/
|----index.php
|----.htaccess
|-vendor/
|-composer.json


Добавим в public/index.php следющий код:
// public/index.php
<?php
 
require_once __DIR__ . '/../vendor/autoload.php';
 
$app = new Silex\Application();
 
$app->run();

Здесь мы создаем экземпляр класса Silex\Application и запускаем наше приложение.
Теперь если вы зайдете на сайт, то увидите сообщение об ошибке. Включим режим дебага в приложении:
$app['debug'] = true;

$app->run();

Снова перейдем на наш сайт и увидим NotFoundHttpException, потому что у нас еще нету роутов.

Роутинг


Регистрация маршрутов в Silex очень проста, нам нужно только добавить url и кэллбек функцию:
// public/index.php
$app->get('/', function(){
    return "Hello world";
});


Нам доступны get, post, put, delete методы. Запрос может возвращать строку или экземпляр класса Symfony\Component\HttpFoundation\Response:
// public/index.php
$app->get('/', function(){
    return new Symfony\Component\HttpFoundation\Response("Hello world");
});


Параметры запроса


$app->get("/users/{id}", function($id){
   return "User - {$id}";
});

Вы можете использовать и несколько параметров в запросе, но только при условии, что они будут переданы как параметры в функцию с такими же именами, иначе вы получите ошибку. Вы так же можете фильтровать параметры и ставить им значения по умолчанию:
$app->get("/users/{id}", function($id){
   return "User - {$id}";
})
    ->value("id", 0) // значение по умолчанию
    ->assert("id", "\d+"); // id может быть только числом


Одна из моих любимых функций — convert: она позволяет нам перехватить запрос и изменить значение, перед тем как вернуть его в функции:
$app->get("/users/{user}", function($user){
    // return the user profile
     
    return "User {$user}";
})->convert("user", function($id){
        $userRepo = new User();
        $user = $userRepo->find($id);
 
        if(!$user){
            return new Response("User #{$id} not found.", 404);
        }
 
        return $user;
    });


В этом примере convert берет id пользователя и ищет его в базе данных, а если его нет — то возвращает ошибку 404.

Если Вы фанат Laravel, то наверняка вы привыкли к фильтрам: auth, csrf и guest. В Silex вы можете заставить анонимную функцию вести себя как фильтр:
$app->get("/users/{user}", function($user){
    // показываем профиль 
 
    return "User {$user}";
})->before(function($request, $app){
    // редирект если пользователь не вошел
})
->after(function($request, $response){
    // записываем логи запроса
})
->finish(function(){
    // записываем лог запроса
});


Имена для роутов


Когда в нашем приложении много роутов, то неплохо бы было давать им имена, для того чтобы было проще генерировать URL:
$app->get("/users/list", function(Silex\Application $app){
    return "List of users";
})->bind('users');


<a href="{{ app.url_generator.generate('users') }}">Users</a>


Контроллеры


Одним из основных преимуществ использования контроллеров в является возможность их группировки. При создании RESTful API, URL, будет что-то вроде этого:
  • /users
  • /users/id (PUT, DELETE)
  • /users/id/edit


В данном случае — лучшим решением будет создание сервиса для контроллеров, где они будут сгрупированны:
// src/MyApp/Controller/Provider/User.php
 
class User implements ControllerProviderInterface{
 
    public function connect(Application $app)
    {
        $users = $app["controllers_factory"];
 
        $users->get("/", "MyApp\\Controller\\UserController::index");
 
        $users->post("/", "MyApp\\Controller\\UserController::store");
 
        $users->get("/{id}", "MyApp\\Controller\\UserController::show");
 
        $users->get("/edit/{id}", "MyApp\\Controller\\UserController::edit");
 
        $users->put("/{id}", "MyApp\\Controller\\UserController::update");
 
        $users->delete("/{id}", "MyApp\\Controller\\UserController::destroy");
 
        return $users;
    }
 
}

$app['controllers_factory'] возвращает нам экземпляр

Silex\ControllerCollection

который содержит нашу коллекцию роутов. В нашем котроллере все будет выглядеть так:
// src/MyApp/Controller/UserController.php
 
class UserController{
 
    public function index(){
        // show the list of users
    }
 
    public function edit($id){
        // show edit form
    }
 
    public function show($id){
        // show the user #id
    }
 
    public function store(){
        // create a new user, using POST method
    }
     
    public function update($id){
        // update the user #id, using PUT method
    }
 
    public function destroy($id){
        // delete the user #id, using DELETE method
    }
}


Осталось только добавить контроллер в наше приложение:
// app/routes.php
 
$app->mount("/users", new \MyApp\Controller\Provider\User());


В коллекции мы так же можем использовать фильтры:
// src/MyApp/Controller/Provider/User.php
 
class User implements ControllerProviderInterface{
 
    public function connect(Application $app)
    {
        //...
        $users->before(function(){
        // check for something here
    });
    }
}


Провайдеры


Провайдер — «поставщики услуг» для нашего приложения. Создадим файл providers.php и добавим в него:
// app/providers.php
$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__.'/../views',
));


Теперь мы можем использовать Twig:
$app->get(function(){
   return $app['twig']->render('home.twig');
});


Заключение


Silex это маленький Symfony. Надеюсь, что эта статья направит вас в правильное русло. Мы не охватили все, но надеюсь я дал Вам понять, как работает этот фреймворк. \

комментарии (0)