Complex classes like Manager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Manager, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 16 | class Manager  | 
            ||
| 17 | { | 
            ||
| 18 | /**  | 
            ||
| 19 | * Manager instance  | 
            ||
| 20 | *  | 
            ||
| 21 | * @var Manager  | 
            ||
| 22 | */  | 
            ||
| 23 | protected static $instance;  | 
            ||
| 24 | |||
| 25 | /**  | 
            ||
| 26 | * Driver Manager  | 
            ||
| 27 | *  | 
            ||
| 28 | * @var \Analogue\ORM\Drivers\Manager  | 
            ||
| 29 | */  | 
            ||
| 30 | protected $drivers;  | 
            ||
| 31 | |||
| 32 | /**  | 
            ||
| 33 | * Registered entity classes and corresponding map objects.  | 
            ||
| 34 | *  | 
            ||
| 35 | * @var array  | 
            ||
| 36 | */  | 
            ||
| 37 | protected $entityClasses = [];  | 
            ||
| 38 | |||
| 39 | /**  | 
            ||
| 40 | * Key value store of ValueObject Classes and corresponding map classes  | 
            ||
| 41 | *  | 
            ||
| 42 | * @var array  | 
            ||
| 43 | */  | 
            ||
| 44 | protected $valueClasses = [];  | 
            ||
| 45 | |||
| 46 | /**  | 
            ||
| 47 | * Morph map  | 
            ||
| 48 | */  | 
            ||
| 49 | protected $morphMap = [];  | 
            ||
| 50 | |||
| 51 | /**  | 
            ||
| 52 | * Loaded Mappers  | 
            ||
| 53 | *  | 
            ||
| 54 | * @var array  | 
            ||
| 55 | */  | 
            ||
| 56 | protected $mappers = [];  | 
            ||
| 57 | |||
| 58 | /**  | 
            ||
| 59 | * Loaded Repositories  | 
            ||
| 60 | *  | 
            ||
| 61 | * @var array  | 
            ||
| 62 | */  | 
            ||
| 63 | protected $repositories = [];  | 
            ||
| 64 | |||
| 65 | /**  | 
            ||
| 66 | * Event dispatcher instance  | 
            ||
| 67 | *  | 
            ||
| 68 | * @var \Illuminate\Contracts\Events\Dispatcher  | 
            ||
| 69 | */  | 
            ||
| 70 | protected $eventDispatcher;  | 
            ||
| 71 | |||
| 72 | /**  | 
            ||
| 73 | * Available Analogue Events  | 
            ||
| 74 | *  | 
            ||
| 75 | * @var array  | 
            ||
| 76 | */  | 
            ||
| 77 | protected $events = [  | 
            ||
| 78 | 'initializing',  | 
            ||
| 79 | 'initialized',  | 
            ||
| 80 | 'store',  | 
            ||
| 81 | 'stored',  | 
            ||
| 82 | 'creating',  | 
            ||
| 83 | 'created',  | 
            ||
| 84 | 'updating',  | 
            ||
| 85 | 'updated',  | 
            ||
| 86 | 'deleting',  | 
            ||
| 87 | 'deleted',  | 
            ||
| 88 | ];  | 
            ||
| 89 | |||
| 90 | /**  | 
            ||
| 91 | * @param \Analogue\ORM\Drivers\Manager $driverManager  | 
            ||
| 92 | * @param Dispatcher $event  | 
            ||
| 93 | */  | 
            ||
| 94 | public function __construct(DriverManager $driverManager, Dispatcher $event)  | 
            ||
| 102 | |||
| 103 | /**  | 
            ||
| 104 | * Create a mapper for a given entity (static alias)  | 
            ||
| 105 | *  | 
            ||
| 106 | * @param \Analogue\ORM\Mappable|string $entity  | 
            ||
| 107 | * @param null|EntityMap $entityMap  | 
            ||
| 108 | * @throws MappingException  | 
            ||
| 109 | * @return Mapper  | 
            ||
| 110 | */  | 
            ||
| 111 | public static function getMapper($entity, $entityMap = null)  | 
            ||
| 112 |     { | 
            ||
| 113 | return static::$instance->mapper($entity, $entityMap);  | 
            ||
| 114 | }  | 
            ||
| 115 | |||
| 116 | /**  | 
            ||
| 117 | * Create a mapper for a given entity  | 
            ||
| 118 | *  | 
            ||
| 119 | * @param \Analogue\ORM\Mappable|string|array|\Traversable $entity  | 
            ||
| 120 | * @param mixed $entityMap  | 
            ||
| 121 | * @throws MappingException  | 
            ||
| 122 | * @throws \InvalidArgumentException  | 
            ||
| 123 | * @return Mapper  | 
            ||
| 124 | */  | 
            ||
| 125 | public function mapper($entity, $entityMap = null)  | 
            ||
| 126 |     { | 
            ||
| 127 |         if ($entity instanceof Wrapper) { | 
            ||
| 128 |             throw new MappingException('Tried to instantiate mapper on wrapped Entity'); | 
            ||
| 129 | }  | 
            ||
| 130 | |||
| 131 | $entity = $this->resolveEntityClass($entity);  | 
            ||
| 132 | |||
| 133 | $entity = $this->getInverseMorphMap($entity);  | 
            ||
| 134 | |||
| 135 | // Return existing mapper instance if exists.  | 
            ||
| 136 |         if (array_key_exists($entity, $this->mappers)) { | 
            ||
| 137 | return $this->mappers[$entity];  | 
            ||
| 138 |         } else { | 
            ||
| 139 | return $this->buildMapper($entity, $entityMap);  | 
            ||
| 140 | }  | 
            ||
| 141 | }  | 
            ||
| 142 | |||
| 143 | /**  | 
            ||
| 144 | * This method resolve entity class from mappable instances or iterators  | 
            ||
| 145 | *  | 
            ||
| 146 | * @param \Analogue\ORM\Mappable|string|array|\Traversable $entity  | 
            ||
| 147 | * @return string  | 
            ||
| 148 | */  | 
            ||
| 149 | protected function resolveEntityClass($entity)  | 
            ||
| 173 | |||
| 174 | /**  | 
            ||
| 175 | * @param string $key  | 
            ||
| 176 | * @return string  | 
            ||
| 177 | */  | 
            ||
| 178 | public function getInverseMorphMap($key)  | 
            ||
| 179 |     { | 
            ||
| 180 | return array_key_exists($key, $this->morphMap) ? $this->morphMap[$key] : $key;  | 
            ||
| 181 | }  | 
            ||
| 182 | |||
| 183 | /**  | 
            ||
| 184 | * Build a new Mapper instance for a given Entity  | 
            ||
| 185 | *  | 
            ||
| 186 | * @param string $entity  | 
            ||
| 187 | * @param $entityMap  | 
            ||
| 188 | * @throws MappingException  | 
            ||
| 189 | * @return Mapper  | 
            ||
| 190 | */  | 
            ||
| 191 | protected function buildMapper($entity, $entityMap)  | 
            ||
| 192 |     { | 
            ||
| 193 | // If an EntityMap hasn't been manually registered by the user  | 
            ||
| 194 | // register it at runtime.  | 
            ||
| 195 |         if (!$this->isRegisteredEntity($entity)) { | 
            ||
| 196 | $this->register($entity, $entityMap);  | 
            ||
| 197 | }  | 
            ||
| 198 | |||
| 199 | $entityMap = $this->entityClasses[$entity];  | 
            ||
| 200 | |||
| 201 | $factory = new MapperFactory($this->drivers, $this->eventDispatcher, $this);  | 
            ||
| 202 | |||
| 203 | $mapper = $factory->make($entity, $entityMap);  | 
            ||
| 204 | |||
| 205 | $this->mappers[$entity] = $mapper;  | 
            ||
| 206 | |||
| 207 | // At this point we can safely call the boot() method on the entityMap as  | 
            ||
| 208 | // the mapper is now instantiated & registered within the manager.  | 
            ||
| 209 | |||
| 210 | $mapper->getEntityMap()->boot();  | 
            ||
| 211 | |||
| 212 | return $mapper;  | 
            ||
| 213 | }  | 
            ||
| 214 | |||
| 215 | /**  | 
            ||
| 216 | * Check if the entity is already registered  | 
            ||
| 217 | *  | 
            ||
| 218 | * @param string|object $entity  | 
            ||
| 219 | * @return boolean  | 
            ||
| 220 | */  | 
            ||
| 221 | public function isRegisteredEntity($entity)  | 
            ||
| 222 |     { | 
            ||
| 223 |         if (!is_string($entity)) { | 
            ||
| 224 | $entity = get_class($entity);  | 
            ||
| 225 | }  | 
            ||
| 226 | |||
| 227 | return array_key_exists($entity, $this->entityClasses);  | 
            ||
| 228 | }  | 
            ||
| 229 | |||
| 230 | /**  | 
            ||
| 231 | * Register an entity  | 
            ||
| 232 | *  | 
            ||
| 233 | * @param string|\Analogue\ORM\Mappable $entity entity's class name  | 
            ||
| 234 | * @param string|EntityMap $entityMap map's class name  | 
            ||
| 235 | * @throws MappingException  | 
            ||
| 236 | * @return void  | 
            ||
| 237 | */  | 
            ||
| 238 | public function register($entity, $entityMap = null)  | 
            ||
| 239 |     { | 
            ||
| 240 | // If an object is provider, get the class name from it  | 
            ||
| 241 |         if (!is_string($entity)) { | 
            ||
| 242 | $entity = get_class($entity);  | 
            ||
| 243 | }  | 
            ||
| 244 | |||
| 245 |         if ($this->isRegisteredEntity($entity)) { | 
            ||
| 246 |             throw new MappingException("Entity $entity is already registered."); | 
            ||
| 247 | }  | 
            ||
| 248 | |||
| 249 |         if (!class_exists($entity)) { | 
            ||
| 250 |             throw new MappingException("Class $entity does not exists"); | 
            ||
| 251 | }  | 
            ||
| 252 | |||
| 253 |         if (is_null($entityMap)) { | 
            ||
| 254 | $entityMap = $this->getEntityMapInstanceFor($entity);  | 
            ||
| 255 | }  | 
            ||
| 256 | |||
| 257 |         if (is_string($entityMap)) { | 
            ||
| 258 | $entityMap = new $entityMap;  | 
            ||
| 259 | }  | 
            ||
| 260 | |||
| 261 |         if (!$entityMap instanceof EntityMap) { | 
            ||
| 262 | throw new MappingException(get_class($entityMap) . ' must be an instance of EntityMap.');  | 
            ||
| 263 | }  | 
            ||
| 264 | |||
| 265 | $entityMap->setClass($entity);  | 
            ||
| 266 | |||
| 267 | $entityMap->setManager($this);  | 
            ||
| 268 | |||
| 269 | $this->entityClasses[$entity] = $entityMap;  | 
            ||
| 270 | }  | 
            ||
| 271 | |||
| 272 | /**  | 
            ||
| 273 | * Get the entity map instance for a custom entity  | 
            ||
| 274 | *  | 
            ||
| 275 | * @param string $entity  | 
            ||
| 276 | * @return \Analogue\ORM\Mappable  | 
            ||
| 277 | */  | 
            ||
| 278 | protected function getEntityMapInstanceFor($entity)  | 
            ||
| 290 | |||
| 291 | /**  | 
            ||
| 292 | * Dynamically create an entity map for a custom entity class  | 
            ||
| 293 | *  | 
            ||
| 294 | * @return EntityMap  | 
            ||
| 295 | */  | 
            ||
| 296 | protected function getNewEntityMap()  | 
            ||
| 297 |     { | 
            ||
| 298 | return new EntityMap;  | 
            ||
| 299 | }  | 
            ||
| 300 | |||
| 301 | /**  | 
            ||
| 302 | * Return the Singleton instance of the manager  | 
            ||
| 303 | *  | 
            ||
| 304 | * @return Manager  | 
            ||
| 305 | */  | 
            ||
| 306 | public static function getInstance()  | 
            ||
| 307 |     { | 
            ||
| 308 | return static::$instance;  | 
            ||
| 309 | }  | 
            ||
| 310 | |||
| 311 | /**  | 
            ||
| 312 | * Return the Driver Manager's instance  | 
            ||
| 313 | *  | 
            ||
| 314 | * @return \Analogue\ORM\Drivers\Manager  | 
            ||
| 315 | */  | 
            ||
| 316 | public function getDriverManager()  | 
            ||
| 317 |     { | 
            ||
| 318 | return $this->drivers;  | 
            ||
| 319 | }  | 
            ||
| 320 | |||
| 321 | /**  | 
            ||
| 322 | * Get the Repository instance for the given Entity  | 
            ||
| 323 | *  | 
            ||
| 324 | * @param \Analogue\ORM\Mappable|string $entity  | 
            ||
| 325 | * @throws \InvalidArgumentException  | 
            ||
| 326 | * @throws MappingException  | 
            ||
| 327 | * @return \Analogue\ORM\Repository  | 
            ||
| 328 | */  | 
            ||
| 329 | public function repository($entity)  | 
            ||
| 330 |     { | 
            ||
| 331 |         if (!is_string($entity)) { | 
            ||
| 332 | $entity = get_class($entity);  | 
            ||
| 333 | }  | 
            ||
| 334 | |||
| 335 | // First we check if the repository is not already created.  | 
            ||
| 336 |         if (array_key_exists($entity, $this->repositories)) { | 
            ||
| 337 | return $this->repositories[$entity];  | 
            ||
| 338 | }  | 
            ||
| 339 | |||
| 340 | $this->repositories[$entity] = new Repository($this->mapper($entity));  | 
            ||
| 341 | |||
| 342 | return $this->repositories[$entity];  | 
            ||
| 343 | }  | 
            ||
| 344 | |||
| 345 | /**  | 
            ||
| 346 | * Return true is the object is registered as value object  | 
            ||
| 347 | *  | 
            ||
| 348 | * @param mixed $object  | 
            ||
| 349 | * @return boolean  | 
            ||
| 350 | */  | 
            ||
| 351 | public function isValueObject($object)  | 
            ||
| 359 | |||
| 360 | /**  | 
            ||
| 361 | * Get the Value Map for a given Value Object Class  | 
            ||
| 362 | *  | 
            ||
| 363 | * @param string $valueObject  | 
            ||
| 364 | * @throws MappingException  | 
            ||
| 365 | * @return \Analogue\ORM\ValueMap  | 
            ||
| 366 | */  | 
            ||
| 367 | public function getValueMap($valueObject)  | 
            ||
| 382 | |||
| 383 | /**  | 
            ||
| 384 | * Register a Value Object  | 
            ||
| 385 | *  | 
            ||
| 386 | * @param string $valueObject  | 
            ||
| 387 | * @param string $valueMap  | 
            ||
| 388 | * @throws MappingException  | 
            ||
| 389 | * @return void  | 
            ||
| 390 | */  | 
            ||
| 391 | public function registerValueObject($valueObject, $valueMap = null)  | 
            ||
| 392 |     { | 
            ||
| 393 |         if (!is_string($valueObject)) { | 
            ||
| 394 | $valueObject = get_class($valueObject);  | 
            ||
| 395 | }  | 
            ||
| 396 | |||
| 397 |         if (is_null($valueMap)) { | 
            ||
| 398 | $valueMap = $valueObject . 'Map';  | 
            ||
| 399 | }  | 
            ||
| 400 | |||
| 401 |         if (!class_exists($valueMap)) { | 
            ||
| 402 |             throw new MappingException("$valueMap doesn't exists"); | 
            ||
| 403 | }  | 
            ||
| 404 | |||
| 405 | $this->valueClasses[$valueObject] = $valueMap;  | 
            ||
| 406 | }  | 
            ||
| 407 | |||
| 408 | /**  | 
            ||
| 409 | * Instantiate a new Value Object instance  | 
            ||
| 410 | *  | 
            ||
| 411 | * @param string $valueObject  | 
            ||
| 412 | * @return \Analogue\ORM\ValueObject  | 
            ||
| 413 | */  | 
            ||
| 414 | public function getValueObjectInstance($valueObject)  | 
            ||
| 415 |     { | 
            ||
| 416 |         $prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($valueObject), $valueObject)); | 
            ||
| 417 | |||
| 418 | return $prototype;  | 
            ||
| 419 | }  | 
            ||
| 420 | |||
| 421 | /**  | 
            ||
| 422 | * Register Analogue Plugin  | 
            ||
| 423 | *  | 
            ||
| 424 | * @param string $plugin class  | 
            ||
| 425 | * @return void  | 
            ||
| 426 | */  | 
            ||
| 427 | public function registerPlugin($plugin)  | 
            ||
| 435 | |||
| 436 | /**  | 
            ||
| 437 | * Register event listeners that will be fired regardless the type  | 
            ||
| 438 | * of the entity.  | 
            ||
| 439 | *  | 
            ||
| 440 | * @param string $event  | 
            ||
| 441 | * @param \Closure $callback  | 
            ||
| 442 | * @throws \Exception  | 
            ||
| 443 | * @return void  | 
            ||
| 444 | */  | 
            ||
| 445 | public function registerGlobalEvent($event, $callback)  | 
            ||
| 452 | |||
| 453 | /**  | 
            ||
| 454 | * Shortcut to Mapper store  | 
            ||
| 455 | *  | 
            ||
| 456 | * @param mixed $entity  | 
            ||
| 457 | * @throws MappingException  | 
            ||
| 458 | * @return mixed  | 
            ||
| 459 | */  | 
            ||
| 460 | public function store($entity)  | 
            ||
| 464 | |||
| 465 | /**  | 
            ||
| 466 | * Shortcut to Mapper delete  | 
            ||
| 467 | *  | 
            ||
| 468 | * @param mixed $entity  | 
            ||
| 469 | * @throws MappingException  | 
            ||
| 470 | * @return \Illuminate\Support\Collection|null  | 
            ||
| 471 | */  | 
            ||
| 472 | public function delete($entity)  | 
            ||
| 473 |     { | 
            ||
| 474 | return $this->mapper($entity)->delete($entity);  | 
            ||
| 475 | }  | 
            ||
| 476 | |||
| 477 | /**  | 
            ||
| 478 | * Shortcut to Mapper query  | 
            ||
| 479 | *  | 
            ||
| 480 | * @param mixed $entity  | 
            ||
| 481 | * @throws MappingException  | 
            ||
| 482 | * @return Query  | 
            ||
| 483 | */  | 
            ||
| 484 | public function query($entity)  | 
            ||
| 488 | |||
| 489 | /**  | 
            ||
| 490 | * Shortcut to Mapper Global Query  | 
            ||
| 491 | *  | 
            ||
| 492 | * @param mixed $entity  | 
            ||
| 493 | * @throws MappingException  | 
            ||
| 494 | * @return Query  | 
            ||
| 495 | */  | 
            ||
| 496 | public function globalQuery($entity)  | 
            ||
| 500 | |||
| 501 | /**  | 
            ||
| 502 | * @param array $morphMap  | 
            ||
| 503 | * @return $this  | 
            ||
| 504 | */  | 
            ||
| 505 | public function morphMap(array $morphMap)  | 
            ||
| 511 | |||
| 512 | /**  | 
            ||
| 513 | * @param string $class  | 
            ||
| 514 | * @return mixed  | 
            ||
| 515 | */  | 
            ||
| 516 | public function getMorphMap($class)  | 
            ||
| 522 | }  | 
            ||
| 523 | 
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: