Привет, %username%!
symfony — популярный PHP-фреймворк, на котором создано не мало серьезных проектов. Но в русскоязычном сообществе он распространен гораздо меньше. То ли это связано с более высоким порогом входа, то ли с отсутствием русскоязычной документации.
В этом статье я хочу рассказать о создании простейшего блога на symfony2.
Веб-сервер (например, Apache) с 5.3.2 или выше.
Сервер базы данных. Мы будем использовать MySQL.
Git (опционально).
Есть два пути: скачать архив с сайта или использовать git. Мы пойдем по второму, т.к. многие бандлы обновляются вслед за репозитарием.
В корне веб-сервера выполняем команды:
Переходим по ссылке http://localhost/symfony/web/config.php. Тут symfony напишет требования и рекомендации по настройке веб-сервера.
В моем случае нужно только указать директиву date.timezone в php.ini.
Там же, внизу страницы написано расположение вашего php.ini.
После того как вы исправите все проблемы, вас ждет самое интересное.
Перейдите по ссылке, с той же страницы, http://localhost/symfony/web/app_dev.php/_configurator/.
Сдесь можно настроить соединение с базой данных и выставить секретный ключ для предотвращение CSRF-аттак.
После этого symfony будет настроена, ну или предложит сама ввести полученую конфигурацию, если файл app/config/parameters.ini не доступен для записи.
Тут стоит упоминуть о бандлах. В данном случае мы будем использовать AcmeDemoBundle — уже созданный бандл, для создания демо-приложений. Углубляться в бандлы я не буду, скажу лишь, что в symfony2 из них, как из кирпичиков, строится ваше приложение.
Так же нам понадобится еще один бандл — FOSUserBundle. Он предоставляет все необходимое для работы с пользователями — вход, регистрация, подтверждение пароля и другое.
Скачиваем:
Добавляем новое пространство имен(namespace) в app/autoload.php:
Добавляем новый бандл в наше приложение в файле app/AppKernel.php:
В app/config/security.yml заменяем параметр providers:
А так же изменяем firewalls и access_control чтобы разрешить анонимный доступ для всех страниц, кроме страницы создания сообщения.
В app/config/config.yml удаляем auto_mapping: true и добавляем следующее:
и в конце файла дописываем:
Так же нужно добавить в framework translator, чтобы включить перевод строк. В частности строк FOSUserBundle.
Создадим файлы в директории src/Acme/DemoBundle/Entity. Если такой папки нет — создайте её.
Post.php:
Комментарии перед переменными — аннотации. В их использовании не должно возникнуть сложностей, если, конечно, не задаваться вопросом «как оно работает?».
User.php:
Мы наследуемся от FOS\UserBundle\Entity\User, так что кроме двух заданных нами будут сгенерированы еще несколько полей, включая username, password и email.
После написания моделей мы можем смело создать таблицы:
Создадим файл PostController.php в папке src/Acme/DemoBundle/Controller/:
Зачем нужен Template() перед каждым экшеном? Без него вместо
нам бы пришлось писать
В src/Acme/DemoBundle/Resources/views/Post создадим вид для каждого экшена.
index.html.twig:
new.html.twig:
О шаблонизаторе Twig уже частично упоминалось на хабре, но есть и отличная официальная документация, правда на английском языке.
В app/config/routing.yml прописываем наши роуты и не забываем про UserBundle
Теперь наш блог будет доступен по ссылке http://localhost/symfony/web/app_dev.php/post, а при попытке зайти на http://localhost/symfony/web/app_dev.php/post/new вы будете перенаправлены на страницу входа.
Я не претендую на полное руководство и оригинальность, это скорее заметка по быстрому старту приложения для себя.
Буду рад если кому то пригодится, так же не откажусь от помощи и критики.
У кого будут вопросы — задавайте, думаю на хабре есть люди которые занимаются этим фреймворком.
Кроме того у нас есть jabber-конференция symfony@conference.jabber.ru
symfony — популярный PHP-фреймворк, на котором создано не мало серьезных проектов. Но в русскоязычном сообществе он распространен гораздо меньше. То ли это связано с более высоким порогом входа, то ли с отсутствием русскоязычной документации.
В этом статье я хочу рассказать о создании простейшего блога на symfony2.
Шаг 0. Требования к ПО
Веб-сервер (например, Apache) с 5.3.2 или выше.
Сервер базы данных. Мы будем использовать MySQL.
Git (опционально).
Шаг 1. Установка.
Есть два пути: скачать архив с сайта или использовать git. Мы пойдем по второму, т.к. многие бандлы обновляются вслед за репозитарием.
В корне веб-сервера выполняем команды:
git clone https://github.com/symfony/symfony-standard.git symfony
cd symfony
php bin/vendors.php
Переходим по ссылке http://localhost/symfony/web/config.php. Тут symfony напишет требования и рекомендации по настройке веб-сервера.
В моем случае нужно только указать директиву date.timezone в php.ini.
Там же, внизу страницы написано расположение вашего php.ini.
После того как вы исправите все проблемы, вас ждет самое интересное.
Перейдите по ссылке, с той же страницы, http://localhost/symfony/web/app_dev.php/_configurator/.
Сдесь можно настроить соединение с базой данных и выставить секретный ключ для предотвращение CSRF-аттак.
После этого symfony будет настроена, ну или предложит сама ввести полученую конфигурацию, если файл app/config/parameters.ini не доступен для записи.
Тут стоит упоминуть о бандлах. В данном случае мы будем использовать AcmeDemoBundle — уже созданный бандл, для создания демо-приложений. Углубляться в бандлы я не буду, скажу лишь, что в symfony2 из них, как из кирпичиков, строится ваше приложение.
Так же нам понадобится еще один бандл — FOSUserBundle. Он предоставляет все необходимое для работы с пользователями — вход, регистрация, подтверждение пароля и другое.
Скачиваем:
git submodule add -f git://github.com/FriendsOfSymfony/UserBundle.git vendor/bundles/FOS/UserBundle
Добавляем новое пространство имен(namespace) в app/autoload.php:
$loader->registerNamespaces(array(<br> 'FOS' => __DIR__.'/../vendor/bundles',<br> // your other namespaces<br>);<br>
Добавляем новый бандл в наше приложение в файле app/AppKernel.php:
public function registerBundles()<br>{<br> return array(<br> // ...<br> new FOS\UserBundle\FOSUserBundle(),<br> // ...<br> );<br>}<br>
В app/config/security.yml заменяем параметр providers:
security:<br> providers:<br> fos_userbundle:<br> id: fos_user.user_manager<br>
А так же изменяем firewalls и access_control чтобы разрешить анонимный доступ для всех страниц, кроме страницы создания сообщения.
firewalls:<br> main:<br> pattern: .*<br> form_login:<br> provider: fos_userbundle<br> login_path: /login<br> use_forward: false<br> check_path: /login_check<br> failure_path: null<br> logout: true<br> anonymous: true<br>access_control:<br> - { path: /post/new, role: ROLE_USER } <br> - { path: /.*, roles: IS_AUTHENTICATED_ANONYMOUSLY}<br>
В app/config/config.yml удаляем auto_mapping: true и добавляем следующее:
doctrine:<br> orm:<br> mappings:<br> FOSUserBundle: ~<br> AcmeDemoBundle: ~<br> # your other bundles<br>
и в конце файла дописываем:
<br>fos_user:<br> db_driver: orm<br> firewall_name: main<br> class:<br> model:<br> user: Acme\DemoBundle\Entity\User<br>
Так же нужно добавить в framework translator, чтобы включить перевод строк. В частности строк FOSUserBundle.
framework:<br> translator: { fallback: en }<br>
Шаг 2. Создание моделей.
Создадим файлы в директории src/Acme/DemoBundle/Entity. Если такой папки нет — создайте её.
Post.php:
<?php<br><br>namespace Acme\DemoBundle\Entity;<br><br>use Doctrine\ORM\Mapping as ORM;<br><br>/**<br> *<br> * @ORM\Entity<br> */<br>class Post<br>{<br> /**<br> * @var integer $id<br> *<br> * @ORM\Id<br> * @ORM\Column(name="id", type="integer")<br> * @ORM\GeneratedValue(strategy="AUTO")<br> */<br> private $id;<br><br> /**<br> * @ORM\ManyToOne(targetEntity="User", inversedBy="posts")<br> * @ORM\JoinColumn(name="user_id", referencedColumnName="id")<br> */<br> public $user;<br><br> /**<br> * @var string $title<br> *<br> * @ORM\Column(name="title", type="string", length=255)<br> */<br> public $title;<br><br> /**<br> * @var text $description<br> *<br> * @ORM\Column(name="description", type="text")<br> */<br> public $description;<br>}<br>
Комментарии перед переменными — аннотации. В их использовании не должно возникнуть сложностей, если, конечно, не задаваться вопросом «как оно работает?».
User.php:
<?php<br>namespace Acme\DemoBundle\Entity;<br>use FOS\UserBundle\Entity\User as BaseUser;<br>use Doctrine\ORM\Mapping as ORM;<br><br>/**<br> * @ORM\Entity<br> * @ORM\Table(name="fos_user")<br> */<br>class User extends BaseUser<br>{<br> /**<br> * @ORM\Id<br> * @ORM\Column(type="integer")<br> * @ORM\generatedValue(strategy="AUTO")<br> */<br> protected $id;<br> <br> /**<br> * @ORM\OneToMany(targetEntity="Post", mappedBy="fos_user")<br> */<br> public $posts;<br><br> public function __construct()<br> {<br> parent::__construct();<br> // your own logic<br> }<br>}<br>
Мы наследуемся от FOS\UserBundle\Entity\User, так что кроме двух заданных нами будут сгенерированы еще несколько полей, включая username, password и email.
После написания моделей мы можем смело создать таблицы:
php app/console doctrine:schema:create
Шаг 3. Создание контроллера.
Создадим файл PostController.php в папке src/Acme/DemoBundle/Controller/:
<?php<br>namespace Acme\DemoBundle\Controller;<br><br>use Symfony\Bundle\FrameworkBundle\Controller\Controller;<br>use Acme\DemoBundle\Entity\Post;<br>use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;<br><br>class PostController extends Controller<br>{<br> /**<br> * @Template()<br> */<br> public function indexAction()<br> {<br> $em = $this->get('doctrine')->getEntityManager();<br> $posts = $em->getRepository('AcmeDemoBundle:Post')->findAll();<br> return array('posts' => $posts);<br> }<br> <br> /**<br> * @Template()<br> */<br> public function newAction()<br> {<br> $post = new Post();<br> // Получаем пользователя и присваиваем новому посту<br> $post->user = $this->get('security.context')->getToken()->getUser();<br> // Создаем форму, по хорошему следовало бы создать отдельный класс, но можно и так<br> $form = $this->get('form.factory')<br> ->createBuilder('form', $post)<br> ->add('title', 'text')<br> ->add('description', 'textarea')<br> ->getForm();<br> $request = $this->get('request');<br> if ($request->getMethod() == 'POST') {<br> $form->bindRequest($request);<br> if ($form->isValid()) {<br> $em = $this->get('doctrine')->getEntityManager();<br> $em->persist($post);<br> $em->flush();<br> return $this->redirect($this->generateUrl('post_index'));<br> }<br> }<br> return array('form' => $form->createView());<br> }<br>}<br>
Зачем нужен Template() перед каждым экшеном? Без него вместо
return array('posts' => $posts);
нам бы пришлось писать
return $this->render('AcmeDemoBundle:Post:index.html.twig', array('posts' => $posts));
Шаг 4. Шаблоны.
В src/Acme/DemoBundle/Resources/views/Post создадим вид для каждого экшена.
index.html.twig:
{% extends 'AcmeDemoBundle::layout.html.twig' %}<br><br>{% block content %}<br><br>{% if is_granted('ROLE_USER') %}<br> <div><a href="{{ path("post_new") }}">New Post</a></div><br>{% endif %}<br><br>{% for post in posts %}<br> <h2>{{ post.title}}</h2><br> <p>{{ post.description }}</p><br> <div>by {{ post.user.username }}</div><br>{% else %}<br> Пока в блоге нет статей.<br>{% endfor %}<br><br>{% endblock %}<br>
new.html.twig:
{% extends 'AcmeDemoBundle::layout.html.twig' %}<br><br>{% block content %}<br> <h1>New Post</h1><br> <br> <form action="{{ path("post_new") }}" method="post"><br> {{ form_widget(form) }}<br><br> <input type="submit" class="symfony-button-grey" value="Create" /><br> </form><br>{% endblock %}<br>
О шаблонизаторе Twig уже частично упоминалось на хабре, но есть и отличная официальная документация, правда на английском языке.
Шаг 5. Роуты.
В app/config/routing.yml прописываем наши роуты и не забываем про UserBundle
post_index:<br> pattern: /post<br> defaults: { _controller: AcmeDemoBundle:Post:index }<br><br>post_new:<br> pattern: /post/new<br> defaults: { _controller: AcmeDemoBundle:Post:new }<br><br>fos_user_security:<br> resource: "@FOSUserBundle/Resources/config/routing/security.xml"<br><br>fos_user_user:<br> resource: "@FOSUserBundle/Resources/config/routing/user.xml"<br> prefix: /user<br><br>* This source code was highlighted with Source Code Highlighter.
Теперь наш блог будет доступен по ссылке http://localhost/symfony/web/app_dev.php/post, а при попытке зайти на http://localhost/symfony/web/app_dev.php/post/new вы будете перенаправлены на страницу входа.
Послесловие
Я не претендую на полное руководство и оригинальность, это скорее заметка по быстрому старту приложения для себя.
Буду рад если кому то пригодится, так же не откажусь от помощи и критики.
У кого будут вопросы — задавайте, думаю на хабре есть люди которые занимаются этим фреймворком.
Кроме того у нас есть jabber-конференция symfony@conference.jabber.ru