PHP Symfony Framework: первые шаги

Как и Вы мне скорее захотелось посмотреть как работает Symfony обратившись к ней в браузере. Но, прежде чем продолжить, тем кто не знает, хочу напомнить, что Symfony изначально умеет работать как минимум в двух окружениях (режимах):

  1. dev — краткое назчание от Developer, используется для информирования разработчика о багах, аннотациях, использовании памяти и т.п.
  2. prod — краткое название от Prodaction, используется для обычных посетителей сайта, которым точно не нужно знать ничего из того, что необходимо знать программисту

Самой главное, что Вы дожны знать прежде чем начать изучать Symfony, это помните о логах, которые для Вас любезно пишутся в директорию /Symfony/app/logs

  1. dev.log — логи от взаимодействия с Symfony в dev-окружении
  2. prod.log — логи от взаимодействия с Symfony в prod-окружении

А первое что нужно сделать прежде чем начать работать с Symfony, это выставить права на запись для директорий:

  • /Symfony/app/cache
  • /Symfony/app/logs

Если этого не сделаете, как собственно это сделал я, то попадете на кучу граблей описанных мной ниже.

Теперь откройте в браузере /config.php На этой странице вы увидите рекомендации по исправлению недочетов и неисправностей, если такие будут присутствовать. Какие-то из них обязательны (MAJOR PROBLEMS) для исполнения, а другие только рекомендованы (RECOMMENDATIONS) для улучшения работы Symfony.

Решение проблемы доступа по IP

Изначально Symfony нам дает dev для тестирования с помощью /app_dev.php однако который не работает и выдает ошибку:

You are not allowed to access this file. Check app_dev.php for more information.

с этим все очень банально нужно закомментировать проверку по IP, которая прописана в файле /app_dev.php

Просто программисты обычно тестируют на своей локальной машине, у которой внутренний IP 127.0.0.1

Чистим кэш

Прежде чем начать работать с prod-окружением нужно знать, что Symfony в этом режиме будет кэшировать все что только может, а значит любая Ваша ошибка будет закэширована. Так вот, чтобы Вы могли исправить ошибку Вам нужно будет очистить кэш, а очистить кэш можно командой:

php app/console cache:clear —env=prod —no-debug

тем не менее, если Вы выполните эту команду в консоли, то получите нехватку прав доступа, а все потому, что команда будет пытаться удалять файлы созданные пользователем Apache. Таким образом, чтобы команда сработала, нужно выполнить ее от пользователя Apache, а это можно сделать двумя способами:

  1. sudo -u www-data php app/console cache:clear —env=prod —no-debug
  2. с помощью вызова в браузере php-скрипта, который выполнит функцию exec

в первом способе Вам понадобится разрешение выполнять команды от пользователя Apache, которого скорее всего у Вас нет, т.к. изначально оно не настроено, а значит нужно будет обратиться к администратору сервера или если Вы самостоятельно админите сервак — настроить себе эту возможность.

Мы не будем прибегать к sudo, т.е. просто напишем вот такой скрипт:

<?php
exec(‘php app/console cache:clear —env=prod —no-debug’);

можно написать и совсем жестко:

<?php
exec(‘rm -rf /Symfony/app/cache/*’);
exec(‘rm -rf /Symfony/app/logs/*’);

Решение проблемы использовать prod-окружение

Протестировав все урлы /app_dev.php например /app_dev.php/demo/ я решил протестировать /app.php т.е. prod.

Однако, открыв главную страницу сайта, я получил ошибку:

Oops! An Error Occurred

The server returned a «500 Internal Server Error».

Something is broken. Please e-mail us at [email] and let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.

эта проблема образовалась из-за того, что я забыл /Symfony/app/config/routing.yml прописать хотя бы один роутинг.

Поэтому я взял и скопировал в файл /Symfony/app/config/routing.yml все содержимое файла /Symfony/app/config/routing_dev.yml

И открыв в браузере урл /app_dev.php я опять получил ошибку 500, это меня смутило и я начал разбираться.

Оказалось в содержании файла /Symfony/app/config/routing_dev.yml в конце написано:

_main:
resource: routing.yml

что означает подключить /Symfony/app/config/routing.yml

Следовательно, Symfony поступил как мы ему сказали:

  1. читал routing.yml
  2. видел что нужно подключить routing.yml (самого себя же)
  3. опять читал routing.yml
  4. и опять видел, что нужно подключить routing.yml (самого себя же)
  5. и так до бесконечности, таким образом мы сделали ему рекурсию

Я думаю, Вы поняли, что в файле /Symfony/app/config/routing_dev.yml нужно закомментировать:

_main:
resource: routing.yml

а в файле /Symfony/app/config/routing.yml вообще эти строчки не нужны.

Хорошо, эту проблему мы побороли, подумал я и решил, что для тестирования хотя бы главной страницы сайта Продакшен-версии, в файле /Symfony/app/config/routing.yml достаточно будет лишь одного роутинга.

_welcome:
pattern: /
defaults: { _controller: AcmeDemoBundle:Welcome:index }

Решение проблемы вызова контроллера прописанного в роутинге

Не смотря на то, что мы прописали всего один роутинг, который отлично работает в dev-окружении, в prod этот роутинг не сработал и в логах появилась ошибка:

request.CRITICAL: Uncaught PHP Exception Symfony\Component\Config\Exception\FileLoaderLoadException: «Cannot import resource «@AcmeDemoBundle/Controller/SecuredController.php» from «/Symfony/app/config/routing.yml». Make sure the «AcmeDemoBundle» bundle is correctly registered and loaded in the application kernel class.» at /Symfony/vendor/symfony/symfony/src/Symfony/Component/Config/Loader/FileLoader.php line 92 [] [

Оказалось, что проблема кроется в том _controller: AcmeDemoBundle:Welcome:index просто неизвестен Symfony в prod-окружении.

Подтверждение тому можете найти в файле /Symfony/app/AppKernel.php где прописано условие:

if (in_array($this->getEnvironment(), array(‘dev’, ‘test’))) {
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();

В этом файле указаны все бандлы, которые регистрирует Symfony, т.е. те о которых она знает. Как Вы поняли, раз Symfony ничего о банле AcmeDemoBundle не знает, значит и обратиться к классу WelcomeController, не говоря уже про вызов метода indexAction.

Поэтому, не мы такие, а Symfony таков, и все в нем правильно, просто мы не знаем про подобные подводные камни.

Ну, а решение данной проблемы может быть двух видов:

  1. прописать prod-окружение в массив проверки (простое решение, скажем так просто для тестирования)
  2. регистрация нового бандла ( у нас ведь своя задача и нам уже не нужен DemoBundle )

Я решу проблему вторым способом, а посему почистил кэш, удалил все что написал в файле /Symfony/app/config/routing.yml и выполнил команду:

php app/console generate:bundle —namespace=Acme/HelloBundle —format=yml

И если на все вопросы отвечать кнопкой Enter, то мы получим следующее:

  • в файл /Symfony/app/AppKernel.php добавится регистрация бандла HelloBundle
  • в файл /Symfony/app/config/routing.yml пропишится подключение роутинга для страницы /hello/Bill
  • появится директория /Symfony/src/Acme/HelloBundle с кучей папок и файлов под все что нам нужно ( спасибо Symfony за заботу ?

Чтобы закрепить знания, давайте напишем роутинг для главной страницы prod-окружения. Для этого в файл /Symfony/src/Acme/HelloBundle/Resources/config/routing.yml добавим:

acme_hello_start:
pattern: /
defaults: { _controller: AcmeHelloBundle:Default:start }

а в файл /Symfony/src/Acme/HelloBundle/Controller/DefaultController.php добавим метод:

public function startAction()
{
return $this->render(‘AcmeHelloBundle:Default:index.html.twig’, array(‘name’ => ‘Bill’));
}

Вот и все, теперь удалите кэш и заходите на страницу /app.php/ или просто /