Container.php 53 KB

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