|
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