{"id":18248254,"url":"https://github.com/district09/symfony_bundle_doctrine-extra","last_synced_at":"2025-04-04T15:32:21.245Z","repository":{"id":56968687,"uuid":"170297159","full_name":"district09/symfony_bundle_doctrine-extra","owner":"district09","description":"Some tools to write complex code more easily and semantically with Doctrine. Including DoctrineFilter objects and and a Manager to manage your entities.","archived":true,"fork":false,"pushed_at":"2019-02-12T10:44:42.000Z","size":39,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-02-26T01:08:14.510Z","etag":null,"topics":["d09check22","symfony","web"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"avandenbogaert/doctrine-extra","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/district09.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-12T10:18:06.000Z","updated_at":"2024-09-27T09:08:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"f3d7086c-d68f-4fd1-b7c1-7f08dbee4a52","html_url":"https://github.com/district09/symfony_bundle_doctrine-extra","commit_stats":null,"previous_names":["digipolisgent/symfony_bundle_doctrine-extra"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/district09%2Fsymfony_bundle_doctrine-extra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/district09%2Fsymfony_bundle_doctrine-extra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/district09%2Fsymfony_bundle_doctrine-extra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/district09%2Fsymfony_bundle_doctrine-extra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/district09","download_url":"https://codeload.github.com/district09/symfony_bundle_doctrine-extra/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247203061,"owners_count":20900906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["d09check22","symfony","web"],"created_at":"2024-11-05T09:36:23.574Z","updated_at":"2025-04-04T15:32:16.234Z","avatar_url":"https://github.com/district09.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Doctrine Extra's\n\n## 1. Example's\nIn this package a BaseManager is included that uses the Assert en Resolvable trait. If we use this Manager\nwe can do the following code examples ;\n\nSelect all new \u0026 processing orders paginated\n```\n$paginator = $manager-\u003epaginate()-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'),new StatusFilter('processing')]\n));\n```\n\nSelect all 'new' \u0026 'processing' orders as an iterator\n\n```\n$iterator = $manager-\u003eiterate()-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'),new StatusFilter('finished')]\n));\n```\n\nCount all 'new' \u0026 'processing' orders\n\n```\n$count = $manager-\u003ecount()-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'),new StatusFilter('finished')]\n));\n```\n\nAdd an extra parameter to an existing query\n\n```\n$queryBuilder = $this-\u003erepository-\u003ebuilder()-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'),new StatusFilter('finished')]\n));\n\n$queryBuilder-\u003eandWhere('category = :category');\n$queryBuilder-\u003esetParameter('category', 'books');\n\n$orders = $queryBuilder-\u003egetResult();\n```\n\nMore example's are available below in the docs.\n\n## 2. Filters\nCreate Filter objects to easily filter your repository.\nThis package contains two default Filter objects to use ; 'AggregateFilter' and 'PropertyFilter'. Both are multipurpose\nbut is is recommended to extend the AbstractFilter and create your own.\n\nThe filtering itself can be done by any class that uses the Resolver trait, and uses the Doctrine QueryBuilder object as\n a starting point.\n\nLets take the following example ;\n\n```\nclass OrderRepository extends \\Doctrine\\ORM\\EntityRepository\n{\n    /** Resolves filters **/\n    use Resolver;\n\n    public function filter($filters)\n    {\n        $builder = $this-\u003ecreateQueryBuilder('root');\n\n        return $this-\u003eresolve($filters, $builder)-\u003egetQuery()-\u003egetResult();\n    }\n}\n```\n\nWe have an OrderRepository that implements the Resolver trait, and has a method \"filter\" that accepts an array of\nDoctrine Filters or one DoctrineFilter.\n\n#### Using the PropertyFilter\nThe property filter can be used to filter on any entity's property. Lets Imagine an order has a \"category\" property,\nwe want to filter on.\n\n```\n/**\n * @var OrderRepository\n */\nprivate $repository;\n\npublic function categoryAction($category)\n{\n    $orders = $this-\u003erepository-\u003efilter(new PropertyFilter($category, 'category'));\n}\n```\n\nBy now we have filtered orders for a certain category. We can also pass multiple filters as an array into the filter()\nmethod as an argument, they will all be combined in an andX expression.\n\n\n#### Using the AggregateFilter\nIn case we want to use multiple filters in an orX expression, we can use the AggregateFilter. In the following example\nwe will filter all 'new' or 'finished' orders;\n\n```\n$orders = $this-\u003erepository-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'),new StatusFilter('finished')]\n));\n```\n\nWe can combine multiple AggregateFilters to make a more complex expression. In the following example we will filter all\n'new' or 'finished' orders that have 'multimedia' or 'books' as a category\n\n```\n$orders = $this-\u003erepository-\u003efilter(\n    new AggregateFilter([new StatusFilter('new'), new StatusFilter('finished')]),\n    new AggregateFilter([new CategoryFilter('multimedia'), new CategoryFilter('books')])\n);\n```\n\n### Creating a custom DoctrineFilter\n\n#### Simple property filter\nWe can also implement CategoryFilter if more entities have category as a property and we want to use it often.\n\nIf we want to create our own CategoryFilter, which is the most basic form of filtering by filtering on a single direct\nproperty we can do it this way ;\n\n```\nclass CategoryFilter extends AbstractFilter\n{\n    public function createExpression($root)\n    {\n        return $this-\u003eexpr()-\u003eeq(\n            sprintf('%s.category', $root),\n            $this-\u003eexpr()-\u003eliteral($this-\u003eparameter)\n        );\n    }\n}\n```\n\nWe only need to implement the __CreateExpression()__ method, and create a simple __expression that will be used\nin the Where clause in the QueryBuilder__. Now this filter can be usd on all entities with the \"category\" property.\n\nSometimes we will need a more complex filter. Assume our Order entity has a relationship with User, and User has a\nusername. We want to filter all orders by a user's username. We can create the following filter ;\n\n#### More advanced example\n\n```\nclass UserEmailFilter extends AbstractFilter\n{\n    public function createExpression($root)\n    {\n        return $this-\u003eexpr()-\u003eeq('user.email', $this-\u003eexpr()-\u003eliteral($this-\u003eparameter));\n    }\n\n    public function getAlias()\n    {\n        return 'user';\n    }\n\n    public function addAlias(QueryBuilder $builder, $root)\n    {\n       $builder-\u003eleftJoin(sprintf('%s.user', $root), 'user');\n    }\n}\n```\n\nThis Filter is a bit more complex. Since we are not filtering a direct property of Order, but instead filter on a\nproperty of User which has a association with our Order object, we need to implement two more methods.\n\nThe function __getAlias()__ will return a string, the alias defines the object's alias that has the property\nwe are filtering on. In this case its __'user' because we will filter on user.email__.\n\nThe __AddAlias()__ method will be triggered by the Resolver when it checks if the 'user' alias is present in the\nQueryBuilder, an alias is present when it is OR selected OR joined. In this case we __Left join our User object to our\n'root' object__, in this example 'Order'.\n\nNow we have finished our UserEmailFilter, we can use this filter on any object that has User as a relation. We can\nfor example have a Reservation entity and a Ticket entity that both have an association with User.\n\nSo by now we can do the following ;\n\n```\n$reservations = $this-\u003ereservationRepository-\u003efilter(new UserEmailFilter('example@doctrine.com'));\n$orders = $this-\u003eorderRepository-\u003efilter(new UserEmailFilter('example@doctrine.com'));\n$tickets = $this-\u003eticketRepository-\u003efilter(new UserEmailFilter('example@doctrine.com'));\n```\n\n##3. Assert Results\nThis package includes the Assertable trait, which allows any class to pass a QueryBuilder object and retrieve different\nresults from that same QueryBuilder object.\n\nFor example, we have a repository that uses the Assertable trait, we the following code ;\n\n```\nclass OrderRepository extends EntityRepository\n{\n    use Assertable;\n\n    public function getOrdersByCategory($category)\n    {\n        $builder = $this-\u003ecreateQueryBuilder('root');\n        $builder-\u003eandWhere('root.category = :category');\n        $builder-\u003esetParameter('category', $category);\n\n        return $this-\u003eassertResult($builder);\n    }\n}\n```\nBecause we use the assertable trait, and we pass our QueryBuilder object through the assertResult() method, we can\nmanipulate what kind of result this function will return. By default this function will act as expected and\nreturn an array with all Order entities by a certain category.\n\n```\n  $orders = $this-\u003erepository-\u003egetOrdersByCategory('some_category');\n```\n\nIf we want to retrieve the orders paginated, we can simply call the builder() method before calling getOrdersByCategory\nand the Assert trait will assert that the result passed as a result will be a Paginator object;\n\n```\n $paginator = $this-\u003erepository-\u003ebuilder()-\u003egetOrdersByCategory('some_category');\n```\n\nTo see all possible outcomes of the assertResult() method, take the following code ;\n\n```\nprotected function assertResult(QueryBuilder $builder, $hydration = Query::HYDRATE_OBJECT)\n{\n    switch($this-\u003eassert) {\n        case Result::ARRAY:\n            return $builder-\u003egetQuery()-\u003egetResult($hydration);\n        case Result::PAGINATE:\n            return new Paginator($builder);\n        case Result::SINGLE:\n            return $builder-\u003egetQuery()-\u003egetOneOrNullResult($hydration);\n        case Result::FIRST:\n            $result = $builder-\u003esetMaxResults(1)-\u003egetQuery()-\u003egetResult();\n            return count($result) \u003e 0 ? $result[0] : null;\n        case Result::ITERATE:\n            return $builder-\u003egetQuery()-\u003eiterate();\n        case Result::COUNT:\n            $paginator = new Paginator($builder);\n            return $paginator-\u003ecount();\n        case Result::QUERY:\n            return $builder-\u003egetQuery();\n        case Result::BUILDER:\n            return $builder;\n        default:\n            throw new AssertResultException(sprintf('Unknown result assertion \"%s\"', $this-\u003eassert));\n    }\n}\n```\n\nThe above code is located in  the Assert trait.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdistrict09%2Fsymfony_bundle_doctrine-extra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdistrict09%2Fsymfony_bundle_doctrine-extra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdistrict09%2Fsymfony_bundle_doctrine-extra/lists"}