视频 https://www.bilibili.com/video/BV14E411t7T4?p=10
1 构建框架的基本结构
1.1 准备工作
2 代码
2.1 修改Request.php
把之前的项目的Request.php文件复制过来,并修改命名空间为 :namespace Core\Http;
2.2 修改composer.json
"psr-4": { "App\\" : "app/" , "Core\\":"core/" }
composer require doctrine/annotations 1.6
composer require nikic/fast-route
composer require php-di/php-di
然后别忘了执行
composer dump-autoload
2.3 env配置文件
配置扫描的路径
scan_dir = ./app/controllers
scan_root_namespace = App\
2.4 使用类注解
把原来的Bean.php复制过来
\core\annotations\Bean.php
<?php namespace Core\annotations; use Doctrine\Common\Annotations\Annotation\Target; /** * @Annotation * @Target({"CLASS"}) */ class Bean { }
2.5 使用属性注解
\core\annotations\Value.php
<?php namespace Core\annotations; use Doctrine\Common\Annotations\Annotation\Target; /** * @Annotation * @Target({"PROPERTY"}) */ class Value { }
2.6 注释的do方法 AnnotationHandler
\pro\core\annotations\AnnotationHandler.php
<?php namespace Core\annotations; return [ //类注解 Bean::class=>function($instance,$container){ //get_class返回对象的类名 $arr = explode("\\",get_class($instance)); $beanName = end($arr); $container->set($beanName,$instance); }, //属性注解 Value::class=>function(){ } ];
2.7 使用类注释要加载的类
\pro\app\controllers\UserController.php
<?php namespace App\controllers; use Core\annotations\Bean; /** * Class UserController * 使用Bean注解加载类 * @Bean() * @package App\controllers */ class UserController { public $version = '1.0'; }
2.8 define.php
pro\app\config\define.php
<?php //pro根目录 定义一个ROOT_PATH define("ROOT_PATH",dirname(dirname(__DIR__)));
2.9 启动文件
pro\test.php
<?php require_once __DIR__.'/vendor/autoload.php'; require_once __DIR__."/app/config/define.php"; \Core\BeanFactory::init(); $user = \Core\BeanFactory::getBean("UserController"); var_dump($user);
2.10 最重要的 \BeanFactory
pro\core\BeanFactory.php
<?php namespace Core; use DI\ContainerBuilder; use \Doctrine\Common\Annotations\AnnotationReader; use \Doctrine\Common\Annotations\AnnotationRegistry; class BeanFactory { //配置文件 private static $env=[]; //IOC容器 private static $container; //初始化函数 public static function init() { self::$env = parse_ini_file(ROOT_PATH."/.env"); //var_dump(self::$env); /** * array(2) { ["scan_dir"]=> string(17) "./app/controllers" ["scan_root_namespace"]=> string(4) "App\" } */ //初始容器Builder $builder = new ContainerBuilder(); //启用注释 主要是用它的Inject注释 $builder->useAnnotations(true); //容器初始化 self::$container=$builder->build(); //扫描(重点) self::ScanBeans(); } //获取env文件的配置内容 private static function _getEnv(string $key,string $default='') { if (isset(self::$env[$key])) return self::$env[$key]; return $default; } public static function ScanBeans() { $annoHandles = require_once (ROOT_PATH."/core/annotations/AnnotationHandler.php"); $scanDir = self::_getEnv("scan_dir",ROOT_PATH."/app"); $scanRootNamespace = self::_getEnv("scan_root_namespace","APP\\"); //glob() 函数返回匹配指定模式的文件名或目录 //搜索要扫描目录下的php文件 返回文件名称 $files = glob($scanDir."/*.php"); foreach ($files as $file){ require_once $file; } //注释类对象 $reader = new AnnotationReader(); //AnnotationRegistry::registerAutoloadNamespace('Core\annotations'); AnnotationRegistry::registerLoader('class_exists'); //回调需返回true //get_declared_classes返回由已定义类的名字所组成的数组 foreach (get_declared_classes() as $class){ if (strstr($class,$scanRootNamespace)){ $refClass = new \ReflectionClass($class); //获取所有类的注释 $classAnnos = $reader->getClassAnnotations($refClass); foreach ($classAnnos as $classAnno){ //根据注释的类型获取对应处理方法 $hander = $annoHandles[get_class($classAnno)]; $hander(self::$container->get($refClass->getName()),self::$container); } } } } public static function getBean($name) { return self::$container->get($name); } }