Skip to content

Commit cc62378

Browse files
committed
Issue #110: update book tutorial
Signed-off-by: horea <horea@rospace.com>
1 parent b1789bd commit cc62378

2 files changed

Lines changed: 70 additions & 52 deletions

File tree

docs/book/v6/tutorials/create-book-module.md

Lines changed: 70 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ The below files structure is what we will have at the end of this tutorial and i
1515
│ │ └── Book.php
1616
│ ├── Handler/
1717
│ │ ├── GetBookCollectionHandler.php
18-
│ │ ├── GetBookHandler.php
19-
│ │ └── PostBookHandler.php
18+
│ │ ├── GetBookResourceHandler.php
19+
│ │ └── PostBookResourceHandler.php
2020
│ ├── InputFilter/
2121
│ │ ├── Input/
2222
│ │ │ ├── AuthorInput.php
@@ -40,17 +40,19 @@ The below files structure is what we will have at the end of this tutorial and i
4040

4141
```
4242

43-
* `src/Book/src/Collection/BookCollection.php` - a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database
44-
* `src/Core/src/Book/src/Entity/Book.php` - an entity refers to a PHP class that represents a persistent object or data structure
45-
* `src/Book/src/Handler/GetBookCollectionHandler.php` - handler that reflects the GET action for the BookCollection class
46-
* `src/Book/src/Handler/GetBookHandler.php` - handler that reflects the GET action for the Book entity
47-
* `src/Book/src/Handler/PostBookHandler.php` - handler that reflects the POST action for the Book entity
48-
* `src/Core/src/Book/src/Repository/BookRepository.php` - a repository is a class responsible for querying and retrieving entities from the database
49-
* `src/Book/src/Service/BookService.php` - is a class or component responsible for performing a specific task or providing functionality to other parts of the application
50-
* `src/Book/src/ConfigProvider.php` - is a class that provides configuration for various aspects of the framework or application
51-
* `src/Book/src/RoutesDelegator.php` - a routes delegator is a delegator factory responsible for configuring routing middleware based on routing configuration provided by the application
52-
* `src/Book/src/InputFilter/CreateBookInputFilter.php` - input filters and validators
53-
* `src/Book/src/InputFilter/Input/*` - input filters and validator configurations
43+
* `src/Book/src/Collection/BookCollection.php` – a collection refers to a container for a group of related objects, typically used to manage sets of related entities fetched from a database
44+
* `src/Book/src/ConfigProvider.php` – is a class that provides configuration for various aspects of the framework or application
45+
* `src/Book/src/Handler/GetBookCollectionHandler.php` – handler that reflects the GET action for the BookCollection class
46+
* `src/Book/src/Handler/GetBookResourceHandler.php` – handler that reflects the GET action for the Book entity
47+
* `src/Book/src/Handler/PostBookResourceHandler.php` – handler that reflects the POST action for the Book entity
48+
* `src/Book/src/InputFilter/CreateBookInputFilter.php` – input filters and validators
49+
* `src/Book/src/InputFilter/Input/*` – input filters and validator configurations
50+
* `src/Book/src/RoutesDelegator.php` – a routes delegator is a delegator factory responsible for configuring routing middleware based on routing configuration provided by the application
51+
* `src/Book/src/Service/BookService.php` – is a class or component responsible for performing a specific task or providing functionality to other parts of the application
52+
* `src/Core/src/Book/src/ConfigProvider.php` – is a class that provides configuration for Doctrine ORM
53+
* `src/Core/src/Book/src/Entity/Book.php` – an entity refers to a PHP class that represents a persistent object or data structure
54+
* `src/Core/src/Book/src/Repository/BookRepository.php` – a repository is a class responsible for querying and retrieving entities from the database
55+
5456

5557
## Creating and configuring the module
5658

@@ -70,8 +72,8 @@ declare(strict_types=1);
7072
namespace Api\Book;
7173

7274
use Api\Book\Handler\GetBookCollectionHandler;
73-
use Api\Book\Handler\GetBookHandler;
74-
use Api\Book\Handler\PostBookHandler;
75+
use Api\Book\Handler\GetBookResourceHandler;
76+
use Api\Book\Handler\PostBookResourceHandler;
7577
use Core\App\ConfigProvider;
7678
use Dot\Router\RouteCollectorInterface;
7779
use Mezzio\Application;
@@ -93,10 +95,10 @@ class RoutesDelegator
9395
$routeCollector = $container->get(RouteCollectorInterface::class);
9496

9597
$routeCollector->group('/book')
96-
->post('', PostBookHandler::class, 'book::create-book');
98+
->post('', PostBookResourceHandler::class, 'book::create-book');
9799

98100
$routeCollector->group('/book/' . $uuid)
99-
->get('', GetBookHandler::class, 'book::view-book');
101+
->get('', GetBookResourceHandler::class, 'book::view-book');
100102

101103
$routeCollector->group('/books')
102104
->get('', GetBookCollectionHandler::class, 'book::list-books');
@@ -119,8 +121,8 @@ use Api\App\ConfigProvider as AppConfigProvider;
119121
use Api\App\Factory\HandlerDelegatorFactory;
120122
use Api\Book\Collection\BookCollection;
121123
use Api\Book\Handler\GetBookCollectionHandler;
122-
use Api\Book\Handler\GetBookHandler;
123-
use Api\Book\Handler\PostBookHandler;
124+
use Api\Book\Handler\GetBookResourceHandler;
125+
use Api\Book\Handler\PostBookResourceHandler;
124126
use Api\Book\Service\BookService;
125127
use Api\Book\Service\BookServiceInterface;
126128
use Core\Book\Entity\Book;
@@ -143,13 +145,13 @@ class ConfigProvider
143145
return [
144146
'delegators' => [
145147
Application::class => [RoutesDelegator::class],
146-
PostBookHandler::class => [HandlerDelegatorFactory::class],
147-
GetBookHandler::class => [HandlerDelegatorFactory::class],
148+
PostBookResourceHandler::class => [HandlerDelegatorFactory::class],
149+
GetBookResourceHandler::class => [HandlerDelegatorFactory::class],
148150
GetBookCollectionHandler::class => [HandlerDelegatorFactory::class],
149151
],
150152
'factories' => [
151-
PostBookHandler::class => AttributedServiceFactory::class,
152-
GetBookHandler::class => AttributedServiceFactory::class,
153+
PostBookResourceHandler::class => AttributedServiceFactory::class,
154+
GetBookResourceHandler::class => AttributedServiceFactory::class,
153155
GetBookCollectionHandler::class => AttributedServiceFactory::class,
154156
BookService::class => AttributedServiceFactory::class,
155157
],
@@ -470,8 +472,6 @@ use Laminas\Filter\StripTags;
470472
use Laminas\InputFilter\Input;
471473
use Laminas\Validator\NotEmpty;
472474

473-
use function sprintf;
474-
475475
class AuthorInput extends Input
476476
{
477477
public function __construct(?string $name = null, bool $isRequired = true)
@@ -486,7 +486,7 @@ class AuthorInput extends Input
486486

487487
$this->getValidatorChain()
488488
->attachByName(NotEmpty::class, [
489-
'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD, 'author'),
489+
'message' => Message::VALIDATOR_REQUIRED_FIELD,
490490
], true);
491491
}
492492
}
@@ -507,8 +507,6 @@ use Laminas\Filter\StripTags;
507507
use Laminas\InputFilter\Input;
508508
use Laminas\Validator\NotEmpty;
509509

510-
use function sprintf;
511-
512510
class NameInput extends Input
513511
{
514512
public function __construct(?string $name = null, bool $isRequired = true)
@@ -523,7 +521,7 @@ class NameInput extends Input
523521

524522
$this->getValidatorChain()
525523
->attachByName(NotEmpty::class, [
526-
'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD, 'name'),
524+
'message' => Message::VALIDATOR_REQUIRED_FIELD,
527525
], true);
528526
}
529527
}
@@ -544,8 +542,6 @@ use Laminas\Filter\StripTags;
544542
use Laminas\InputFilter\Input;
545543
use Laminas\Validator\Date;
546544

547-
use function sprintf;
548-
549545
class ReleaseDateInput extends Input
550546
{
551547
public function __construct(?string $name = null, bool $isRequired = true)
@@ -560,7 +556,7 @@ class ReleaseDateInput extends Input
560556

561557
$this->getValidatorChain()
562558
->attachByName(Date::class, [
563-
'message' => sprintf(Message::INVALID_VALUE, 'releaseDate'),
559+
'message' => Message::INVALID_VALUE,
564560
], true);
565561
}
566562
}
@@ -593,7 +589,7 @@ class CreateBookInputFilter extends AbstractInputFilter
593589
}
594590
```
595591

596-
We split all the inputs just for the purpose of this tutorial and to demonstrate a clean `BookInputFiler` but you could have all the inputs created directly in the `CreateBookInputFilter` like this:
592+
We split all the inputs just for the purpose of this tutorial and to demonstrate a clean `CreateBookInputFilter` but you could have all the inputs created directly in the `CreateBookInputFilter` like this:
597593

598594
```php
599595
$nameInput = new Input();
@@ -605,10 +601,38 @@ $nameInput->getFilterChain()
605601

606602
$nameInput->getValidatorChain()
607603
->attachByName(NotEmpty::class, [
608-
'message' => sprintf(Message::VALIDATOR_REQUIRED_FIELD_BY_NAME, 'name'),
604+
'message' => Message::VALIDATOR_REQUIRED_FIELD,
609605
], true);
610606

611607
$this->add($nameInput);
608+
609+
$authorInput = new Input();
610+
$authorInput->setRequired(true);
611+
612+
$authorInput->getFilterChain()
613+
->attachByName(StringTrim::class)
614+
->attachByName(StripTags::class);
615+
616+
$authorInput->getValidatorChain()
617+
->attachByName(NotEmpty::class, [
618+
'message' => Message::VALIDATOR_REQUIRED_FIELD,
619+
], true);
620+
621+
$this->add($authorInput);
622+
623+
$releaseDateInput = new Input();
624+
$releaseDateInput->setRequired(true);
625+
626+
$releaseDateInput->getFilterChain()
627+
->attachByName(StringTrim::class)
628+
->attachByName(StripTags::class);
629+
630+
$releaseDateInput->getValidatorChain()
631+
->attachByName(NotEmpty::class, [
632+
'message' => Message::VALIDATOR_REQUIRED_FIELD,
633+
], true);
634+
635+
$this->add($releaseDateInput);
612636
```
613637

614638
Now it's time to create the handlers.
@@ -649,7 +673,7 @@ class GetBookCollectionHandler extends AbstractHandler
649673
}
650674
```
651675

652-
* `src/Book/src/Handler/GetBookHandler.php`
676+
* `src/Book/src/Handler/GetBookResourceHandler.php`
653677

654678
```php
655679
<?php
@@ -662,7 +686,7 @@ use Core\Book\Entity\Book;
662686
use Psr\Http\Message\ResponseInterface;
663687
use Psr\Http\Message\ServerRequestInterface;
664688

665-
class GetBookHandler extends AbstractHandler
689+
class GetBookResourceHandler extends AbstractHandler
666690
{
667691
#[Resource(entity: Book::class)]
668692
public function handle(ServerRequestInterface $request): ResponseInterface
@@ -675,7 +699,7 @@ class GetBookHandler extends AbstractHandler
675699
}
676700
```
677701

678-
* `src/Book/src/Handler/PostBookHandler.php`
702+
* `src/Book/src/Handler/PostBookResourceHandler.php`
679703

680704
```php
681705
<?php
@@ -694,7 +718,7 @@ use Psr\Http\Message\ResponseInterface;
694718
use Psr\Http\Message\ServerRequestInterface;
695719
use Psr\Http\Server\RequestHandlerInterface;
696720

697-
class PostBookHandler extends AbstractHandler implements RequestHandlerInterface
721+
class PostBookResourceHandler extends AbstractHandler implements RequestHandlerInterface
698722
{
699723
#[Inject(
700724
CreateBookInputFilter::class,
@@ -736,8 +760,8 @@ declare(strict_types=1);
736760
namespace Api\Book;
737761

738762
use Api\Book\Handler\GetBookCollectionHandler;
739-
use Api\Book\Handler\GetBookHandler;
740-
use Api\Book\Handler\PostBookHandler;
763+
use Api\Book\Handler\GetBookResourceHandler;
764+
use Api\Book\Handler\PostBookResourceHandler;
741765
use Core\App\ConfigProvider;
742766
use Dot\Router\RouteCollectorInterface;
743767
use Mezzio\Application;
@@ -758,22 +782,17 @@ class RoutesDelegator
758782
/** @var RouteCollectorInterface $routeCollector */
759783
$routeCollector = $container->get(RouteCollectorInterface::class);
760784

761-
$routeCollector->group('/book')
762-
->post('', PostBookHandler::class, 'book::create-book');
763-
764-
$routeCollector->group('/book/' . $uuid)
765-
->get('', GetBookHandler::class, 'book::view-book');
766-
767-
$routeCollector->group('/books')
768-
->get('', GetBookCollectionHandler::class, 'book::list-books');
785+
$routeCollector->post('/book', PostBookHandler::class, 'book::create-book');
786+
$routeCollector->get('/book/' . $uuid, GetBookHandler::class, 'book::view-book');
787+
$routeCollector->get('/books', GetBookCollectionHandler::class, 'book::list-books');
769788

770789
return $callback();
771790
}
772791
}
773792
```
774793

775794
We need to configure access to the newly created endpoints, add `books::list-books`, `book::view-book` and `book::create-book` to the authorization rbac array, under the `UserRole::ROLE_GUEST` key.
776-
> Make sure you read and understand the rbac documentation.
795+
> Make sure you read and understand the rbac [documentation](https://docs.dotkernel.org/dot-rbac-guard/v4/configuration/).
777796
778797
## Migrations
779798

@@ -788,15 +807,15 @@ php bin/doctrine orm:validate-schema
788807
Doctrine can handle the table creation, run the following command:
789808

790809
```shell
791-
vendor/bin/doctrine-migrations diff --filter-expression='/^(?!oauth_)/'
810+
php ./vendor/bin/doctrine-migrations diff
792811
```
793812

794813
This will check for differences between your entities and database structure and create migration files if necessary, in `data/doctrine/migrations`.
795814

796815
To execute the migrations run:
797816

798817
```shell
799-
vendor/bin/doctrine-migrations migrate
818+
php ./vendor/bin/doctrine-migrations
800819
```
801820

802821
## Checking endpoints

mkdocs.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ nav:
4343
- "Route Grouping": v6/extended-features/route-grouping.md
4444
- "Problem Details": v6/extended-features/problem-details.md
4545
- "Injectable Input Filters": v6/extended-features/injectable-input-filters.md
46-
- "Email sending and content parsing": v6/extended-features/email.md
4746
- Commands:
4847
- "Create admin account": v6/commands/create-admin-account.md
4948
- "Generate database migrations": v6/commands/generate-database-migrations.md

0 commit comments

Comments
 (0)