Skip to content

Commit 97e055e

Browse files
committed
Code chapter 3
Signed-off-by: Howriq <[email protected]>
1 parent 8761a5f commit 97e055e

File tree

13 files changed

+295
-6
lines changed

13 files changed

+295
-6
lines changed

bin/doctrine-fixtures.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
declare(strict_types=1);
5+
6+
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
7+
use Doctrine\Common\DataFixtures\Loader;
8+
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
9+
use Doctrine\ORM\EntityManager;
10+
11+
require_once 'vendor/autoload.php';
12+
13+
$container = require 'config/container.php';
14+
15+
$entityManager = $container->get(EntityManager::class);
16+
$config = $container->get('config');
17+
18+
// Get fixtures directory from config
19+
$fixturesPath = $config['doctrine']['fixtures'];
20+
21+
if (! is_dir($fixturesPath)) {
22+
echo "Fixtures directory not found: {$fixturesPath}\n";
23+
exit(1);
24+
}
25+
26+
// Load fixtures
27+
$loader = new Loader();
28+
$loader->loadFromDirectory($fixturesPath);
29+
30+
// Execute fixtures
31+
$purger = new ORMPurger();
32+
$executor = new ORMExecutor($entityManager, $purger);
33+
34+
echo "Loading fixtures from: {$fixturesPath}\n";
35+
36+
$executor->execute($loader->getFixtures());
37+
38+
echo "Fixtures loaded successfully!\n";

composer.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,20 @@
2727
},
2828
"require": {
2929
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
30+
"doctrine/data-fixtures": "^2.2",
3031
"dotkernel/dot-cache": "^4.0",
31-
"ramsey/uuid": "^4.5.0",
32-
"ramsey/uuid-doctrine": "^2.1.0",
33-
"roave/psr-container-doctrine": "^5.2.2 || ^6.0.0",
3432
"dotkernel/dot-errorhandler": "^4.4.0",
3533
"laminas/laminas-component-installer": "^3.5.0",
3634
"laminas/laminas-config-aggregator": "^1.17.0",
3735
"mezzio/mezzio": "^3.24.0",
3836
"mezzio/mezzio-fastroute": "^3.13.0",
39-
"mezzio/mezzio-twigrenderer": "^2.17.0"
37+
"mezzio/mezzio-twigrenderer": "^2.17.0",
38+
"ramsey/uuid": "^4.5.0",
39+
"ramsey/uuid-doctrine": "^2.1.0",
40+
"roave/psr-container-doctrine": "^5.2.2 || ^6.0.0"
4041
},
4142
"require-dev": {
43+
"doctrine/doctrine-fixtures-bundle": "^4.3",
4244
"filp/whoops": "^2.17.0",
4345
"laminas/laminas-coding-standard": "^3.0.1",
4446
"laminas/laminas-development-mode": "^3.13.0",

config/autoload/local.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
'page' => [
4242
'about' => 'about',
4343
'who-we-are' => 'who-we-are',
44+
'books' => 'books',
4445
],
4546
],
4647
];

src/App/src/ConfigProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* class: class-string<MappingDriver>,
5757
* },
5858
* },
59+
* fixtures: non-empty-string,
5960
* migrations: array{
6061
* migrations_paths: array<non-empty-string, non-empty-string>,
6162
* all_or_nothing: bool,
@@ -165,6 +166,7 @@ private function getDoctrineConfig(): array
165166
'class' => MappingDriverChain::class,
166167
],
167168
],
169+
'fixtures' => getcwd() . '/src/App/src/Fixture',
168170
'migrations' => [
169171
'table_storage' => [
170172
'table_name' => 'doctrine_migration_versions',
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\App\Factory;
6+
7+
use Light\Book\Handler\GetBooksHandler;
8+
use Light\Book\Repository\BookRepository;
9+
use Mezzio\Template\TemplateRendererInterface;
10+
use Psr\Container\ContainerExceptionInterface;
11+
use Psr\Container\ContainerInterface;
12+
use Psr\Container\NotFoundExceptionInterface;
13+
14+
use function assert;
15+
16+
class BookHandlerFactory
17+
{
18+
/**
19+
* @throws ContainerExceptionInterface
20+
* @throws NotFoundExceptionInterface
21+
*/
22+
public function __invoke(ContainerInterface $container, string $requestedName): GetBooksHandler
23+
{
24+
$repository = $container->get(BookRepository::class);
25+
$template = $container->get(TemplateRendererInterface::class);
26+
27+
assert($repository instanceof BookRepository);
28+
assert($template instanceof TemplateRendererInterface);
29+
30+
return new GetBooksHandler($template, $repository);
31+
}
32+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\App\Factory;
6+
7+
use Doctrine\ORM\EntityManager;
8+
use Light\Book\Entity\Book;
9+
use Light\Book\Repository\BookRepository;
10+
use Psr\Container\ContainerExceptionInterface;
11+
use Psr\Container\ContainerInterface;
12+
use Psr\Container\NotFoundExceptionInterface;
13+
14+
use function assert;
15+
16+
class BookRepositoryFactory
17+
{
18+
/**
19+
* @throws ContainerExceptionInterface
20+
* @throws NotFoundExceptionInterface
21+
*/
22+
public function __invoke(ContainerInterface $container): BookRepository
23+
{
24+
$entityManager = $container->get(EntityManager::class);
25+
26+
$repository = $entityManager->getRepository(Book::class);
27+
assert($repository instanceof BookRepository);
28+
29+
return $repository;
30+
}
31+
}

src/App/src/Fixture/BookLoader.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\App\Fixture;
6+
7+
use Doctrine\Bundle\FixturesBundle\Fixture;
8+
use Doctrine\Persistence\ObjectManager;
9+
use Light\Book\Entity\Book;
10+
11+
class BookLoader extends Fixture
12+
{
13+
public function load(ObjectManager $manager): void
14+
{
15+
$book1 = new Book();
16+
$book1->setTitle('A Game of Thrones');
17+
$book1->setAuthor('George Martin');
18+
$manager->persist($book1);
19+
20+
$book2 = new Book();
21+
$book2->setTitle('The Lord of the Rings');
22+
$book2->setAuthor('J.R.R. Tolkien');
23+
$manager->persist($book2);
24+
25+
$book3 = new Book();
26+
$book3->setTitle('Dune');
27+
$book3->setAuthor('Frank Herbert');
28+
$manager->persist($book3);
29+
30+
$manager->flush();
31+
}
32+
}

src/App/templates/layout/default.html.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
<div class="dropdown-menu" aria-labelledby="pageDropdown">
4747
<a class="dropdown-item" href="{{ url('page::about') }}">About Us</a>
4848
<a class="dropdown-item" href="{{ url('page::who-we-are') }}">Who We Are</a>
49+
<a class="dropdown-item" href="{{ url('books::list') }}">Books</a>
4950
</div>
5051
</li>
5152
<li class="nav-item">

src/Book/src/ConfigProvider.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
88
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
9+
use Light\App\Factory\BookHandlerFactory;
10+
use Light\App\Factory\BookRepositoryFactory;
11+
use Light\Book\Handler\GetBooksHandler;
12+
use Light\Book\Repository\BookRepository;
13+
use Mezzio\Application;
914

1015
/**
1116
* @phpstan-type ConfigType array{
@@ -23,6 +28,10 @@
2328
* },
2429
* },
2530
* }
31+
* @phpstan-type DependenciesType array{
32+
* delegators: array<class-string, array<class-string>>,
33+
* factories: array<class-string, class-string>,
34+
* }
2635
*/
2736
class ConfigProvider
2837
{
@@ -32,7 +41,26 @@ class ConfigProvider
3241
public function __invoke(): array
3342
{
3443
return [
35-
'doctrine' => $this->getDoctrineConfig(),
44+
'dependencies' => $this->getDependencies(),
45+
'doctrine' => $this->getDoctrineConfig(),
46+
];
47+
}
48+
49+
/**
50+
* @return DependenciesType
51+
*/
52+
private function getDependencies(): array
53+
{
54+
return [
55+
'delegators' => [
56+
Application::class => [
57+
RoutesDelegator::class,
58+
],
59+
],
60+
'factories' => [
61+
GetBooksHandler::class => BookHandlerFactory::class,
62+
BookRepository::class => BookRepositoryFactory::class,
63+
],
3664
];
3765
}
3866

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Light\Book\Handler;
6+
7+
use Laminas\Diactoros\Response\HtmlResponse;
8+
use Light\Book\Repository\BookRepository;
9+
use Mezzio\Template\TemplateRendererInterface;
10+
use Psr\Http\Message\ResponseInterface;
11+
use Psr\Http\Message\ServerRequestInterface;
12+
use Psr\Http\Server\RequestHandlerInterface;
13+
14+
class GetBooksHandler implements RequestHandlerInterface
15+
{
16+
public function __construct(
17+
protected TemplateRendererInterface $template,
18+
protected BookRepository $bookRepository,
19+
) {
20+
}
21+
22+
public function handle(ServerRequestInterface $request): ResponseInterface
23+
{
24+
$titles = $this->bookRepository->getTitles();
25+
$authors = $this->bookRepository->getAuthors();
26+
27+
return new HtmlResponse(
28+
$this->template->render('page::books', [
29+
'titles' => $titles,
30+
'authors' => $authors,
31+
])
32+
);
33+
}
34+
}

0 commit comments

Comments
 (0)