|
1 | 1 | # Proposed solution |
2 | 2 |
|
3 | | -Solution is inspired by Symfony's way of loading templates into a controller |
4 | | -and rendering response. |
| 3 | +Solution is inspired by Symfony's way of loading templates into a controller and rendering response. |
5 | 4 |
|
6 | | -Symfony proposes convention where template code is separated (as per MVC) |
7 | | -from application logic and held in `templates` (or `Resources/views`) directory. |
8 | | -Required rendering logic can be coded in templates by using very powerful templating |
9 | | -language Twig. Rendering of templates is executed via dedicated service, |
10 | | -while templates are identified via path or bundle resource locator syntax |
11 | | -(e.g. `@BundleName::template.html.twig`). |
| 5 | +Symfony proposes convention where template code is separated (as per MVC) from application logic and held in |
| 6 | +`templates` (or `Resources/views`) directory. Required rendering logic can be coded in templates by using very powerful |
| 7 | +templating language Twig. Rendering of templates is executed via dedicated service, while templates are identified via |
| 8 | +path or bundle resource locator syntax(e.g. `@BundleName::template.html.twig`). |
12 | 9 |
|
13 | | -Inspired with that convention, this bundle proposes similar approach (if |
14 | | -not the same approach): |
| 10 | +Inspired with that convention, this bundle proposes similar approach: |
15 | 11 |
|
16 | | -- Your queries are held in separate files in your bundles, in `query` or |
17 | | -`Resources/query` directories (or any other per your desire). |
| 12 | +- Your queries are held in separate files in `query` directory of your application (or `Resources/query` directories for |
| 13 | + bundles, or any other per your desire). |
18 | 14 | - Queries are files where only query code should exist. |
19 | | -- Complex queries with some kind of query building logic can use Twig as |
20 | | -pre-processing script language. |
21 | | -- You can use a dedicated service `runopencode.query_loader` to load query from |
22 | | -its location by using service locator (which is bad practice) or inject the instance |
23 | | -of `RunOpenCode\Bundle\QueryResourcesLoader\Contract\ManagerInterface` into your class |
24 | | -and let dependency injection do its magic (recommended). |
| 15 | +- Complex queries with some kind of query building logic can use Twig as pre-processing script language. |
| 16 | +- You can use a dedicated service `RunOpenCode\Bundle\QueryResourcesLoader\Contract\QueryResourcesLoaderInterface` to |
| 17 | + load query from its location and execute it. |
25 | 18 |
|
26 | 19 | ## Example |
27 | 20 |
|
28 | | -In image below, a real-world example of directory structure of project |
29 | | -reporting bundle which uses this bundle is presented: |
| 21 | +In image below, a real-world example of directory structure of project reporting bundle which uses this bundle is |
| 22 | +presented: |
30 | 23 |
|
31 | 24 |  |
32 | 25 |
|
33 | | -In that matter, in order to execute the query stored within one of those files, |
34 | | -following code can be used for data source/repository class: |
| 26 | +**NOTE**: _This image is from project using Symfony 3, that is how old this bundle is, but it is still actively |
| 27 | +maintained, battle tested and used in production for latest Symfony version._ |
35 | 28 |
|
36 | | - // file: ReportingBundle/Repository/ReportingDataSource.php |
37 | | - |
38 | | - namespace MyApp\ReportingBundle\Repository; |
39 | | - |
40 | | - use RunOpenCode\Bundle\QueryResourcesLoader\Contract\ManagerInterface; |
41 | | - |
42 | | - final class ReportingDataSource |
| 29 | +In that matter, in order to execute the query stored within one of those files, following code can be used for data |
| 30 | +source/repository class: |
| 31 | + |
| 32 | +```php |
| 33 | +declare(strict_types=1); |
| 34 | + |
| 35 | +namespace App\Reporting\Repository; |
| 36 | + |
| 37 | +use RunOpenCode\Bundle\QueryResourcesLoader\Contract\QueryResourcesLoaderInterface; |
| 38 | +use RunOpenCode\Bundle\QueryResourcesLoader\Executor\Dbal\DbalParameters; |
| 39 | + |
| 40 | +final readonly class ReportingDataSource |
| 41 | +{ |
| 42 | + public function __construct(private QueryResourcesLoaderInterface $loader) { } |
| 43 | + |
| 44 | + public function getLedgerData(Filters $filters): iterable |
43 | 45 | { |
44 | | - private ManagerInterface $queryLoader; |
45 | | - |
46 | | - public function __construct(ManagerInterface $queryLoader) |
47 | | - { |
48 | | - $this->queryLoader = $queryLoader; |
49 | | - } |
50 | | - |
51 | | - public function getLedgerData(array $filters = []): iterable |
52 | | - { |
53 | | - return $this->queryLoader->execute('@MyAppReporting/common.ledger.sql', array( |
54 | | - 'year' => !empty($filters['year']) ? $filters['year'] : date('Y') |
55 | | - )); |
56 | | - } |
| 46 | + return $this->loader->execute('common.ledger.sql', DbalParameters::create() |
| 47 | + ->dateTimeImmutable('from', $filters->getFrom()) |
| 48 | + ->dateTimeImmutable('to', $filters->getTo()) |
| 49 | + ->integer('account', $filters->getAccount()) |
| 50 | + ); |
57 | 51 | } |
58 | | - |
59 | | -If you do not use autowiring, you should register your data source class within service |
60 | | -container: |
61 | | - |
62 | | - // file: ReportingBundle/Resources/config/services.yml |
63 | | - |
64 | | - services: |
65 | | - |
66 | | - MyApp\ReportingBundle\Repository\ReportingDataSource: |
67 | | - arguments: [ "@RunOpenCode\Bundle\QueryResourcesLoader\Contract\ManagerInterface" ] |
68 | | - |
69 | | -Note how your code gets cleaner by just omitting query statements from |
70 | | -your PHP code. |
71 | | - |
72 | | - |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +Note how your code gets cleaner by just omitting query statements from your PHP code. |
| 56 | + |
| 57 | +Do note that Doctrine query language for fetching entities is not powerful as raw SQL. However, with this bundle, you |
| 58 | +can easily leverage raw SQL queries to fetch identifiers of entities and then fetch entities with Doctrine. |
| 59 | + |
73 | 60 | [<< Introduction](introduction.md) | [Table of contents](index.md) | [Twig support >>](twig-support.md) |
0 commit comments