Проектирование и разработка веб-приложения на основе технологий Symfony Framework

Обзор типовых решений в области веб-разработки. Назначение и установка Symfony Framework. Настройка develop-сервера и установка Symfony. Установка дополнительных библиотек через composer. Определение маршрутов и контроллеров. Генерация сущностей и форм.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 30.07.2017
Размер файла 897,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

{

$this->genres->add($genre);

return $this;

}

public function removeGenre(Genre $genre)

{

$this->genres->removeElement($genre);

return $this;

}

public function getGenres()

{

return $this->genres;

}

public function setGenres(ArrayCollection $genres)

{

$this->genres = $genres;

}

public function addScreenshot(Image $screenshot)

{

$this->screenshots->add($screenshot);

return $this;

}

public function removeScreenshot(Image $screenshot)

{

$this->screenshots->removeElement($screenshot);

return $this;

}

public function getScreenshots()

{

return $this->screenshots;

}

public function setScreenshots(ArrayCollection $screenshots)

{

$this->screenshots = $screenshots;

}

public function getDeveloper()

{

return $this->developer;

}

public function setDeveloper(Developer $developer)

{

$this->developer = $developer;

return $this;

}

public function getPublisher()

{

return $this->publisher;

}

public function setPublisher(Publisher $publisher)

{

$this->publisher = $publisher;

return $this;

}

public function getKeys()

{

$unPayedKeys = new ArrayCollection();

foreach ($this->keys as $key) {

if ($key->getStatus() == 0) {

$unPayedKeys->add($key);

}

}

return $unPayedKeys;

}

public function addKey(Key $key)

{

$this->keys->add($key);

$key->setGame($this);

return $this;

}

public function removeKey(Key $key)

{

$this->keys->removeElement($key);

return $this;

}

public function getReviews()

{

return $this->reviews;

}

public function addReview(Review $review)

{

$this->reviews->add($review);

$review->setGame($this);

$rate = $review->getRate();

$count = 1;

foreach ($this->getReviews() as $newReview) {

$rate += $newReview->getRate();

++$count;

}

$rate = round($rate / $count, 1);

$this->setRate($rate);

return $this;

}

public function removeReview(Review $review)

{

$this->reviews->removeElement($review);

return $this;

}

public function getRate()

{

return $this->rate;

}

public function setRate(float $rate)

{

$this->rate = $rate;

return $this;

}

public function getIntRate()

{

return (int) $this->getRate();

}

public function setMultiplayer(bool $multiplayer)

{

$this->multiplayer = $multiplayer;

return $this;

}

public function getMultiplayer()

{

return $this->multiplayer;

}

public function getDiscount()

{

return $this->discount;

}

public function setDiscount($discount)

{

$this->discount = $discount;

return $this;

}

public function removeDiscount()

{

$this->discount = null;

return $this;

}

public function getDiscountPrice()

{

if ($this->getDiscount()) {

$discountPrice = $this->getPrice() - $this->discount->getValue() * $this->getPrice() / 100;

} else {

$discountPrice = $this->getPrice();

}

return (int) $discountPrice;

}

public function getIsDiscount()

{

return $this->getDiscountPrice() != $this->getPrice();

}

public function getBasketProducts()

{

return $this->basketProducts;

}

public function getBuyCount()

{

return $this->buyCount;

}

public function setBuyCount($buyCount)

{

$this->buyCount = $buyCount;

return $this;

}

public function getLastBuy()

{

return $this->lastBuy;

}

public function setLastBuy(\DateTime $lastBuy)

{

$this->lastBuy = $lastBuy;

return $this;

}

public function getIsReleased()

{

return $this->isReleased;

}

public function setIsReleased(bool $isReleased)

{

$this->isReleased = $isReleased;

return $this;

}

public function getIsFavorite(User $user = null)

{

if ($user == null) {

return false;

}

$favorites = $user->getFavoriteGames();

foreach ($favorites as $favorite) {

if ($favorite->getId() == $this->getId()) {

return true;

}

}

return false;

}

public function getReviewCount()

{

return $this->reviews->count();

}

public function getIsRus()

{

return $this->isRus;

}

public function setIsRus(bool $isRus)

{

$this->isRus = $isRus;

return $this;

}

public function getKeysCount()

{

return $this->getKeys()->count();

}

}

Листинг 21. Класс сущности Game

Приложение C. Репозиторий GameRepository сущности Game

<?

namespace Difuks\DazzleBundle\Repository;

use Doctrine\ORM\EntityRepository;

use Doctrine\ORM\Query\Expr\Join;

class GameRepository extends EntityRepository

{

public function count(): int

{

$db = $this->createQueryBuilder('t');

return $db

->select('count(t.id)')

->getQuery()

->getSingleScalarResult();

}

public function maxPrice()

{

$db = $this->createQueryBuilder('t');

return $db

->select('MAX(t.price)')

->getQuery()

->getSingleScalarResult();

}

public function minPrice()

{

$minPrice = $this->getEntityManager()

->createQuery(

'SELECT

round(MIN(CASE WHEN g.discount IS NULL THEN g.price ELSE (g.price - g.price * d.value / 100) END),1)

FROM DifuksDazzleBundle:Game g

LEFT JOIN DifuksDazzleBundle:Discount d

WHERE g.discount = d'

)

->getSingleScalarResult();

return $minPrice;

}

public function maxAgeRest()

{

$db = $this->createQueryBuilder('t');

return $db

->select('MAX(t.ageRestrictions)')

->getQuery()

->getSingleScalarResult();

}

public function minAgeRest()

{

$db = $this->createQueryBuilder('t');

return $db

->select('MIN(t.ageRestrictions)')

->getQuery()

->getSingleScalarResult();

}

public function findByFilter(array $filter = [], array $sort = [], int $page = 1, $count = 9)

{

$query = $this->createQueryBuilder('g');

$actualPrice = 'CASE WHEN g.discount IS NULL THEN g.price ELSE (g.price - g.price * d.value / 100) END';

$query->select("g, $actualPrice AS HIDDEN price");

$query

->leftJoin('DifuksDazzleBundle:Discount', 'd', Join::WITH, 'g.discount = d');

if (isset($filter['price']['min'])) {

$minPrice = $filter['price']['min'];

$query->andWhere("$actualPrice >= $minPrice");

}

if (isset($filter['price']['max'])) {

$maxPrice = $filter['price']['max'];

$query->andWhere("$actualPrice <= $maxPrice");

}

if (isset($filter['age']['min'])) {

$ageMin = $filter['age']['min'];

$query->andWhere("g.ageRestrictions >= $ageMin");

}

if (isset($filter['age']['max'])) {

$ageMax = $filter['age']['max'];

$query->andWhere("g.ageRestrictions <= $ageMax");

}

if (isset($filter['rate']['min'])) {

$rateMin = $filter['rate']['min'];

$query->andWhere("g.rate >= $rateMin");

}

if (isset($filter['rate']['max'])) {

$rateMax = $filter['rate']['max'];

$query->andWhere("g.rate <= $rateMax");

}

if (isset($filter['isReleased'])) {

$query->andWhere('g.isReleased = TRUE');

}

if (isset($filter['isDiscount'])) {

$query->andWhere('g.discount IS NOT NULL');

}

if (isset($filter['genre'])) {

$query->andWhere(':genres MEMBER OF g.genres');

$query->setParameter('genres', $filter['genre']);

}

$order = $sort['order'];

$by = $sort['by'];

if ($order == 'price') {

$query->addOrderBy('price', $by);

} else {

$query->addOrderBy("g.$order", $by);

}

$games = $query->getQuery()->setMaxResults($count * $page)->setFirstResult(($page - 1) * $count)->getResult();

$totalCount = count($query->select('g.id')->orderBy('g.id')->getQuery()->getResult());

return [

'elements' => $games,

'page' => [

'count' => ceil($totalCount / $count),

'current' => $page,

],

];

}

public function getDisocuntGames()

{

$db = $this->createQueryBuilder('g');

$db->where('g.discount IS NOT NULL')->setFirstResult(0)->setMaxResults(10);

return $db->getQuery()->getResult();

}

}

Листинг 22. Репозиторий GameRepository сущности Game

Приложение D. Класс генерации формы на основе сущности

<?

namespace Difuks\DazzleBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Component\Validator\Constraints as Assert;

/**

* Feedback.

*

* @ORM\Table(name="feedback")

* @ORM\Entity()

*/

class Feedback

{

/**

* @var int

*

* @ORM\Column(name="id", type="integer")

* @ORM\Id

* @ORM\GeneratedValue(strategy="AUTO")

*/

private $id;

/**

* @var string

*

* @Assert\NotBlank()

* @ORM\Column(name="name", type="string", length=255, nullable=false)

*/

private $name;

/**

* @var string

*

* @Assert\NotBlank()

* @Assert\Email()

* @ORM\Column(name="email", type="string", length=255, nullable=false)

*/

private $email;

/**

* @var string

*

* @Assert\NotBlank()

* @ORM\Column(name="text", type="text", length=255, nullable=false)

*/

private $text;

/**

* @var \DateTime

*

* @ORM\Column(name="date", type="datetime")

*/

private $date;

public function __construct()

{

$this->date = new \DateTime();

}

public function getId()

{

return $this->id;

}

public function getName()

{

return $this->name;

}

public function setName(string $name)

{

$this->name = $name;

}

public function getEmail()

{

return $this->email;

}

public function setEmail(string $email)

{

$this->email = $email;

}

public function getText()

{

return $this->text;

}

public function setText(string $text)

{

$this->text = $text;

}

public function getDate()

{

return $this->date;

}

public function setDate(\DateTime $date)

{

$this->date = $date;

}

}

Листинг 22. Сущность Feedback

<?

namespace Difuks\DazzleBundle\Form;

use Difuks\DazzleBundle\Entity\Feedback;

use Symfony\Component\Form\AbstractType;

use Symfony\Component\Form\Extension\Core\Type\EmailType;

use Symfony\Component\Form\Extension\Core\Type\TextType;

use Symfony\Component\Form\Extension\Core\Type\TextareaType;

use Symfony\Component\Form\FormBuilderInterface;

use Symfony\Component\OptionsResolver\OptionsResolver;

class FeedbackType extends AbstractType

{

public function buildForm(FormBuilderInterface $builder, array $options)

{

$builder

->add('name', TextType::class, [

'label' => 'Имя',

'required' => false,

'mapped' => true,

])

->add('email', EmailType::class, [

'label' => 'Email',

'required' => false,

])

->add('text', TextareaType::class, [

'label' => 'Текст обращения',

'required' => false,

])

;

}

public function configureOptions(OptionsResolver $resolver)

{

$resolver->setDefaults([

'data_class' => Feedback::class,

]);

}

}

Листинг 23. Класс генерации формы обратной связи

Приложение E. Маршруты и контроллер публичной части сайта

index:

path: /

defaults: { _controller: DifuksDazzleBundle:Public:index }

genres:

path: /genres/

defaults: { _controller: DifuksDazzleBundle:Public:genres }

catalog_all:

path: /catalog/

defaults: { _controller: DifuksDazzleBundle:Public:catalog }

catalog:

path: /catalog/{code}

defaults: { _controller: DifuksDazzleBundle:Public:catalog }

product:

path: /product/{code}

defaults: { _controller: DifuksDazzleBundle:Public:product, code: default }

basket:

path: /basket/

defaults: { _controller: DifuksDazzleBundle:Public:basket }

feedback:

path: /feedback/

defaults: { _controller: DifuksDazzleBundle:Public:feedback }

unsubscribe:

path: /unsubscribe/{hash}

defaults: { _controller: DifuksDazzleBundle:Public:unsubscribe }

Листинг 24. Конфигурация маршрутов публичной части

<?

declare(strict_types=1);

namespace Difuks\DazzleBundle\Controller;

use Difuks\DazzleBundle\Entity\Feedback;

use Difuks\DazzleBundle\Entity\Game;

use Difuks\DazzleBundle\Entity\Genre;

use Difuks\DazzleBundle\Entity\Subscribes;

use Difuks\DazzleBundle\Form\FeedbackType;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use Symfony\Component\HttpFoundation\Response;

class PublicController extends Controller

{

public function indexAction(): Response

{

return $this->render('DifuksDazzleBundle:Public:index.html.twig');

}

public function genresAction(): Response

{

$genres = $this->getDoctrine()->getRepository(Genre::class)->findBy([], ['id' => 'ASC']);

$totalCount = $this->getDoctrine()->getRepository(Game::class)->count();

return $this->render('DifuksDazzleBundle:Public:genres.html.twig', ['genres' => $genres, 'totalCount' => $totalCount]);

}

public function catalogAction(Genre $genre = null): Response

{

return $this->render('DifuksDazzleBundle:Public:catalog.html.twig', ['genre' => $genre]);

}

public function productAction(Game $game): Response

{

return $this->render('DifuksDazzleBundle:Public:product.html.twig', ['game' => $game]);

}

public function basketAction(): Response

{

return $this->render('@DifuksDazzle/Public/basket.html.twig');

}

public function feedbackAction(): Response

{

$form = $this->createForm(FeedbackType::class);

return $this->render('@DifuksDazzle/Public/feedback.html.twig', ['form' => $form->createView()]);

}

public function unsubscribeAction(Subscribes $subscribe): Response

{

$this->get('difuks.dazzle.social_service')->unSubscribe($subscribe);

return $this->render('@DifuksDazzle/Public/unsubscribe.html.twig');

}

}

Листинг 25. Контроллер публичной части сайта

Приложение F. Сервис для работы с корзиной и заказами. Настройка сервисов

<?

namespace Difuks\DazzleBundle\Services;

use Difuks\DazzleBundle\Entity\Basket;

use Difuks\DazzleBundle\Entity\BasketProduct;

use Difuks\DazzleBundle\Entity\Game;

use Doctrine\ORM\EntityManager;

use Symfony\Component\DependencyInjection\Container;

class OrderService

{

protected $container;

protected $pass;

protected $pass2;

protected $login;

protected $em;

protected $mailer;

public function __construct(Container $container, EntityManager $em, \Swift_Mailer $mailer)

{

$this->container = $container;

$this->mailer = $mailer;

$this->em = $em;

$this->login = $container->getParameter('robokassa.login');

$this->pass = $container->getParameter('robokassa.password');

$this->pass2 = $container->getParameter('robokassa.password2');

}

/**

* Получает url для перевода в систему оплаты.

*

* @param int $id id заказа

* @param float $sum сумма заказа

*

* @return string url

*/

public function getUrl(int $id, float $sum): string

{

$descr = 'Оформление заказа №'.$id;

$crc = md5("$this->login:$sum:$id:$this->pass");

$url = "https://auth.robokassa.ru/Merchant/Index.aspx?MrchLogin=$this->login&".

"OutSum=$sum&InvId=$id&Description=$descr&SignatureValue=$crc&IsTest=1";

return $url;

}

/**

* Обрабатывает результат запроса от службы оплаты.

*

* @param int $id id заказа

* @param float $sum сумма заказа

* @param string $crc хэш

*

* @throws \Exception в случае несовпадения хэша

*/

public function setResult(int $id, float $sum, string $crc): void

{

$crc = strtoupper($crc);

$myCrc = strtoupper(md5("$sum:$id:$this->pass2"));

if ($myCrc != $crc) {

throw new \Exception('Неверные данные оплаты. Хеш '.$myCrc.' и '.$crc.' не совпадают');

}

$basket = $this->em->getRepository(Basket::class)->find($id);

$fromEmail = $this->container->getParameter('mailer_user');

if ($basket->getPaymentState() != 2) {

$this->sendEmailAboutPay($basket, $fromEmail);

$this->refreshGamesRate($basket);

$basket->setPaymentState(2);

$this->em->persist($basket);

$this->em->flush();

}

}

/**

* Отправляет email об успешной оплате.

*

* @param Basket $basket

* @param string $email

*/

protected function sendEmailAboutPay(Basket $basket, string $email): void

{

$body = [];

$keys = $basket->getKeys();

/*

* @var Key

*/

foreach ($keys as $key) {

$body[$key->getGame()->getName()][] = $key->getKey();

}

$message = \Swift_Message::newInstance()

->setSubject('Покупка игр')

->setFrom($email)

->setTo($basket->getUser()->getEmail())

->setBody($this->container->get('templating')->render(

'@DifuksDazzle/Email/keys.send.html.twig',

['body' => $body]

),

'text/html');

$this->mailer->send($message);

}

/**

* Обновляет количество покупок игры, а так же дату последней покупки.

*

* @param Basket $basket

*/

protected function refreshGamesRate(Basket $basket): void

{

$products = $basket->getProducts();

foreach ($products as $product) {

$game = $product->getGame();

$currentCount = ($game->getBuyCount()) ?: 0;

$game->setBuyCount($currentCount + $product->getQuantity());

$game->setLastBuy(new \DateTime());

$this->em->persist($game);

$this->em->flush();

}

}

/**

* Обрабатывает запрос на странице завершения оплаты.

*

* @param int $id id заказа

* @param float $sum сумма заказа

* @param string $crc хэш

*

* @throws \Exception в случае несовпадения хэша

*

* @return string текст с результатом

*/

public function getDone(int $id, float $sum, string $crc): string

{

$crc = strtoupper($crc);

$myCrc = strtoupper(md5("$sum:$id:$this->pass"));

if ($myCrc != $crc) {

throw new \Exception('Неверные данные оплаты. Хеш '.$myCrc.' и '.$crc.' не совпадают');

}

$basket = $this->em->getRepository(Basket::class)->find($id);

if (isset($basket)) {

if ($basket->getPaymentState() != 2) {

$basket->setPaymentState(1);

$this->em->persist($basket);

$this->em->flush();

}

return 'Операция прошла успешно. После проведения оплаты ключи отправят вам на email. Спасибо за покупку!';

} else {

return 'Нет заказа с таким номером';

}

}

/**

* Получает текущую корзину пользователя.

*

* @return Basket

*/

public function getCurrentBasket(): Basket

{

$user = $this->container->get('security.token_storage')->getToken()->getUser();

$basket = $this->em->getRepository(Basket::class)->getCurrentBasketByUser($user);

return $basket;

}

/**

* Добавляет необходимое количество игр в корзину. Возвращает оставшееся количество ключей.

*

* @param Basket $basket

* @param Game $game

* @param int $quantity

*

* @return int

*/

public function addToBasket(Basket $basket, Game $game, int $quantity): int

{

$basket->addGame($game, $quantity);

$this->em->persist($basket);

$this->em->flush();

return $game->getKeysCount();

}

/**

* Изменят количество находящейся в корзине игр

*

* @param BasketProduct $basketProduct

* @param int $quantity

*/

public function changeBasketProductCount(BasketProduct $basketProduct, int $quantity): void

{

$basketProduct->getBasket()->changeGameCount($basketProduct->getGame(), $quantity);

$this->em->persist($basketProduct);

$this->em->flush();

}

/**

* Удаляет игру из корзины.

*

* @param BasketProduct $basketProduct

*/

public function deleteBasketProduct(BasketProduct $basketProduct): void

{

$basket = $basketProduct->getBasket();

$basket->removeProduct($basketProduct);

if ($basket->getProductCount() == 0) {

$this->em->remove($basket);

} else {

$this->em->persist($basket);

}

$this->em->flush();

}

/**

* Удаляет старые корзины.

*

* @param int $notPayDay количество дней для удаления корзин в статусе неоплачено

* @param int $payDay количество дней для удаления корзин в статусе ожидания оплаты

*

* @return int число удалённых корзин

*/

public function clearOldBasket(int $notPayDay, int $payDay): int

{

$oldBaskets = $this->em

->getRepository(Basket::class)

->getOldBaskets(

$notPayDay,

$payDay

);

$count = count($oldBaskets);

foreach ($oldBaskets as $basket) {

$this->em->remove($basket);

}

$this->em->flush();

return $count;

}

}

Листинг 26. Сервис для работы с корзиной и заказами

services:

difuks.dazzle.file.twig.extension:

class: Difuks\DazzleBundle\Extension\Twig\FileExtension

arguments: ['@service_container']

tags:

- { name: twig.extension }

difuks.dazzle.flush_handler:

class: Difuks\DazzleBundle\EventHandler\FlushHandler

arguments: ['@swiftmailer.mailer.cron', '@service_container']

tags:

- { name: doctrine.event_listener, event: onFlush }

difuks.dazzle.authentication_handler:

class: Difuks\DazzleBundle\EventHandler\AuthenticationHandler

arguments: ['@router', '@security.authorization_checker']

difuks.dazzle.order_service:

class: Difuks\DazzleBundle\Services\OrderService

arguments: ['@service_container', '@doctrine.orm.entity_manager', '@swiftmailer.mailer.moment']

difuks.dazzle.social_service:

class: Difuks\DazzleBundle\Services\SocialService

arguments: ['@service_container', '@doctrine.orm.entity_manager']

difuks.dazzle.form.registration:

class: Difuks\DazzleBundle\Form\RegistrationType

tags:

- { name: form.type, alias: difuks_dazzle_user_registration }

difuks.dazzle.form.profile:

class: Difuks\DazzleBundle\Form\ProfileType

tags:

- { name: form.type, alias: difuks_dazzle_user_profile }

Листинг 27. Файл настройки собственных сервисов

Приложение F. Класс консольной команды очистки заброшенных корзин

<?

declare(strict_types=1);

namespace Difuks\DazzleBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

use Symfony\Component\Console\Input\InputInterface;

use Symfony\Component\Console\Input\InputOption;

use Symfony\Component\Console\Output\OutputInterface;

class ClearOldBasketCommand extends ContainerAwareCommand

{

protected function configure()

{

$this->addOption('not-pay-day', null, InputOption::VALUE_REQUIRED, 'Количество дней для удаление корзин со статусом 0', 1);

$this->addOption('pay-day', null, InputOption::VALUE_REQUIRED, 'Количество дней для удаление корзин со статусом 1', 3);

$this

->setName('difuks:dazzle:basket:clear-old')

->setDescription('Очищает старые корзины')

->setHelp('Очищает корзины со статусом 0 (старее одного дня) и 1 (старее трёх дней)');

}

protected function execute(InputInterface $input, OutputInterface $output)

{

$notPayDay = (int) $input->getOption('not-pay-day');

$payDay = (int) $input->getOption('pay-day');

$count = $this->getContainer()->get('difuks.dazzle.order_service')->clearOldBasket($notPayDay, $payDay);

$output->writeln((new \DateTime())->format('d.m.Y H:i:s')." Remove $count baskets");

}

}

Листинг 28. Класс консольной команды очистки заброшенных корзин

Приложение G. Функциональный тест виджета добавления в корзину и конфигурация PHPUnit

<?

namespace Difuks\DazzleBundle\Tests\Functional\Controller;

use Difuks\DazzleBundle\Tests\Functional\BaseControllerTest;

class WidgetControllerTest extends BaseControllerTest

{

public function testProductSliderWidget()

{

$crawler = $this->client->request('GET', '/');

$gameButtons = $crawler->filter('button:contains("В корзину")');

$this->assertTrue($gameButtons->count() > 0, 'Ни одной доступной для покупки игры');

if ($gameButtons->count()) {

$this->checkUrl('/ajax/add-to-basket/'.$gameButtons->first()->attr('data-id'));

$answer = json_decode($this->client->getResponse()->getContent(), true);

$this->assertTrue(isset($answer['error']) && $answer['error'] == true, 'Добавление в корзину доступно неавторизованному пользователю');

$this->logIn();

$this->checkUrl('/ajax/add-to-basket/'.$gameButtons->first()->attr('data-id'));

$this->logout();

}

}

}

Листинг 29. Функциональный тест виджета добавления в корзину

<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"

backupGlobals="false"

colors="true"

bootstrap="app/autoload.php"

>

<php>

<ini name="error_reporting" value="-1" />

<server name="KERNEL_DIR" value="app/" />

</php>

<testsuites>

<testsuite name="Project Test Suite">

<directory>src/Difuks/DazzleBundle/Tests/</directory>

</testsuite>

</testsuites>

<filter>

<whitelist>

<directory>src</directory>

<exclude>

<directory>src/*Bundle/Resources</directory>

<directory>src/*/*Bundle/Resources</directory>

<directory>src/*/Bundle/*Bundle/Resources</directory>

</exclude>

</whitelist>

</filter>

</phpunit>

Листинг 30. Конфигурационный файл PHPUnit

Размещено на Allbest.ru


Подобные документы

  • История развития веб-технологий и существующие проблемы. Назначение и установка Symfony Framework. Создание приложения на основе технологий Symfony Framework. Установка дополнительных библиотек через composer, верстка шаблона, настройка сервисов.

    дипломная работа [712,6 K], добавлен 05.07.2017

  • Обзор существующих технологий разработки программного обеспечения. Описание платформы NET Framework. Принцип работы платформы: компиляция исходного кода; процесс загрузки и исполнения кода; IL-код и верификация. Новые возможности платформы NET Framework.

    реферат [30,7 K], добавлен 01.03.2011

  • Анализ существующих решений для построения сети. Настройка и установка дополнительных программ. Сравнение платформ программного маршрутизатора. Установка DHCP и DNS серверов. Выбор монтажного оборудования. Создание и настройка Active Directory.

    дипломная работа [4,8 M], добавлен 24.03.2015

  • Установка VirtualBox. Создание двух виртуальных машин с операционной системой CentOS. Настройка сетевых интерфейсов в режиме bridgeс и хоста как маршрутизатора для сети. Установка www-сервера. Настройка динамической маршрутизации по протоколу RIP.

    курсовая работа [807,5 K], добавлен 14.07.2012

  • Настройка и установка изолированной среды разработки для создания области, базы данных, ресурсов и ролей удалённого доступа к системам Cachе. Установка операционной системы и обязательных компонентов. Переключение пользователя на новую область при старте.

    презентация [783,5 K], добавлен 05.01.2014

  • Многопоточный веб-сервер с входным и обрабатывающими модулями. HTTP—протокол передачи гипертекста. Установка и настройка локального веб-сервера "OpenServer". Установка phpMyAdmin, конфигурация PHP. Настройка веб-сервера и виртуальных хостов, модулей.

    курсовая работа [3,2 M], добавлен 08.12.2013

  • Установка и настройка локального web–сервера и его компонентов. Конфигурационные файлы сервера Apache и их натройка. Настройка PHP, MySQL и Sendmail. Проверка работоспособности виртуальных серверов. Создание виртуальных хостов. Тест Server Side Includes.

    учебное пособие [6,2 M], добавлен 27.04.2009

  • Быстрая загрузка, простая установка и автоматическое обновление чата. Поддержка форматирования текста. Аутентификация и различные пиктограммы пользователей. Установка и настройка чата под Linux. Подготовка к инсталяции чата. Безопасность на хостинге.

    лекция [3,4 M], добавлен 27.04.2009

  • Создание, изучение и разработка приложение на Android. Среда разработки приложения DelphiXE5. Установка и настройка среды программирования. Этапы разработки приложения. Инструменты для упрощения конструирования графического интерфейса пользователя.

    курсовая работа [1,6 M], добавлен 19.04.2017

  • Методическое обеспечение теоретических занятий по теме "Установка и настройка Windows XP на рабочей станции". Настройка системы безопасности Windows XP. Методическое обеспечение лабораторных занятий по данной теме. Порядок устранения возможных проблем.

    методичка [55,7 K], добавлен 07.02.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.