Container.php 33 KB

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