symfony2 - RIP Tutorial · 2019-01-18 · from: symfony2 It is an unofficial and free symfony2...
Transcript of symfony2 - RIP Tutorial · 2019-01-18 · from: symfony2 It is an unofficial and free symfony2...
symfony2
#symfony2
1
1: symfony2 2
2
2
Examples 3
3
Symfony Installer 3
3
Symfony 4
Symfony 6
Symfony 6
2: 8
Examples 8
8
YAML 8
3: 10
10
Examples 10
10
Twig PHP. 10
4: 12
12
Examples 12
app / config / config.yml 12
12
5: 14
Examples 14
404 14
14
POST 15
15
Symfony Routing.yml 16
6: : 17
Examples 17
, 17
7: 20
20
Examples 20
20
20
20
JsonResponse 21
8: 22
Examples 22
--, 22
9: 26
26
26
26
Examples 26
26
27
27
10: Symfony Twig Extenstion 30
30
Examples 30
Symfony Twig Extension 30
11: 33
Examples 33
33
12: Symfony2 36
Examples 36
Symfony 2 36
13: Symfony Twig 37
Examples 37
Twig - Symfony 2.8 37
, , 1000 -> 1k, 1 000 000 -> 1M . . 39
14: Entity Entity 41
Examples 41
41
ExpressionBuilder IN () 42
- 42
15: - Symfony 2.8 44
Examples 44
API RESTFul 44
Symfony 2.8 44
SOAP API 49
16: - Symfony Rest 57
Examples 57
Symfony REST Edition 57
17: Symfony 59
Examples 59
59
18: Symfony 61
Examples 61
, Symfony2 61
19: Symfony2 localhost 63
Examples 63
63
63
20: Symfony 65
Examples 65
65
67
ОколоYou can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: symfony2
It is an unofficial and free symfony2 ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official symfony2.
The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ru/home 1
глава 1: Начало работы с symfony2
замечания
В этом разделе приведен обзор того, что такое Symfony2 и почему разработчик может захотеть его использовать.
Следует также упомянуть любые крупные темы в Symfony2 и ссылки на связанные темы. Поскольку Documentation for Symfony2 является новым, вам может потребоваться создать начальные версии этих связанных тем.
Версии
Последняя стабильная версия на момент написания статьи - Symfony 3.1, которая будет поддерживаться до конца июля 2017 года.
Symfony имеет версии с поддержкой Long Term Support, которые поддерживаются в общей сложности 4 года (3 года для исправлений ошибок, 1 дополнительный год для исправлений ошибок безопасности)
Стандартная незначительная версия поддерживается в течение восьми месяцев для исправления ошибок и в течение четырнадцатимесячного периода для исправления проблемы безопасности.
Долгосрочные версии поддержки:
Symfony 2.3 - May 2016 end of support for bug fixes May 2017 end of support for security fixes(end of life) Symfony 2.7 - May 2018 end of support for bug fixes May 2019 end of support for security fixes(end of life) Symfony 2.8 - November 2018 end of support for bug fixes November 2019 end of support for security fixes(end of life)
Начиная с версии 3.X, младшие версии будут ограничены до 5, а последняя младшая версия будет LTS.
Syfmony имеет режим двойного обслуживания, выпускающий второстепенные версии каждые шесть месяцев один раз в мае и один раз в ноябре. Основная версия выпускается каждые два года, то есть будет один год для перехода от предыдущей основной версии к последней, предоставляя пользователю выбор между новейшими функциями стандартной версии или версией LTS, которая поддерживается для исправления ошибок.
Symfony придерживается строгой обратной совместимости, все, что нарушает BC,
https://riptutorial.com/ru/home 2
выполняется в следующей крупной версии. Реализация функции, которая является улучшением, но разрывает BC, поддерживается рядом со старой реализацией, которая будет устаревать
Подробнее о версиях и процессе разработки см. В официальной документации [здесь] [1]
[1]: http: //symfony.com/doc/current/contributing/community/releases.html | Версия | Дата выпуска | | ------- | ------------ | | 2.3.0 | 2013-06-03 | | 2.7.0 | 2015-05-30 | | 2.8.0 | 2015-11-30 |
Examples
Установка или настройка
Symfony Framework, созданная с помощью компонентов symfony, является одной из ведущих фреймворков PHP, используемой для создания надежных веб-сайтов и веб-приложений.
Symfony можно быстро установить двумя рекомендуемыми способами.
Официальная документация рекомендует установить инфраструктуру через установщик Symfony, который представляет собой крошечное приложение php,
которое устанавливается один раз в локальной системе, что помогает загружать фреймворк и настраивать конфигурацию структуры. Установщик Symfony требует PHP 5.4 или новее. Для установки в старой версии PHP используйте Composer.
1.
Через менеджера зависимостей PHP Composer2.
Установка через Symfony Installer
В Linux / Mac OS X выполните следующие команды:
$ sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony $ sudo chmod a+x /usr/local/bin/symfony
В Windows перейдите в каталог проекта и выполните следующую команду:
php -r "file_put_contents('symfony', file_get_contents('https://symfony.com/installer'));"
Проект symfony может быть создан путем запуска symfony new my_project [2.8] в Linux / Mac OS X
В Windows php symfony new my_project [2.8]
или, альтернативно, symfony new my_project lts будет использовать последнюю версию Symfony для долгосрочной поддержки.
https://riptutorial.com/ru/home 3
Установка через композиторСкачать композитор•
Используйте команду create-project Composer для загрузки Symfony
composer create-project symfony/framework-standard-edition my_project_name ["2.8.*"]
•
Отличная подробная официальная документация здесь
Запуск приложения Symfony
Для запуска внутреннего веб-сервера symfony (доступного с PHP 5.4) перейдите в каталог проекта и выполните следующую команду:
для symfony <= 2.8
php app/console server:start
и для symfony> = 3.0
php bin/console server:start
Это запустит веб-сервер на localhost:8000 в фоновом режиме, который служит вашему приложению Symfony. Затем откройте свой браузер и обратитесь к http://localhost:8000/ URL, чтобы увидеть страницу приветствия Symfony:
https://riptutorial.com/ru/home 4
https://riptutorial.com/ru/home 5
Самый простой пример в Symfony
Установите symfony правильно, как указано выше.1.
Запустите сервер symfony, если вы не установлены в каталоге www.2.
Убедитесь, что http: // localhost: 8000 работает, если используется сервер symfony.3.
Теперь он готов играть с простейшим примером.4. Добавьте следующий код в новый файл /src/AppBundle/Controller/MyController.php в каталоге установки symfony.
5.
Проверьте пример, посетив http: // localhost: 8000 / hello
(Если вы не используете встроенный http-сервер Symfony, посетите http: // localhost / (symfony-dir) /web/app_dev.php/hello)
6.
Это все. Далее: используйте ветку, чтобы отобразить ответ.7.
<?php // src/AppBundle/Controller/MyController.php namespace AppBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Component\HttpFoundation\Response; class MyController { /** * @Route("/hello") */ public function myHelloAction() { return new Response( '<html><body> I\'m the response for request <b>/hello</b> </body></html>' ); } }
ПРИМЕЧАНИЕ. Все классы контроллеров должны иметь концы со словом « Контроллер »,
а методы, связанные с маршрутами, должны заканчиваться словом « Действие ». Кроме того, в том случае, когда контроллер размещается в ваших действиях, не имеет значения, пока вы не определите префикс маршрута для контроллера.
Установка и настройка Symfony
Проверка требований
Запустите bin/symfony_requirements для проверки требований symfony и настройки php cli.
Установите все пакеты, необходимые для запуска проекта symfony. Настройка php.ini,
например, установка часового пояса и short_open_tag. Установка php.ini для вашего веб-сервера php (например: /etc/php/apache2/php.ini) и php cli (например: /etc/php/cli/php.ini).
Откройте http: //localhost/config.php для проверки настройки веб-сервера php. Если все
https://riptutorial.com/ru/home 6
прошло, вы готовы запустить свой проект symfony.
Запуск проекта
Запустите composer install для установки всех зависимостей. Затем настройте разрешение для var/cache , var/logs и var/sessions .
Подробная официальная документация здесь
Прочитайте Начало работы с symfony2 онлайн: https://riptutorial.com/ru/symfony2/topic/909/
начало-работы-с-symfony2
https://riptutorial.com/ru/home 7
глава 2: Базовая маршрутизация
Examples
Маршрутизация на основе аннотаций
По умолчанию все контроллеры, которые вы создаете с помощью встроенной команды symfony generate:controller будут использовать аннотации Symfony для маршрутизации:
namespace AppBundle\Controller; // You have to add a use statement for the annotation use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class AcmeController { /** * @Route("/index") */ public function indexAction() { // ... } }
Чтобы инфраструктура обрабатывала эти маршруты, вам необходимо импортировать их в свой routing.yml следующим образом (обратите внимание на тип annotation ):
app: resource: "@AppBundle/Controller" type: annotation
Маршруты YAML
Вместо аннотаций вы также можете указать свои маршруты как YAML:
app_index: path: /index defaults: { _controller: AppBundle:Acme:index }
Те же варианты применяются как к аннотациям, так и к настройкам YAML. Чтобы импортировать конфигурацию маршрутизации YAML в конфигурацию корневой маршрутизации, вам не нужно указывать тип:
app: prefix: /app resource: "@AppBundle/Resources/config/routing.yml"
https://riptutorial.com/ru/home 8
Прочитайте Базовая маршрутизация онлайн: https://riptutorial.com/ru/symfony2/topic/5881/
базовая-маршрутизация
https://riptutorial.com/ru/home 9
глава 3: Запрос
замечания
Ссылки на документацию API (мастер):
Запрос•RequestStack•
Объект Request содержит несколько важных данных, таких как текущий локаль и согласованный контроллер. Вы можете использовать и управлять ими событиями HttpKernel. Для надежного понимания живого цикла Request-Responce прочитайте эту страницу документа компонента HttpKernel (очень полезно!).
Examples
Доступ к запросу в контроллере
<?php use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; class TestController extends Controller { //Inject Request HTTP Component in your function then able to exploit it public function myFunctionAction(Request $request) { //BASICS //retrieve $_POST variables from request $postRequest = $request->request->get('my_data'); //retrieve $_GET variables from request $getRequest = $request->query->get('my_data'); //get current locale $locale = $request->getLocale(); } }
Обратите внимание, что введенный объект запроса применяется к текущему запросу (он может быть или не соответствовать основному запросу).
Доступ к запросу в шаблоне Twig или PHP.
В шаблоне Twig объект запроса доступен по адресу
{{ app.request }}
https://riptutorial.com/ru/home 10
Когда вы хотите использовать метод запроса на просмотр в Twig, попробуйте следующее:
<p>Request method: {{ app.request.method }}</p>
В шаблоне PHP
<p>Request method: <?php echo $app->getRequest()->getMethod() ?></p>
Прочитайте Запрос онлайн: https://riptutorial.com/ru/symfony2/topic/4870/запрос
https://riptutorial.com/ru/home 11
глава 4: Конфигурация для собственных пакетов
Вступление
Это описание того, как вы можете создать конфигурацию для своего собственного пакета в файле /app/config/config.{yml,xml}
Examples
Создайте конфигурацию в app / config / config.yml
amazingservice: url: 'http://amazing.com' client_id: 'test_client_1' client_secret: 'test_secret'
Это базовый пример для создания конфигурации в формате yml, поскольку для последующего формата yml вы можете использовать более глубокую конфигурацию.
Установите конфигурацию в созданном комплекте
Например, у вас есть пакет, который генерируется консолью symfony. В этом случае в DependencyInjection / Configuration.php вам необходимо вставить конфигурационное представление:
$treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('amazingservice'); $rootNode->children() ->scalarNode('url')->end() ->scalarNode('client_id')->end() ->scalarNode('client_secret')->end() ->end() ->end();
В основном в DependencyInjection / AmazingserviceExtension.php вы увидите следующие строки:
$configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs);
Этого недостаточно для получения конфигурации в Srevices. Вы должны взять его в контейнер.
https://riptutorial.com/ru/home 12
$container->setParameter( 'amazingservice.config', $config );
В этом случае config в контейнере, поэтому, если ваша Служба получает контейнер в качестве параметра конструктора:
base.amazingservice: class: Base\AmazingBundle\Services\AmazingServices arguments: [@service_container]
Затем вы можете получить конфигурацию в службе со следующим кодом, где конфигурация будет ассоциативным массивом:
private $config; public function __construct(Container $container){ $this->config = $container->getParameter('amazingservice.config'); }
Прочитайте Конфигурация для собственных пакетов онлайн: https://riptutorial.com/ru/symfony2/topic/8153/конфигурация-для-собственных-пакетов
https://riptutorial.com/ru/home 13
глава 5: маршрутизация
Examples
Возвратите ответ 404
404 ответа возвращаются, когда ресурс не найден на сервере, в Symfony этот статус может быть создан путем NotFoundHttpException исключения NotFoundHttpException . Чтобы избежать use инструкции дополнительного use внутри контроллера, используйте createNotFoundException() предоставляемый классом Controller
<?php namespace Bundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class TestController extends Controller { /** * @Route("/{id}", name="test") * Recommended to avoid template() as it has a lot of background processing. * Query database for 'test' record with 'id' using param converters. */ public function testAction(Test $test) { if (!$test) { throw $this->createNotFoundException('Test record not found.'); } return $this->render('::Test/test.html.twig', array('test' => $test)); } }
Несколько маршрутов
В Symfony можно определить несколько маршрутов для одного действия. Это может быть очень полезно, если у вас есть функции, которые делают то же самое, но имеют разные параметры.
class TestController extends Controller { /** * @Route("/test1/{id}", name="test") * @Route("/test2/{id}", name="test2") * Here you can define multiple routes with multiple names */ public function testAction(Test $test) { if (!$test) {
https://riptutorial.com/ru/home 14
throw $this->createNotFoundException('Test record not found.'); } return $this->render('::Test/test.html.twig', array('test' => $test)); } }
Отправка запроса POST
Когда вы находитесь в контроллереAction. И вы получаете запрос POST , но хотите перенаправить его на другой маршрут , сохраняя при этом метод POST и объект запроса , вы можете использовать следующее:
return $this->redirectToRoute('route', array( 'request' => $request, ), 307);
Код 307 здесь сохраняет метод запроса.
Подземная маршрутизация
Маршрутизация на основе субдомена может обрабатываться в Symfony с использованием параметра host . Например, параметр _locale может использоваться как значение поддомена.
Если предположить,
locale: en domain: somedomain.com
параметры определяется в parameters.yml конфигурационного файла, маршрут будет:
/** * @Route( * "/", * name="homepage", * host="{_locale}.{domain}", * defaults={"_locale" = "%locale%", "domain" = "%domain%"}, * requirements={"_locale" = "%locale%|de|fr", "domain" = "%domain%"} * ) * @Route( * "/", * name="homepage_default", * defaults={"_locale" = "%locale%"} * ) */
С этого момента маршрутизатор может обрабатывать URI, например http://de.somedomain.com . Вторая аннотация @Route может использоваться в качестве резервной @Route для локали по умолчанию и void subdomain, http://somedomain.com .
https://riptutorial.com/ru/home 15
Маршруты Symfony с использованием Routing.yml
profile_user_profile: path: /profile/{id} defaults: { _controller: ProfileBundle:Profile:profile } requirements: id: \d+ methods: [get, delete]
Если вы решили использовать Routing.yml вместо аннотаций, вы можете получить лучший обзор всех маршрутов и проще найти и найти его.
Вы можете выбирать между Routing.yml и Annotations . Вы можете использовать оба для разных маршрутов, но это не лучшее решение.
@Route() эквивалентно:
class ProfileController extends Controller { /** * @Route("/profile/{id}", name="profile_user_profile", requirements={"id": "\d+"}) * @Method("GET", "DELETE") */ public function profileAction($id) { if (!$id) { throw $this->createNotFoundException('User not found.'); } return $this->render('::Profile/profile.html.twig', array('id' => $id)); } }
Прочитайте маршрутизация онлайн: https://riptutorial.com/ru/symfony2/topic/1691/
маршрутизация
https://riptutorial.com/ru/home 16
глава 6: Монолог: улучшите свои журналы
Examples
Добавить данные пользователя и опубликованные параметры, отправленные в журналы
Журналы очень важны. Повторное создание контекста ошибки иногда может быть очень болезненным из-за отсутствия информации о том, как и когда произошла ошибка.
Этот пример показывает:
Как добавить данные пользователя в журналы ошибок•
Как добавить параметры сообщения, отправленные при возникновении ошибки•
Как использовать WebProcessor , чтобы добавить все данные, касающиеся запроса:
URL○
IP○
метод http○
сервер○
ссылающейся○
•
Конфигурация сервиса
services: # Permits to convert logs in HTML format for email notification monolog.formatter.html: class: Monolog\Formatter\HtmlFormatter # Add request data (url, ip, http method, server, referrer) monolog.processor.web_processor: class: Monolog\Processor\WebProcessor tags: - { name: monolog.processor, method: __invoke } # Custom class to include user's data and posted parameters in the logs monolog.processor.user: class: Company\ToolBoxBundle\Services\Monolog\ExtraProcessor arguments: ["@security.token_storage"] tags: - { name: monolog.processor } - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Код услуги
namespace Company\ToolBoxBundle\Services\Monolog;
https://riptutorial.com/ru/home 17
use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class ExtraProcessor { /** * @var string */ private $postParams = null; /** * @var TokenStorageInterface */ private $tokenStorage = null; /** * @var \Company\UserBundle\Entity\User */ private $user = null; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } // Called when an error occurred and a log (record) is creating public function __invoke(array $record) { if (null !== $this->user) { // $this->user is your user's entity. Extract all pertinent data you would need. In this case, getUserDetails method create a summary including alias, name, role, ... $record['extra']['user'] = $this->user->getUserDetails(); } if (null !== $this->postParams) { // Includes all posted parameter when the error occurred $record['extra']['postParams'] = $this->postParams; } return $record; } public function onKernelRequest(GetResponseEvent $event) { // Retain post parameters sent (serialized) in order to log them if needed $postParams = $event->getRequest()->request->all(); if(false === empty($postParams)){ $this->postParams = serialize($postParams); } // Do not continue if user is not logged if (null === $token = $this->tokenStorage->getToken()) { return; } if (!is_object($user = $token->getUser())) { // e.g. anonymous authentication return; }
https://riptutorial.com/ru/home 18
// Retain the user entity in order to use it $this->user = $user; } }
Прочитайте Монолог: улучшите свои журналы онлайн: https://riptutorial.com/ru/symfony2/topic/6671/монолог--улучшите-свои-журналы
https://riptutorial.com/ru/home 19
глава 7: отклик
параметры
параметр подробности
string контент Содержание ответа.
integer статус Код состояния HTTP.
заголовки array Массив ответных заголовков.
Examples
Простое использование
public function someAction(){ // Action's code return new Response('<span>Hello world</span>'); }
Установить код состояния
public function someAction(){ // Action's code return new Response($error, 500); }
Другой пример:
public function someAction(){ // Action's code $response = new Response(); $response->setStatusCode(500) $response->setContent($content); return $response; }
Установить заголовок
https://riptutorial.com/ru/home 20
См. Список заголовков http .
public function someAction(){ // Action's code $response = new Response(); $response->headers->set('Content-Type', 'text/html'); return $response; }
JsonResponse
Возвращаемый ответ JSON:
use Symfony\Component\HttpFoundation\JsonResponse; public function someAction(){ // Action's code $data = array( // Array data ); return new JsonResponse($data); }
Прочитайте отклик онлайн: https://riptutorial.com/ru/symfony2/topic/9218/отклик
https://riptutorial.com/ru/home 21
глава 8: Отношения сущностей доктрины
Examples
Один-ко-многим, двунаправленный
Это двунаправленное отображение требует mappedBy атрибут на OneToMany ассоциации и inversedBy атрибута на ManyToOne ассоциации.
Двунаправленное отношение имеет как собственную, так и обратную сторону . OneToMany могут использовать таблицы соединений, поэтому вам нужно указать сторону владельца. OneToMany всегда является обратной стороной двунаправленной ассоциации.
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="users") */ class User { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @var string * * @ORM\Column(name="username", type="string", length=255) */ protected $username; /** * @var Group|null * * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Group", inversedBy="users") * @ORM\JoinColumn(name="group_id", referencedColumnName="id", nullable=true) */ protected $group; /** * @param string $username * @param Group|null $group */ public function __construct($username, Group $group = null)
https://riptutorial.com/ru/home 22
{ $this->username = $username; $this->group = $group; } /** * Set username * * @param string $username */ public function setUsername($username) { $this->username = $username; } /** * Get username * * @return string */ public function getUsername() { return $this->username; } /** * @param Group|null $group */ public function setGroup(Group $group = null) { if($this->group !== null) { $this->group->removeUser($this); } if ($group !== null) { $group->addUser($this); } $this->group = $group; } /** * Get group * * @return Group|null */ public function getGroup() { return $this->group; } }
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection;
https://riptutorial.com/ru/home 23
/** * @ORM\Entity * @ORM\Table(name="groups") */ class Group { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @ORM\Column(name="name", type="string", length=255) */ protected $name; /** * @ORM\OneToMany(targetEntity="AppBundle\Entity\User", mappedBy="group") */ protected $users; /** * @param string $name */ public function __construct($name) { $this->name = $name; $this->users = new ArrayCollection(); } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name */ public function setName($name) { $this->name = $name; } public function addUser(User $user) { if (!$this->getUsers()->contains($user)) { $this->getUsers()->add($user); } } public function removeUser(User $user) { if ($this->getUsers()->contains($user)) { $this->getUsers()->removeElement($user); }
https://riptutorial.com/ru/home 24
} public function getUsers() { return $this->users; } public function __toString() { return (string) $this->getName(); } }
Прочитайте Отношения сущностей доктрины онлайн: https://riptutorial.com/ru/symfony2/topic/3043/отношения-сущностей-доктрины
https://riptutorial.com/ru/home 25
глава 9: Отправка параметров в класс формы
Синтаксис
$ form = $ this-> createForm (Тип_объекта: класс, $ домохозяйство, $ formOptions);•
параметры
параметр Определение
HouseholdType :: класс класс пользовательской формы для субъекта быта
$ домохозяйство экземпляр субъекта домохозяйства (обычно созданный по $household = new Household(); )
$ formOptionsмассив определенных пользователем опций, которые должны быть переданы классу формы, например $formOptions = array('foo' => 'bar');
замечания
Когда вы создаете класс формы, поля формы добавляются в public function buildForm(FormBuilderInterface $builder, array $options) {...} . Параметр $options включает набор параметров по умолчанию, таких как attr и label . Чтобы включить ваши настраиваемые параметры в классе формы, параметры необходимо инициализировать в configureOptions(OptionsResolver $resolver)
Итак, для нашего реального примера:
public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\Household', 'disabledOptions' => [], )); }
Examples
Реальный пример от контроллера домохозяйства
https://riptutorial.com/ru/home 26
Предпосылки: объект «Бытие» включает в себя набор опций, каждый из которых является объектом, который управляется в бэкэнде администратора. Каждая опция имеет флаг boolean enabled . Если ранее включенная опция отключена, ее необходимо будет сохранить в последующих изменениях Домашнего Редактирования, но ее нельзя отредактировать. Для этого определение поля в классе формы отобразит поле как поле выбора отключенного, если опция enabled = false (но сохраняется, поскольку кнопка отправки запускает javascript, который удаляет disabled атрибут.) Определение поля также предотвращает отключенные параметры от отображения.
Затем класс формы должен знать, для данного субъекта домохозяйства, какой из его вариантов был отключен. Определена служба, которая возвращает массив имен объектов-параметров, которые были отключены. Этот массив равен $disabledOptions .
$formOptions = [ 'disabledOptions' => $disabledOptions, ]; $form = $this->createForm(HouseholdType::class, $household, $formOptions);
Как настраиваемые параметры используются в классе формы
->add('housing', EntityType::class, array( 'class' => 'AppBundle:Housing', 'choice_label' => 'housing', 'placeholder' => '', 'attr' => (in_array('Housing', $options['disabledOptions']) ? ['disabled' => 'disabled'] : []), 'label' => 'Housing: ', 'query_builder' => function (EntityRepository $er) use ($options) { if (false === in_array('Housing', $options['disabledOptions'])) { return $er->createQueryBuilder('h') ->orderBy('h.housing', 'ASC') ->where('h.enabled=1'); } else { return $er->createQueryBuilder('h') ->orderBy('h.housing', 'ASC'); } }, ))
Объект размещения
/** * Housing. * * @ORM\Table(name="housing") * @ORM\Entity */ class Housing { /** * @var int
https://riptutorial.com/ru/home 27
* * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @var bool * * @ORM\Column(name="housing", type="string", nullable=false) * @Assert\NotBlank(message="Housing may not be blank") */ protected $housing; /** * @var bool * * @ORM\Column(name="enabled", type="boolean", nullable=false) */ protected $enabled; /** * Get id. * * @return int */ public function getId() { return $this->id; } /** * Set housing. * * @param int $housing * * @return housing */ public function setHousing($housing) { $this->housing = $housing; return $this; } /** * Get housing. * * @return int */ public function getHousing() { return $this->housing; } /** * Set enabled. * * @param int $enabled *
https://riptutorial.com/ru/home 28
* @return enabled */ public function setEnabled($enabled) { $this->enabled = $enabled; return $this; } /** * Get enabled. * * @return int */ public function getEnabled() { return $this->enabled; } /** * @var \Doctrine\Common\Collections\Collection * * @ORM\OneToMany(targetEntity="Household", mappedBy="housing") */ protected $households; public function addHousehold(Household $household) { $this->households[] = $household; } public function getHouseholds() { return $this->households; } }
Прочитайте Отправка параметров в класс формы онлайн: https://riptutorial.com/ru/symfony2/topic/7237/отправка-параметров-в-класс-формы
https://riptutorial.com/ru/home 29
глава 10: Пример использования Symfony Twig Extenstion
параметры
параметры Описание
$ доктрина доктрина, которую мы передаем из службы.
Examples
Основной пример Symfony Twig Extension
В этом примере я определяю две пользовательские функции. 1 - функция countryFilter
получает код страны в качестве ввода и возвращает полное имя страны. 2 - _countPrinterTasks используется для вычисления количества задач, назначенных конкретному пользователю.
<?php namespace DashboardBundle\Twig\Extension; use Symfony\Bridge\Doctrine\RegistryInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\SecurityContext; /** * Class DashboardExtension * @package DashboardBundle\Twig\Extension */ class DashboardExtension extends \Twig_Extension { protected $doctrine; private $context; /** * DashboardExtension constructor. * @param RegistryInterface $doctrine * @param SecurityContext $context */ public function __construct(RegistryInterface $doctrine,SecurityContext $context) { $this->doctrine = $doctrine; $this->context = $context; } /**
https://riptutorial.com/ru/home 30
* @return mixed */ public function getUser() { return $this->context->getToken()->getUser(); } /** * @return array */ public function getFilters() { return array( new \Twig_SimpleFilter('country', array($this, 'countryFilter')), new \Twig_SimpleFilter('count_printer_tasks', array($this, '_countPrinterTasks')), ); } /** * @param $countryCode * @param string $locale * @return mixed */ public function countryFilter($countryCode,$locale = "en") { $c = \Symfony\Component\Intl\Intl::getRegionBundle()->getCountryNames($locale); return array_key_exists($countryCode, $c) ? $c[$countryCode] : $countryCode; } /** * Returns total count of printer's tasks. * @return mixed */ public function _countPrinterTasks(){ $count = $this->doctrine->getRepository('DashboardBundle:Task')->countPrinterTasks($this->getUser()); return $count; } /** * {@inheritdoc} */ public function getName() { return 'app_extension'; } }
Чтобы назвать это из Twig, мы просто должны использовать, как показано ниже;
{% set printer_tasks = 0|count_printer_tasks() %}
https://riptutorial.com/ru/home 31
<tr> <td>Nationality</td> <td> {{ user.getnationality|country|ucwords }} </td> </tr>
И объявите это extenstion как услугу в файле bundle/resource/config/service.yml .
services: app.twig_extension: class: DashboardBundle\Twig\Extension\DashboardExtension arguments: ["@doctrine", @security.context] tags: - { name: twig.extension }
Прочитайте Пример использования Symfony Twig Extenstion онлайн: https://riptutorial.com/ru/symfony2/topic/5891/пример-использования-symfony-twig-extenstion
https://riptutorial.com/ru/home 32
глава 11: Проверка формы
Examples
Простая проверка формы с использованием ограничений
Пример действия контроллера
use Symfony\Component\HttpFoundation\Request; public function exampleAction(Request $request) { /* * First you need object ready for validation. * You can create new object or load it from database. * You need to add some constraints for this object (next example) */ $book = new Book(); /* * Now create Form object. * You can do it manually using FormBuilder (below) or by creating * FormType class and passing it to builder. */ $form = $this->createFormBuilder($book) ->add('title', TextType::class) ->add('pages', IntegerType::class) ->add('save', SubmitType::class, array('label' => 'Create Book')) ->getForm(); /* * Handling Request by form. * All data submitted to form by POST(default) is mapped to * to object passed to FormBuilder ($book object) */ $form->handleRequest($request); /* * Form Validation * In this step we check if form is submitted = data passed in POST * and is your object valid. Object is valid only if it pass form validation * in function isValid(). Validation constraints are loaded from config files * depending on format (annotations, YAML, XML etc). * IMPORTANT - object passed (book) is validated NOT form object * Function isValid() using Symfony Validator component. */ if ($form->isSubmitted() && $form->isValid()) { /* * Now object is valid and you can save or update it * Original object ($book) passed into form builder has been updated * but you can also get variable by function getData: * $book = $form->getData(); */ // You can now redirect user to success page return $this->redirectToRoute('book_success_route');
https://riptutorial.com/ru/home 33
} /* * If form is not submitted you show empty form to user. * If validation fail then the form object contains list of FormErrors. * Form errors are displayed in form_row template (read about form templates) */ return $this->render('book/create.html.twig', array( 'form' => $form->createView(), )); }
Пример ограничений для объекта
@Annotations
namespace AppBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; class Book { /** * @Assert\Length( * min = 2, * max = 100, * minMessage = "Book title must be at least {{ limit }} characters long", * maxMessage = "Book title cannot be longer than {{ limit }} characters" * ) */ private $title; /** * @Assert\Range( * min = 3, * max = 10000, * minMessage = "Book must have at least {{ limit }} pages", * maxMessage = "Book cannot have more than {{ limit }} pages" * ) */ private $pages; // [...] getters/setters }
@YAML
# src/AppBundle/Resources/config/validation.yml AppBundle\Entity\Book: properties: title: - Length: min: 2 max: 50 minMessage: 'Book title must be at least {{ limit }} characters long' maxMessage: 'Book title cannot be longer than {{ limit }} characters'
https://riptutorial.com/ru/home 34
pages: - Range: min: 3 max: 10000 minMessage: Book must have at least {{ limit }} pages maxMessage: Book cannot have more than {{ limit }} pages
Ссылка на ограничения проверки: https://symfony.com/doc/current/reference/constraints.html
Проверка формы: http://symfony.com/doc/current/forms.html#form-validation
Прочитайте Проверка формы онлайн: https://riptutorial.com/ru/symfony2/topic/7813/проверка-формы
https://riptutorial.com/ru/home 35
глава 12: Развертывание Symfony2
Examples
Шаги по перемещению проекта Symfony 2 на хостинг вручную
Это зависит от вашего хостинга:
Если у вас SSH-консоль, вы можете сделать это на хостинге после шага 2, если вы не сделаете это локально: запустите команду
php app/console cache:clear --env=prod'.
1.
Предположим, у вас есть у вас хостинг папок youdomain/public_html , поэтому в public_html должны быть размещены все веб-файлы. Таким образом , вы должны загрузить все из проекта Symfony (папок: app , src , vendors , bin ; файлы: deps , deps.lock ), за исключением папки web в папке youdomain . Все из папки web загрузки в папку public_html .
2.
Проверьте CHMOD для app/cache кешей папок и app/logs , должен быть доступ на запись.
3.
Если в public_html нет файла .htaccess, создайте его и добавьте в него такой код: https://raw.github.com/symfony/symfony-standard/master/web/.htaccess
4.
Теперь вы должны использовать youdomain.com/index вместо youdomain.com/app_dev.php/index , который вы используете локально. Если сайт по-прежнему не работает, вы можете открыть файл web/config.php и найти код, где выполняется проверка на IP, вы найдете там только IP 127.0.0.1 . Добавьте текущий IP-адрес в этот список и загрузите новую конфигурацию на сервер. Затем вы можете открыть путь yourdomain/config.php и проверить, что не так. Если config.php показывает, что все в порядке, но оно все равно не работает, вы можете включить app_dev.php для отладки: откройте app/app_dev.php и ваш IP так же, как в config.php . Теперь вы можете запускать скрипты локально, используя app_dev.php .
5.
Прочитайте Развертывание Symfony2 онлайн: https://riptutorial.com/ru/symfony2/topic/6039/
развертывание-symfony2
https://riptutorial.com/ru/home 36
глава 13: Расширения Symfony Twig
Examples
Простое расширение Twig - Symfony 2.8
Перед созданием любого расширения всегда проверяйте, было ли оно уже реализовано .
Первое, что нужно сделать, это определить класс расширения, в котором будут размещаться фильтры ветвей и / или функции.
<?php namespace AppBundle\Twig; class DemoExtension extends \Twig_Extension { /** * A unique identifier for your application * * @return string */ public function getName() { return 'demo'; } /** * This is where one defines the filters one would to use in their twig * templates * * @return Array */ public function getFilters() { return array ( new \Twig_SimpleFilter ( 'price', // The name of the twig filter array($this, 'priceFilter') ), ); } public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') { return '$' . number_format($number, $decimals, $decPoint, $thousandsSep); } /** * Define the functions one would like availed in their twig template * * @return Array */ public function getFunctions() { return array ( new \Twig_SimpleFunction (
https://riptutorial.com/ru/home 37
'lipsum', // The name of the twig function array($this, 'loremIpsum') ) ); } public function loremIpsum($length=30) { $string = array (); $words = array ( 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'a', 'ac', 'accumsan', 'ad', 'aenean', 'aliquam', 'aliquet', 'ante', 'aptent', 'arcu', 'at', 'auctor', 'augue', 'bibendum', 'blandit', 'class', 'commodo', 'condimentum', 'congue', 'consequat', 'conubia', 'convallis', 'cras', 'cubilia', 'cum', 'curabitur', 'curae', 'cursus', 'dapibus', 'diam', 'dictum', 'dictumst', 'dignissim', 'dis', 'donec', 'dui', 'duis', 'egestas', 'eget', 'eleifend', 'elementum', 'enim', 'erat', 'eros', 'est', 'et', 'etiam', 'eu', 'euismod', 'facilisi', 'facilisis', 'fames', 'faucibus', 'felis', 'fermentum', 'feugiat', 'fringilla', 'fusce', 'gravida', 'habitant', 'habitasse', 'hac', 'hendrerit', 'himenaeos', 'iaculis', 'id', 'imperdiet', 'in', 'inceptos', 'integer', 'interdum', 'justo', 'lacinia', 'lacus', 'laoreet', 'lectus', 'leo', 'libero', 'ligula', 'litora', 'lobortis', 'luctus', 'maecenas', 'magna', 'magnis', 'malesuada', 'massa', 'mattis', 'mauris', 'metus', 'mi', 'molestie' ); for ( $i=0; $i<$length; $i++ ) $string[] = $words[rand(0, 99)]; return implode(" ", $string); } }
Затем вы предупреждаете контейнер службы только что созданного расширения ветки.
# app/config/services.yml services: app.twig.demo_extension: class: AppBundle\Twig\DemoExtension tags: - { name: twig.extension }
При этом у вас есть все, что вам нужно, чтобы использовать свой недавно созданный фильтр или функцию ветви в ваших шаблонах ветви
<p>Price Filter test {{ '5500' | price }}</p> <p>{{ lipsum(25) }}</p>
https://riptutorial.com/ru/home 38
Сделайте короткое число, например, 1000 -> 1k, 1 000 000 -> 1M и т. Д.
Symfony 2.8
# AppBundle\Twig\AppExtension.php <?php namespace AppBundle\Twig; class AppExtension extends \Twig_Extension { /** * This is where one defines the filters one would to use in their twig * templates * * @return Array */ public function getFilters() { return array( new \Twig_SimpleFilter('shortNumber', array($this, 'shortNumber')), ); } /** * Shorten the number * * @param integer * @return string */ public function shortNumber($number) { $k = pow(10,3); $mil = pow(10,6); $bil = pow(10,9); if ($number >= $bil) return number_format((float)$number / $bil, 1, '.', '').'Billion'; else if ($number >= $mil) return number_format((float)$number / $mil, 1, '.', '').'M'; else if ($number >= $k) return number_format((float)$number / $k, 1, '.', '').'K'; else return (int) $number; } /** * Get name */ public function getName() { return 'app_extension'; } }
Добавьте расширение для services.yml
# app/config/services.yml services:
https://riptutorial.com/ru/home 39
app.twig_extension: class: AppBundle\Twig\AppExtension public: false tags: - { name: twig.extension }
Используйте его в TWIG
<span>{{ number|shortNumber }}</span> e.g. <span>{{ 1234|shortNumber }}</span> -> <span>1.2k</span>
Прочитайте Расширения Symfony Twig онлайн: https://riptutorial.com/ru/symfony2/topic/6000/
расширения-symfony-twig
https://riptutorial.com/ru/home 40
глава 14: Репозиторий Entity Entity
Examples
Создание нового репозитория
Вы можете создать новый репозиторий, где захотите, но рекомендуется создавать их в отдельной папке Repository .
Хотя вы можете назвать файл и класс репозитория по EntityNameRepository усмотрению, рекомендуется EntityNameRepository репозиторий EntityNameRepository , чтобы вы могли быстро найти их в своей папке.
Предположим, что у нас есть объект Project , который хранится в AppBundle\Entity , он будет выглядеть так:
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Project Entity - some information * * @ORM\Table(name="project") * @ORM\Entity(repositoryClass="AppBundle\Repository\ProjectRepository") */ class Project { // definition of the entity with attributes, getters, setter whatsoever } ?>
Важной частью здесь является строка @ORM\Entity(repositoryClass="AppBundle\Repository\ProjectRepository") , поскольку она соединяет этот Entity с данным классом репозитория.
Также вам нужно использовать класс \Doctrine\ORM\Mapping для использования параметров сопоставления.
Сам репозиторий довольно прост
<?php namespace AppBundle\Repository; class ProjectRepository extends \Doctrine\ORM\EntityRepository
https://riptutorial.com/ru/home 41
{ public function getLastTenProjects() { // creates a QueryBuilder instance $qb = $this->_em->createQueryBuilder() ->select('p') ->from($this->_entityName, 'p') ->orderBy('p.id', 'DESC') ->setMaxResults(10) ; // uses the build query and gets the data from the Database return $qb->getQuery()->getResult(); } } ?>
Важно заметить, что класс Repository должен расширять \Doctrine\ORM\EntityRepository , чтобы он мог работать правильно. Теперь вы можете добавить столько функций для разных запросов, сколько хотите.
Функция ExpressionBuilder IN ()
Если вы хотите использовать команду MySQL IN() в QueryBuilder, вы можете сделать это с помощью функции in() класса ExpressionBuilder .
// get an ExpressionBuilder instance, so that you $expressionBulder = $this->_em->getExpressionBuilder(); $qb = $this->_em->createQueryBuilder() ->select('p') ->from($this->_entityName, 'p'); ->where($expressionBuilder->in('p.id', array(1,2,3,4,5))); return $qb->getQuery()->getResult();
Сделать запрос с суб-запросом
В качестве примера, только для демонстрации HOW-TO использовать оператор выбора подзапроса внутри оператора select, предположим, что мы найдем всех пользователей, которые еще не скомпилировали адрес (в таблице адресов нет записей):
// get an ExpressionBuilder instance, so that you $expr = $this->_em->getExpressionBuilder(); // create a subquery in order to take all address records for a specified user id $sub = $this->_em->createQueryBuilder() ->select('a') ->from($this->_addressEntityName, 'a') ->where('a.user = u.id'); $qb = $this->_em->createQueryBuilder() ->select('u') ->from($this->_userEntityName, 'u')
https://riptutorial.com/ru/home 42
->where($expr->not($expr->exists($sub->getDQL()))); return $qb->getQuery()->getResult();
Прочитайте Репозиторий Entity Entity онлайн: https://riptutorial.com/ru/symfony2/topic/6032/
репозиторий-entity-entity
https://riptutorial.com/ru/home 43
глава 15: Создание веб-сервисов с Symfony 2.8
Examples
Работа с API RESTFul
REpresentational State Transfer (REST) - это архитектурный стиль, используемый для веб-разработки, введенный и определенный в 2000 году Роем Филдингом.
См. Его на wiki: REST wiki
Он основан на HTTP-протоколе ( HTTP на Wiki ), HTTP-запросах (GET, POST, PATCH,
DELETE ...) / кодах ответов (404, 400, 200, 201, 500 ...) и структуре тел.
Это отличный способ разоблачить ваши данные в другой системе в Интернете.
Представьте, что вы хотите сделать RESTFul api для управления вашим StackOverFlower
(User) в вашей локальной базе данных.
Давайте сделаем пример!
Концепция Symfony 2.8
Веб сервер :1.
Вы должны установить и настроить веб-сервер на своей локальной машине, см. Wamp или Lamp или Mamp : у вас должна быть последняя версия PHP ( !!! Требования Symfony !!! )
Php cli и композитор:2.
Вы должны настроить PHP cli (в зависимости от нашей системы), введите это «PHP-cli [OS-
NAME] how-to» в нашего друга Google! Вы должны установить композитор, см. « Установка композитора»
Symfony:3.
Вы должны установить Symfony 2.8 (с композитором, это лучший способ), открыть терминал (или cmd на окнах) и перейти на ваш веб-сервер.
Symfony 2 работает с одним из лучших типов структуры: Связки. Все - Связки на Symfony!
Мы можем проверить это выше.
cd /your-web-server-path/
https://riptutorial.com/ru/home 44
composer create-project symfony/framework-standard-edition example "2.8.*"
Перейдите к древовидной структуре и увидите: Symfony 2.8 установлен в каталоге «example».
FOSRest (для FriendsOfSymfony) на JMSSerializer Bundle:4.
Вы должны установить эти два пакета:
JMSSerializer ( установить ):
composer require jms/serializer-bundle "~0.13"
FosRestBundle ( установить ):
composer require friendsofsymfony/rest-bundle
Не забудьте активировать их в AppKernel.php!
Основная конфигурация:5.
Создайте свой собственный «пример» и создайте базу данных.
cd /path/to/your/symfony/ php app/console generate:bundle php app/console doctrine:generate:database
Перейдите в конец файла конфигурации приложения Symfony 2.8 и вставьте его:
#app/config/config.yml fos_rest: format_listener: rules: - { path: '^/stackoverflower', priorities: ['xml', 'json'], fallback_format: xml, prefer_extension: true } - { path: '^/', priorities: [ 'text/html', '*/*'], fallback_format: html, prefer_extension: true }
Создайте свой каталог доктрины ("example / src / ExampleBundle / Entity") и файл ресурсов ("StackOverFlower.orm.yml"):
# src/ExampleBundle/Resources/config/doctrine/StackOverFlower.orm.yml ExampleBundle\Entity\StackOverFlower: type: entity table: stackoverflower id: id: type: integer generator: { strategy: AUTO } fields: name:
https://riptutorial.com/ru/home 45
type: string length: 100
Создание схемы сущности и обновления:
php app/console doctrine:generate:entity StackOverFlower php app/console doctrine:schema:update --force
Создайте контроллер по умолчанию:
#src/ExampleBundle/Controller/StackOverFlowerController.php namespace ExampleBundle\Controller; use FOS\RestBundle\Controller\FOSRestController; use Symfony\Component\HttpFoundation\Request; use FOS\RestBundle\Controller\Annotations\Get; use FOS\RestBundle\Controller\Annotations\Post; use FOS\RestBundle\Controller\Annotations\Delete; use ExampleBundle\Entity\StackOverFlower; class StackOverFlowerController extends FOSRestController { /** * findStackOverFlowerByRequest * * @param Request $request * @return StackOverFlower * @throws NotFoundException */ private function findStackOverFlowerByRequest(Request $request) { $id = $request->get('id'); $user = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:StackOverFlower")->findOneBy(array('id' => $id)); return $user; } /** * validateAndPersistEntity * * @param StackOverFlower $user * @param Boolean $delete * @return View the view */ private function validateAndPersistEntity(StackOverFlower $user, $delete = false) { $template = "ExampleBundle:StackOverFlower:example.html.twig"; $validator = $this->get('validator'); $errors_list = $validator->validate($user); if (count($errors_list) == 0) { $em = $this->getDoctrine()->getManager();
https://riptutorial.com/ru/home 46
if ($delete === true) { $em->remove($user); } else { $em->persist($user); } $em->flush(); $view = $this->view($user) ->setTemplateVar('user') ->setTemplate($template); } else { $errors = ""; foreach ($errors_list as $error) { $errors .= (string) $error->getMessage(); } $view = $this->view($errors) ->setTemplateVar('errors') ->setTemplate($template); } return $view; } /** * newStackOverFlowerAction * * @Get("/stackoverflower/new/{name}") * * @param Request $request * @return String */ public function newStackOverFlowerAction(Request $request) { $user = new StackOverFlower(); $user->setName($request->get('name')); $view = $this->validateAndPersistEntity($user); return $this->handleView($view); } /** * editStackOverFlowerAction * * @Get("/stackoverflower/edit/{id}/{name}") * * @param Request $request * @return type */ public function editStackOverFlowerAction(Request $request) { $user = $this->findStackOverFlowerByRequest($request); if (! $user) { $view = $this->view("No StackOverFlower found for this id:". $request->get('id'), 404);
https://riptutorial.com/ru/home 47
return $this->handleView($view); } $user->setName($request->get('name')); $view = $this->validateAndPersistEntity($user); return $this->handleView($view); } /** * deleteStackOverFlowerAction * * @Get("/stackoverflower/delete/{id}") * * @param Request $request * @return type */ public function deleteStackOverFlowerAction(Request $request) { $user = $this->findStackOverFlowerByRequest($request); if (! $user) { $view = $this->view("No StackOverFlower found for this id:". $request->get('id'), 404); return $this->handleView(); } $view = $this->validateAndPersistEntity($user, true); return $this->handleView($view); } /** * getStackOverFlowerAction * * @Get("/stackoverflowers") * * @param Request $request * @return type */ public function getStackOverFlowerAction(Request $request) { $template = "ExampleBundle:StackOverFlower:example.html.twig"; $users = $this->getDoctrine()->getManager()->getRepository("ExampleBundle:StackOverFlower")->findAll(); if (count($users) === 0) { $view = $this->view("No StackOverFlower found.", 404); return $this->handleView(); } $view = $this->view($users) ->setTemplateVar('users') ->setTemplate($template); return $this->handleView($view); } }
https://riptutorial.com/ru/home 48
Сделайте свой твиг по умолчанию:
#src/ExampleBundle/Resources/views/StackOverFlower.html.twig {% if errors is defined %} {{ errors }} {% else %} {% if users is defined %} {{ users | serialize }} {% else %} {{ user | serialize }} {% endif %} {% endif %}
Вы только что создали свой первый RESTFul API!
Вы можете проверить его на: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflower/new/test .
Как вы можете видеть в базе данных, новый пользователь был создан с именем «test».
Вы можете получить список stackoverflower на: http: //your-server-name/your-symfony-path/app_dev.php/stackoverflowers
У вас есть полный пример в моей учетной записи github этого примера: пример Git Hub , в ветке «master» в этом примере, а в ветке «real-routes» - пример с более подходящим URL (
например, POST и DELETE).
Увидимся позже с примером SOAP!
С уважением,
Матье
Работа с SOAP API
SOAP (Протокол объектов простого доступа) основан на XML, например XML-RPC,
является предком с файлом WSDL , описывающим метод, который должен быть показан.
Этот протокол часто основан на SOAP-Enveloppe , SOAP-Body и, альтернативно, SOAP-заголовке , данные окутываются в структуру и интерпретируются как один и тот же путь из разных языков.
https://riptutorial.com/ru/home 49
Для получения дополнительной информации см .: SOAP on wiki
Как описано выше, наиболее важным для описания вашего веб-сервиса является файл WSDL , см. Объяснение WSDL в wiki
Основная часть работы будет заключаться в том, чтобы определить, что отображается в вашем SOAP API, ваш класс и ваш бизнес-процесс будут автоматически обрабатываться базовым классом PHP SOAPServer . Вам все еще нужен код!
Посмотрим, как будет построен файл:
Сервис. Установите URI API и то, что будет связано.1.
Переплет: он определяет операции, связанные с сервисом2. Операции: некоторые методы, которые вы хотите открыть в Интернете3. PortTypes: определение запросов и ответов4.
Запросы и ответы: что вы ожидаете ввода и вывода5. Сообщения: какой formt вы ожидаете (параметры) для каждого ввода-вывода, они могут быть простыми (string, integer, float ...) или сложным типом (структурированный формат)
6.
С помощью этой базовой информации вы можете достичь всего необходимого API.
Представьте, что вы хотите сделать SOAP api для управления вашим StackOverFlower (
Пользователь) в вашей локальной базе данных.
Давайте сделаем пример!
Установите веб-сервер, Php cli, Composer, Symfony 2.8, создайте новый Bundle
«ExampleBundle» и постройте схему, как описано выше.
Прежде чем мы начнем строить свою бизнес-логику, нам нужно было знать, что вывести из нашего контроллера. Эта работа выполняется с использованием WSDL. Это пример хорошего синтаксиса WSDL:
<definitions name="StackOverFlowerService" targetNamespace="http://example/soap/stackoverflower.wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://example/soap/stackoverflower.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <message name="NewRequest"> <part name="name" type="xsd:string"/> </message> <message name="NewResponse"> <part name="status" type="xsd:string"/> </message> <message name="getListRequest"></message>
https://riptutorial.com/ru/home 50
<message name="getListResponse"> <part name="list" type="xsd:string"/> </message> <message name="editRequest"> <part name="id" type="xsd:string"/> <part name="name" type="xsd:string"/> </message> <message name="editResponse"> <part name="status" type="xsd:string"/> </message> <message name="deleteRequest"> <part name="id" type="xsd:string"/> </message> <message name="deleteResponse"> <part name="status" type="xsd:string"/> </message> <portType name="StackOverFlower_PortType"> <operation name="newStack"> <input message="tns:NewRequest"/> <output message="tns:NewResponse"/> </operation> <operation name="getList"> <input message="tns:getListRequest"/> <output message="tns:getListResponse"/> </operation> <operation name="edit"> <input message="tns:editRequest"/> <output message="tns:editResponse"/> </operation> <operation name="delete"> <input message="tns:deleteRequest"/> <output message="tns:deleteResponse"/> </operation> </portType> <binding name="StackOverFlower_Binding" type="tns:StackOverFlower_PortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="newStack"> <soap:operation soapAction="newStack"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:new" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:new" use="encoded"/> </output> </operation>
https://riptutorial.com/ru/home 51
<operation name="getList"> <soap:operation soapAction="getList"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:get-list" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:get-list" use="encoded"/> </output> </operation> <operation name="edit"> <soap:operation soapAction="edit"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:edit" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:edit" use="encoded"/> </output> </operation> <operation name="delete"> <soap:operation soapAction="delete"/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:delete" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:example:delete" use="encoded"/> </output> </operation> </binding> <service name="StackOverFlower_Service"> <documentation>Description File of StackOverFlowerService</documentation> <port binding="tns:StackOverFlower_Binding" name="StackOverFlower_Port"> <soap:address location="http://example/stackoverflower/" /> </port> </service> </definitions>
https://riptutorial.com/ru/home 52
Мы должны это сделать в вашем веб-каталоге symfony (в подкаталоге soap и называть это «stackoverflower.wsdl»).
Действительно вдохновлен примером WSDl . Вы можете проверить это с помощью онлайн-проверки WSDl
После этого мы можем сделать наш основной сервис и контроллер, вдохновленные SOAP Symfony 2.8 Doc .
Сервис, который обрабатывается PHP SOAPServer:
#src\ExampleBundle\Services\StackOverFlowerService.php namespace ExampleBundle\Services; use Doctrine\ORM\EntityManager; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use ExampleBundle\Entity\StackOverFlower; class StackOverFlowerService { private $em; private $stackoverflower; public function __construct(EntityManager $em) { $this->em = $em; } public function newStack($name) { $stackoverflower = new StackOverFlower(); $stackoverflower->setName($name); $this->em->persist($stackoverflower); $this->em->flush(); return "ok"; } public function getList() { $stackoverflowers = $this->em->getRepository("ExampleBundle:StackOverFlower")->findAll(); $encoders = array(new XmlEncoder(), new JsonEncoder()); $normalizers = array(new ObjectNormalizer()); $serializer = new Serializer($normalizers, $encoders); return $serializer->serialize($stackoverflowers, 'json'); } public function edit($id, $name) { $stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")-
https://riptutorial.com/ru/home 53
>findOneById($id); $stackoverflower->setName($name); $this->em->persist($stackoverflower); $this->em->flush(); return "ok"; } public function delete($id) { $stackoverflower = $this->em->getRepository("ExampleBundle:StackOverFlower")->findOneById($id); $this->em->remove($stackoverflower); $this->em->flush(); return "ok"; } }
Настройте эту службу:
#src\ExampleBundle\Resources\config\services.yml services: stackoverflower_service: class: ExampleBundle\Services\StackOverFlowerService arguments: [@doctrine.orm.entity_manager]
Как вы можете видеть, мы вставляем Entity Manger в качестве зависимости, потому что мы должны использовать это для объекта CRUD StackOverFlower.
Контроллер, который выставляет объект службы:
#src\ExampleBundle\Controller\StackOverFlowerController.php namespace ExampleBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class StackOverFlowerController extends Controller { public function indexAction() { ini_set("soap.wsdl_cache_enabled", "0"); $options = array( 'uri' => 'http://example/app_dev.php/soap', 'cache_wsdl' => WSDL_CACHE_NONE, 'exceptions' => true ); $server = new \SoapServer(dirname(__FILE__).'/../../../**web/soap/stackoverflower.wsdl**', $options); $server->setObject($this->get('stackoverflower_service'));
https://riptutorial.com/ru/home 54
$response = new Response(); $response->headers->set('Content-Type', 'text/xml; charset=utf-8'); ob_start(); $server->handle(); $response->setContent(ob_get_clean()); return $response; } }
Дополнительные сведения об услугах см. В разделе: Сервисный контейнер на Symfony doc
Маршрут:
example_soap: path: /soap defaults: { _controller: ExampleBundle:StackOverFlower:index }
Основной шаблон Twig:
#src\ExampleBundle\Resources\views\Soap\default.html.twig {% if status is defined %} {{ status }} {% else %} {{ list }} {% endif %}
Мы создали ваш первый SOAP API с Symfony 2.8!
Прежде чем вы откроете его, мы должны проверить!
В вашем StackOverFlowerController добавьте следующее:
public function testNewAction(Request $request) { $service = $this->get('stackoverflower_service'); $result = $service->newStack($request->query->get('name')); return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result)); } public function testEditAction(Request $request) { $service = $this->get('stackoverflower_service'); $result = $service->edit($request->query->get('id'), $request->query->get('name')); return $this->render('ExampleBundle:Soap:default.html.twig', array('status' => $result)); } public function testGetListAction(Request $request) { $service = $this->get('stackoverflower_service'); $result = $service->getList(); return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result));
https://riptutorial.com/ru/home 55
} public function testDeleteAction(Request $request) { $service = $this->get('stackoverflower_service'); $result = $service->delete($request->query->get('id')); return $this->render('ExampleBundle:Soap:default.html.twig', array('list' => $result)); } // To test this from an another server, you can type this : // $client = new \SoapClient("http://example/app_dev.php/soap?wsdl", array("trace" => 1, "exception" => 1)); // $result = $client->newStack($request->query->get('name')); // print_r($result);
Маршруты:
test_new: path: /stackoverflower/new defaults: { _controller: ExampleBundle:StackOverFlower:testNew } test_edit: path: /stackoverflower/edit defaults: { _controller: ExampleBundle:StackOverFlower:testEdit } test_get_list: path: /stackoverflower/get-list defaults: { _controller: ExampleBundle:StackOverFlower:testGetList } test_delete: path: /stackoverflower/delete defaults: { _controller: ExampleBundle:StackOverFlower:testDelete }
Вы можете ввести его в своем браузере:
GetList1. новый2. редактировать3. удалять4.
Это очень простой пример не защищенного API с SOAP, и я могу сделать пример защищенного примера после аутентификации ключа api позже.
Что все люди ...
Матье
Прочитайте Создание веб-сервисов с Symfony 2.8 онлайн: https://riptutorial.com/ru/symfony2/topic/6355/создание-веб-сервисов-с-symfony-2-8
https://riptutorial.com/ru/home 56
глава 16: Создание веб-сервисов с помощью Symfony с использованием Rest
Examples
Использование Symfony REST Edition
Symfony REST Edition - это полнофункциональное приложение Symfony2, которое можно использовать в качестве скелета для новых приложений.
Доступно на Github
Он поставляется с предварительно сконфигурированными со следующими пакетами:
сверток Описание
FrameworkBundle Ядро Symfony.
SensioFrameworkExtraBundleДобавляет несколько улучшений, таких как возможность аннотации шаблонов и маршрутизации.
DoctrineBundle Добавляет поддержку ORM доктрины.
TwigBundle Добавляет поддержку движка шаблонов Twig .
SecurityBundleДобавляет безопасность, интегрируя компонент безопасности Symfony.
SwiftmailerBundleДобавляет поддержку Swiftmailer , библиотеки для отправки электронных писем.
MonologBundleДобавляет поддержку Monolog , библиотеке регистрации.
AsseticBundleДобавляет поддержку для Assetic , библиотеки обработки активов.
WebProfilerBundle (в среде dev / test)
Добавляет функции профилирования и панель инструментов веб-отладки.
SensioDistributionBundle (в среде dev / test)
Добавляет функциональность для настройки и работы с дистрибутивами Symfony .
https://riptutorial.com/ru/home 57
сверток Описание
SensioGeneratorBundle (в среде dev / test)
Добавляет возможности генерации кода.
AcmeDemoBundle (в среде dev / test)
Демо-пакет с некоторым примером кода.
FOSRestBundleFOSRestBundle добавляет функциональность REST.
FOSHttpCacheBundleЭтот пакет предлагает инструменты для улучшения кеширования HTTP с помощью Symfony2 .
NelmioApiDocBundle Добавляет функции документации API.
BazingaHateoasBundle Добавляет поддержку HATEOAS.
HautelookTemplatedUriBundle Добавляет поддержку шаблонов URI (RFC 6570).
BazingaRestExtraBundleBazingaRestExtraBundle Предоставляет дополнительные функции для API REST,
построенных с использованием Symfony2.
Прочитайте Создание веб-сервисов с помощью Symfony с использованием Rest онлайн: https://riptutorial.com/ru/symfony2/topic/6020/создание-веб-сервисов-с-помощью-symfony-с-использованием-rest
https://riptutorial.com/ru/home 58
глава 17: Управление брандмауэрами и безопасностью Symfony
Examples
Управление безопасностью
Безопасность была частью темной стороны документации по symfony, она имеет выделенный компонент с именем Security Component .
Этот компонент настроен в файле security.yml основного проекта приложения.
Конфигурация по умолчанию выглядит так:
# app/config/security.yml security: providers: in_memory: memory: ~ firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false default: anonymous: ~
Вы можете определить конкретные межсетевые экраны, чтобы ограничить доступ к некоторым URL- адресам определенным ролям на основе иерархии для ваших пользователей , которые определены Поставщиком и кодонами, которые управляют безопасностью пароля.
Например, если вы хотите создать настраиваемый поставщик , из своего механизма базы данных вы можете определить security.yml следующим образом:
providers: your_db_provider: entity: class: AppBundle:User property: apiKey
Это подробно описано в документации Symfony. Как определить пользовательский UserProvider и, например, из базы данных или LDAP .
После этого вы можете определить брандмауэр, чтобы ограничить некоторый URL на основе пользовательского провайдера (security.yml), как это явно:
https://riptutorial.com/ru/home 59
firewalls: secured_area: pattern: ^/admin
Или с контролем доступа :
access_control: - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN } - { path: ^/admin, roles: ROLE_ADMIN }
Подробнее Более детальную документацию здесь .
Лучший способ управлять пользователем - использовать FosUserBundle, который расширяет некоторые функциональные функции Framework.
Прочитайте Управление брандмауэрами и безопасностью Symfony онлайн: https://riptutorial.com/ru/symfony2/topic/7486/управление-брандмауэрами-и-безопасностью-symfony
https://riptutorial.com/ru/home 60
глава 18: Услуги Symfony
Examples
Как объявить, написать и использовать простой сервис в Symfony2
Объявление услуг:
# src/Acme/YourBundle/Resources/config/services.yml services: my_service: class: Acme\YourBundle\Service\MyService arguments: ["@doctrine", "%some_parameter%", "@another_service"] another_service: class: Acme\YourBundle\Service\AnotherService arguments: []
Код услуги:
<?php namespace Acme\YourBundle\Service\Service; class MyService { /** * Constructor * You can had whatever you want to use in your service by dependency injection * @param $doctrine Doctrine * @param $some_parameter Some parameter defined in app/config/parameters.yml * @param $another_service Another service */ public function __construct($doctrine, $some_parameter, $another_service) { $this->doctrine = $doctrine; $this->some_parameter = $some_parameter; $this->another_service = $another_service; } public function doMagic() { // Your code here } }
Используйте его в контроллере:
<?php namespace Acme\YourBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Acme\YourBundle\Service\Service\MyService;
https://riptutorial.com/ru/home 61
class MyController extends Controller { /** * One action */ public function oneAction(Request $request) { $myService = $this->get('my_service'); $myService->doMagic(); // ... } }
Прочитайте Услуги Symfony онлайн: https://riptutorial.com/ru/symfony2/topic/4587/услуги-symfony
https://riptutorial.com/ru/home 62
глава 19: Установка Symfony2 на localhost
Examples
Использование командной строки
Лучший способ установки и настройки проекта Symfony2 описан в официальной документации следующим образом:
Mac OS X / Linux
$ sudo curl -LsS http://symfony.com/installer -o /usr/local/bin/symfony $ sudo chmod a+x /usr/local/bin/symfony
Windows
c:\> php -r "file_put_contents('symfony', file_get_contents('https://symfony.com/installer'));"
Затем вы можете использовать двоичный код Symfony для создания правильных лесов:
$ symfony new my_project
Использование композитора над консолью
Учитывая, что вы уже установили композитор и работаете, и он доступен по всему миру, вы можете просто создать новые проекты Symfony, как указано в официальной документации .
Теперь вы можете создать новый проект Symfony с композитором:
composer create-project symfony/framework-standard-edition my_project_name
Это создаст проект в текущем каталоге, в котором вы находитесь.
Если вы хотите создать проект с определенной версией Symfony, вы можете добавить параметр с номером версии:
composer create-project symfony/framework-standard-edition my_project_name "2.8.*"
Подсказка: если вы думаете, что композитор ничего не сделает, добавьте в -vvv флаг -vvv . Таким образом, вы получите подробную информацию о том, что делает композитор прямо сейчас.
https://riptutorial.com/ru/home 63
Прочитайте Установка Symfony2 на localhost онлайн: https://riptutorial.com/ru/symfony2/topic/6340/установка-symfony2-на-localhost
https://riptutorial.com/ru/home 64
глава 20: Шаблоны дизайна Symfony
Examples
Схема впрыска зависимостей
Представьте, что у вас есть менеджер классов для управления отправкой писем (называется MailManager).
В этом случае вы должны регистрировать отправленные письма. Хорошим решением является преобразование класса MailManager в service , а затем впрыснуть класс для создания журналов ( Monolog , например) в MailManager создание службы.
Сделать это :
1- Объявить будущий класс MailManager как службу (в services.yml)
services: mail.manager.class: class: Vendor/YourBundle/Manager/MailManager
2- Вводит регистратор службы с использованием вообще отсутствует argument методы
services: mail.manager.class: class: Project/Bundle/Manager/MailManager arguments: ["@logger"] # inject logger service into constructor
3- Создать класс MailManager
<?php namespace Project\Bundle\Manager; use Symfony\Component\HttpKernel\Log\LoggerInterface; class MailManager { protected $logger; //initialized logger object public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function sendMail($parameters) { //some codes to send mail
https://riptutorial.com/ru/home 65
//example using logger $this->logger->info('Mail sending'); } }
4- вызов MailManager в контроллере, например
<?php class TestController extends Controller { public function indexAction() { //some codes... //call mail manager service $mailManager = $this->get('mail.manager.class'); //call 'sendMail' function from this service $mailManager->sendMail($parameters); } }
Прочитайте Шаблоны дизайна Symfony онлайн: https://riptutorial.com/ru/symfony2/topic/6289/
шаблоны-дизайна-symfony
https://riptutorial.com/ru/home 66
кредиты
S. No
Главы Contributors
1Начало работы с symfony2
althaus, COil, Community, Dheeraj, Hendra Huang, Jakub Zalas, karel, kix, mgh, Redjan Ymeraj, TRiNE, uddhab
2Базовая маршрутизация
kix
3 ЗапросA.L, Arkemlar, DOZ, Hermann Döppes, Mathieu Dormeval, mgh, Paweł Brzoski
4Конфигурация для собственных пакетов
PumpkinSeed
5 маршрутизацияafkplus, Bob, Dheeraj, Farahmand, Kid Binary, kix, pinch boi triggered af, Sam Janssens, Scott Flack, Stephan Vierkant, Stevan Tosic, Stony, tchap
6Монолог: улучшите свои журналы
sdespont
7 отклик CStff
8Отношения сущностей доктрины
Federkun, palra
9Отправка параметров в класс формы
geoB
10
Пример использования Symfony Twig Extenstion
Muhammad Taqi
11 Проверка формы Griva
12Развертывание Symfony2
sphinks
Расширения 13 Sand, Strabek
https://riptutorial.com/ru/home 67
Symfony Twig
14Репозиторий Entity Entity
doydoy44, KhorneHoly, Matteo
15Создание веб-сервисов с Symfony 2.8
Barathon, Mathieu Dormeval
16
Создание веб-сервисов с помощью Symfony с использованием Rest
Barathon, Sunitrams'
17
Управление брандмауэрами и безопасностью Symfony
Mathieu Dormeval
18 Услуги Symfony DonCallisto, enricog, moins52
19Установка Symfony2 на localhost
Barathon, KhorneHoly, sentenza
20Шаблоны дизайна Symfony
DOZ
https://riptutorial.com/ru/home 68