Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
20 | class Types |
||
21 | { |
||
22 | /** |
||
23 | * @var array mapping of type name to type instances |
||
24 | */ |
||
25 | private $types = []; |
||
26 | |||
27 | /** |
||
28 | * @var ObjectTypeFactory |
||
29 | */ |
||
30 | private $objectTypeFactory; |
||
31 | |||
32 | /** |
||
33 | * @var InputTypeFactory |
||
34 | */ |
||
35 | private $inputTypeFactory; |
||
36 | |||
37 | /** |
||
38 | * @var EntityManager |
||
39 | */ |
||
40 | private $entityManager; |
||
41 | |||
42 | 16 | public function __construct(EntityManager $entityManager, array $customTypeMapping = []) |
|
57 | |||
58 | /** |
||
59 | * Always return the same instance of `Type` for the given class name |
||
60 | * |
||
61 | * All entity getter methods will be exposed, unless specified otherwise |
||
62 | * with annotations. |
||
63 | * |
||
64 | * @param string $className the class name of either a scalar type (`PostStatus::class`), or an entity (`Post::class`) |
||
65 | * @return Type |
||
66 | */ |
||
67 | 14 | public function get(string $className): Type |
|
78 | |||
79 | /** |
||
80 | * Returns an input type for the given entity to be used in mutations |
||
81 | * |
||
82 | * All entity setter methods will be exposed, unless specified otherwise |
||
83 | * with annotations. |
||
84 | * |
||
85 | * @param string $className the class name of an entity (`Post::class`) |
||
86 | * @return InputObjectType |
||
87 | */ |
||
88 | 2 | View Code Duplication | public function getInput(string $className): InputObjectType |
100 | |||
101 | /** |
||
102 | * Returns an special ID type for the given entity |
||
103 | * |
||
104 | * This is mostly useful for internal usage when a getter has an entity |
||
105 | * as parameter. This type will automatically load the entity from DB, so |
||
106 | * the resolve functions can use a real instance of entity instead of an ID. |
||
107 | * |
||
108 | * @param string $className the class name of an entity (`Post::class`) |
||
109 | * @return EntityIDType |
||
110 | */ |
||
111 | 2 | View Code Duplication | public function getId(string $className): EntityIDType |
123 | |||
124 | /** |
||
125 | * Register the given type in our internal registry |
||
126 | * @param string $key |
||
127 | * @param Type $instance |
||
128 | */ |
||
129 | 16 | private function registerInstance(string $key, Type $instance): void |
|
134 | |||
135 | /** |
||
136 | * Create an instance of either a custom, scalar or ObjectType |
||
137 | * @param string $className |
||
138 | * @return Type |
||
139 | */ |
||
140 | 16 | private function createInstance(string $className): Type |
|
150 | |||
151 | /** |
||
152 | * Checks if a className is a valid doctrine entity |
||
153 | * |
||
154 | * @return bool |
||
155 | */ |
||
156 | 12 | public function isEntity(string $className): bool |
|
160 | |||
161 | /** |
||
162 | * Returns the list of native GraphQL types |
||
163 | * @return array |
||
164 | */ |
||
165 | 16 | private function getPhpToGraphQLMapping(): array |
|
175 | |||
176 | /** |
||
177 | * Throw an exception if the class name is not Doctrine entity |
||
178 | * @param string $className |
||
179 | * @throws \UnexpectedValueException |
||
180 | */ |
||
181 | 12 | private function throwIfNotEntity(string $className): void |
|
187 | |||
188 | /** |
||
189 | * Remove the leading `\` that may exists in FQCN |
||
190 | * @param string $className |
||
191 | * @return string |
||
192 | */ |
||
193 | 14 | private function normalizedClassName(string $className): string |
|
197 | } |
||
198 |
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.