Основа бандла.
Итак, в предыдущей статье наш бандл установлен. Давайте создадим его первый роутер /newtop/.
Прежде чем Вы перейдете по этому адресу, не забудьте добавить в файл myapp\config\routes\annotations.yaml
newstop_bundle:
resource: '@NewsTopBundle/config/routes.yaml'
Мы напишем бандл под названием NewsTop, который будет выводить новости с обновлением данных через ajax.
NewsTop – приложение для вывода новостей на сайте.
Все новости буду иметь изображение, поэтому для работы с изображениями нам понадобится прекрасная библиотека «liip», установить которую можно следующим образом:
composer require liip/imagine-bundle
итак создадим путь и файл myapp/bundles/NewsTopBundle/config/routes.yaml следующего содержания:
# Add this file to app routes.yaml to use routes custom loader.
newstop_routes:
type: annotation
resource: '../src/Controller/'
Обратите внимание маршруты будут строится на основе механизма аннотаций «type: annotation».
В директории Controller необходимо создать следующие классы:
• myapp/bundles/NewsTopBundle/src/Controller/NewsTopController.php
• myapp/bundles/NewsTopBundle/src/Controller/NewsTopEditorController.php
• myapp/bundles/NewsTopBundle/src/Controller/NewsTopAjaxController.php
• NewsTopController.php –класс для работы с бандлом.
• NewsTopEditorController.php –класс для вывода списка новостей и редактирования сущностей.
• NewsTopAjaxController.php – основной класс для обработки ajax запросов.
Весь код я не буду размещать в статье, код бандла Вы сможете обнаружить на github.com по ссылке https://github.com/eap1985/newstop
Я остановлюсь на тех частях, которые наиболее сложны в понимании.
Новости будут строится на основе сущности (entity), для этого нам нужно создать файл по адресу: myapp/bundles/NewsTopBundle/src/Entity/NewsTop.php
<?php
namespace eap1985\NewsTopBundle\Entity;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Table(name="newstop")
* @ORM\Entity
* @Vich\Uploadable()
* @Assert\Callback("validate")
*/
class NewsTop
{
//здесь будет код ORM сущности, свойства и методы
}
Сущность ORM привязана к таблице базы данных newstop, тестовая структура которой следующая:
CREATE TABLE `newstop` (
`id` mediumint(9) NOT NULL,
`name` text,
`opisanie` text,
`razdel` varchar(50) NOT NULL,
`avtor` text,
`count` int(10) NOT NULL,
`comment` int(11) NOT NULL,
`time` datetime NOT NULL,
`arhiv` datetime NOT NULL,
`href` varchar(50) DEFAULT NULL,
`si` varchar(255) NOT NULL,
`bi` varchar(255) NOT NULL,
`metka` varchar(255) NOT NULL,
`archived` varchar(255) NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`thumbnail` varchar(200) NOT NULL,
`pdf` varchar(200) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Дамп данных таблицы `newstop`
--
INSERT INTO `newstop` (`id`, `name`, `opisanie`, `razdel`, `avtor`, `count`, `comment`, `time`, `arhiv`, `href`, `si`, `bi`, `metka`, `archived`, `created_at`, `updated_at`, `thumbnail`, `pdf`) VALUES
(1, 'Paginator bundle for Symfony!', 'Paginator bundle for Symfony to automate pagination and simplify sorting and other features', 'articlephp', 'Ермаков А.П.', 3272, 11, '2011-11-11 00:00:00', '2015-11-11 00:00:00', '1.php', '1.jpeg', '20090912202040.jpg', 'Symfony', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(2, 'Создание xls(excel) файлов с помощью Spreadsheet_Excel_Writer.', 'Продолжаем изучать возможности php при работе с excel файлами. На этот раз мы рассмотрим создание excel файлов с помощью пакета pear Spreadsheet_Excel_Writer.', 'articlephp', 'Ермаков А.П.', 4353, 5, '2012-01-27 00:00:00', '2015-11-11 00:00:00', '2.php', '2.jpeg', '20090916230741.jpg', '', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(3, 'Погодный информер с jquery, php и mysql', 'В статье я расскажу о создании погодного информера с использованием jquery, php и mysql. В итоге Вы будете иметь погодный информер не хуже чем у Yandex или Rambler.', 'jquery', 'Ермаков А.П.', 47626, 13, '2011-11-11 00:00:00', '2015-11-11 00:00:00', '5.php', '3.jpeg', '20091007193451.png', 'Основы Аякс', '1', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(4, 'Как написать первый плагин на jQuery, с использованием ajax?', 'В статье рассматриваются в основном две функции jquery.fn.extend() и jquery.extend, с помощью которых создаются плагины jQuery. После прочтения Вы научитесь работать с плагинами jQuery, создавать собственные. Статья объясняет функции на основе примера использующего ajax и анимацию с различными эффектами. \r\n', 'jquery', 'Ермаков А.П.', 4856, 14, '2011-12-04 01:02:00', '2015-11-11 00:00:00', '4.php', '4.jpg', '', 'Основы Аякс', '1', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(5, 'jQuery примеры', '<div>В статье рассматриваются примеры jQuery при взаимодействии с элементами форм, jquery ajax, post, малоизученные функции - jQuery.noConflict(), serialize(). К тому же, после прочтения, Вы научитесь писать ошибкоустойчивый код jquery с другими библиотеками, например с mootools, в заключении я расскажу о постраничном выводе с jquery, php и mysql</div>', 'jquery', 'Ермаков А.П.', 111341, 24, '2015-11-05 19:00:00', '2015-11-11 00:00:00', '3.php', '5.jpg', '', 'Основы Аякс', '1', '2020-05-28 22:29:00', '2020-05-29 09:16:11', '03e4c127a178c1b44fd71daf62f1ce75.jpg', 'диплом.pdf'),
(6, 'Lightbox без фреймовика!', 'Подробно о создании lightbox без использования любых фреймовиков, только на javascript. ', 'javascript', 'Ермаков А.П.', 826, 2, '2011-12-04 00:00:00', '2015-11-11 00:00:00', '7.php', '6.jpg', '', '', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(7, '7 обязательных дополнений для работы в css от Firefox', 'В статье я раcскажу о 5 популярнейших плагинах для FireFox ', 'htmlcss', 'Ермаков А.П.', 513, 2, '2011-12-03 00:00:00', '2015-11-11 00:00:00', '8.php', '7.jpg', '', 'cssmanual', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(8, 'Доздравствует новый Firefox 4!', 'Почитайте о возможностях Firefox 4 с поддержкой CSS трансформаций. ', 'htmlcss', 'Ермаков А.П.', 302, 0, '2011-12-01 00:00:00', '2015-11-11 00:00:00', '9.php', '8.jpg', '', '', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(9, 'Реклама Google – советы, ошибки и секреты', 'На многих сайтах публикуется информация относительно Google Adsense, многое является правильным, но всё разбросано по разным сайтам, в этой статье автор соберёт полезную информацию о Google Adsense, на основе обобщения в единый материал для изучения. ', 'seo', 'Ермаков А.П.', 367, 2, '2011-12-02 00:00:00', '2015-11-11 00:00:00', '11.php', '9.jpg', '20100801185912.jpeg', '', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(10, 'Slybox на jQuery', '<div>Узнайте как создать свой lightbox прочитав статью об этом. </div>', 'jquery', 'Ермаков А.П.', 2147, 12, '2020-05-11 23:48:00', '2015-11-11 00:00:00', '6.php', '10.jpg', '20100807230720.jpg', '', '1', '2020-05-28 22:29:00', '2020-05-28 22:29:29', '', ''),
(11, 'jQuery для начинающих!', 'В статье я расскажу о jQuery ajax - jquer.post(),jquery.load(), jquery.ajax. Статья рассчитана не только на начинающих пользователей jQuery, но и на более опытных.', 'jquery', 'Ермаков А.П.', 4298, 8, '2011-12-04 00:00:00', '2015-11-02 00:00:00', '26.php', 'study.jpg', '', 'Основы Аякс', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(12, 'jQuery для начинающего! Продолжение.', 'В статье я расскажу о jQuery методах измерения всего, что измеряется в сравнении с javascript методами. Всё о методах jQuery и javscript (height, width, clientWidth, clientHeight, scrollTop, scrollLeft, scrollHeight, scrollWidth, position, offset и т.д.).', 'jquery', 'Ермаков А.П.', 2701, 4, '2011-12-01 00:00:00', '2015-11-11 00:00:00', '27.php', 'study.jpg', '', 'Основы Аякс', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(13, 'jQuery слайдер', 'jQuery слайдер с методами animate, each, mouseover, mouseout, mousemove, mouseenter, mouseleave, mouseout, lightbox.\r\n', 'jquery', 'Ермаков А.П.', 401, 0, '2015-01-03 00:00:00', '2015-11-12 00:00:00', '14.php', 'nopicjq.jpg', '', 'Основы ', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(14, 'JWPalyer и свой YouTube', 'JWPalyer - самый популярный плагин для работы с видео в интернте - YouTube!', 'jquery', 'Ермаков А.П.', 271, 1, '2011-12-04 00:00:00', '2015-11-11 00:00:00', '15.php', 'youtube.png', '', '', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', ''),
(15, 'Покупка ссылок у посторонних сайтов', 'Стоит ли покупать ссылки у сайтов или продвигать сайт уникальным содержимым?', 'seo', 'Ермаков А.П.', 54, 0, '2015-01-28 00:00:00', '2015-11-11 00:00:00', '16.php', 'nopics.jpg', 'nopics.jpg', 'php', '0', '2020-05-28 22:29:29', '2020-05-28 22:29:29', '', '');
Вы можете создать ее вручную, можно сделать лучше через команду:
php bin/console doctrine:schema:update --force
Единственное у Вас не получиться обновить таблицу если Вы запустите данную команду не имея файла myapp/bundles/NewsTopBundle/src/Entity/NewsTop.php аналога в директории myapp/ src/Entity/NewsTop.php
Не знаю почему, но запустить данную команду только внутри бандла у меня не получилось.
Следующий код создаст сущность из таблиц базы:
php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity
а точнее создаст в директории src/Entity
файл : Newstop.php
Для того, чтобы указанная команда обновляла сущности изнутри нашего бандла необходимо добавить в файл myapp/config/packages/doctrine.yaml код:
NewsTop:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/bundles/NewsTopBundle/src/Entity'
prefix: 'NewsTop\Entity'
alias: NewsTop
Для установки методов:
php bin/console make:entity --regenerate "App\Entity\NewsTop"
Все миграции можно посмотреть по команде:
bin/console doctrine:migrations:list
Выбрать прежние версии базы данных:
php bin/console doctrine:migrations:execute --down 'DoctrineMigrations\Version20220313153903'
После создания таблицы в базе данных необходим основанный метод для роутера newstop:
/**
* @Route("/", name="index", methods={"GET"})
*/
public function index(EntityManagerInterface $em, PaginatorInterface $paginator, Request $request): Response
{
$events = $this->eventRepository->findAll();
$dql = "SELECT n FROM NewsTopBundle:NewsTop n";
$query = $em->createQuery($dql);
foreach( $events as &$event) {
if($event->getSi()) {
$si = $event->getSi();
$si = '/img/'.$si;
if(!is_file($_SERVER['DOCUMENT_ROOT'].$si)) {
$event->setSi('/img/defaultimg.png');
} else {
$event->setSi($si);
}
}
}
$pagination = $paginator->paginate(
$query, /* query NOT result */
$request->query->getInt('page', 1), /*page number*/
10 /*limit per page*/
);
return $this->render('@NewsTop/editor/index.html.twig', [
'events' => $events,
'isSoftDeleteEnabled' => $this->isSoftDeleteEnabled,
'pagination' => $pagination,
]);
}
Разберём его подробно.
строка
$events = $this->eventRepository->findAll();
Предоставляет доступ ко всему набору сущностей Newstop, которые с помощью foreach обходим для обработки изображений, которые являются тестовыми.
Далее следует строка
pagination = $paginator->paginate(
Ничего сложного это постраничная навигация.
И последним мы отображаем наш шаблон:
return $this->render('@NewsTop/editor/index.html.twig', [
'events' => $events,
'isSoftDeleteEnabled' => $this->isSoftDeleteEnabled,
'pagination' => $pagination,
]);
Код шаблона
{% extends '@NewsTop/base.html.twig' %}
{% block newstop_title %}Редактор{% endblock %}
{% block newstop_body %}
<div class="container">
<div class="row align-items-center mb-3">
<div class="col">
<h1>Список мероприятий</h1>
</div>
<div class="col text-right">
<a href="{{ path('editor.new') }}" class="btn btn-light">Добавить</a>
</div>
</div>
<div class="count">
Всего: {{ pagination.getTotalItemCount }}
</div>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Название</th>
<th>Начало</th>
<th>Конец</th>
<th>Статус</th>
<th>Изображение</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for event in pagination %}
<tr>
<td>{{ event.id }}</td>
<td><a href="{{ path('editor.edit', {'id': event.id}) }}">{{ event.name }}</a></td>
<td>
{% if event.time is not empty %}
{{ event.time | ru_datetime }} — {{ event.arhiv | ru_datetime }}
{% else %}
{{ event.time | ru_datetime }}
{% endif %}
</td>
<td>
{% if event.arhiv is not empty %}
{{ event.arhiv | ru_datetime }} — {{ event.arhiv | ru_datetime }}
{% else %}
{{ event.arhiv | ru_datetime }}
{% endif %}
</td>
<td>{{ event.archived ? 'В архиве' : 'Опубликовано' }}</td>
<td>
<a class="group1" href="{{ asset( event.si)}}" title="Me and my grandfather on the Ohoopee.">
<img src="{{ asset( event.si) | imagine_filter('my_thumb') }}" />
</a>
</td>
<td class="d-flex">
<div class="btn-group" role="group">
<a href="{{ path('editor.edit', {'id': event.id}) }}" class="btn btn-sm btn-light">
<i class="fas fa-pencil-alt"></i>
</a>
<a href="{{ path('event.show', {'id': event.id}) }}" class="btn btn-sm btn-light" target="_blank">
<i class="fas fa-eye"></i>
</a>
{% if not isSoftDeleteEnabled %}
<a href="{{ path('editor.delete', {'id': event.id}) }}" class="btn btn-sm btn-danger"
title="Удалить"><i class="fas fa-trash-alt"></i></a>
{% elseif not (isSoftDeleteEnabled and event.archived) %}
<a href="{{ path('editor.delete', {'id': event.id}) }}" class="btn btn-sm btn-warning"
title="В архив"><i class="fas fa-trash-alt"></i></a>
{% endif %}
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="9">События не найдены</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="navigation">
{{ knp_pagination_render(pagination) }}
</div>
</div>
{% endblock %}
Сам шаблон twig не сложный. Для стилизации в моём случае подключается также bootstrap, следующим образом:
@import "~@fortawesome/fontawesome-free/css/all.css";
@import "~bootstrap/scss/bootstrap.scss";
@import '~bootstrap/scss/_functions';
@import '~bootstrap/scss/_variables';
@import '~bootstrap/scss/mixins/_breakpoints';
В файле myapp/bundles/NewsTopBundle/assets/scss/widget/_newstop.scss. Если у вас не установлен bootrstrap, установите его следующим образом:
yarn add bootstrap --dev
Одновременно с этим подключите jQuery:
yarn add jquery --dev
yarn encore dev --watch
Также нам понадобится подключить конфигурационные файлы бандла в файле:
myapp/bundles/NewsTopBundle/src/DependencyInjection/NewsTopExtension.php
<?php
namespace eap1985\NewsTopBundle\DependencyInjection;
use eap1985\NewsTopBundle\Controller\NewsTopEditorController;
use Exception;
use Liip\ImagineBundle\Service\FilterService;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class NewsTopExtension extends Extension
{
/**
* Loads a specific configuration.
*
* @param array $configs
* @param ContainerBuilder $container
* @throws Exception
*/
public function load(array $configs, ContainerBuilder $container)
{
Метод load должен содержать подключаемые файлы yaml:
$loader = new YamlFileLoader(
$container,
new FileLocator(__DIR__.'/../../config')
);
$loader->load('services.yaml');
Дополнительные параметры внутри метода load носят тестовый характер. Так же как и сам бандл. В дальнейшем будем надеется что весь бандл мы сможем выложить на packagist.org
Не забудьте про файл myapp/bundles/NewsTopBundle/config/packeges/liip_imagine.yaml, в нём указываются настройки бандла liip_imagine
После этого Вы должны увидеть примерно следующую структуру.
Если, что-то не получилось, скачайте код бандла из репозитория .
В следующей статей я расскажу, как интегрировать наш бандл NewsTop в админ панель на основе Easy Admin, создать категории для наших новостей и вывести все на сайт.
2429 просмотров
Взаимосвязанные материалы
В этой статья я хочу рассказать о создании собственных событий и собственных обработчиков этих событий в Symfony 6 с использованием EventDispatcher.
читать...Не могу не рассказать о создании собственного шаблона для полей формы с select, поскольку потратил на это пол дня. читать...
Symfony. Администраторский раздел Sonata Admin. А также об основных командах для работы с ORM в своём расширении (bundles). читать...
Мы напишем бандл под названием NewsTop, который будет выводить новости с обновлением данных через ajax. NewsTop – приложение для вывода новостей на сайте. читать...