Створення блогу на Symfony 2.8 lts [ Частина 3 ]




Огляд



Doctrine 2 являє собою хороший приклад механізму об'єктно-реляційного відображення (ORM) для PHP 5.3+, що дозволяє працювати з базою даних максимально прозоро, де в якості проміжного шару використовуються звичайні об'єкти PHP. В якості основи використовується досить потужний шар абстракції бази даних (DBAL). Основне завдання ORM — зв'язати дві концепції: об'єкти PHP і запису в реляційній базі даних. Одна з ключових особливостей Doctrine — можливість написання запитів на власному об'єктно-орієнтованою мовою, ніж-то нагадує SQL, званим Doctrine Query Language (DQL). Крім невеликих відмінностей від SQL, він дозволяє значно посилити ступінь абстракції між об'єктами і рядками бази даних, що дозволяє створювати потужні та гнучкі запити, при цьому зберігаючи цілісність.

На додаток до Doctrine 2, ми також ознайомимося з концепцією Фікстур даних. Фікстури даних являють собою механізм для заповнення баз даних для розробки і тестування відповідними тестовими даними. В кінці цієї глави ви визначите модель блогу, оновлення бази даних, щоб відобразити нову модель, і створите кілька фікстур даних.

Проект на Github

Дізнатися як встановити потрібну вам частину керівництва, можна в описі до дерева з посилання. (Наприклад, якщо ви хочете почати це з уроку не проходячи попередній)

Doctrine 2: Модель

Щоб наш блог функціонував нам потрібно подумати про те, як ми будемо зберігати дані. Doctrine 2 надає бібліотеку ОRМ, призначену саме для цієї мети. Вона дозволяє використовувати різні СУБД включаючи MySQL, PostgreSQL та SQLite. Ми будемо використовувати MySQL, але її можна легко замінити інший СУБД.
Примітка

Якщо ви не знайомі з ORM ми розкриємо базові принципи. Ухвалу від Wikipedia говорить:
ORM (англ. Object-Relational Mapping, рос. об'єктно-реляційне відображення) — технологія програмування, яка пов'язує бази даних концепцій об'єктно-орієнтованих мов програмування, створюючи «віртуальну об'єктну базу даних».

ОRМ полегшує переклад даних з реляційної бази даних, такі як MySQL PHP об'єкти, якими ми можемо маніпулювати. Це дозволяє нам инкапсулировать потрібну функціональність, яка нам необхідна в таблиці, через клас. Уявіть таблицю користувача, вона ймовірно має поля:username, password, first_name,last_name, e та job. З допомогою ОRМ це стає класом з властивостями username, password, first_name і т. д., що дозволяє нам викликати такі методи, як getUsername() та setPassword(). ORM пішло набагато далі, воно також дозволяє отримати зв'язані таблиці, в той час як ми витягуємо об'єкт користувача або пізніше. Тепер припустимо, що наш користувач має кілька друзів, пов'язаних з ним. Це буде таблиця друзів, з первинним ключем для таблиці користувача. Тепер з допомогою ORM ми можемо викликати метод $user->getFriends() щоб повернути об'єкти з таблиці друзів. ORM також займається збереженням даних, так що ми можемо створювати об'єкти в PHP, викликати метод save() і ORM займеться збереженням даних в базу. Так як ми використовуємо Doctrine 2 ORM бібліотеку, ви набагато краще дізнаєтеся про її можливості по ходу проходження керівництва.


Примітка

У той час як, це керівництво буде використовувати бібліотеку Doctrine 2 ORM, ви можете вибрати бібліотеку Doctrine 2 ODM. Існує кілька варіацій цієї бібліотеки, включаючи реалізації для MongoDB і CouchDB. Дивіться сторінку Doctrine Projects для отримання додаткової інформації.
Так само ви можете подивитися цю статтю, яка пояснює, як встановити ODM з Symfony 2.


База даних



Створення Бази даних

Якщо ви проходите керівництво з першої частини, у вас вже повинні бути прописані параметри бази даних. Якщо ви пропустили першу частину, то оновіть значення database_ * в файлі параметрів, розташованого в
app/config/parameters.yml


Створимо базу даних з допомогою команди Doctrine 2. Ця команда лише створює базу даних і не створює ніяких таблиць у базі. Якщо база даних з таким іменем вже існує буде виведено повідомлення про помилку, а існуюча база даних буде залишена без змін.
$ php app/console doctrine:database:create


Сутність Blog



Ми почнемо зі створення класу сутності Blog. Ми вже говорили про сутності в попередній частині, коли створювали сутність Enquiry. Оскільки сутність призначена для зберігання даних, має сенс використовувати одну сутність для подання записи в блозі. Коли ми визначаємо сутність ми не говоримо цим щоб дані автоматично були зіставлені з базою. Ми бачили це в нашій сутності Enquiry (Запит) де дані, що зберігаються в суті були лише відправлені по електронній пошті веб-майстру.
Створіть новий файл
src/Blogger/BlogBundle/Entity/Blog.php 
і вставити наступне:
<?php
// src/Blogger/BlogBundle/Entity/Blog.php

namespace Blogger\BlogBundle\Entity;

class Blog
{
protected $title;

protected $author;

protected $blog;

protected $image;

protected $tags;

protected $comments;

protected $created;

protected $updated;
}



Як ви бачите це простий PHP клас. Він не розширює батьківський і не має методів доступу. Кожне властивість заявлено як protected таким чином, ми не в змозі отримати доступ до них при роботі з об'єктом цього класу. Ми могли б прописати геттери і сетери для цих властивостей, але в Doctrine 2 є команда, яка виконує цю задачу за нас.
Перед тим як запустити цю команду, ми повинні повідомити Doctrine 2 яким чином сутність Blog повинна бути відображена в базі даних. Інформація вказана в якості метаданих, використовуючи Doctrine 2 зіставлення. Метадані можуть бути визначені в різних форматах, включаючи: YAML, PHP, XML та Анотації. У цьому керівництві ми будемо використовувати анотації. Важливо відзначити, що не всі властивості в об'єкті повинні бути збережені, так що ми не будемо надавати метадані для них. Це дає нам можливість вибрати тільки ті елементи, які нам потрібні, щоб Doctrine 2 зіставити їх з базою даних. Замініть вміст класу сутності Blog, розташованої
src/Blogger/BlogBundle/Entity/Blog.php 
наступним:
<?php
// src/Blogger/BlogBundle/Entity/Blog.php

namespace Blogger\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="blog")
*/
class Blog
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="АВТО")
*/
protected $id;

/**
* @ORM\Column(type="string")
*/
protected $title;

/**
* @ORM\Column(type="string", length=100)
*/
protected $author;

/**
* @ORM\Column(type="text")
*/
protected $blog;

/**
* @ORM\Column(type="string", length=20)
*/
protected $image;

/**
* @ORM\Column(type="text")
*/
protected $tags;

protected $comments;

/**
* @ORM\Column(type="datetime")
*/
protected $created;

/**
* @ORM\Column(type="datetime")
*/
protected $updated;
}



По-перше, ми імпортуємо і визначаємо простір імен Doctrine 2 ОRМ Mappings. Це дозволяє нам використовувати анотації для опису метаданих сутності. Метадані містять інформацію про те, як властивості повинні бути відображені в базі даних.

Примітка

Ми використовували тільки невелику частину надаються Doctrine 2 типів зіставлення. Повний список типів зв'язку можна знайти на веб-сайті Doctrine 2. Інші типи зіставлень будуть розглянуті пізніше в цьому керівництві.


Поглянувши уважніше, ви, можливо, помітили, що для властивості $comments не описані метадані. Це сталося тому, що ми не потребуємо збереженні, воно буде просто надавати набір коментарів, що належать до повідомлення в блозі. Подумайте про це абстрагуючись від бази даних. Наступний код покаже більш наочно.
// Create a blog object.
$blog = new Blog();
$blog->setTitle("symblog - A Symfony2 Tutorial");
$blog->setAuthor("dsyph3r");
$blog->setBlog("symblog is a fully featured blogging website ...");

// Create a comment and add it to our blog
$comment = new Comment();
$comment->setComment("Symfony2 rocks!");
$blog->addComment($comment);

Наведений вище фрагмент коду демонструє нормальна поведінка, якого ви очікуєте від блогу і коментарів класу. Внутрішній метод $blog->addComment() може бути реалізований наступним чином.
class Blog
{
protected $comments = array();

public function addComment(Comment $comment)
{
$this->comments[] = $comment;
}
}

Метод addComment просто додає новий об'єкт коментаря властивості блогу $comments. Отримання коментарів теж реалізується досить просто.
class Blog
{
protected $comments = array();

public function getComments()
{
return $this->comments;
}
}

Як ви можете бачити властивість$comments це просто список об'єктів Comment. Doctrine 2 не змінює, то як це працює. Doctrine 2 буде мати можливість автоматично заповнювати $comments властивість об'єктами, пов'язаних з об'єктом blog.
Тепер, коли ми поговорили як зіставити властивості сутності в Doctrine 2, ми можемо згенерувати методи доступу, використовуючи наступну команду в консолі.
$ php app/console doctrine:generate:entities Blogger

Ви будете повідомлені, що сутність Blog була оновлена з методами доступу. Кожен раз, коли ми робимо зміни метаданих ORM класів наших сутностей ми можемо запустити цю команду, щоб згенерувати які-небудь додаткові методи доступу. Ця команда не буде робити зміни в методах доступу, вже наявних у сутності, так що ваші існуючі доступи, ніколи не будуть перевизначені цією командою. Це важливо, оскільки згодом ви можете змінити деякі методи.

Примітка

У той час як ми використовуємо анотації в нашій сутності, можна перетворити інформацію зіставлення в інші підтримувані формати зіставлення використовуючи команду doctrine:mapping:convert. Наприклад, наступна команда, перетворює зіставлення сутності вище в yml формат.

$ php app/console doctrine:mapping:convert --namespace="Blogger\BlogBundle\Entity\Blog" yaml src/Blogger/BlogBundle/Resources/config/doctrine


І створить файл
src/Blogger/BlogBundle/Resources/config/doctrine/Blogger.BlogBundle.Entity.Blog.orm.yml 
, який буде містити зіставлення сутності blog в yml форматі.


Тепер ми готові створити уявлення сутності Blog в базі даних. Є 2 способи за допомогою яких ми можемо досягти цього. Ми можемо використовувати Doctrine 2 schema команди для оновлення бази даних або більш потужні, міграції Doctrine 2. Зараз ми будемо використати schema команди. Міграції Doctrine буду розглянуто в наступній частині посібника.

Створення таблиці blog



Для створення таблиці blog ми можемо скористатися наступною командою.

$ php app/console doctrine:schema:create


Це викличе дії для генерації схеми бази даних для сутності blog. Ви можете також передати --dump-sql опцію, щоб зробити дамп SQL. Якщо ви подивитеся на базу даних, то ви побачите, що таблиця blog була створена з полями, до яких ми зробили зіставлення.

Підказка

Ми використали ряд консольних команд Symfony2. Ви можете отримати допомогу по будь-якій команді ввівши опцію --help. Наприклад, щоб побачити допомога по команді doctrine:schema:create введіть:

$ php app/console doctrine:schema:create --help


Довідкова інформація виведе методи використання, а також доступні опції. Більшість команд виконуються з декількома опціями, які можуть розширити її.


Модель і відображення. Висновок запису блогу.



Зараз у нас є сутність Blog і оновлена база даних для її подання, ми можемо почати інтегрувати модель відображення. Ми почнемо зі створення сторінки show нашого блогу.

Маршрут Show Blog

Ми почнемо зі створення маршруту для blog show action. Блог буде ідентифікувати запис по унікальному ID, таким чином цей ID повинен бути представлений в URL. Оновіть BloggerBlogBundle маршрут, розташований
src/Blogger/BlogBundle/Resources/config/routing.yml
наступним:

# src/Blogger/BlogBundle/Resources/config/routing.yml
BloggerBlogBundle_blog_show:
path: /{id}
defaults: { _controller: BloggerBlogBundle:Blog:show }
вимога:
methods: GET
id: \d+


Так як ID запису повинен бути представлений в URL, ми визначили id placeholder. Це означає, що URL виду http://localhost:8000/1 і http://localhost:8000/my-blog відповідатимуть цим маршрутом. Однак, ми знаємо, що id блогу має бути цілим числом, (він визначений таким чином у зіставленні сутності) тому ми можемо додати обмеження, визначальна що цей маршрут буде відповідати тільки тоді, коли параметр id містить ціле число. Це досягається з допомогою id: \d+ вимогою маршруту. Тепер тільки перший приклад URL буде відповідати, а http://localhost:8000/my-blog вже немає. Ви також можете побачити, як відповідний маршрут виконає showAction, метод контролера Blogger\BlogBundle\Blog. Цей контролер ще повинен бути створений.

Метод showAction



Клей зв'язує Модель і відображення — це контролер, це те місце де ми почнемо створення сторінки. Ми могли б додати метод showAction до нашого існуючого контролеру Page, але так як ця сторінка присвячена відображенню сутностей blog, буде краще додати їх в свій власний контролер Blog.
Створіть новий файл, розташований в
src/Blogger/BlogBundle/Controller/BlogController.php 
і вставити наступне.
<?php
// src/Blogger/BlogBundle/Controller/BlogController.php

namespace Blogger\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

/**
* Blog controller.
*/
class BlogController extends Controller
{
/**
* Show a blog entry
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();

$blog = $em->getRepository('BloggerBlogBundle:Blog')->find($id);

if (!$blog) {
throw $this->createNotFoundException('Unable to find Blog post.');
}

return $this- > render('BloggerBlogBundle:Blog:show.html.twig', array(
'blog' => $blog,
));
}
}

Ми створили новий контролер для сутності Blog і визначили метод showAction, а також поставили id параметр в BloggerBlogBundle_blog_show правилі маршруту, він буде вставлений в якості аргументу в методshowAction. Якщо б ми визначили більше параметрів у правилі маршруту, вони б так само були вставлені в якості аргументів, через кому.
Далі нам потрібно отримати сутність Blog з бази даних. Вперше ми використовуємо інший допоміжний метод класу Symfony\Bundle\FrameworkBundle\Controller\Controller, щоб отримати Doctrine2 Manager. Роботою Manager є оброблення, вилучення і збереження об'єктів в базу даних і з неї. Далі ми використовуємо об'єкт Manager для отримання Doctrine 2 Репозиторію для сутності BloggerBlogBundle:Blog. Синтаксис, вказаний тут, просто скорочення, які можуть бути використані в Doctrine 2 замість зазначення повної назви сутності Blogger\BlogBundle\Entity\Blog. Разом з об'єктом репозиторію ми викликаємо метод find() і передаємо в аргументі $id. Цей метод буде отримувати об'єкт за його первинному ключу.
І в кінці ми перевіряємо, що сутність була знайдена і передаємо її відображення. Якщо суті не буде знайдено, то повернеться createNotFoundException. Це сформує відповідь 404 Not Found.

Примітка

Об'єкт репозиторію надає доступ до ряду корисних допоміжних методів, включаючи
// Return entities where 'author' matches 'dsyph3r'
$em->getRepository('BloggerBlogBundle:Blog')->findBy(array('author' => 'dsyph3r'));

// Return one entity where 'slug' matches 'symblog-tutorial'
$em->getRepository('BloggerBlogBundle:Blog')->findOneBySlug('symblog-tutorial');

Ми будемо створювати свої власні користувальницькі класи в Репозиторії в наступній частині, коли нам будуть потрібні більш складні запити до бази даних.

Показати



Ми створили метод showAction для контролера Blog і можемо сфокусуватися на відображення сутності Blog. Як зазначено в методі showAction буде виведений шаблон BloggerBlogBundle:Blog:show.html.twig. Давайте створимо цей шаблон
src/Blogger/BlogBundle/Resouces/views/Blog/show.html.twig
і вставимо наступне.
{# src/Blogger/BlogBundle/Resouces/views/Blog/show.html.twig #}
{% extends 'BloggerBlogBundle::layout.html.twig' %}

{% block title %}{{ blog.title }}{% endblock %}

{% block body %}
<article class="blog">
<header>
<div class="date"><time datetime="{{ blog.created|date('c') }}">{{ blog.created|date('l, F j, Y') }}</time></div>
<h2>{{ blog.title }}</h2>
</header>
<img src="{{ asset(['images/', blog.image]|join) }}" alt="{{ blog.title }} image not found" class="large" />
<div>
<p>{{ blog.blog }}</p>
</div>
</article>
{% endblock %}

Як і слід було очікувати, ми почнемо з розширення основного шаблону Blogger BlogBundle. Далі ми переопределим заголовок сторінки заголовком для нашого блогу. Це буде корисно для SEO, так як заголовок сторінки блогу є описовим, ніж заголовок за замовчуванням. Нарешті, ми переопределим блок body для виведення вмісту сутності Blog. Ми використовуємо функцію asset знову, щоб вивести зображення в блозі. Зображення блогу повинні бути поміщені в директорію web/images. Завантажити зображення можнапосилання.

CSS



Для того зробити візуальне оформлення, нам потрібно додати деякий стилі. Додайте стилі нижче в
src/Blogger/BlogBundle/Resouces/public/css/blog.css.
 

.date { margin-bottom: 20px; border-bottom: 1px solid #ccc; font-size: 24px; color: #666; line-height: 30px }
.blog { margin-bottom: 20px; }
.blog img { width: 190px; float: left; padding: 5px; border: 1px solid #ccc; margin: 0 10px 10px 0; }
.blog .meta { clear: left; margin-bottom: 20px; }
.blog .snippet p.continue { margin-bottom: 0; text-align: right; }
.blog .meta { font-style: italic; font-size: 12px; color: #666; }
.blog .meta p { margin-bottom: 5px; line-height: 1.2 em; }
.blog img.large { width: 300px; min-height: 165px; }


Примітка

Якщо ви не використовуєте метод символічних посилань для звернення до assets бандла в папці web, ви повинні повторно запустити команду установки assets.
$ php app/console assets:install web

Так як ми створили контролер і відображення для методу showAction давайте поглянемо на сторінку. Введіть ваш браузер http://localhost:8000/1. Це не та сторінка, яку ви очікували побачити?



Symfony згенерував відповідь 404 Not Found. Це сталося тому що у нас немає даних в базі, тобто сутність з id рівним 1 не може бути знайдена. Можна просто вставити рядок в таблицю blog вашої бази даних, але ми будемо використовувати метод значно краще: Фікстури даних.

Фікстури даних



Ми можемо використовувати фікстури для заповнення бази даних деякими простими тестовими даними. Для цього ми використовуємо doctrine-fixtures-bundle і data-fixtures. Розширення Doctrine Fixtures не поставляється з Symfony2, ми повинні вручну встановити його. На щастя це просте завдання. Відкрийте файл composer.json розташований в корені проекту і вставити наступне:
"require": {
// ...
"doctrine/doctrine-fixtures-bundle": "dev-master",
"doctrine/data-fixtures" : "dev-master"
}

Далі оновіть бібліотеки командою.
$ composer update


Це оновить всі бібліотеки з Github та встановить їх в необхідні директорії.
Тепер давайте зареєструємо DoctrineFixturesBundle в kernel розташованого в
app/AppKernel.php
 

// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
// ...
);
// ...
}

Фікстури Блогу



Тепер ми готові визначити фікстури для нашого блогу. Створіть файл фікстур
src/Blogger/BlogBundle/DataFixtures/ORM/BlogFixtures.php 
та вставте наступне:
<?php
// src/Blogger/BlogBundle/DataFixtures/ORM/BlogFixtures.php

namespace Blogger\BlogBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Blogger\BlogBundle\Entity\Blog;

class BlogFixtures implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$blog1 = new Blog();
$blog1->setTitle('A day with Symfony2');
$blog1->setBlog('Lorem ipsum dolor sit amet, consectetur adipiscing eletra electrify denim vel ports.\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ut velocity magna. Etiam vehicula nunc non leo hendrerit commodo. Vestibulum vulputate mauris eget erat congue dapibus imperdiet justo scelerisque. Nulla consectetur tempus nisl vitae viverra. Cras el mauris eget erat congue dapibus imperdiet justo scelerisque. Nulla consectetur tempus nisl vitae viverra. Cras elementum molestie vestibulum. Morbi id quam nisl. Praesent hendrerit, orci sed elementum lobortis, justo mauris lacinia libero, non facilisis purus ipsum non mi. Aliquam sollicitudin, augue id vestibulum iaculis, sem lectus convallis nunc, vel scelerisque lorem tortor ac nunc. Donec pharetra eleifend enim vel porta.');
$blog1->setImage('beach.jpg');
$blog1->setAuthor('dsyph3r');
$blog1->setTags('symfony2, php, paradise, symblog');
$blog1->setCreated(new \DateTime());
$blog1->setUpdated($blog1->getCreated());
$manager->persist($blog1);

$blog2 = new Blog();
$blog2->setTitle('The pool on the roof must have a leak');
$blog2->setBlog('Vestibulum vulputate mauris eget erat congue dapibus imperdiet justo scelerisque. Na. Cras elementum molestie vestibulum. Morbi id quam nisl. Praesent hendrerit, orci sed elementum lobortis.');
$blog2->setImage('pool_leak.jpg');
$blog2->setAuthor('Zero Cool');
$blog2->setTags('pool, leaky, hacked, movie, hacking, symblog');
$blog2->setCreated(new \DateTime("2011-07-23 06:12:33"));
$blog2->setUpdated($blog2->getCreated());
$manager->persist($blog2);

$blog3 = new Blog();
$blog3->setTitle('Misdirection. What the eyes see and the ears hear the mind believes');
$blog3->setBlog('Lorem ipsumvehicula nunc non leo hendrerit commodo. Vestibulum vulputate mauris eget erat congue dapibus imperdiet justo scelerisque.');
$blog3->setImage('misdirection.jpg');
$blog3->setAuthor('Gabriel');
$blog3->setTags('misdirection, magic, movie, hacking, symblog');
$blog3->setCreated(new \DateTime("2011-07-16 16:14:06"));
$blog3->setUpdated($blog3->getCreated());
$manager->persist($blog3);

$blog4 = new Blog();
$blog4->setTitle('The grid - A digital frontier');
$blog4->setBlog('Lorem commodo. Vestibulum vulputate mauris eget erat congue dapibus imperdiet justo scelerisque. Nulla consectetur tempus nisl vitae viverra.');
$blog4->setImage('the_grid.jpg');
$blog4->setAuthor('Kevin Flynn');
$blog4->setTags('grid, daftpunk, movie, symblog');
$blog4->setCreated(new \DateTime("2011-06-02 18:54:12"));
$blog4->setUpdated($blog4->getCreated());
$manager->persist($blog4);

$blog5 = new Blog();
$blog5->setTitle('You\'re either a one or a zero. Alive or dead');
$blog5->setBlog('Lorem ipsum dolor sit amet, consectetur adipiscing elittibulum vulputate mauris eget erat congue dapibus imperdiet justo scelerisque.');
$blog5->setImage('one_or_zero.jpg');
$blog5->setAuthor('Gary Winston');
$blog5->setTags('binary, one, zero, alive, dead !trusting, movie, symblog');
$blog5->setCreated(new \DateTime("2011-04-25 15:34:18"));
$blog5->setUpdated($blog5->getCreated());
$manager->persist($blog5);

$manager->flush();
}

}




Файл фікстур демонструє ряд важливих особливостей при використанні Doctrine 2, в тому числі, як зберігати об'єкти в базу даних.
Давайте подивимося, як ми створюємо одну запис у блозі.

$blog1 = new Blog();
$blog1->setTitle('A day in paradise - A day with Symfony2');
$blog1->setBlog('Lorem ipsum dolor sit d us imperdiet justo scelerisque. Nulla consectetur...');
$blog1->setImage('beach.jpg');
$blog1->setAuthor('dsyph3r');
$blog1->setTags('symfony2, php, paradise, symblog');
$blog1->setCreated(new \DateTime());
$blog1->setUpdated($this->getCreated());
$manager->persist($blog1);
// ..

$manager->flush();

Ми починаємо зі створення об'єкта Blog і визначення значень його властивостей. На даний момент Doctrine 2 нічого не знає про об'єкт сутності. Це станеться тільки тоді, коли ми викликаємо $manager->persist($blog1), цим ми доручаємо Doctrine 2, приступити до управління цього об'єкта сутності. Об'єкт $manager тут є екземпляром об'єкта Manager, який ми бачили раніше при отриманні об'єктів з бази даних. Важливо відзначити, що в той час як Doctrine 2 в даний час відомо про об'єкт суті, вона досі не зберігається в базі даних. Для цього необхідний виклик $manager->flush() Метод flush змушує Doctrine 2, почати взаємодіяти з базою даних і задіяти всі сутності, якими вона управляє. Для кращої продуктивності слід групувати команди Doctrine 2 і виконувати всі дії за один раз. Ми створили кожен об'єкт, попросили Doctrine 2, почати керувати ними, а потім виконали необхідні операції.

Завантаження фікстур



Тепер ми готові завантажити фікстури в базу даних
$ php app/console doctrine:fixtures:load


На питання продовжувати виконання команди відповідаємо: yes

Якщо ми поглянемо на сторінку http://localhost:8000/1 ми побачимо запис у блозі.



Спробуйте поміняти id URL на 2. Ви повинні побачити наступну запис.

Якщо ви перейдете за URL http://localhost:8000/100 ви побачите помилку 404 Not Found. Це сталося, як і очікувалося так як немає сутності Blog з id рівним 100. Тепер спробуйте ввестиhttp://localhost:8000/symfony2-blog Чому немає помилки 404 Not Found? Це пов'язано з тим, що метод showAction не був викликаний. URL-адреса не відповідає ні одному маршруту в додатку в зв'язку з \d+ вимогою, яке ми встановили в BloggerBlogBundle_blog_show маршруті. Ось чому ви бачите не знайдено маршрут для виключення «GET /symfony2-blog».

Мітка часу



Нарешті, у цій частині ми подивимося на 2 властивості міток часу в сутності Blog: created і updated. Функціональні можливості для цих 2-х членів, зазвичай називають як поведінка Timestampable. Ці властивості включають час, коли була створена запис і час її останнього оновлення. Оскільки ми не хочемо, вручну встановлювати ці поля кожен раз, коли ми створюємо або оновлюємо запис, ми можемо використовувати Doctrine 2 для цих цілей.
Doctrine 2 поставляється з Event System, яка забезпечує Lifecycle Callbacks. Ми можемо використовувати ці події зворотного виклику, щоб зареєструвати наші суті, отримувати повідомлення про події протягом всього терміну життя об'єкта. Кілька прикладів подій, про які ми можемо бути повідомлені, перш ніж відбудеться оновлення, після збереження і видалення. Щоб використовувати Lifecycle Callbacks в нашій сутності, нам потрібно зареєструвати сутність для них. Це робиться за допомогою метаданих, в сутності. Оновіть сутність Blog
src/Blogger/BlogBundle/Entity/Blog.php

<?php
// src/Blogger/BlogBundle/Entity/Blog.php

// ..

/**
* @ORM\Entity
* @ORM\Table(name="blog")
* @ORM\HasLifecycleCallbacks
*/
class Blog
{
// ..
}

Тепер давайте додамо метод в сутності Blog який реєструє подія PreUpdate. Ми також додамо конструктор, щоб встановити значення за умовчанням для властивостей created і updated.

<?php
// src/Blogger/BlogBundle/Entity/Blog.php

// ..

/**
* @ORM\Entity
* @ORM\Table(name="blog")
* @ORM\HasLifecycleCallbacks
*/
class Blog
{
// ..

public function __construct()
{
$this->setCreated(new \DateTime());
$this->setUpdated(new \DateTime());
}

/**
* @ORM\PreUpdate
*/
public function setUpdatedValue()
{
$this->setUpdated(new \DateTime());
}

// ..
}

Ми зареєстрували сутність Blog яка буде повідомлена про подію preUpdate, щоб встановити updated значення властивості. Тепер, коли ви видалите фікстури з таблиці, а також видаліть з кожного об'єкта

setCreated();
setUpdated();


у файлі
src/Blogger/BlogBundle/DataFixtures/ORM/BlogFixtures.php
 


і повторно запустіть завдання завантаження фікстур ви побачите, що created і updated властивості встановлені автоматично.

Примітка

Так як властивості timestampable є дуже поширеною потребою, є бандл який їх підтримує. StofDoctrineExtensionsBundle надає ряд корисних Doctrine 2 розширень, включаючи Timestampable, Sluggable і Sortable.
Ми розглянемо інтеграцію цього пакету пізніше. Кому не терпиться подивитися перейдіть по посиланню.


Висновок



Ми розглянули ряд концепцій для роботи з моделями, у Doctrine 2. Розглянули Фікстури даних, які надали нам простий спосіб, отримання тестових даних для розробки і тестування нашого застосування.
Далі ми розглянемо розширення моделі, додавши сутність для коментарів. Ми почнемо створювати домашню сторінку і застосуємо для цього власний репозиторій. Ми також введемо поняття Міграцій Doctrine і як форми взаємодіють з Doctrine 2, для того щоб ми могли розміщувати коментарі в блозі.

Джерела і допоміжні матеріали:

https://symfony.com/
http://tutorial.symblog.co.uk/
http://twig.sensiolabs.org/
http://www.doctrine-project.org/
http://odiszapc.ru/doctrine/

Post Scriptum
дякую Всім за увагу і зауваження зроблені за проектом, якщо у вас виникли труднощі чи питання, отписывайтесь в коментарі або особисті повідомлення, додавайтеся в друзі.

Частина 1 — Конфігурація Symfony2 і шаблонів
Частина 2 — Сторінка з контактною інформацією: валідатори, форми та електронна пошта
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.