Passed
Push — 5.2 ( 6fe42f...897d87 )
by liu
02:39
created

App::runningInConsole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use Opis\Closure\SerializableClosure;
16
use think\exception\ClassNotFoundException;
17
use think\exception\HttpException;
18
use think\initializer\BootService;
19
use think\initializer\Error;
20
use think\initializer\RegisterService;
21
22
/**
23
 * App 基础类
24
 * @property Route                 $route
25
 * @property Config                $config
26
 * @property Cache                 $cache
27
 * @property Request               $request
28
 * @property Http                  $http
29
 * @property Console               $console
30
 * @property Env                   $env
31
 * @property Debug                 $debug
32
 * @property Event                 $event
33
 * @property Middleware            $middleware
34
 * @property Log                   $log
35
 * @property Lang                  $lang
36
 * @property Db                    $db
37
 * @property Cookie                $cookie
38
 * @property Session               $session
39
 * @property Url                   $url
40
 * @property Validate              $validate
41
 * @property Build                 $build
42
 * @property \think\route\RuleName $rule_name
43
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
44
class App extends Container
45
{
46
    const VERSION = '5.2.0RC1';
47
48
    /**
49
     * 是否多应用模式
50
     * @var bool
51
     */
52
    protected $multi = false;
53
54
    /**
55
     * 是否自动多应用
56
     * @var bool
57
     */
58
    protected $auto = false;
59
60
    /**
61
     * 默认应用名(多应用模式)
62
     * @var string
63
     */
64
    protected $defaultApp = 'index';
65
66
    /**
67
     * 应用名称
68
     * @var string
69
     */
70
    protected $name;
71
72
    /**
73
     * 应用调试模式
74
     * @var bool
75
     */
76
    protected $appDebug = true;
77
78
    /**
79
     * 应用映射
80
     * @var array
81
     */
82
    protected $map = [];
83
84
    /**
85
     * 应用开始时间
86
     * @var float
87
     */
88
    protected $beginTime;
89
90
    /**
91
     * 应用内存初始占用
92
     * @var integer
93
     */
94
    protected $beginMem;
95
96
    /**
97
     * 应用类库顶级命名空间
98
     * @var string
99
     */
100
    protected $rootNamespace = 'app';
101
102
    /**
103
     * 当前应用类库命名空间
104
     * @var string
105
     */
106
    protected $namespace = '';
107
108
    /**
109
     * 应用根目录
110
     * @var string
111
     */
112
    protected $rootPath = '';
113
114
    /**
115
     * 框架目录
116
     * @var string
117
     */
118
    protected $thinkPath = '';
119
120
    /**
121
     * 配置后缀
122
     * @var string
123
     */
124
    protected $configExt = '.php';
125
126
    /**
127
     * 是否需要事件响应
128
     * @var bool
129
     */
130
    protected $withEvent = true;
131
132
    /**
133
     * 应用初始化器
134
     * @var array
135
     */
136
    protected static $initializers = [
137
        Error::class,
138
        RegisterService::class,
139
        BootService::class,
140
    ];
141
142
    /**
143
     * 注册的系统服务
144
     * @var array
145
     */
146
    protected $services = [];
147
148
    /**
149
     * 架构方法
150
     * @access public
151
     * @param  string $rootPath 应用根目录
152
     */
153
    public function __construct(string $rootPath = '')
154
    {
155
        $this->thinkPath = dirname(__DIR__) . DIRECTORY_SEPARATOR;
156
        $this->rootPath  = $rootPath ? realpath($rootPath) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
157
        $this->multi     = is_dir($this->getBasePath() . 'controller') ? false : true;
158
159
        static::setInstance($this);
160
161
        $this->instance('app', $this);
162
    }
163
164
    /**
165
     * 注册服务
166
     * @access public
167
     * @param  Service|string $service 服务
168
     * @param  bool           $force 强制重新注册
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
169
     * @return Service|null
170
     */
171
    public function register($service, bool $force = false)
172
    {
173
        $registered = $this->getService($service);
174
175
        if ($registered && !$force) {
176
            return $registered;
177
        }
178
179
        if (is_string($service)) {
180
            $service = new $service($this);
181
        }
182
183
        if (method_exists($service, 'register')) {
184
            $service->register();
185
        }
186
187
        $this->services[] = $service;
188
    }
189
190
    /**
191
     * 执行服务
192
     * @access public
193
     * @param  Service $service 服务
194
     * @return mixed
195
     */
196
    public function bootService(Service $service)
197
    {
198
        if (method_exists($service, 'boot')) {
199
            return $this->invoke([$service, 'boot']);
200
        }
201
    }
202
203
    /**
204
     * 获取服务
205
     * @param  string|Service $service
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
206
     * @return Service|null
207
     */
208
    public function getService($service)
209
    {
210
        $name = is_string($service) ? $service : get_class($service);
211
        return array_values(array_filter($this->services, function ($value) use ($name) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
212
            return $value instanceof $name;
213
        }, ARRAY_FILTER_USE_BOTH))[0] ?? null;
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
214
    }
215
216
    /**
217
     * 自动多应用访问
218
     * @access public
219
     * @param  array $map 应用路由映射
220
     * @return $this
221
     */
222
    public function autoMulti(array $map = [])
223
    {
224
        $this->multi = true;
225
        $this->auto  = true;
226
        $this->map   = $map;
227
228
        return $this;
229
    }
230
231
    /**
232
     * 是否为自动多应用模式
233
     * @access public
234
     * @return bool
235
     */
236
    public function isAutoMulti(): bool
237
    {
238
        return $this->auto;
239
    }
240
241
    /**
242
     * 设置应用模式
243
     * @access public
244
     * @param  bool $multi
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
245
     * @return $this
246
     */
247
    public function multi(bool $multi)
248
    {
249
        $this->multi = $multi;
250
        return $this;
251
    }
252
253
    /**
254
     * 是否为多应用模式
255
     * @access public
256
     * @return bool
257
     */
258
    public function isMulti(): bool
259
    {
260
        return $this->multi;
261
    }
262
263
    /**
264
     * 设置默认应用(对多应用有效)
265
     * @access public
266
     * @param  string $name 应用名
267
     * @return $this
268
     */
269
    public function defaultApp(string $name)
270
    {
271
        $this->defaultApp = $name;
272
        return $this;
273
    }
274
275
    /**
276
     * 设置是否使用事件机制
277
     * @access public
278
     * @param  bool $event
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
279
     * @return $this
280
     */
281
    public function withEvent(bool $event)
282
    {
283
        $this->withEvent = $event;
284
        return $this;
285
    }
286
287
    /**
288
     * 开启应用调试模式
289
     * @access public
290
     * @param  bool $debug 开启应用调试模式
291
     * @return $this
292
     */
293
    public function debug(bool $debug = true)
294
    {
295
        $this->appDebug = $debug;
296
        return $this;
297
    }
298
299
    /**
300
     * 是否为调试模式
301
     * @access public
302
     * @return bool
303
     */
304
    public function isDebug(): bool
305
    {
306
        return $this->appDebug;
307
    }
308
309
    /**
310
     * 设置应用名称
311
     * @access public
312
     * @param  string $name 应用名称
313
     * @return $this
314
     */
315
    public function name(string $name)
316
    {
317
        $this->name = $name;
318
        return $this;
319
    }
320
321
    /**
322
     * 设置应用命名空间
323
     * @access public
324
     * @param  string $namespace 应用命名空间
325
     * @return $this
326
     */
327
    public function setNamespace(string $namespace)
328
    {
329
        $this->namespace = $namespace;
330
        return $this;
331
    }
332
333
    /**
334
     * 设置应用根命名空间
335
     * @access public
336
     * @param  string $rootNamespace 应用命名空间
337
     * @return $this
338
     */
339
    public function setRootNamespace(string $rootNamespace)
340
    {
341
        $this->rootNamespace = $rootNamespace;
342
        return $this;
343
    }
344
345
    /**
346
     * 获取框架版本
347
     * @access public
348
     * @return string
349
     */
350
    public function version(): string
351
    {
352
        return static::VERSION;
353
    }
354
355
    /**
356
     * 获取应用名称
357
     * @access public
358
     * @return string
359
     */
360
    public function getName(): string
361
    {
362
        return $this->name ?: '';
363
    }
364
365
    /**
366
     * 获取应用根目录
367
     * @access public
368
     * @return string
369
     */
370
    public function getRootPath(): string
371
    {
372
        return $this->rootPath;
373
    }
374
375
    /**
376
     * 获取应用基础目录
377
     * @access public
378
     * @return string
379
     */
380
    public function getBasePath(): string
381
    {
382
        return $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
383
    }
384
385
    /**
386
     * 获取当前应用目录
387
     * @access public
388
     * @return string
389
     */
390
    public function getAppPath(): string
391
    {
392
        return $this->getBasePath() . ($this->multi ? $this->name . DIRECTORY_SEPARATOR : '');
393
    }
394
395
    /**
396
     * 获取应用运行时目录
397
     * @access public
398
     * @return string
399
     */
400
    public function getRuntimePath(): string
401
    {
402
        return $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR . ($this->multi ? $this->name . DIRECTORY_SEPARATOR : '');
403
    }
404
405
    /**
406
     * 获取核心框架目录
407
     * @access public
408
     * @return string
409
     */
410
    public function getThinkPath(): string
411
    {
412
        return $this->thinkPath;
413
    }
414
415
    /**
416
     * 获取应用配置目录
417
     * @access public
418
     * @return string
419
     */
420
    public function getConfigPath(): string
421
    {
422
        return $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
423
    }
424
425
    /**
426
     * 获取配置后缀
427
     * @access public
428
     * @return string
429
     */
430
    public function getConfigExt(): string
431
    {
432
        return $this->configExt;
433
    }
434
435
    /**
436
     * 获取应用类基础命名空间
437
     * @access public
438
     * @return string
439
     */
440
    public function getRootNamespace(): string
441
    {
442
        return $this->rootNamespace;
443
    }
444
445
    /**
446
     * 获取应用类库命名空间
447
     * @access public
448
     * @return string
449
     */
450
    public function getNamespace(): string
451
    {
452
        return $this->namespace;
453
    }
454
455
    /**
456
     * 获取应用开启时间
457
     * @access public
458
     * @return float
459
     */
460
    public function getBeginTime(): float
461
    {
462
        return $this->beginTime;
463
    }
464
465
    /**
466
     * 获取应用初始内存占用
467
     * @access public
468
     * @return integer
469
     */
470
    public function getBeginMem(): int
471
    {
472
        return $this->beginMem;
473
    }
474
475
    /**
476
     * 初始化应用
477
     * @access public
478
     * @return $this
479
     */
480
    public function initialize()
481
    {
482
        $this->beginTime = microtime(true);
483
        $this->beginMem  = memory_get_usage();
484
485
        //加载环境变量
486
        if (is_file($this->rootPath . '.env')) {
487
            $this->env->load($this->rootPath . '.env');
488
        }
489
490
        $this->configExt = $this->env->get('config_ext', '.php');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->env->get('config_ext', '.php') can also be of type boolean. However, the property $configExt is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
491
492
        $this->parseAppName();
493
494
        if (!$this->namespace) {
495
            $this->namespace = $this->multi ? $this->rootNamespace . '\\' . $this->name : $this->rootNamespace;
496
        }
497
498
        // 加载初始化文件
499
        if (is_file($this->getRuntimePath() . 'init.php')) {
500
            //直接加载缓存
501
            include $this->getRuntimePath() . 'init.php';
502
        } else {
503
            $this->load();
504
        }
505
506
        // 设置开启事件机制
507
        $this->event->withEvent($this->withEvent);
508
509
        // 监听AppInit
510
        $this->event->trigger('AppInit');
511
512
        $this->debugModeInit();
513
514
        date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));
0 ignored issues
show
Bug introduced by
It seems like $this->config->get('app....zone', 'Asia/Shanghai') can also be of type array and array; however, parameter $timezone_identifier of date_default_timezone_set() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

514
        date_default_timezone_set(/** @scrutinizer ignore-type */ $this->config->get('app.default_timezone', 'Asia/Shanghai'));
Loading history...
515
516
        // 初始化
517
        foreach (self::$initializers as $initializer) {
518
            $this->make($initializer)->init($this);
519
        }
520
521
        return $this;
522
    }
523
524
    /**
525
     * 引导应用
526
     * @access public
527
     * @return void
528
     */
529
    public function boot(): void
530
    {
531
        array_walk($this->services, function ($service) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
532
            $this->bootService($service);
533
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
534
    }
535
536
    /**
537
     * 加载应用文件和配置
538
     * @access protected
539
     * @return void
540
     */
541
    protected function load(): void
542
    {
543
        $basePath = $this->getBasePath();
544
        $appPath  = $this->getAppPath();
545
546
        if ($this->multi && is_file($basePath . 'common.php')) {
547
            include_once $basePath . 'common.php';
548
        }
549
550
        if (is_file($appPath . 'common.php')) {
551
            include_once $appPath . 'common.php';
552
        }
553
554
        include $this->thinkPath . 'helper.php';
555
556
        $configPath = $this->getConfigPath();
557
558
        $files = [];
559
560
        if (is_dir($configPath)) {
561
            $files = glob($configPath . '*' . $this->configExt);
562
        }
563
564
        if ($this->multi) {
565
            if (is_dir($appPath . 'config')) {
566
                $files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->configExt));
567
            } elseif (is_dir($configPath . $this->name)) {
568
                $files = array_merge($files, glob($configPath . $this->name . DIRECTORY_SEPARATOR . '*' . $this->configExt));
569
            }
570
        }
571
572
        foreach ($files as $file) {
573
            $this->config->load($file, pathinfo($file, PATHINFO_FILENAME));
574
        }
575
576
        if ($this->multi && is_file($basePath . 'event.php')) {
577
            $this->loadEvent(include $basePath . 'event.php');
578
        }
579
580
        if (is_file($appPath . 'event.php')) {
581
            $this->loadEvent(include $appPath . 'event.php');
582
        }
583
584
        if ($this->multi && is_file($basePath . 'middleware.php')) {
585
            $this->middleware->import(include $basePath . 'middleware.php');
586
        }
587
588
        if (is_file($appPath . 'middleware.php')) {
589
            $this->middleware->import(include $appPath . 'middleware.php');
590
        }
591
592
        if ($this->multi && is_file($basePath . 'provider.php')) {
593
            $this->bind(include $basePath . 'provider.php');
594
        }
595
596
        if (is_file($appPath . 'provider.php')) {
597
            $this->bind(include $appPath . 'provider.php');
598
        }
599
    }
600
601
    /**
602
     * 调试模式设置
603
     * @access protected
604
     * @return void
605
     */
606
    protected function debugModeInit(): void
607
    {
608
        // 应用调试模式
609
        if (!$this->appDebug) {
610
            $this->appDebug = $this->env->get('app_debug', false);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->env->get('app_debug', false) can also be of type string. However, the property $appDebug is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
611
        }
612
613
        if (!$this->appDebug) {
614
            ini_set('display_errors', 'Off');
615
        } elseif (!$this->runningInConsole()) {
616
            //重新申请一块比较大的buffer
617
            if (ob_get_level() > 0) {
618
                $output = ob_get_clean();
619
            }
620
            ob_start();
621
            if (!empty($output)) {
622
                echo $output;
623
            }
624
        }
625
    }
626
627
    /**
628
     * 注册应用事件
629
     * @access protected
630
     * @param  array $event 事件数据
631
     * @return void
632
     */
633
    protected function loadEvent(array $event): void
634
    {
635
        if (isset($event['bind'])) {
636
            $this->event->bind($event['bind']);
637
        }
638
639
        if (isset($event['listen'])) {
640
            $this->event->listenEvents($event['listen']);
641
        }
642
643
        if (isset($event['subscribe'])) {
644
            $this->event->subscribe($event['subscribe']);
645
        }
646
    }
647
648
    /**
649
     * 解析应用类的类名
650
     * @access public
651
     * @param  string $layer 层名 controller model ...
652
     * @param  string $name  类名
653
     * @return string
654
     */
655
    public function parseClass(string $layer, string $name): string
656
    {
657
        $name  = str_replace(['/', '.'], '\\', $name);
658
        $array = explode('\\', $name);
659
        $class = self::parseName(array_pop($array), 1);
660
        $path  = $array ? implode('\\', $array) . '\\' : '';
661
662
        return $this->namespace . '\\' . $layer . '\\' . $path . $class;
663
    }
664
665
    /**
666
     * 是否运行在命令行下
667
     * @return bool
668
     */
669
    public function runningInConsole()
670
    {
671
        return php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg';
672
    }
673
674
    /**
675
     * 分析当前请求的应用名
676
     * @access protected
677
     * @return void
678
     */
679
    protected function parseAppName(): void
680
    {
681
        if (!$this->runningInConsole()) {
682
            if ($this->auto) {
683
                // 自动多应用识别
684
                $path = $this->request->path();
685
                $name = current(explode('/', $path));
686
687
                if (isset($this->map[$name])) {
688
                    if ($this->map[$name] instanceof \Closure) {
689
                        call_user_func_array($this->map[$name], [$this]);
690
                    } else {
691
                        $this->name = $this->map[$name];
692
                    }
693
                } elseif ($name && false !== array_search($name, $this->map)) {
694
                    throw new HttpException(404, 'app not exists:' . $name);
695
                } else {
696
                    $this->name = $name ?: $this->defaultApp;
697
                }
698
            } elseif ($this->multi) {
699
                $this->name = $this->name ?: $this->getScriptName();
700
            }
701
702
            $this->request->setApp($this->name ?: '');
703
        }
704
    }
705
706
    /**
707
     * 获取当前运行入口名称
708
     * @access protected
709
     * @return string
710
     */
711
    protected function getScriptName(): string
712
    {
713
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
714
            $file = $_SERVER['SCRIPT_FILENAME'];
715
        } elseif (isset($_SERVER['argv'][0])) {
716
            $file = realpath($_SERVER['argv'][0]);
717
        }
718
719
        return isset($file) ? pathinfo($file, PATHINFO_FILENAME) : $this->defaultApp;
720
    }
721
722
    /**
723
     * 获取应用根目录
724
     * @access protected
725
     * @return string
726
     */
727
    protected function getDefaultRootPath(): string
728
    {
729
        $path = dirname(dirname(dirname(dirname($this->thinkPath))));
730
731
        return $path . DIRECTORY_SEPARATOR;
732
    }
733
734
    /**
735
     * 字符串命名风格转换
736
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
737
     * @access public
738
     * @param  string  $name    字符串
739
     * @param  integer $type    转换类型
740
     * @param  bool    $ucfirst 首字母是否大写(驼峰规则)
741
     * @return string
742
     */
743
    public static function parseName(string $name = null, int $type = 0, bool $ucfirst = true): string
744
    {
745
        if ($type) {
746
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
747
                return strtoupper($match[1]);
748
            }, $name);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
749
            return $ucfirst ? ucfirst($name) : lcfirst($name);
750
        }
751
752
        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
753
    }
754
755
    /**
756
     * 获取类名(不包含命名空间)
757
     * @access public
758
     * @param  string|object $class
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
759
     * @return string
760
     */
761
    public static function classBaseName($class): string
762
    {
763
        $class = is_object($class) ? get_class($class) : $class;
764
        return basename(str_replace('\\', '/', $class));
765
    }
766
767
    /**
0 ignored issues
show
Coding Style introduced by
Parameter ...$args should have a doc-comment as per coding-style.
Loading history...
768
     * 创建工厂对象实例
769
     * @access public
770
     * @param  string $name      工厂类名
771
     * @param  string $namespace 默认命名空间
772
     * @return mixed
773
     */
774
    public static function factory(string $name, string $namespace = '', ...$args)
775
    {
776
        $class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
777
778
        if (class_exists($class)) {
779
            return Container::getInstance()->invokeClass($class, $args);
780
        }
781
782
        throw new ClassNotFoundException('class not exists:' . $class, $class);
783
    }
784
785
    public static function serialize($data): string
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
786
    {
787
        SerializableClosure::enterContext();
788
        SerializableClosure::wrapClosures($data);
789
        $data = \serialize($data);
790
        SerializableClosure::exitContext();
791
        return $data;
792
    }
793
794
    public static function unserialize(string $data)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
795
    {
796
        SerializableClosure::enterContext();
797
        $data = \unserialize($data);
798
        SerializableClosure::unwrapClosures($data);
799
        SerializableClosure::exitContext();
800
        return $data;
801
    }
802
}
803