Проектирование и разработка веб-приложения на основе технологий 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