Container.php 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851
  1. <?php
  2. namespace Illuminate\Container;
  3. use ArrayAccess;
  4. use Closure;
  5. use Exception;
  6. use Illuminate\Container\Attributes\Bind;
  7. use Illuminate\Container\Attributes\Scoped;
  8. use Illuminate\Container\Attributes\Singleton;
  9. use Illuminate\Contracts\Container\BindingResolutionException;
  10. use Illuminate\Contracts\Container\CircularDependencyException;
  11. use Illuminate\Contracts\Container\Container as ContainerContract;
  12. use Illuminate\Contracts\Container\ContextualAttribute;
  13. use Illuminate\Contracts\Container\SelfBuilding;
  14. use Illuminate\Support\Traits\ReflectsClosures;
  15. use LogicException;
  16. use ReflectionAttribute;
  17. use ReflectionClass;
  18. use ReflectionException;
  19. use ReflectionFunction;
  20. use ReflectionParameter;
  21. use TypeError;
  22. class Container implements ArrayAccess, ContainerContract
  23. {
  24. use ReflectsClosures;
  25. /**
  26. * The current globally available container (if any).
  27. *
  28. * @var static
  29. */
  30. protected static $instance;
  31. /**
  32. * An array of the types that have been resolved.
  33. *
  34. * @var bool[]
  35. */
  36. protected $resolved = [];
  37. /**
  38. * The container's bindings.
  39. *
  40. * @var array[]
  41. */
  42. protected $bindings = [];
  43. /**
  44. * The container's method bindings.
  45. *
  46. * @var \Closure[]
  47. */
  48. protected $methodBindings = [];
  49. /**
  50. * The container's shared instances.
  51. *
  52. * @var object[]
  53. */
  54. protected $instances = [];
  55. /**
  56. * The container's scoped instances.
  57. *
  58. * @var array
  59. */
  60. protected $scopedInstances = [];
  61. /**
  62. * The registered type aliases.
  63. *
  64. * @var string[]
  65. */
  66. protected $aliases = [];
  67. /**
  68. * The registered aliases keyed by the abstract name.
  69. *
  70. * @var array[]
  71. */
  72. protected $abstractAliases = [];
  73. /**
  74. * The extension closures for services.
  75. *
  76. * @var array[]
  77. */
  78. protected $extenders = [];
  79. /**
  80. * All of the registered tags.
  81. *
  82. * @var array[]
  83. */
  84. protected $tags = [];
  85. /**
  86. * The stack of concretions currently being built.
  87. *
  88. * @var array[]
  89. */
  90. protected $buildStack = [];
  91. /**
  92. * The parameter override stack.
  93. *
  94. * @var array[]
  95. */
  96. protected $with = [];
  97. /**
  98. * The contextual binding map.
  99. *
  100. * @var array[]
  101. */
  102. public $contextual = [];
  103. /**
  104. * The contextual attribute handlers.
  105. *
  106. * @var array[]
  107. */
  108. public $contextualAttributes = [];
  109. /**
  110. * Whether an abstract class has already had its attributes checked for bindings.
  111. *
  112. * @var array<class-string, true>
  113. */
  114. protected $checkedForAttributeBindings = [];
  115. /**
  116. * Whether a class has already been checked for Singleton or Scoped attributes.
  117. *
  118. * @var array<class-string, "scoped"|"singleton"|null>
  119. */
  120. protected $checkedForSingletonOrScopedAttributes = [];
  121. /**
  122. * All of the registered rebound callbacks.
  123. *
  124. * @var array[]
  125. */
  126. protected $reboundCallbacks = [];
  127. /**
  128. * All of the global before resolving callbacks.
  129. *
  130. * @var \Closure[]
  131. */
  132. protected $globalBeforeResolvingCallbacks = [];
  133. /**
  134. * All of the global resolving callbacks.
  135. *
  136. * @var \Closure[]
  137. */
  138. protected $globalResolvingCallbacks = [];
  139. /**
  140. * All of the global after resolving callbacks.
  141. *
  142. * @var \Closure[]
  143. */
  144. protected $globalAfterResolvingCallbacks = [];
  145. /**
  146. * All of the before resolving callbacks by class type.
  147. *
  148. * @var array[]
  149. */
  150. protected $beforeResolvingCallbacks = [];
  151. /**
  152. * All of the resolving callbacks by class type.
  153. *
  154. * @var array[]
  155. */
  156. protected $resolvingCallbacks = [];
  157. /**
  158. * All of the after resolving callbacks by class type.
  159. *
  160. * @var array[]
  161. */
  162. protected $afterResolvingCallbacks = [];
  163. /**
  164. * All of the after resolving attribute callbacks by class type.
  165. *
  166. * @var array[]
  167. */
  168. protected $afterResolvingAttributeCallbacks = [];
  169. /**
  170. * The callback used to determine the container's environment.
  171. *
  172. * @var (callable(array<int, string>|string): bool|string)|null
  173. */
  174. protected $environmentResolver = null;
  175. /**
  176. * Define a contextual binding.
  177. *
  178. * @param array|string $concrete
  179. * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
  180. */
  181. public function when($concrete)
  182. {
  183. $aliases = [];
  184. foreach (Util::arrayWrap($concrete) as $c) {
  185. $aliases[] = $this->getAlias($c);
  186. }
  187. return new ContextualBindingBuilder($this, $aliases);
  188. }
  189. /**
  190. * Define a contextual binding based on an attribute.
  191. *
  192. * @return void
  193. */
  194. public function whenHasAttribute(string $attribute, Closure $handler)
  195. {
  196. $this->contextualAttributes[$attribute] = $handler;
  197. }
  198. /**
  199. * Determine if the given abstract type has been bound.
  200. *
  201. * @param string $abstract
  202. * @return bool
  203. */
  204. public function bound($abstract)
  205. {
  206. return isset($this->bindings[$abstract]) ||
  207. isset($this->instances[$abstract]) ||
  208. $this->isAlias($abstract);
  209. }
  210. /**
  211. * {@inheritdoc}
  212. */
  213. public function has(string $id): bool
  214. {
  215. return $this->bound($id);
  216. }
  217. /**
  218. * Determine if the given abstract type has been resolved.
  219. *
  220. * @param string $abstract
  221. * @return bool
  222. */
  223. public function resolved($abstract)
  224. {
  225. if ($this->isAlias($abstract)) {
  226. $abstract = $this->getAlias($abstract);
  227. }
  228. return isset($this->resolved[$abstract]) ||
  229. isset($this->instances[$abstract]);
  230. }
  231. /**
  232. * Determine if a given type is shared.
  233. *
  234. * @param string $abstract
  235. * @return bool
  236. */
  237. public function isShared($abstract)
  238. {
  239. if (isset($this->instances[$abstract])) {
  240. return true;
  241. }
  242. if (isset($this->bindings[$abstract]['shared']) && $this->bindings[$abstract]['shared'] === true) {
  243. return true;
  244. }
  245. if (! class_exists($abstract)) {
  246. return false;
  247. }
  248. if (($scopedType = $this->getScopedTyped($abstract)) === null) {
  249. return false;
  250. }
  251. if ($scopedType === 'scoped') {
  252. if (! in_array($abstract, $this->scopedInstances, true)) {
  253. $this->scopedInstances[] = $abstract;
  254. }
  255. }
  256. return true;
  257. }
  258. /**
  259. * Determine if a ReflectionClass has scoping attributes applied.
  260. *
  261. * @param ReflectionClass<object>|class-string $reflection
  262. * @return "singleton"|"scoped"|null
  263. */
  264. protected function getScopedTyped(ReflectionClass|string $reflection): ?string
  265. {
  266. $className = $reflection instanceof ReflectionClass
  267. ? $reflection->getName()
  268. : $reflection;
  269. if (array_key_exists($className, $this->checkedForSingletonOrScopedAttributes)) {
  270. return $this->checkedForSingletonOrScopedAttributes[$className];
  271. }
  272. try {
  273. $reflection = $reflection instanceof ReflectionClass
  274. ? $reflection
  275. : new ReflectionClass($reflection);
  276. } catch (ReflectionException) {
  277. return $this->checkedForSingletonOrScopedAttributes[$className] = null;
  278. }
  279. $type = null;
  280. if (! empty($reflection->getAttributes(Singleton::class))) {
  281. $type = 'singleton';
  282. } elseif (! empty($reflection->getAttributes(Scoped::class))) {
  283. $type = 'scoped';
  284. }
  285. return $this->checkedForSingletonOrScopedAttributes[$className] = $type;
  286. }
  287. /**
  288. * Determine if a given string is an alias.
  289. *
  290. * @param string $name
  291. * @return bool
  292. */
  293. public function isAlias($name)
  294. {
  295. return isset($this->aliases[$name]);
  296. }
  297. /**
  298. * Register a binding with the container.
  299. *
  300. * @param \Closure|string $abstract
  301. * @param \Closure|string|null $concrete
  302. * @param bool $shared
  303. * @return void
  304. *
  305. * @throws \TypeError
  306. * @throws ReflectionException
  307. */
  308. public function bind($abstract, $concrete = null, $shared = false)
  309. {
  310. if ($abstract instanceof Closure) {
  311. return $this->bindBasedOnClosureReturnTypes(
  312. $abstract, $concrete, $shared
  313. );
  314. }
  315. $this->dropStaleInstances($abstract);
  316. // If no concrete type was given, we will simply set the concrete type to the
  317. // abstract type. After that, the concrete type to be registered as shared
  318. // without being forced to state their classes in both of the parameters.
  319. if (is_null($concrete)) {
  320. $concrete = $abstract;
  321. }
  322. // If the factory is not a Closure, it means it is just a class name which is
  323. // bound into this container to the abstract type and we will just wrap it
  324. // up inside its own Closure to give us more convenience when extending.
  325. if (! $concrete instanceof Closure) {
  326. if (! is_string($concrete)) {
  327. throw new TypeError(self::class.'::bind(): Argument #2 ($concrete) must be of type Closure|string|null');
  328. }
  329. $concrete = $this->getClosure($abstract, $concrete);
  330. }
  331. $this->bindings[$abstract] = ['concrete' => $concrete, 'shared' => $shared];
  332. // If the abstract type was already resolved in this container we'll fire the
  333. // rebound listener so that any objects which have already gotten resolved
  334. // can have their copy of the object updated via the listener callbacks.
  335. if ($this->resolved($abstract)) {
  336. $this->rebound($abstract);
  337. }
  338. }
  339. /**
  340. * Get the Closure to be used when building a type.
  341. *
  342. * @param string $abstract
  343. * @param string $concrete
  344. * @return \Closure
  345. */
  346. protected function getClosure($abstract, $concrete)
  347. {
  348. return function ($container, $parameters = []) use ($abstract, $concrete) {
  349. if ($abstract == $concrete) {
  350. return $container->build($concrete);
  351. }
  352. return $container->resolve(
  353. $concrete, $parameters, raiseEvents: false
  354. );
  355. };
  356. }
  357. /**
  358. * Determine if the container has a method binding.
  359. *
  360. * @param string $method
  361. * @return bool
  362. */
  363. public function hasMethodBinding($method)
  364. {
  365. return isset($this->methodBindings[$method]);
  366. }
  367. /**
  368. * Bind a callback to resolve with Container::call.
  369. *
  370. * @param array|string $method
  371. * @param \Closure $callback
  372. * @return void
  373. */
  374. public function bindMethod($method, $callback)
  375. {
  376. $this->methodBindings[$this->parseBindMethod($method)] = $callback;
  377. }
  378. /**
  379. * Get the method to be bound in class@method format.
  380. *
  381. * @param array|string $method
  382. * @return string
  383. */
  384. protected function parseBindMethod($method)
  385. {
  386. if (is_array($method)) {
  387. return $method[0].'@'.$method[1];
  388. }
  389. return $method;
  390. }
  391. /**
  392. * Get the method binding for the given method.
  393. *
  394. * @param string $method
  395. * @param mixed $instance
  396. * @return mixed
  397. */
  398. public function callMethodBinding($method, $instance)
  399. {
  400. return call_user_func($this->methodBindings[$method], $instance, $this);
  401. }
  402. /**
  403. * Add a contextual binding to the container.
  404. *
  405. * @param string $concrete
  406. * @param \Closure|string $abstract
  407. * @param \Closure|string $implementation
  408. * @return void
  409. */
  410. public function addContextualBinding($concrete, $abstract, $implementation)
  411. {
  412. $this->contextual[$concrete][$this->getAlias($abstract)] = $implementation;
  413. }
  414. /**
  415. * Register a binding if it hasn't already been registered.
  416. *
  417. * @param \Closure|string $abstract
  418. * @param \Closure|string|null $concrete
  419. * @param bool $shared
  420. * @return void
  421. */
  422. public function bindIf($abstract, $concrete = null, $shared = false)
  423. {
  424. if (! $this->bound($abstract)) {
  425. $this->bind($abstract, $concrete, $shared);
  426. }
  427. }
  428. /**
  429. * Register a shared binding in the container.
  430. *
  431. * @param \Closure|string $abstract
  432. * @param \Closure|string|null $concrete
  433. * @return void
  434. */
  435. public function singleton($abstract, $concrete = null)
  436. {
  437. $this->bind($abstract, $concrete, true);
  438. }
  439. /**
  440. * Register a shared binding if it hasn't already been registered.
  441. *
  442. * @param \Closure|string $abstract
  443. * @param \Closure|string|null $concrete
  444. * @return void
  445. */
  446. public function singletonIf($abstract, $concrete = null)
  447. {
  448. if (! $this->bound($abstract)) {
  449. $this->singleton($abstract, $concrete);
  450. }
  451. }
  452. /**
  453. * Register a scoped binding in the container.
  454. *
  455. * @param \Closure|string $abstract
  456. * @param \Closure|string|null $concrete
  457. * @return void
  458. */
  459. public function scoped($abstract, $concrete = null)
  460. {
  461. $this->scopedInstances[] = $abstract;
  462. $this->singleton($abstract, $concrete);
  463. }
  464. /**
  465. * Register a scoped binding if it hasn't already been registered.
  466. *
  467. * @param \Closure|string $abstract
  468. * @param \Closure|string|null $concrete
  469. * @return void
  470. */
  471. public function scopedIf($abstract, $concrete = null)
  472. {
  473. if (! $this->bound($abstract)) {
  474. $this->scoped($abstract, $concrete);
  475. }
  476. }
  477. /**
  478. * Register a binding with the container based on the given Closure's return types.
  479. *
  480. * @param \Closure|string $abstract
  481. * @param \Closure|string|null $concrete
  482. * @param bool $shared
  483. * @return void
  484. */
  485. protected function bindBasedOnClosureReturnTypes($abstract, $concrete = null, $shared = false)
  486. {
  487. $abstracts = $this->closureReturnTypes($abstract);
  488. $concrete = $abstract;
  489. foreach ($abstracts as $abstract) {
  490. $this->bind($abstract, $concrete, $shared);
  491. }
  492. }
  493. /**
  494. * "Extend" an abstract type in the container.
  495. *
  496. * @param string $abstract
  497. * @return void
  498. *
  499. * @throws \InvalidArgumentException
  500. */
  501. public function extend($abstract, Closure $closure)
  502. {
  503. $abstract = $this->getAlias($abstract);
  504. if (isset($this->instances[$abstract])) {
  505. $this->instances[$abstract] = $closure($this->instances[$abstract], $this);
  506. $this->rebound($abstract);
  507. } else {
  508. $this->extenders[$abstract][] = $closure;
  509. if ($this->resolved($abstract)) {
  510. $this->rebound($abstract);
  511. }
  512. }
  513. }
  514. /**
  515. * Register an existing instance as shared in the container.
  516. *
  517. * @template TInstance of mixed
  518. *
  519. * @param string $abstract
  520. * @param TInstance $instance
  521. * @return TInstance
  522. */
  523. public function instance($abstract, $instance)
  524. {
  525. $this->removeAbstractAlias($abstract);
  526. $isBound = $this->bound($abstract);
  527. unset($this->aliases[$abstract]);
  528. // We'll check to determine if this type has been bound before, and if it has
  529. // we will fire the rebound callbacks registered with the container and it
  530. // can be updated with consuming classes that have gotten resolved here.
  531. $this->instances[$abstract] = $instance;
  532. if ($isBound) {
  533. $this->rebound($abstract);
  534. }
  535. return $instance;
  536. }
  537. /**
  538. * Remove an alias from the contextual binding alias cache.
  539. *
  540. * @param string $searched
  541. * @return void
  542. */
  543. protected function removeAbstractAlias($searched)
  544. {
  545. if (! isset($this->aliases[$searched])) {
  546. return;
  547. }
  548. foreach ($this->abstractAliases as $abstract => $aliases) {
  549. foreach ($aliases as $index => $alias) {
  550. if ($alias == $searched) {
  551. unset($this->abstractAliases[$abstract][$index]);
  552. }
  553. }
  554. }
  555. }
  556. /**
  557. * Assign a set of tags to a given binding.
  558. *
  559. * @param array|string $abstracts
  560. * @param mixed ...$tags
  561. * @return void
  562. */
  563. public function tag($abstracts, $tags)
  564. {
  565. $tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1);
  566. foreach ($tags as $tag) {
  567. if (! isset($this->tags[$tag])) {
  568. $this->tags[$tag] = [];
  569. }
  570. foreach ((array) $abstracts as $abstract) {
  571. $this->tags[$tag][] = $abstract;
  572. }
  573. }
  574. }
  575. /**
  576. * Resolve all of the bindings for a given tag.
  577. *
  578. * @param string $tag
  579. * @return iterable
  580. */
  581. public function tagged($tag)
  582. {
  583. if (! isset($this->tags[$tag])) {
  584. return [];
  585. }
  586. return new RewindableGenerator(function () use ($tag) {
  587. foreach ($this->tags[$tag] as $abstract) {
  588. yield $this->make($abstract);
  589. }
  590. }, count($this->tags[$tag]));
  591. }
  592. /**
  593. * Alias a type to a different name.
  594. *
  595. * @param string $abstract
  596. * @param string $alias
  597. * @return void
  598. *
  599. * @throws \LogicException
  600. */
  601. public function alias($abstract, $alias)
  602. {
  603. if ($alias === $abstract) {
  604. throw new LogicException("[{$abstract}] is aliased to itself.");
  605. }
  606. $this->removeAbstractAlias($alias);
  607. $this->aliases[$alias] = $abstract;
  608. $this->abstractAliases[$abstract][] = $alias;
  609. }
  610. /**
  611. * Bind a new callback to an abstract's rebind event.
  612. *
  613. * @param string $abstract
  614. * @return mixed
  615. */
  616. public function rebinding($abstract, Closure $callback)
  617. {
  618. $this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
  619. if ($this->bound($abstract)) {
  620. return $this->make($abstract);
  621. }
  622. }
  623. /**
  624. * Refresh an instance on the given target and method.
  625. *
  626. * @param string $abstract
  627. * @param mixed $target
  628. * @param string $method
  629. * @return mixed
  630. */
  631. public function refresh($abstract, $target, $method)
  632. {
  633. return $this->rebinding($abstract, function ($app, $instance) use ($target, $method) {
  634. $target->{$method}($instance);
  635. });
  636. }
  637. /**
  638. * Fire the "rebound" callbacks for the given abstract type.
  639. *
  640. * @param string $abstract
  641. * @return void
  642. */
  643. protected function rebound($abstract)
  644. {
  645. if (! $callbacks = $this->getReboundCallbacks($abstract)) {
  646. return;
  647. }
  648. $instance = $this->make($abstract);
  649. foreach ($callbacks as $callback) {
  650. $callback($this, $instance);
  651. }
  652. }
  653. /**
  654. * Get the rebound callbacks for a given type.
  655. *
  656. * @param string $abstract
  657. * @return array
  658. */
  659. protected function getReboundCallbacks($abstract)
  660. {
  661. return $this->reboundCallbacks[$abstract] ?? [];
  662. }
  663. /**
  664. * Wrap the given closure such that its dependencies will be injected when executed.
  665. *
  666. * @return \Closure
  667. */
  668. public function wrap(Closure $callback, array $parameters = [])
  669. {
  670. return fn () => $this->call($callback, $parameters);
  671. }
  672. /**
  673. * Call the given Closure / class@method and inject its dependencies.
  674. *
  675. * @param callable|string $callback
  676. * @param array<string, mixed> $parameters
  677. * @param string|null $defaultMethod
  678. * @return mixed
  679. *
  680. * @throws \InvalidArgumentException
  681. */
  682. public function call($callback, array $parameters = [], $defaultMethod = null)
  683. {
  684. $pushedToBuildStack = false;
  685. if (($className = $this->getClassForCallable($callback)) && ! in_array(
  686. $className,
  687. $this->buildStack,
  688. true
  689. )) {
  690. $this->buildStack[] = $className;
  691. $pushedToBuildStack = true;
  692. }
  693. $result = BoundMethod::call($this, $callback, $parameters, $defaultMethod);
  694. if ($pushedToBuildStack) {
  695. array_pop($this->buildStack);
  696. }
  697. return $result;
  698. }
  699. /**
  700. * Get the class name for the given callback, if one can be determined.
  701. *
  702. * @param callable|string $callback
  703. * @return string|false
  704. */
  705. protected function getClassForCallable($callback)
  706. {
  707. if (is_callable($callback) &&
  708. ! ($reflector = new ReflectionFunction($callback(...)))->isAnonymous()) {
  709. return $reflector->getClosureScopeClass()->name ?? false;
  710. }
  711. return false;
  712. }
  713. /**
  714. * Get a closure to resolve the given type from the container.
  715. *
  716. * @template TClass of object
  717. *
  718. * @param string|class-string<TClass> $abstract
  719. * @return ($abstract is class-string<TClass> ? \Closure(): TClass : \Closure(): mixed)
  720. */
  721. public function factory($abstract)
  722. {
  723. return fn () => $this->make($abstract);
  724. }
  725. /**
  726. * An alias function name for make().
  727. *
  728. * @template TClass of object
  729. *
  730. * @param string|class-string<TClass>|callable $abstract
  731. * @return ($abstract is class-string<TClass> ? TClass : mixed)
  732. *
  733. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  734. */
  735. public function makeWith($abstract, array $parameters = [])
  736. {
  737. return $this->make($abstract, $parameters);
  738. }
  739. /**
  740. * Resolve the given type from the container.
  741. *
  742. * @template TClass of object
  743. *
  744. * @param string|class-string<TClass> $abstract
  745. * @return ($abstract is class-string<TClass> ? TClass : mixed)
  746. *
  747. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  748. */
  749. public function make($abstract, array $parameters = [])
  750. {
  751. return $this->resolve($abstract, $parameters);
  752. }
  753. /**
  754. * {@inheritdoc}
  755. *
  756. * @template TClass of object
  757. *
  758. * @param string|class-string<TClass> $id
  759. * @return ($id is class-string<TClass> ? TClass : mixed)
  760. */
  761. public function get(string $id)
  762. {
  763. try {
  764. return $this->resolve($id);
  765. } catch (Exception $e) {
  766. if ($this->has($id) || $e instanceof CircularDependencyException) {
  767. throw $e;
  768. }
  769. throw new EntryNotFoundException($id, is_int($e->getCode()) ? $e->getCode() : 0, $e);
  770. }
  771. }
  772. /**
  773. * Resolve the given type from the container.
  774. *
  775. * @template TClass of object
  776. *
  777. * @param string|class-string<TClass>|callable $abstract
  778. * @param array $parameters
  779. * @param bool $raiseEvents
  780. * @return ($abstract is class-string<TClass> ? TClass : mixed)
  781. *
  782. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  783. * @throws \Illuminate\Contracts\Container\CircularDependencyException
  784. */
  785. protected function resolve($abstract, $parameters = [], $raiseEvents = true)
  786. {
  787. $abstract = $this->getAlias($abstract);
  788. // First we'll fire any event handlers which handle the "before" resolving of
  789. // specific types. This gives some hooks the chance to add various extends
  790. // calls to change the resolution of objects that they're interested in.
  791. if ($raiseEvents) {
  792. $this->fireBeforeResolvingCallbacks($abstract, $parameters);
  793. }
  794. $concrete = $this->getContextualConcrete($abstract);
  795. $needsContextualBuild = ! empty($parameters) || ! is_null($concrete);
  796. // If an instance of the type is currently being managed as a singleton we'll
  797. // just return an existing instance instead of instantiating new instances
  798. // so the developer can keep using the same objects instance every time.
  799. if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
  800. return $this->instances[$abstract];
  801. }
  802. $this->with[] = $parameters;
  803. if (is_null($concrete)) {
  804. $concrete = $this->getConcrete($abstract);
  805. }
  806. // We're ready to instantiate an instance of the concrete type registered for
  807. // the binding. This will instantiate the types, as well as resolve any of
  808. // its "nested" dependencies recursively until all have gotten resolved.
  809. $object = $this->isBuildable($concrete, $abstract)
  810. ? $this->build($concrete)
  811. : $this->make($concrete);
  812. // If we defined any extenders for this type, we'll need to spin through them
  813. // and apply them to the object being built. This allows for the extension
  814. // of services, such as changing configuration or decorating the object.
  815. foreach ($this->getExtenders($abstract) as $extender) {
  816. $object = $extender($object, $this);
  817. }
  818. // If the requested type is registered as a singleton we'll want to cache off
  819. // the instances in "memory" so we can return it later without creating an
  820. // entirely new instance of an object on each subsequent request for it.
  821. if ($this->isShared($abstract) && ! $needsContextualBuild) {
  822. $this->instances[$abstract] = $object;
  823. }
  824. if ($raiseEvents) {
  825. $this->fireResolvingCallbacks($abstract, $object);
  826. }
  827. // Before returning, we will also set the resolved flag to "true" and pop off
  828. // the parameter overrides for this build. After those two things are done
  829. // we will be ready to return back the fully constructed class instance.
  830. if (! $needsContextualBuild) {
  831. $this->resolved[$abstract] = true;
  832. }
  833. array_pop($this->with);
  834. return $object;
  835. }
  836. /**
  837. * Get the concrete type for a given abstract.
  838. *
  839. * @param string|callable $abstract
  840. * @return mixed
  841. */
  842. protected function getConcrete($abstract)
  843. {
  844. // If we don't have a registered resolver or concrete for the type, we'll just
  845. // assume each type is a concrete name and will attempt to resolve it as is
  846. // since the container should be able to resolve concretes automatically.
  847. if (isset($this->bindings[$abstract])) {
  848. return $this->bindings[$abstract]['concrete'];
  849. }
  850. if ($this->environmentResolver === null ||
  851. ($this->checkedForAttributeBindings[$abstract] ?? false) || ! is_string($abstract)) {
  852. return $abstract;
  853. }
  854. return $this->getConcreteBindingFromAttributes($abstract);
  855. }
  856. /**
  857. * Get the concrete binding for an abstract from the Bind attribute.
  858. *
  859. * @param string $abstract
  860. * @return mixed
  861. */
  862. protected function getConcreteBindingFromAttributes($abstract)
  863. {
  864. $this->checkedForAttributeBindings[$abstract] = true;
  865. try {
  866. $reflected = new ReflectionClass($abstract);
  867. } catch (ReflectionException) {
  868. return $abstract;
  869. }
  870. $bindAttributes = $reflected->getAttributes(Bind::class);
  871. if ($bindAttributes === []) {
  872. return $abstract;
  873. }
  874. $concrete = $maybeConcrete = null;
  875. foreach ($bindAttributes as $reflectedAttribute) {
  876. $instance = $reflectedAttribute->newInstance();
  877. if ($instance->environments === ['*']) {
  878. $maybeConcrete = $instance->concrete;
  879. continue;
  880. }
  881. if ($this->currentEnvironmentIs($instance->environments)) {
  882. $concrete = $instance->concrete;
  883. break;
  884. }
  885. }
  886. if ($maybeConcrete !== null && $concrete === null) {
  887. $concrete = $maybeConcrete;
  888. }
  889. if ($concrete === null) {
  890. return $abstract;
  891. }
  892. match ($this->getScopedTyped($reflected)) {
  893. 'scoped' => $this->scoped($abstract, $concrete),
  894. 'singleton' => $this->singleton($abstract, $concrete),
  895. null => $this->bind($abstract, $concrete),
  896. };
  897. return $this->bindings[$abstract]['concrete'];
  898. }
  899. /**
  900. * Get the contextual concrete binding for the given abstract.
  901. *
  902. * @param string|callable $abstract
  903. * @return \Closure|string|array|null
  904. */
  905. protected function getContextualConcrete($abstract)
  906. {
  907. if (! is_null($binding = $this->findInContextualBindings($abstract))) {
  908. return $binding;
  909. }
  910. // Next we need to see if a contextual binding might be bound under an alias of the
  911. // given abstract type. So, we will need to check if any aliases exist with this
  912. // type and then spin through them and check for contextual bindings on these.
  913. if (empty($this->abstractAliases[$abstract])) {
  914. return;
  915. }
  916. foreach ($this->abstractAliases[$abstract] as $alias) {
  917. if (! is_null($binding = $this->findInContextualBindings($alias))) {
  918. return $binding;
  919. }
  920. }
  921. }
  922. /**
  923. * Find the concrete binding for the given abstract in the contextual binding array.
  924. *
  925. * @param string|callable $abstract
  926. * @return \Closure|string|null
  927. */
  928. protected function findInContextualBindings($abstract)
  929. {
  930. return $this->contextual[end($this->buildStack)][$abstract] ?? null;
  931. }
  932. /**
  933. * Determine if the given concrete is buildable.
  934. *
  935. * @param mixed $concrete
  936. * @param string $abstract
  937. * @return bool
  938. */
  939. protected function isBuildable($concrete, $abstract)
  940. {
  941. return $concrete === $abstract || $concrete instanceof Closure;
  942. }
  943. /**
  944. * Instantiate a concrete instance of the given type.
  945. *
  946. * @template TClass of object
  947. *
  948. * @param \Closure(static, array): TClass|class-string<TClass> $concrete
  949. * @return TClass
  950. *
  951. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  952. * @throws \Illuminate\Contracts\Container\CircularDependencyException
  953. */
  954. public function build($concrete)
  955. {
  956. // If the concrete type is actually a Closure, we will just execute it and
  957. // hand back the results of the functions, which allows functions to be
  958. // used as resolvers for more fine-tuned resolution of these objects.
  959. if ($concrete instanceof Closure) {
  960. $this->buildStack[] = spl_object_hash($concrete);
  961. try {
  962. return $concrete($this, $this->getLastParameterOverride());
  963. } finally {
  964. array_pop($this->buildStack);
  965. }
  966. }
  967. try {
  968. $reflector = new ReflectionClass($concrete);
  969. } catch (ReflectionException $e) {
  970. throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);
  971. }
  972. // If the type is not instantiable, the developer is attempting to resolve
  973. // an abstract type such as an Interface or Abstract Class and there is
  974. // no binding registered for the abstractions so we need to bail out.
  975. if (! $reflector->isInstantiable()) {
  976. return $this->notInstantiable($concrete);
  977. }
  978. if (is_a($concrete, SelfBuilding::class, true) &&
  979. ! in_array($concrete, $this->buildStack, true)) {
  980. return $this->buildSelfBuildingInstance($concrete, $reflector);
  981. }
  982. $this->buildStack[] = $concrete;
  983. $constructor = $reflector->getConstructor();
  984. // If there are no constructors, that means there are no dependencies then
  985. // we can just resolve the instances of the objects right away, without
  986. // resolving any other types or dependencies out of these containers.
  987. if (is_null($constructor)) {
  988. array_pop($this->buildStack);
  989. $this->fireAfterResolvingAttributeCallbacks(
  990. $reflector->getAttributes(), $instance = new $concrete
  991. );
  992. return $instance;
  993. }
  994. $dependencies = $constructor->getParameters();
  995. // Once we have all the constructor's parameters we can create each of the
  996. // dependency instances and then use the reflection instances to make a
  997. // new instance of this class, injecting the created dependencies in.
  998. try {
  999. $instances = $this->resolveDependencies($dependencies);
  1000. } finally {
  1001. array_pop($this->buildStack);
  1002. }
  1003. $this->fireAfterResolvingAttributeCallbacks(
  1004. $reflector->getAttributes(), $instance = new $concrete(...$instances)
  1005. );
  1006. return $instance;
  1007. }
  1008. /**
  1009. * Instantiate a concrete instance of the given self building type.
  1010. *
  1011. * @template TClass of object
  1012. *
  1013. * @param object{'newInstance': \Closure(static, array): TClass|class-string<TClass>} $concrete
  1014. * @param \ReflectionClass $reflector
  1015. * @return TClass
  1016. *
  1017. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1018. */
  1019. protected function buildSelfBuildingInstance($concrete, $reflector)
  1020. {
  1021. if (! method_exists($concrete, 'newInstance')) {
  1022. throw new BindingResolutionException("No newInstance method exists for [$concrete].");
  1023. }
  1024. $this->buildStack[] = $concrete;
  1025. $instance = $this->call([$concrete, 'newInstance']);
  1026. array_pop($this->buildStack);
  1027. $this->fireAfterResolvingAttributeCallbacks(
  1028. $reflector->getAttributes(), $instance
  1029. );
  1030. return $instance;
  1031. }
  1032. /**
  1033. * Resolve all of the dependencies from the ReflectionParameters.
  1034. *
  1035. * @param \ReflectionParameter[] $dependencies
  1036. * @return array
  1037. *
  1038. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1039. */
  1040. protected function resolveDependencies(array $dependencies)
  1041. {
  1042. $results = [];
  1043. foreach ($dependencies as $dependency) {
  1044. // If the dependency has an override for this particular build we will use
  1045. // that instead as the value. Otherwise, we will continue with this run
  1046. // of resolutions and let reflection attempt to determine the result.
  1047. if ($this->hasParameterOverride($dependency)) {
  1048. $results[] = $this->getParameterOverride($dependency);
  1049. continue;
  1050. }
  1051. $result = null;
  1052. if (! is_null($attribute = Util::getContextualAttributeFromDependency($dependency))) {
  1053. $result = $this->resolveFromAttribute($attribute);
  1054. }
  1055. // If the class is null, it means the dependency is a string or some other
  1056. // primitive type which we can not resolve since it is not a class and
  1057. // we will just bomb out with an error since we have no-where to go.
  1058. $result ??= is_null($className = Util::getParameterClassName($dependency))
  1059. ? $this->resolvePrimitive($dependency)
  1060. : $this->resolveClass($dependency, $className);
  1061. $this->fireAfterResolvingAttributeCallbacks($dependency->getAttributes(), $result);
  1062. if ($dependency->isVariadic()) {
  1063. $results = array_merge($results, $result);
  1064. } else {
  1065. $results[] = $result;
  1066. }
  1067. }
  1068. return $results;
  1069. }
  1070. /**
  1071. * Determine if the given dependency has a parameter override.
  1072. *
  1073. * @param \ReflectionParameter $dependency
  1074. * @return bool
  1075. */
  1076. protected function hasParameterOverride($dependency)
  1077. {
  1078. return array_key_exists(
  1079. $dependency->name, $this->getLastParameterOverride()
  1080. );
  1081. }
  1082. /**
  1083. * Get a parameter override for a dependency.
  1084. *
  1085. * @param \ReflectionParameter $dependency
  1086. * @return mixed
  1087. */
  1088. protected function getParameterOverride($dependency)
  1089. {
  1090. return $this->getLastParameterOverride()[$dependency->name];
  1091. }
  1092. /**
  1093. * Get the last parameter override.
  1094. *
  1095. * @return array
  1096. */
  1097. protected function getLastParameterOverride()
  1098. {
  1099. return count($this->with) ? array_last($this->with) : [];
  1100. }
  1101. /**
  1102. * Resolve a non-class hinted primitive dependency.
  1103. *
  1104. * @return mixed
  1105. *
  1106. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1107. */
  1108. protected function resolvePrimitive(ReflectionParameter $parameter)
  1109. {
  1110. if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->getName()))) {
  1111. return Util::unwrapIfClosure($concrete, $this);
  1112. }
  1113. if ($parameter->isDefaultValueAvailable()) {
  1114. return $parameter->getDefaultValue();
  1115. }
  1116. if ($parameter->isVariadic()) {
  1117. return [];
  1118. }
  1119. if ($parameter->hasType() && $parameter->allowsNull()) {
  1120. return null;
  1121. }
  1122. $this->unresolvablePrimitive($parameter);
  1123. }
  1124. /**
  1125. * Resolve a class based dependency from the container.
  1126. *
  1127. * @return mixed
  1128. *
  1129. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1130. */
  1131. protected function resolveClass(ReflectionParameter $parameter, ?string $className = null)
  1132. {
  1133. $className ??= Util::getParameterClassName($parameter);
  1134. // First we will check if a default value has been defined for the parameter.
  1135. // If it has, and no explicit binding exists, we should return it to avoid
  1136. // overriding any of the developer specified defaults for the parameters.
  1137. if ($parameter->isDefaultValueAvailable() &&
  1138. ! $this->bound($className) &&
  1139. $this->findInContextualBindings($className) === null) {
  1140. return $parameter->getDefaultValue();
  1141. }
  1142. try {
  1143. return $parameter->isVariadic()
  1144. ? $this->resolveVariadicClass($parameter)
  1145. : $this->make($className);
  1146. }
  1147. // If we can not resolve the class instance, we will check to see if the value
  1148. // is variadic. If it is, we will return an empty array as the value of the
  1149. // dependency similarly to how we handle scalar values in this situation.
  1150. catch (BindingResolutionException $e) {
  1151. if ($parameter->isVariadic()) {
  1152. array_pop($this->with);
  1153. return [];
  1154. }
  1155. throw $e;
  1156. }
  1157. }
  1158. /**
  1159. * Resolve a class based variadic dependency from the container.
  1160. *
  1161. * @return mixed
  1162. */
  1163. protected function resolveVariadicClass(ReflectionParameter $parameter)
  1164. {
  1165. $className = Util::getParameterClassName($parameter);
  1166. $abstract = $this->getAlias($className);
  1167. if (! is_array($concrete = $this->getContextualConcrete($abstract))) {
  1168. return $this->make($className);
  1169. }
  1170. return array_map(fn ($abstract) => $this->resolve($abstract), $concrete);
  1171. }
  1172. /**
  1173. * Resolve a dependency based on an attribute.
  1174. *
  1175. * @return mixed
  1176. */
  1177. public function resolveFromAttribute(ReflectionAttribute $attribute)
  1178. {
  1179. $handler = $this->contextualAttributes[$attribute->getName()] ?? null;
  1180. $instance = $attribute->newInstance();
  1181. if (is_null($handler) && method_exists($instance, 'resolve')) {
  1182. $handler = $instance->resolve(...);
  1183. }
  1184. if (is_null($handler)) {
  1185. throw new BindingResolutionException("Contextual binding attribute [{$attribute->getName()}] has no registered handler.");
  1186. }
  1187. return $handler($instance, $this);
  1188. }
  1189. /**
  1190. * Throw an exception that the concrete is not instantiable.
  1191. *
  1192. * @param string $concrete
  1193. * @return void
  1194. *
  1195. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1196. */
  1197. protected function notInstantiable($concrete)
  1198. {
  1199. if (! empty($this->buildStack)) {
  1200. $previous = implode(', ', $this->buildStack);
  1201. $message = "Target [$concrete] is not instantiable while building [$previous].";
  1202. } else {
  1203. $message = "Target [$concrete] is not instantiable.";
  1204. }
  1205. throw new BindingResolutionException($message);
  1206. }
  1207. /**
  1208. * Throw an exception for an unresolvable primitive.
  1209. *
  1210. * @return void
  1211. *
  1212. * @throws \Illuminate\Contracts\Container\BindingResolutionException
  1213. */
  1214. protected function unresolvablePrimitive(ReflectionParameter $parameter)
  1215. {
  1216. $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";
  1217. throw new BindingResolutionException($message);
  1218. }
  1219. /**
  1220. * Register a new before resolving callback for all types.
  1221. *
  1222. * @param \Closure|string $abstract
  1223. * @return void
  1224. */
  1225. public function beforeResolving($abstract, ?Closure $callback = null)
  1226. {
  1227. if (is_string($abstract)) {
  1228. $abstract = $this->getAlias($abstract);
  1229. }
  1230. if ($abstract instanceof Closure && is_null($callback)) {
  1231. $this->globalBeforeResolvingCallbacks[] = $abstract;
  1232. } else {
  1233. $this->beforeResolvingCallbacks[$abstract][] = $callback;
  1234. }
  1235. }
  1236. /**
  1237. * Register a new resolving callback.
  1238. *
  1239. * @param \Closure|string $abstract
  1240. * @return void
  1241. */
  1242. public function resolving($abstract, ?Closure $callback = null)
  1243. {
  1244. if (is_string($abstract)) {
  1245. $abstract = $this->getAlias($abstract);
  1246. }
  1247. if (is_null($callback) && $abstract instanceof Closure) {
  1248. $this->globalResolvingCallbacks[] = $abstract;
  1249. } else {
  1250. $this->resolvingCallbacks[$abstract][] = $callback;
  1251. }
  1252. }
  1253. /**
  1254. * Register a new after resolving callback for all types.
  1255. *
  1256. * @param \Closure|string $abstract
  1257. * @return void
  1258. */
  1259. public function afterResolving($abstract, ?Closure $callback = null)
  1260. {
  1261. if (is_string($abstract)) {
  1262. $abstract = $this->getAlias($abstract);
  1263. }
  1264. if ($abstract instanceof Closure && is_null($callback)) {
  1265. $this->globalAfterResolvingCallbacks[] = $abstract;
  1266. } else {
  1267. $this->afterResolvingCallbacks[$abstract][] = $callback;
  1268. }
  1269. }
  1270. /**
  1271. * Register a new after resolving attribute callback for all types.
  1272. *
  1273. * @return void
  1274. */
  1275. public function afterResolvingAttribute(string $attribute, \Closure $callback)
  1276. {
  1277. $this->afterResolvingAttributeCallbacks[$attribute][] = $callback;
  1278. }
  1279. /**
  1280. * Fire all of the before resolving callbacks.
  1281. *
  1282. * @param string $abstract
  1283. * @param array $parameters
  1284. * @return void
  1285. */
  1286. protected function fireBeforeResolvingCallbacks($abstract, $parameters = [])
  1287. {
  1288. $this->fireBeforeCallbackArray($abstract, $parameters, $this->globalBeforeResolvingCallbacks);
  1289. foreach ($this->beforeResolvingCallbacks as $type => $callbacks) {
  1290. if ($type === $abstract || is_subclass_of($abstract, $type)) {
  1291. $this->fireBeforeCallbackArray($abstract, $parameters, $callbacks);
  1292. }
  1293. }
  1294. }
  1295. /**
  1296. * Fire an array of callbacks with an object.
  1297. *
  1298. * @param string $abstract
  1299. * @param array $parameters
  1300. * @return void
  1301. */
  1302. protected function fireBeforeCallbackArray($abstract, $parameters, array $callbacks)
  1303. {
  1304. foreach ($callbacks as $callback) {
  1305. $callback($abstract, $parameters, $this);
  1306. }
  1307. }
  1308. /**
  1309. * Fire all of the resolving callbacks.
  1310. *
  1311. * @param string $abstract
  1312. * @param mixed $object
  1313. * @return void
  1314. */
  1315. protected function fireResolvingCallbacks($abstract, $object)
  1316. {
  1317. $this->fireCallbackArray($object, $this->globalResolvingCallbacks);
  1318. $this->fireCallbackArray(
  1319. $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
  1320. );
  1321. $this->fireAfterResolvingCallbacks($abstract, $object);
  1322. }
  1323. /**
  1324. * Fire all of the after resolving callbacks.
  1325. *
  1326. * @param string $abstract
  1327. * @param mixed $object
  1328. * @return void
  1329. */
  1330. protected function fireAfterResolvingCallbacks($abstract, $object)
  1331. {
  1332. $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);
  1333. $this->fireCallbackArray(
  1334. $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
  1335. );
  1336. }
  1337. /**
  1338. * Fire all of the after resolving attribute callbacks.
  1339. *
  1340. * @param \ReflectionAttribute[] $attributes
  1341. * @param mixed $object
  1342. * @return void
  1343. */
  1344. public function fireAfterResolvingAttributeCallbacks(array $attributes, $object)
  1345. {
  1346. foreach ($attributes as $attribute) {
  1347. if (is_a($attribute->getName(), ContextualAttribute::class, true)) {
  1348. $instance = $attribute->newInstance();
  1349. if (method_exists($instance, 'after')) {
  1350. $instance->after($instance, $object, $this);
  1351. }
  1352. }
  1353. $callbacks = $this->getCallbacksForType(
  1354. $attribute->getName(), $object, $this->afterResolvingAttributeCallbacks
  1355. );
  1356. foreach ($callbacks as $callback) {
  1357. $callback($attribute->newInstance(), $object, $this);
  1358. }
  1359. }
  1360. }
  1361. /**
  1362. * Get all callbacks for a given type.
  1363. *
  1364. * @param string $abstract
  1365. * @param object $object
  1366. * @return array
  1367. */
  1368. protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
  1369. {
  1370. $results = [];
  1371. foreach ($callbacksPerType as $type => $callbacks) {
  1372. if ($type === $abstract || $object instanceof $type) {
  1373. $results = array_merge($results, $callbacks);
  1374. }
  1375. }
  1376. return $results;
  1377. }
  1378. /**
  1379. * Fire an array of callbacks with an object.
  1380. *
  1381. * @param mixed $object
  1382. * @return void
  1383. */
  1384. protected function fireCallbackArray($object, array $callbacks)
  1385. {
  1386. foreach ($callbacks as $callback) {
  1387. $callback($object, $this);
  1388. }
  1389. }
  1390. /**
  1391. * Get the name of the binding the container is currently resolving.
  1392. *
  1393. * @return class-string|string|null
  1394. */
  1395. public function currentlyResolving()
  1396. {
  1397. return array_last($this->buildStack) ?: null;
  1398. }
  1399. /**
  1400. * Get the container's bindings.
  1401. *
  1402. * @return array
  1403. */
  1404. public function getBindings()
  1405. {
  1406. return $this->bindings;
  1407. }
  1408. /**
  1409. * Get the alias for an abstract if available.
  1410. *
  1411. * @param string $abstract
  1412. * @return string
  1413. */
  1414. public function getAlias($abstract)
  1415. {
  1416. return isset($this->aliases[$abstract])
  1417. ? $this->getAlias($this->aliases[$abstract])
  1418. : $abstract;
  1419. }
  1420. /**
  1421. * Get the extender callbacks for a given type.
  1422. *
  1423. * @param string $abstract
  1424. * @return array
  1425. */
  1426. protected function getExtenders($abstract)
  1427. {
  1428. return $this->extenders[$this->getAlias($abstract)] ?? [];
  1429. }
  1430. /**
  1431. * Remove all of the extender callbacks for a given type.
  1432. *
  1433. * @param string $abstract
  1434. * @return void
  1435. */
  1436. public function forgetExtenders($abstract)
  1437. {
  1438. unset($this->extenders[$this->getAlias($abstract)]);
  1439. }
  1440. /**
  1441. * Drop all of the stale instances and aliases.
  1442. *
  1443. * @param string $abstract
  1444. * @return void
  1445. */
  1446. protected function dropStaleInstances($abstract)
  1447. {
  1448. unset($this->instances[$abstract], $this->aliases[$abstract]);
  1449. }
  1450. /**
  1451. * Remove a resolved instance from the instance cache.
  1452. *
  1453. * @param string $abstract
  1454. * @return void
  1455. */
  1456. public function forgetInstance($abstract)
  1457. {
  1458. unset($this->instances[$abstract]);
  1459. }
  1460. /**
  1461. * Clear all of the instances from the container.
  1462. *
  1463. * @return void
  1464. */
  1465. public function forgetInstances()
  1466. {
  1467. $this->instances = [];
  1468. }
  1469. /**
  1470. * Clear all of the scoped instances from the container.
  1471. *
  1472. * @return void
  1473. */
  1474. public function forgetScopedInstances()
  1475. {
  1476. foreach ($this->scopedInstances as $scoped) {
  1477. if ($scoped instanceof Closure) {
  1478. foreach ($this->closureReturnTypes($scoped) as $type) {
  1479. unset($this->instances[$type]);
  1480. }
  1481. } else {
  1482. unset($this->instances[$scoped]);
  1483. }
  1484. }
  1485. }
  1486. /**
  1487. * Set the callback which determines the current container environment.
  1488. *
  1489. * @param (callable(array<int, string>|string): bool|string)|null $callback
  1490. * @return void
  1491. */
  1492. public function resolveEnvironmentUsing(?callable $callback)
  1493. {
  1494. $this->environmentResolver = $callback;
  1495. }
  1496. /**
  1497. * Determine the environment for the container.
  1498. *
  1499. * @param array<int, string>|string $environments
  1500. * @return bool
  1501. */
  1502. public function currentEnvironmentIs($environments)
  1503. {
  1504. return $this->environmentResolver === null
  1505. ? false
  1506. : call_user_func($this->environmentResolver, $environments);
  1507. }
  1508. /**
  1509. * Flush the container of all bindings and resolved instances.
  1510. *
  1511. * @return void
  1512. */
  1513. public function flush()
  1514. {
  1515. $this->aliases = [];
  1516. $this->resolved = [];
  1517. $this->bindings = [];
  1518. $this->instances = [];
  1519. $this->abstractAliases = [];
  1520. $this->scopedInstances = [];
  1521. $this->checkedForAttributeBindings = [];
  1522. $this->checkedForSingletonOrScopedAttributes = [];
  1523. }
  1524. /**
  1525. * Get the globally available instance of the container.
  1526. *
  1527. * @return static
  1528. */
  1529. public static function getInstance()
  1530. {
  1531. return static::$instance ??= new static;
  1532. }
  1533. /**
  1534. * Set the shared instance of the container.
  1535. *
  1536. * @return \Illuminate\Contracts\Container\Container|static
  1537. */
  1538. public static function setInstance(?ContainerContract $container = null)
  1539. {
  1540. return static::$instance = $container;
  1541. }
  1542. /**
  1543. * Determine if a given offset exists.
  1544. *
  1545. * @param string $key
  1546. */
  1547. public function offsetExists($key): bool
  1548. {
  1549. return $this->bound($key);
  1550. }
  1551. /**
  1552. * Get the value at a given offset.
  1553. *
  1554. * @param string $key
  1555. */
  1556. public function offsetGet($key): mixed
  1557. {
  1558. return $this->make($key);
  1559. }
  1560. /**
  1561. * Set the value at a given offset.
  1562. *
  1563. * @param string $key
  1564. * @param mixed $value
  1565. */
  1566. public function offsetSet($key, $value): void
  1567. {
  1568. $this->bind($key, $value instanceof Closure ? $value : fn () => $value);
  1569. }
  1570. /**
  1571. * Unset the value at a given offset.
  1572. *
  1573. * @param string $key
  1574. */
  1575. public function offsetUnset($key): void
  1576. {
  1577. unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
  1578. }
  1579. /**
  1580. * Dynamically access container services.
  1581. *
  1582. * @param string $key
  1583. * @return mixed
  1584. */
  1585. public function __get($key)
  1586. {
  1587. return $this[$key];
  1588. }
  1589. /**
  1590. * Dynamically set container services.
  1591. *
  1592. * @param string $key
  1593. * @param mixed $value
  1594. * @return void
  1595. */
  1596. public function __set($key, $value)
  1597. {
  1598. $this[$key] = $value;
  1599. }
  1600. }