App.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. use think\exception\ClassNotFoundException;
  13. use think\exception\HttpResponseException;
  14. use think\route\Dispatch;
  15. /**
  16. * App 应用管理
  17. */
  18. class App implements \ArrayAccess
  19. {
  20. const VERSION = '5.1.5';
  21. /**
  22. * 当前模块路径
  23. * @var string
  24. */
  25. protected $modulePath;
  26. /**
  27. * 应用调试模式
  28. * @var bool
  29. */
  30. protected $debug = true;
  31. /**
  32. * 应用开始时间
  33. * @var float
  34. */
  35. protected $beginTime;
  36. /**
  37. * 应用内存初始占用
  38. * @var integer
  39. */
  40. protected $beginMem;
  41. /**
  42. * 应用类库命名空间
  43. * @var string
  44. */
  45. protected $namespace = 'app';
  46. /**
  47. * 应用类库后缀
  48. * @var bool
  49. */
  50. protected $suffix = false;
  51. /**
  52. * 严格路由检测
  53. * @var bool
  54. */
  55. protected $routeMust;
  56. /**
  57. * 应用类库目录
  58. * @var string
  59. */
  60. protected $appPath;
  61. /**
  62. * 框架目录
  63. * @var string
  64. */
  65. protected $thinkPath;
  66. /**
  67. * 应用根目录
  68. * @var string
  69. */
  70. protected $rootPath;
  71. /**
  72. * 运行时目录
  73. * @var string
  74. */
  75. protected $runtimePath;
  76. /**
  77. * 配置目录
  78. * @var string
  79. */
  80. protected $configPath;
  81. /**
  82. * 路由目录
  83. * @var string
  84. */
  85. protected $routePath;
  86. /**
  87. * 配置后缀
  88. * @var string
  89. */
  90. protected $configExt;
  91. /**
  92. * 应用调度实例
  93. * @var Dispatch
  94. */
  95. protected $dispatch;
  96. /**
  97. * 容器对象实例
  98. * @var Container
  99. */
  100. protected $container;
  101. /**
  102. * 绑定模块(控制器)
  103. * @var string
  104. */
  105. protected $bind;
  106. public function __construct($appPath = '')
  107. {
  108. $this->appPath = $appPath ?: realpath(dirname($_SERVER['SCRIPT_FILENAME']) . '/../application') . '/';
  109. $this->container = Container::getInstance();
  110. }
  111. /**
  112. * 绑定模块或者控制器
  113. * @access public
  114. * @param string $bind
  115. * @return $this
  116. */
  117. public function bind($bind)
  118. {
  119. $this->bind = $bind;
  120. return $this;
  121. }
  122. /**
  123. * 设置应用类库目录
  124. * @access public
  125. * @param string $path 路径
  126. * @return $this
  127. */
  128. public function path($path)
  129. {
  130. $this->appPath = $path;
  131. return $this;
  132. }
  133. /**
  134. * 初始化应用
  135. * @access public
  136. * @return void
  137. */
  138. public function initialize()
  139. {
  140. $this->beginTime = microtime(true);
  141. $this->beginMem = memory_get_usage();
  142. $this->thinkPath = dirname(dirname(__DIR__)) . '/';
  143. $this->rootPath = dirname(realpath($this->appPath)) . '/';
  144. $this->runtimePath = $this->rootPath . 'runtime/';
  145. $this->routePath = $this->rootPath . 'route/';
  146. $this->configPath = $this->rootPath . 'config/';
  147. // 设置路径环境变量
  148. $this->env->set([
  149. 'think_path' => $this->thinkPath,
  150. 'root_path' => $this->rootPath,
  151. 'app_path' => $this->appPath,
  152. 'config_path' => $this->configPath,
  153. 'route_path' => $this->routePath,
  154. 'runtime_path' => $this->runtimePath,
  155. 'extend_path' => $this->rootPath . 'extend/',
  156. 'vendor_path' => $this->rootPath . 'vendor/',
  157. ]);
  158. // 加载环境变量配置文件
  159. if (is_file($this->rootPath . '.env')) {
  160. $this->env->load($this->rootPath . '.env');
  161. }
  162. $this->namespace = $this->env->get('app_namespace', $this->namespace);
  163. $this->env->set('app_namespace', $this->namespace);
  164. // 注册应用命名空间
  165. Loader::addNamespace($this->namespace, $this->appPath);
  166. $this->configExt = $this->env->get('config_ext', '.php');
  167. // 初始化应用
  168. $this->init();
  169. // 开启类名后缀
  170. $this->suffix = $this->config('app.class_suffix');
  171. // 应用调试模式
  172. $this->debug = $this->env->get('app_debug', $this->config('app.app_debug'));
  173. $this->env->set('app_debug', $this->debug);
  174. if (!$this->debug) {
  175. ini_set('display_errors', 'Off');
  176. } elseif (PHP_SAPI != 'cli') {
  177. //重新申请一块比较大的buffer
  178. if (ob_get_level() > 0) {
  179. $output = ob_get_clean();
  180. }
  181. ob_start();
  182. if (!empty($output)) {
  183. echo $output;
  184. }
  185. }
  186. // 注册根命名空间
  187. if (!empty($this->config('app.root_namespace'))) {
  188. Loader::addNamespace($this->config('app.root_namespace'));
  189. }
  190. // 注册类库别名
  191. Loader::addClassAlias($this->config->pull('alias'));
  192. // 设置系统时区
  193. date_default_timezone_set($this->config('app.default_timezone'));
  194. // 监听app_init
  195. $this->hook->listen('app_init');
  196. }
  197. /**
  198. * 初始化应用或模块
  199. * @access public
  200. * @param string $module 模块名
  201. * @return void
  202. */
  203. public function init($module = '')
  204. {
  205. // 定位模块目录
  206. $module = $module ? $module . DIRECTORY_SEPARATOR : '';
  207. $path = $this->appPath . $module;
  208. // 加载初始化文件
  209. if (is_file($path . 'init.php')) {
  210. include $path . 'init.php';
  211. } elseif (is_file($this->runtimePath . $module . 'init.php')) {
  212. include $this->runtimePath . $module . 'init.php';
  213. } else {
  214. // 加载行为扩展文件
  215. if (is_file($path . 'tags.php')) {
  216. $this->hook->import(include $path . 'tags.php');
  217. }
  218. // 加载公共文件
  219. if (is_file($path . 'common.php')) {
  220. include $path . 'common.php';
  221. }
  222. if ('' == $module) {
  223. // 加载系统助手函数
  224. include $this->thinkPath . 'helper.php';
  225. }
  226. // 注册服务的容器对象实例
  227. if (is_file($path . 'provider.php')) {
  228. $this->container->bind(include $path . 'provider.php');
  229. }
  230. // 自动读取配置文件
  231. if (is_dir($path . 'config')) {
  232. $dir = $path . 'config';
  233. } elseif (is_dir($this->configPath . $module)) {
  234. $dir = $this->configPath . $module;
  235. }
  236. $files = isset($dir) ? scandir($dir) : [];
  237. foreach ($files as $file) {
  238. if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
  239. $filename = $dir . DIRECTORY_SEPARATOR . $file;
  240. $this->config->load($filename, pathinfo($file, PATHINFO_FILENAME));
  241. }
  242. }
  243. }
  244. $this->request->filter($this->config('app.default_filter'));
  245. }
  246. /**
  247. * 执行应用程序
  248. * @access public
  249. * @return Response
  250. * @throws Exception
  251. */
  252. public function run()
  253. {
  254. // 初始化应用
  255. $this->initialize();
  256. try {
  257. if ($this->bind) {
  258. // 模块/控制器绑定
  259. $this->route->bind($this->bind);
  260. } elseif ($this->config('app.auto_bind_module')) {
  261. // 入口自动绑定
  262. $name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME);
  263. if ($name && 'index' != $name && is_dir($this->appPath . $name)) {
  264. $this->route->bind($name);
  265. }
  266. }
  267. // 读取默认语言
  268. $this->lang->range($this->config('app.default_lang'));
  269. if ($this->config('app.lang_switch_on')) {
  270. // 开启多语言机制 检测当前语言
  271. $this->lang->detect();
  272. }
  273. $this->request->langset($this->lang->range());
  274. // 加载系统语言包
  275. $this->lang->load([
  276. $this->thinkPath . 'lang/' . $this->request->langset() . '.php',
  277. $this->appPath . 'lang/' . $this->request->langset() . '.php',
  278. ]);
  279. // 监听app_dispatch
  280. $this->hook->listen('app_dispatch');
  281. // 获取应用调度信息
  282. $dispatch = $this->dispatch;
  283. if (empty($dispatch)) {
  284. // 进行URL路由检测
  285. $dispatch = $this->routeCheck();
  286. }
  287. // 记录当前调度信息
  288. $this->request->dispatch($dispatch);
  289. // 记录路由和请求信息
  290. if ($this->debug) {
  291. $this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true));
  292. $this->log('[ HEADER ] ' . var_export($this->request->header(), true));
  293. $this->log('[ PARAM ] ' . var_export($this->request->param(), true));
  294. }
  295. // 监听app_begin
  296. $this->hook->listen('app_begin');
  297. // 请求缓存检查
  298. $this->request->cache(
  299. $this->config('app.request_cache'),
  300. $this->config('app.request_cache_expire'),
  301. $this->config('app.request_cache_except')
  302. );
  303. // 执行调度
  304. $data = $dispatch->run();
  305. } catch (HttpResponseException $exception) {
  306. $data = $exception->getResponse();
  307. }
  308. $this->middlewareDispatcher->add(function (Request $request, $next) use ($data) {
  309. // 输出数据到客户端
  310. if ($data instanceof Response) {
  311. $response = $data;
  312. } elseif (!is_null($data)) {
  313. // 默认自动识别响应输出类型
  314. $isAjax = $request->isAjax();
  315. $type = $isAjax ? $this->config('app.default_ajax_return') : $this->config('app.default_return_type');
  316. $response = Response::create($data, $type);
  317. } else {
  318. $response = Response::create();
  319. }
  320. return $response;
  321. });
  322. $response = $this->middlewareDispatcher->dispatch($this->request);
  323. // 监听app_end
  324. $this->hook->listen('app_end', $response);
  325. return $response;
  326. }
  327. /**
  328. * 设置当前请求的调度信息
  329. * @access public
  330. * @param Dispatch $dispatch 调度信息
  331. * @return $this
  332. */
  333. public function dispatch(Dispatch $dispatch)
  334. {
  335. $this->dispatch = $dispatch;
  336. return $this;
  337. }
  338. /**
  339. * 记录调试信息
  340. * @access public
  341. * @param mixed $msg 调试信息
  342. * @param string $type 信息类型
  343. * @return void
  344. */
  345. public function log($log, $type = 'info')
  346. {
  347. $this->debug && $this->log->record($log, $type);
  348. }
  349. /**
  350. * 获取配置参数 为空则获取所有配置
  351. * @access public
  352. * @param string $name 配置参数名(支持二级配置 .号分割)
  353. * @return mixed
  354. */
  355. public function config($name = '')
  356. {
  357. return $this->config->get($name);
  358. }
  359. /**
  360. * URL路由检测(根据PATH_INFO)
  361. * @access public
  362. * @return Dispatch
  363. */
  364. public function routeCheck()
  365. {
  366. $path = $this->request->path();
  367. $depr = $this->config('app.pathinfo_depr');
  368. // 路由检测
  369. $files = scandir($this->routePath);
  370. foreach ($files as $file) {
  371. if (strpos($file, '.php')) {
  372. $filename = $this->routePath . $file;
  373. // 导入路由配置
  374. $rules = include $filename;
  375. if (is_array($rules)) {
  376. $this->route->import($rules);
  377. }
  378. }
  379. }
  380. if ($this->config('app.route_annotation')) {
  381. // 自动生成路由定义
  382. if ($this->debug) {
  383. $this->build->buildRoute($this->config('app.controller_suffix'));
  384. }
  385. $filename = $this->runtimePath . 'build_route.php';
  386. if (is_file($filename)) {
  387. include $filename;
  388. }
  389. }
  390. // 是否强制路由模式
  391. $must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must');
  392. // 路由检测 返回一个Dispatch对象
  393. return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match'));
  394. }
  395. /**
  396. * 设置应用的路由检测机制
  397. * @access public
  398. * @param bool $must 是否强制检测路由
  399. * @return $this
  400. */
  401. public function routeMust($must = false)
  402. {
  403. $this->routeMust = $must;
  404. return $this;
  405. }
  406. /**
  407. * 解析模块和类名
  408. * @access protected
  409. * @param string $name 资源地址
  410. * @param string $layer 验证层名称
  411. * @param bool $appendSuffix 是否添加类名后缀
  412. * @return array
  413. */
  414. protected function parseModuleAndClass($name, $layer, $appendSuffix)
  415. {
  416. if (false !== strpos($name, '\\')) {
  417. $class = $name;
  418. $module = $this->request->module();
  419. } else {
  420. if (strpos($name, '/')) {
  421. list($module, $name) = explode('/', $name, 2);
  422. } else {
  423. $module = $this->request->module();
  424. }
  425. $class = $this->parseClass($module, $layer, $name, $appendSuffix);
  426. }
  427. return [$module, $class];
  428. }
  429. /**
  430. * 实例化应用类库
  431. * @access public
  432. * @param string $name 类名称
  433. * @param string $layer 业务层名称
  434. * @param bool $appendSuffix 是否添加类名后缀
  435. * @param string $common 公共模块名
  436. * @return object
  437. * @throws ClassNotFoundException
  438. */
  439. public function create($name, $layer, $appendSuffix = false, $common = 'common')
  440. {
  441. $guid = $name . $layer;
  442. if ($this->__isset($guid)) {
  443. return $this->__get($guid);
  444. }
  445. list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
  446. if (class_exists($class)) {
  447. $object = $this->__get($class);
  448. } else {
  449. $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
  450. if (class_exists($class)) {
  451. $object = $this->__get($class);
  452. } else {
  453. throw new ClassNotFoundException('class not exists:' . $class, $class);
  454. }
  455. }
  456. $this->__set($guid, $class);
  457. return $object;
  458. }
  459. /**
  460. * 实例化(分层)模型
  461. * @access public
  462. * @param string $name Model名称
  463. * @param string $layer 业务层名称
  464. * @param bool $appendSuffix 是否添加类名后缀
  465. * @param string $common 公共模块名
  466. * @return Model
  467. * @throws ClassNotFoundException
  468. */
  469. public function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
  470. {
  471. return $this->create($name, $layer, $appendSuffix, $common);
  472. }
  473. /**
  474. * 实例化(分层)控制器 格式:[模块名/]控制器名
  475. * @access public
  476. * @param string $name 资源地址
  477. * @param string $layer 控制层名称
  478. * @param bool $appendSuffix 是否添加类名后缀
  479. * @param string $empty 空控制器名称
  480. * @return object
  481. * @throws ClassNotFoundException
  482. */
  483. public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
  484. {
  485. list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
  486. if (class_exists($class)) {
  487. return $this->__get($class);
  488. } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {
  489. return $this->__get($emptyClass);
  490. } else {
  491. throw new ClassNotFoundException('class not exists:' . $class, $class);
  492. }
  493. }
  494. /**
  495. * 实例化验证类 格式:[模块名/]验证器名
  496. * @access public
  497. * @param string $name 资源地址
  498. * @param string $layer 验证层名称
  499. * @param bool $appendSuffix 是否添加类名后缀
  500. * @param string $common 公共模块名
  501. * @return Validate
  502. * @throws ClassNotFoundException
  503. */
  504. public function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
  505. {
  506. $name = $name ?: $this->config('default_validate');
  507. if (empty($name)) {
  508. return new Validate;
  509. }
  510. return $this->create($name, $layer, $appendSuffix, $common);
  511. }
  512. /**
  513. * 数据库初始化
  514. * @access public
  515. * @param mixed $config 数据库配置
  516. * @param bool|string $name 连接标识 true 强制重新连接
  517. * @return \think\db\Query
  518. */
  519. public function db($config = [], $name = false)
  520. {
  521. return Db::connect($config, $name);
  522. }
  523. /**
  524. * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
  525. * @access public
  526. * @param string $url 调用地址
  527. * @param string|array $vars 调用参数 支持字符串和数组
  528. * @param string $layer 要调用的控制层名称
  529. * @param bool $appendSuffix 是否添加类名后缀
  530. * @return mixed
  531. * @throws ClassNotFoundException
  532. */
  533. public function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
  534. {
  535. $info = pathinfo($url);
  536. $action = $info['basename'];
  537. $module = '.' != $info['dirname'] ? $info['dirname'] : $this->request->controller();
  538. $class = $this->controller($module, $layer, $appendSuffix);
  539. if (is_scalar($vars)) {
  540. if (strpos($vars, '=')) {
  541. parse_str($vars, $vars);
  542. } else {
  543. $vars = [$vars];
  544. }
  545. }
  546. return $this->container->invokeMethod([$class, $action . $this->config('action_suffix')], $vars);
  547. }
  548. /**
  549. * 解析应用类的类名
  550. * @access public
  551. * @param string $module 模块名
  552. * @param string $layer 层名 controller model ...
  553. * @param string $name 类名
  554. * @param bool $appendSuffix
  555. * @return string
  556. */
  557. public function parseClass($module, $layer, $name, $appendSuffix = false)
  558. {
  559. $name = str_replace(['/', '.'], '\\', $name);
  560. $array = explode('\\', $name);
  561. $class = Loader::parseName(array_pop($array), 1) . ($this->suffix || $appendSuffix ? ucfirst($layer) : '');
  562. $path = $array ? implode('\\', $array) . '\\' : '';
  563. return $this->namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
  564. }
  565. /**
  566. * 获取框架版本
  567. * @access public
  568. * @return string
  569. */
  570. public function version()
  571. {
  572. return static::VERSION;
  573. }
  574. /**
  575. * 是否为调试模式
  576. * @access public
  577. * @return bool
  578. */
  579. public function isDebug()
  580. {
  581. return $this->debug;
  582. }
  583. /**
  584. * 获取模块路径
  585. * @access public
  586. * @return string
  587. */
  588. public function getModulePath()
  589. {
  590. return $this->modulePath;
  591. }
  592. /**
  593. * 设置模块路径
  594. * @access public
  595. * @param string $path 路径
  596. * @return void
  597. */
  598. public function setModulePath($path)
  599. {
  600. $this->modulePath = $path;
  601. $this->env->set('module_path', $path);
  602. }
  603. /**
  604. * 获取应用根目录
  605. * @access public
  606. * @return string
  607. */
  608. public function getRootPath()
  609. {
  610. return $this->rootPath;
  611. }
  612. /**
  613. * 获取应用类库目录
  614. * @access public
  615. * @return string
  616. */
  617. public function getAppPath()
  618. {
  619. return $this->appPath;
  620. }
  621. /**
  622. * 获取应用运行时目录
  623. * @access public
  624. * @return string
  625. */
  626. public function getRuntimePath()
  627. {
  628. return $this->runtimePath;
  629. }
  630. /**
  631. * 获取核心框架目录
  632. * @access public
  633. * @return string
  634. */
  635. public function getThinkPath()
  636. {
  637. return $this->thinkPath;
  638. }
  639. /**
  640. * 获取路由目录
  641. * @access public
  642. * @return string
  643. */
  644. public function getRoutePath()
  645. {
  646. return $this->routePath;
  647. }
  648. /**
  649. * 获取应用配置目录
  650. * @access public
  651. * @return string
  652. */
  653. public function getConfigPath()
  654. {
  655. return $this->configPath;
  656. }
  657. /**
  658. * 获取配置后缀
  659. * @access public
  660. * @return string
  661. */
  662. public function getConfigExt()
  663. {
  664. return $this->configExt;
  665. }
  666. /**
  667. * 获取应用类库命名空间
  668. * @access public
  669. * @return string
  670. */
  671. public function getNamespace()
  672. {
  673. return $this->namespace;
  674. }
  675. /**
  676. * 设置应用类库命名空间
  677. * @access public
  678. * @param string $namespace 命名空间名称
  679. * @return $this
  680. */
  681. public function setNamespace($namespace)
  682. {
  683. $this->namespace = $namespace;
  684. return $this;
  685. }
  686. /**
  687. * 是否启用类库后缀
  688. * @access public
  689. * @return bool
  690. */
  691. public function getSuffix()
  692. {
  693. return $this->suffix;
  694. }
  695. /**
  696. * 获取应用开启时间
  697. * @access public
  698. * @return float
  699. */
  700. public function getBeginTime()
  701. {
  702. return $this->beginTime;
  703. }
  704. /**
  705. * 获取应用初始内存占用
  706. * @access public
  707. * @return integer
  708. */
  709. public function getBeginMem()
  710. {
  711. return $this->beginMem;
  712. }
  713. /**
  714. * 获取容器实例
  715. * @access public
  716. * @return Container
  717. */
  718. public function container()
  719. {
  720. return $this->container;
  721. }
  722. public function __set($name, $value)
  723. {
  724. $this->container->bind($name, $value);
  725. }
  726. public function __get($name)
  727. {
  728. return $this->container->make($name);
  729. }
  730. public function __isset($name)
  731. {
  732. return $this->container->bound($name);
  733. }
  734. public function __unset($name)
  735. {
  736. $this->container->__unset($name);
  737. }
  738. public function offsetExists($key)
  739. {
  740. return $this->__isset($key);
  741. }
  742. public function offsetGet($key)
  743. {
  744. return $this->__get($key);
  745. }
  746. public function offsetSet($key, $value)
  747. {
  748. $this->__set($key, $value);
  749. }
  750. public function offsetUnset($key)
  751. {
  752. $this->__unset($key);
  753. }
  754. }