Container.php 33KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. <?php
  2. namespace Illuminate\Container;
  3. use Closure;
  4. use ArrayAccess;
  5. use LogicException;
  6. use ReflectionClass;
  7. use ReflectionParameter;
  8. use Illuminate\Contracts\Container\BindingResolutionException;
  9. use Illuminate\Contracts\Container\Container as ContainerContract;
  10. class Container implements ArrayAccess, ContainerContract
  11. {
  12. /**
  13. * The current globally available container (if any).
  14. *
  15. * @var static
  16. */
  17. protected static $instance;
  18. /**
  19. * An array of the types that have been resolved.
  20. *
  21. * @var array
  22. */
  23. protected $resolved = [];
  24. /**
  25. * The container's bindings.
  26. *
  27. * @var array
  28. */
  29. protected $bindings = [];
  30. /**
  31. * The container's method bindings.
  32. *
  33. * @var array
  34. */
  35. protected $methodBindings = [];
  36. /**
  37. * The container's shared instances.
  38. *
  39. * @var array
  40. */
  41. protected $instances = [];
  42. /**
  43. * The registered type aliases.
  44. *
  45. * @var array
  46. */
  47. protected $aliases = [];
  48. /**
  49. * The registered aliases keyed by the abstract name.
  50. *
  51. * @var array
  52. */
  53. protected $abstractAliases = [];
  54. /**
  55. * The extension closures for services.
  56. *
  57. * @var array
  58. */
  59. protected $extenders = [];
  60. /**
  61. * All of the registered tags.
  62. *
  63. * @var array
  64. */
  65. protected $tags = [];
  66. /**
  67. * The stack of concretions currently being built.
  68. *
  69. * @var array
  70. */
  71. protected $buildStack = [];
  72. /**
  73. * The parameter override stack.
  74. *
  75. * @var array
  76. */
  77. protected $with = [];
  78. /**
  79. * The contextual binding map.
  80. *
  81. * @var array
  82. */
  83. public $contextual = [];
  84. /**
  85. * All of the registered rebound callbacks.
  86. *
  87. * @var array
  88. */
  89. protected $reboundCallbacks = [];
  90. /**
  91. * All of the global resolving callbacks.
  92. *
  93. * @var array
  94. */
  95. protected $globalResolvingCallbacks = [];
  96. /**
  97. * All of the global after resolving callbacks.
  98. *
  99. * @var array
  100. */
  101. protected $globalAfterResolvingCallbacks = [];
  102. /**
  103. * All of the resolving callbacks by class type.
  104. *
  105. * @var array
  106. */
  107. protected $resolvingCallbacks = [];
  108. /**
  109. * All of the after resolving callbacks by class type.
  110. *
  111. * @var array
  112. */
  113. protected $afterResolvingCallbacks = [];
  114. /**
  115. * Define a contextual binding.
  116. *
  117. * @param string $concrete
  118. * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
  119. */
  120. public function when($concrete)
  121. {
  122. return new ContextualBindingBuilder($this, $this->getAlias($concrete));
  123. }
  124. /**
  125. * Determine if the given abstract type has been bound.
  126. *
  127. * @param string $abstract
  128. * @return bool
  129. */
  130. public function bound($abstract)
  131. {
  132. return isset($this->bindings[$abstract]) ||
  133. isset($this->instances[$abstract]) ||
  134. $this->isAlias($abstract);
  135. }
  136. /**
  137. * {@inheritdoc}
  138. */
  139. public function has($id)
  140. {
  141. return $this->bound($id);
  142. }
  143. /**
  144. * Determine if the given abstract type has been resolved.
  145. *
  146. * @param string $abstract
  147. * @return bool
  148. */
  149. public function resolved($abstract)
  150. {
  151. if ($this->isAlias($abstract)) {
  152. $abstract = $this->getAlias($abstract);
  153. }
  154. return isset($this->resolved[$abstract]) ||
  155. isset($this->instances[$abstract]);
  156. }
  157. /**
  158. * Determine if a given type is shared.
  159. *
  160. * @param string $abstract
  161. * @return bool
  162. */
  163. public function isShared($abstract)
  164. {
  165. return isset($this->instances[$abstract]) ||
  166. (isset($this->bindings[$abstract]['shared']) &&
  167. $this->bindings[$abstract]['shared'] === true);
  168. }
  169. /**
  170. * Determine if a given string is an alias.
  171. *
  172. * @param string $name
  173. * @return bool
  174. */
  175. public function isAlias($name)
  176. {
  177. return isset($this->aliases[$name]);
  178. }
  179. /**
  180. * Register a binding with the container.
  181. *
  182. * @param string $abstract
  183. * @param \Closure|string|null $concrete
  184. * @param bool $shared
  185. * @return void
  186. */
  187. public function bind($abstract, $concrete = null, $shared = false)
  188. {
  189. // If no concrete type was given, we will simply set the concrete type to the
  190. // abstract type. After that, the concrete type to be registered as shared
  191. // without being forced to state their classes in both of the parameters.
  192. $this->dropStaleInstances($abstract);
  193. if (is_null($concrete)) {
  194. $concrete = $abstract;
  195. }
  196. // If the factory is not a Closure, it means it is just a class name which is
  197. // bound into this container to the abstract type and we will just wrap it
  198. // up inside its own Closure to give us more convenience when extending.
  199. if (! $concrete instanceof Closure) {
  200. $concrete = $this->getClosure($abstract, $concrete);
  201. }
  202. $this->bindings[$abstract] = compact('concrete', 'shared');
  203. // If the abstract type was already resolved in this container we'll fire the
  204. // rebound listener so that any objects which have already gotten resolved
  205. // can have their copy of the object updated via the listener callbacks.
  206. if ($this->resolved($abstract)) {
  207. $this->rebound($abstract);
  208. }
  209. }
  210. /**
  211. * Get the Closure to be used when building a type.
  212. *
  213. * @param string $abstract
  214. * @param string $concrete
  215. * @return \Closure
  216. */
  217. protected function getClosure($abstract, $concrete)
  218. {
  219. return function ($container, $parameters = []) use ($abstract, $concrete) {
  220. if ($abstract == $concrete) {
  221. return $container->build($concrete);
  222. }
  223. return $container->make($concrete, $parameters);
  224. };
  225. }
  226. /**
  227. * Determine if the container has a method binding.
  228. *
  229. * @param string $method
  230. * @return bool
  231. */
  232. public function hasMethodBinding($method)
  233. {
  234. return isset($this->methodBindings[$method]);
  235. }
  236. /**
  237. * Bind a callback to resolve with Container::call.
  238. *
  239. * @param array|string $method
  240. * @param \Closure $callback
  241. * @return void
  242. */
  243. public function bindMethod($method, $callback)
  244. {
  245. $this->methodBindings[$this->parseBindMethod($method)] = $callback;
  246. }
  247. /**
  248. * Get the method to be bound in class@method format.
  249. *
  250. * @param array|string $method
  251. * @return string
  252. */
  253. protected function parseBindMethod($method)
  254. {
  255. if (is_array($method)) {
  256. return $method[0].'@'.$method[1];
  257. }
  258. return $method;
  259. }
  260. /**
  261. * Get the method binding for the given method.
  262. *
  263. * @param string $method
  264. * @param mixed $instance
  265. * @return mixed
  266. */
  267. public function callMethodBinding($method, $instance)
  268. {
  269. return call_user_func($this->methodBindings[$method], $instance, $this);
  270. }
  271. /**
  272. * Add a contextual binding to the container.
  273. *
  274. * @param string $concrete
  275. * @param string $abstract
  276. * @param \Closure|string $implementation
  277. * @return void
  278. */
  279. public function addContextualBinding($concrete, $abstract, $implementation)
  280. {
  281. $this->contextual[$concrete][$this->getAlias($abstract)] = $implementation;
  282. }
  283. /**
  284. * Register a binding if it hasn't already been registered.
  285. *
  286. * @param string $abstract
  287. * @param \Closure|string|null $concrete
  288. * @param bool $shared
  289. * @return void
  290. */
  291. public function bindIf($abstract, $concrete = null, $shared = false)
  292. {
  293. if (! $this->bound($abstract)) {
  294. $this->bind($abstract, $concrete, $shared);
  295. }
  296. }
  297. /**
  298. * Register a shared binding in the container.
  299. *
  300. * @param string $abstract
  301. * @param \Closure|string|null $concrete
  302. * @return void
  303. */
  304. public function singleton($abstract, $concrete = null)
  305. {
  306. $this->bind($abstract, $concrete, true);
  307. }
  308. /**
  309. * "Extend" an abstract type in the container.
  310. *
  311. * @param string $abstract
  312. * @param \Closure $closure
  313. * @return void
  314. *
  315. * @throws \InvalidArgumentException
  316. */
  317. public function extend($abstract, Closure $closure)
  318. {
  319. $abstract = $this->getAlias($abstract);
  320. if (isset($this->instances[$abstract])) {
  321. $this->instances[$abstract] = $closure($this->instances[$abstract], $this);
  322. $this->rebound($abstract);
  323. } else {
  324. $this->extenders[$abstract][] = $closure;
  325. if ($this->resolved($abstract)) {
  326. $this->rebound($abstract);
  327. }
  328. }
  329. }
  330. /**
  331. * Register an existing instance as shared in the container.
  332. *
  333. * @param string $abstract
  334. * @param mixed $instance
  335. * @return mixed
  336. */
  337. public function instance($abstract, $instance)
  338. {
  339. $this->removeAbstractAlias($abstract);
  340. $isBound = $this->bound($abstract);
  341. unset($this->aliases[$abstract]);
  342. // We'll check to determine if this type has been bound before, and if it has
  343. // we will fire the rebound callbacks registered with the container and it
  344. // can be updated with consuming classes that have gotten resolved here.
  345. $this->instances[$abstract] = $instance;
  346. if ($isBound) {
  347. $this->rebound($abstract);
  348. }
  349. return $instance;
  350. }
  351. /**
  352. * Remove an alias from the contextual binding alias cache.
  353. *
  354. * @param string $searched
  355. * @return void
  356. */
  357. protected function removeAbstractAlias($searched)
  358. {
  359. if (! isset($this->aliases[$searched])) {
  360. return;
  361. }
  362. foreach ($this->abstractAliases as $abstract => $aliases) {
  363. foreach ($aliases as $index => $alias) {
  364. if ($alias == $searched) {
  365. unset($this->abstractAliases[$abstract][$index]);
  366. }
  367. }
  368. }
  369. }
  370. /**
  371. * Assign a set of tags to a given binding.
  372. *
  373. * @param array|string $abstracts
  374. * @param array|mixed ...$tags
  375. * @return void
  376. */
  377. public function tag($abstracts, $tags)
  378. {
  379. $tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1);
  380. foreach ($tags as $tag) {
  381. if (! isset($this->tags[$tag])) {
  382. $this->tags[$tag] = [];
  383. }
  384. foreach ((array) $abstracts as $abstract) {
  385. $this->tags[$tag][] = $abstract;
  386. }
  387. }
  388. }
  389. /**
  390. * Resolve all of the bindings for a given tag.
  391. *
  392. * @param string $tag
  393. * @return array
  394. */
  395. public function tagged($tag)
  396. {
  397. $results = [];
  398. if (isset($this->tags[$tag])) {
  399. foreach ($this->tags[$tag] as $abstract) {
  400. $results[] = $this->make($abstract);
  401. }
  402. }
  403. return $results;
  404. }
  405. /**
  406. * Alias a type to a different name.
  407. *
  408. * @param string $abstract
  409. * @param string $alias
  410. * @return void
  411. */
  412. public function alias($abstract, $alias)
  413. {
  414. $this->aliases[$alias] = $abstract;
  415. $this->abstractAliases[$abstract][] = $alias;
  416. }
  417. /**
  418. * Bind a new callback to an abstract's rebind event.
  419. *
  420. * @param string $abstract
  421. * @param \Closure $callback
  422. * @return mixed
  423. */
  424. public function rebinding($abstract, Closure $callback)
  425. {
  426. $this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
  427. if ($this->bound($abstract)) {
  428. return $this->make($abstract);
  429. }
  430. }
  431. /**
  432. * Refresh an instance on the given target and method.
  433. *
  434. * @param string $abstract
  435. * @param mixed $target
  436. * @param string $method
  437. * @return mixed
  438. */
  439. public function refresh($abstract, $target, $method)
  440. {
  441. return $this->rebinding($abstract, function ($app, $instance) use ($target, $method) {
  442. $target->{$method}($instance);
  443. });
  444. }
  445. /**
  446. * Fire the "rebound" callbacks for the given abstract type.
  447. *
  448. * @param string $abstract
  449. * @return void
  450. */
  451. protected function rebound($abstract)
  452. {
  453. $instance = $this->make($abstract);
  454. foreach ($this->getReboundCallbacks($abstract) as $callback) {
  455. call_user_func($callback, $this, $instance);
  456. }
  457. }
  458. /**
  459. * Get the rebound callbacks for a given type.
  460. *
  461. * @param string $abstract
  462. * @return array
  463. */
  464. protected function getReboundCallbacks($abstract)
  465. {
  466. if (isset($this->reboundCallbacks[$abstract])) {
  467. return $this->reboundCallbacks[$abstract];
  468. }
  469. return [];
  470. }
  471. /**
  472. * Wrap the given closure such that its dependencies will be injected when executed.
  473. *
  474. * @param \Closure $callback
  475. * @param array $parameters
  476. * @return \Closure
  477. */
  478. public function wrap(Closure $callback, array $parameters = [])
  479. {
  480. return function () use ($callback, $parameters) {
  481. return $this->call($callback, $parameters);
  482. };
  483. }
  484. /**
  485. * Call the given Closure / class@method and inject its dependencies.
  486. *
  487. * @param callable|string $callback
  488. * @param array $parameters
  489. * @param string|null $defaultMethod
  490. * @return mixed
  491. */
  492. public function call($callback, array $parameters = [], $defaultMethod = null)
  493. {
  494. return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
  495. }
  496. /**
  497. * Get a closure to resolve the given type from the container.
  498. *
  499. * @param string $abstract
  500. * @return \Closure
  501. */
  502. public function factory($abstract)
  503. {
  504. return function () use ($abstract) {
  505. return $this->make($abstract);
  506. };
  507. }
  508. /**
  509. * An alias function name for make().
  510. *
  511. * @param string $abstract
  512. * @param array $parameters
  513. * @return mixed
  514. */
  515. public function makeWith($abstract, array $parameters = [])
  516. {
  517. return $this->make($abstract, $parameters);
  518. }
  519. /**
  520. * Resolve the given type from the container.
  521. *
  522. * @param string $abstract
  523. * @param array $parameters
  524. * @return mixed
  525. */
  526. public function make($abstract, array $parameters = [])
  527. {
  528. return $this->resolve($abstract, $parameters);
  529. }
  530. /**
  531. * {@inheritdoc}
  532. */
  533. public function get($id)
  534. {
  535. if ($this->has($id)) {
  536. return $this->resolve($id);
  537. }
  538. throw new EntryNotFoundException;
  539. }
  540. /**
  541. * Resolve the given type from the container.
  542. *
  543. * @param string $abstract
  544. * @param array $parameters
  545. * @return mixed
  546. */
  547. protected function resolve($abstract, $parameters = [])
  548. {
  549. $abstract = $this->getAlias($abstract);
  550. $needsContextualBuild = ! empty($parameters) || ! is_null(
  551. $this->getContextualConcrete($abstract)
  552. );
  553. // If an instance of the type is currently being managed as a singleton we'll
  554. // just return an existing instance instead of instantiating new instances
  555. // so the developer can keep using the same objects instance every time.
  556. if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
  557. return $this->instances[$abstract];
  558. }
  559. $this->with[] = $parameters;
  560. $concrete = $this->getConcrete($abstract);
  561. // We're ready to instantiate an instance of the concrete type registered for
  562. // the binding. This will instantiate the types, as well as resolve any of
  563. // its "nested" dependencies recursively until all have gotten resolved.
  564. if ($this->isBuildable($concrete, $abstract)) {
  565. $object = $this->build($concrete);
  566. } else {
  567. $object = $this->make($concrete);
  568. }
  569. // If we defined any extenders for this type, we'll need to spin through them
  570. // and apply them to the object being built. This allows for the extension
  571. // of services, such as changing configuration or decorating the object.
  572. foreach ($this->getExtenders($abstract) as $extender) {
  573. $object = $extender($object, $this);
  574. }
  575. // If the requested type is registered as a singleton we'll want to cache off
  576. // the instances in "memory" so we can return it later without creating an
  577. // entirely new instance of an object on each subsequent request for it.
  578. if ($this->isShared($abstract) && ! $needsContextualBuild) {
  579. $this->instances[$abstract] = $object;
  580. }
  581. $this->fireResolvingCallbacks($abstract, $object);
  582. // Before returning, we will also set the resolved flag to "true" and pop off
  583. // the parameter overrides for this build. After those two things are done
  584. // we will be ready to return back the fully constructed class instance.
  585. $this->resolved[$abstract] = true;
  586. array_pop($this->with);
  587. return $object;
  588. }
  589. /**
  590. * Get the concrete type for a given abstract.
  591. *
  592. * @param string $abstract
  593. * @return mixed $concrete
  594. */
  595. protected function getConcrete($abstract)
  596. {
  597. if (! is_null($concrete = $this->getContextualConcrete($abstract))) {
  598. return $concrete;
  599. }
  600. // If we don't have a registered resolver or concrete for the type, we'll just
  601. // assume each type is a concrete name and will attempt to resolve it as is
  602. // since the container should be able to resolve concretes automatically.
  603. if (isset($this->bindings[$abstract])) {
  604. return $this->bindings[$abstract]['concrete'];
  605. }
  606. return $abstract;
  607. }
  608. /**
  609. * Get the contextual concrete binding for the given abstract.
  610. *
  611. * @param string $abstract
  612. * @return string|null
  613. */
  614. protected function getContextualConcrete($abstract)
  615. {
  616. if (! is_null($binding = $this->findInContextualBindings($abstract))) {
  617. return $binding;
  618. }
  619. // Next we need to see if a contextual binding might be bound under an alias of the
  620. // given abstract type. So, we will need to check if any aliases exist with this
  621. // type and then spin through them and check for contextual bindings on these.
  622. if (empty($this->abstractAliases[$abstract])) {
  623. return;
  624. }
  625. foreach ($this->abstractAliases[$abstract] as $alias) {
  626. if (! is_null($binding = $this->findInContextualBindings($alias))) {
  627. return $binding;
  628. }
  629. }
  630. }
  631. /**
  632. * Find the concrete binding for the given abstract in the contextual binding array.
  633. *
  634. * @param string $abstract
  635. * @return string|null
  636. */
  637. protected function findInContextualBindings($abstract)
  638. {
  639. if (isset($this->contextual[end($this->buildStack)][$abstract])) {
  640. return $this->contextual[end($this->buildStack)][$abstract];
  641. }
  642. }
  643. /**
  644. * Determine if the given concrete is buildable.
  645. *
  646. * @param mixed $concrete
  647. * @param string $abstract
  648. * @return bool
  649. */
  650. protected function isBuildable($concrete, $abstract)
  651. {
  652. return $concrete === $abstract || $concrete instanceof Closure;
  653. }
  654. /**
  655. * Instantiate a concrete instance of the given type.
  656. *
  657. * @param string $concrete
  658. * @return mixed
  659. *
  660. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  661. */
  662. public function build($concrete)
  663. {
  664. // If the concrete type is actually a Closure, we will just execute it and
  665. // hand back the results of the functions, which allows functions to be
  666. // used as resolvers for more fine-tuned resolution of these objects.
  667. if ($concrete instanceof Closure) {
  668. return $concrete($this, $this->getLastParameterOverride());
  669. }
  670. $reflector = new ReflectionClass($concrete);
  671. // If the type is not instantiable, the developer is attempting to resolve
  672. // an abstract type such as an Interface of Abstract Class and there is
  673. // no binding registered for the abstractions so we need to bail out.
  674. if (! $reflector->isInstantiable()) {
  675. return $this->notInstantiable($concrete);
  676. }
  677. $this->buildStack[] = $concrete;
  678. $constructor = $reflector->getConstructor();
  679. // If there are no constructors, that means there are no dependencies then
  680. // we can just resolve the instances of the objects right away, without
  681. // resolving any other types or dependencies out of these containers.
  682. if (is_null($constructor)) {
  683. array_pop($this->buildStack);
  684. return new $concrete;
  685. }
  686. $dependencies = $constructor->getParameters();
  687. // Once we have all the constructor's parameters we can create each of the
  688. // dependency instances and then use the reflection instances to make a
  689. // new instance of this class, injecting the created dependencies in.
  690. $instances = $this->resolveDependencies(
  691. $dependencies
  692. );
  693. array_pop($this->buildStack);
  694. return $reflector->newInstanceArgs($instances);
  695. }
  696. /**
  697. * Resolve all of the dependencies from the ReflectionParameters.
  698. *
  699. * @param array $dependencies
  700. * @return array
  701. */
  702. protected function resolveDependencies(array $dependencies)
  703. {
  704. $results = [];
  705. foreach ($dependencies as $dependency) {
  706. // If this dependency has a override for this particular build we will use
  707. // that instead as the value. Otherwise, we will continue with this run
  708. // of resolutions and let reflection attempt to determine the result.
  709. if ($this->hasParameterOverride($dependency)) {
  710. $results[] = $this->getParameterOverride($dependency);
  711. continue;
  712. }
  713. // If the class is null, it means the dependency is a string or some other
  714. // primitive type which we can not resolve since it is not a class and
  715. // we will just bomb out with an error since we have no-where to go.
  716. $results[] = is_null($dependency->getClass())
  717. ? $this->resolvePrimitive($dependency)
  718. : $this->resolveClass($dependency);
  719. }
  720. return $results;
  721. }
  722. /**
  723. * Determine if the given dependency has a parameter override.
  724. *
  725. * @param \ReflectionParameter $dependency
  726. * @return bool
  727. */
  728. protected function hasParameterOverride($dependency)
  729. {
  730. return array_key_exists(
  731. $dependency->name, $this->getLastParameterOverride()
  732. );
  733. }
  734. /**
  735. * Get a parameter override for a dependency.
  736. *
  737. * @param \ReflectionParameter $dependency
  738. * @return mixed
  739. */
  740. protected function getParameterOverride($dependency)
  741. {
  742. return $this->getLastParameterOverride()[$dependency->name];
  743. }
  744. /**
  745. * Get the last parameter override.
  746. *
  747. * @return array
  748. */
  749. protected function getLastParameterOverride()
  750. {
  751. return count($this->with) ? end($this->with) : [];
  752. }
  753. /**
  754. * Resolve a non-class hinted primitive dependency.
  755. *
  756. * @param \ReflectionParameter $parameter
  757. * @return mixed
  758. *
  759. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  760. */
  761. protected function resolvePrimitive(ReflectionParameter $parameter)
  762. {
  763. if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
  764. return $concrete instanceof Closure ? $concrete($this) : $concrete;
  765. }
  766. if ($parameter->isDefaultValueAvailable()) {
  767. return $parameter->getDefaultValue();
  768. }
  769. $this->unresolvablePrimitive($parameter);
  770. }
  771. /**
  772. * Resolve a class based dependency from the container.
  773. *
  774. * @param \ReflectionParameter $parameter
  775. * @return mixed
  776. *
  777. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  778. */
  779. protected function resolveClass(ReflectionParameter $parameter)
  780. {
  781. try {
  782. return $this->make($parameter->getClass()->name);
  783. }
  784. // If we can not resolve the class instance, we will check to see if the value
  785. // is optional, and if it is we will return the optional parameter value as
  786. // the value of the dependency, similarly to how we do this with scalars.
  787. catch (BindingResolutionException $e) {
  788. if ($parameter->isOptional()) {
  789. return $parameter->getDefaultValue();
  790. }
  791. throw $e;
  792. }
  793. }
  794. /**
  795. * Throw an exception that the concrete is not instantiable.
  796. *
  797. * @param string $concrete
  798. * @return void
  799. *
  800. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  801. */
  802. protected function notInstantiable($concrete)
  803. {
  804. if (! empty($this->buildStack)) {
  805. $previous = implode(', ', $this->buildStack);
  806. $message = "Target [$concrete] is not instantiable while building [$previous].";
  807. } else {
  808. $message = "Target [$concrete] is not instantiable.";
  809. }
  810. throw new BindingResolutionException($message);
  811. }
  812. /**
  813. * Throw an exception for an unresolvable primitive.
  814. *
  815. * @param \ReflectionParameter $parameter
  816. * @return void
  817. *
  818. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  819. */
  820. protected function unresolvablePrimitive(ReflectionParameter $parameter)
  821. {
  822. $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";
  823. throw new BindingResolutionException($message);
  824. }
  825. /**
  826. * Register a new resolving callback.
  827. *
  828. * @param \Closure|string $abstract
  829. * @param \Closure|null $callback
  830. * @return void
  831. */
  832. public function resolving($abstract, Closure $callback = null)
  833. {
  834. if (is_string($abstract)) {
  835. $abstract = $this->getAlias($abstract);
  836. }
  837. if (is_null($callback) && $abstract instanceof Closure) {
  838. $this->globalResolvingCallbacks[] = $abstract;
  839. } else {
  840. $this->resolvingCallbacks[$abstract][] = $callback;
  841. }
  842. }
  843. /**
  844. * Register a new after resolving callback for all types.
  845. *
  846. * @param \Closure|string $abstract
  847. * @param \Closure|null $callback
  848. * @return void
  849. */
  850. public function afterResolving($abstract, Closure $callback = null)
  851. {
  852. if (is_string($abstract)) {
  853. $abstract = $this->getAlias($abstract);
  854. }
  855. if ($abstract instanceof Closure && is_null($callback)) {
  856. $this->globalAfterResolvingCallbacks[] = $abstract;
  857. } else {
  858. $this->afterResolvingCallbacks[$abstract][] = $callback;
  859. }
  860. }
  861. /**
  862. * Fire all of the resolving callbacks.
  863. *
  864. * @param string $abstract
  865. * @param mixed $object
  866. * @return void
  867. */
  868. protected function fireResolvingCallbacks($abstract, $object)
  869. {
  870. $this->fireCallbackArray($object, $this->globalResolvingCallbacks);
  871. $this->fireCallbackArray(
  872. $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
  873. );
  874. $this->fireAfterResolvingCallbacks($abstract, $object);
  875. }
  876. /**
  877. * Fire all of the after resolving callbacks.
  878. *
  879. * @param string $abstract
  880. * @param mixed $object
  881. * @return void
  882. */
  883. protected function fireAfterResolvingCallbacks($abstract, $object)
  884. {
  885. $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);
  886. $this->fireCallbackArray(
  887. $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
  888. );
  889. }
  890. /**
  891. * Get all callbacks for a given type.
  892. *
  893. * @param string $abstract
  894. * @param object $object
  895. * @param array $callbacksPerType
  896. *
  897. * @return array
  898. */
  899. protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
  900. {
  901. $results = [];
  902. foreach ($callbacksPerType as $type => $callbacks) {
  903. if ($type === $abstract || $object instanceof $type) {
  904. $results = array_merge($results, $callbacks);
  905. }
  906. }
  907. return $results;
  908. }
  909. /**
  910. * Fire an array of callbacks with an object.
  911. *
  912. * @param mixed $object
  913. * @param array $callbacks
  914. * @return void
  915. */
  916. protected function fireCallbackArray($object, array $callbacks)
  917. {
  918. foreach ($callbacks as $callback) {
  919. $callback($object, $this);
  920. }
  921. }
  922. /**
  923. * Get the container's bindings.
  924. *
  925. * @return array
  926. */
  927. public function getBindings()
  928. {
  929. return $this->bindings;
  930. }
  931. /**
  932. * Get the alias for an abstract if available.
  933. *
  934. * @param string $abstract
  935. * @return string
  936. *
  937. * @throws \LogicException
  938. */
  939. public function getAlias($abstract)
  940. {
  941. if (! isset($this->aliases[$abstract])) {
  942. return $abstract;
  943. }
  944. if ($this->aliases[$abstract] === $abstract) {
  945. throw new LogicException("[{$abstract}] is aliased to itself.");
  946. }
  947. return $this->getAlias($this->aliases[$abstract]);
  948. }
  949. /**
  950. * Get the extender callbacks for a given type.
  951. *
  952. * @param string $abstract
  953. * @return array
  954. */
  955. protected function getExtenders($abstract)
  956. {
  957. $abstract = $this->getAlias($abstract);
  958. if (isset($this->extenders[$abstract])) {
  959. return $this->extenders[$abstract];
  960. }
  961. return [];
  962. }
  963. /**
  964. * Remove all of the extender callbacks for a given type.
  965. *
  966. * @param string $abstract
  967. * @return void
  968. */
  969. public function forgetExtenders($abstract)
  970. {
  971. unset($this->extenders[$this->getAlias($abstract)]);
  972. }
  973. /**
  974. * Drop all of the stale instances and aliases.
  975. *
  976. * @param string $abstract
  977. * @return void
  978. */
  979. protected function dropStaleInstances($abstract)
  980. {
  981. unset($this->instances[$abstract], $this->aliases[$abstract]);
  982. }
  983. /**
  984. * Remove a resolved instance from the instance cache.
  985. *
  986. * @param string $abstract
  987. * @return void
  988. */
  989. public function forgetInstance($abstract)
  990. {
  991. unset($this->instances[$abstract]);
  992. }
  993. /**
  994. * Clear all of the instances from the container.
  995. *
  996. * @return void
  997. */
  998. public function forgetInstances()
  999. {
  1000. $this->instances = [];
  1001. }
  1002. /**
  1003. * Flush the container of all bindings and resolved instances.
  1004. *
  1005. * @return void
  1006. */
  1007. public function flush()
  1008. {
  1009. $this->aliases = [];
  1010. $this->resolved = [];
  1011. $this->bindings = [];
  1012. $this->instances = [];
  1013. $this->abstractAliases = [];
  1014. }
  1015. /**
  1016. * Set the globally available instance of the container.
  1017. *
  1018. * @return static
  1019. */
  1020. public static function getInstance()
  1021. {
  1022. if (is_null(static::$instance)) {
  1023. static::$instance = new static;
  1024. }
  1025. return static::$instance;
  1026. }
  1027. /**
  1028. * Set the shared instance of the container.
  1029. *
  1030. * @param \Illuminate\Contracts\Container\Container|null $container
  1031. * @return \Illuminate\Contracts\Container\Container|static
  1032. */
  1033. public static function setInstance(ContainerContract $container = null)
  1034. {
  1035. return static::$instance = $container;
  1036. }
  1037. /**
  1038. * Determine if a given offset exists.
  1039. *
  1040. * @param string $key
  1041. * @return bool
  1042. */
  1043. public function offsetExists($key)
  1044. {
  1045. return $this->bound($key);
  1046. }
  1047. /**
  1048. * Get the value at a given offset.
  1049. *
  1050. * @param string $key
  1051. * @return mixed
  1052. */
  1053. public function offsetGet($key)
  1054. {
  1055. return $this->make($key);
  1056. }
  1057. /**
  1058. * Set the value at a given offset.
  1059. *
  1060. * @param string $key
  1061. * @param mixed $value
  1062. * @return void
  1063. */
  1064. public function offsetSet($key, $value)
  1065. {
  1066. $this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
  1067. return $value;
  1068. });
  1069. }
  1070. /**
  1071. * Unset the value at a given offset.
  1072. *
  1073. * @param string $key
  1074. * @return void
  1075. */
  1076. public function offsetUnset($key)
  1077. {
  1078. unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
  1079. }
  1080. /**
  1081. * Dynamically access container services.
  1082. *
  1083. * @param string $key
  1084. * @return mixed
  1085. */
  1086. public function __get($key)
  1087. {
  1088. return $this[$key];
  1089. }
  1090. /**
  1091. * Dynamically set container services.
  1092. *
  1093. * @param string $key
  1094. * @param mixed $value
  1095. * @return void
  1096. */
  1097. public function __set($key, $value)
  1098. {
  1099. $this[$key] = $value;
  1100. }
  1101. }