# mymvc **Repository Path**: vicgoo_liang/mymvc ## Basic Information - **Project Name**: mymvc - **Description**: PHP_easymvc 是 基于composer 搭建自己的mvc练习,本人是个小白。参考easyswoole(传送门) 和thinkphp5(传送门)通过composer来练习搭建自己的mvc框架,没有考虑性能,都是凭感觉弄得。有什么建议可以发送给邮箱327907762@qq.com - **Primary Language**: PHP - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2018-05-24 - **Last Updated**: 2022-08-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README - # mymvc - #### 项目介绍 基于composer 搭建自己的mvc练习,本人是个小白。参考easyswoole([传送门](https://www.easyswoole.com/)) 和thinkphp5([传送门](https://www.kancloud.cn/manual/thinkphp5_1/353946))通过composer来练习搭建自己的mvc框架,没有考虑性能,都是凭感觉弄得。有什么建议可以发送给邮箱327907762@qq.com 命名规范 类库、函数文件统一以.php为后缀; 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致; 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写); - 1、入口文件 用户发起的请求都会经过应用的入口文件,通常是 public/index.php文件。当然,你也可以更改或者增加新的入口文件。 通常入口文件的代码都比较简单,一个普通的入口文件代码如下: // 应用入口文件 ``` send(); ``` 一般入口文件以定义一些常量为主; - 2、引导文件 ``` self::init (); // 初始化加载配置 self::registerWhoops ();// 注册whoops来捕捉框架的异常 self::checkPhpVersion ();// 检测php版本 self::initCommon ();// 初始化公共信息 self::registerDi ();// 注册Di的依赖 self::registerRoute ();// 注册路由 // 清空实例化的 ``` - 路由 通过fastRoute开发的路由,并且支持fastRoute所有方式,并且项目支持无限路由。该类允许您直接将其投入项目并立即开始使用。模块/控制器/操作这是默认的分发请求机制,系统会根据URL或者路由地址来判断当前请求的模块、控制器和操作名,并自动调用相应的访问控制器类,执行操作对应的方法。 简单的路由重写 ``` class Router extends RouterInterface { function register(RouteCollector $routeCollector) { // TODO: Implement register() method. // 路由拦截若未执行end,请求还会继续进入系统自带的控制器路由匹配 $routeCollector->get('/register', '/Api/Common/register'); // /loginIndex/1.html $routeCollector->get('/loginIndex/{id:\d+}', '/Api/Login/index'); // /loginIndex/1/jll.html $routeCollector->get('/loginIndex/{id:\d+}/{name:\d+}', '/Api/Login/index'); $routeCollector->get('/checkIsLogin', '/Api/Common/checkIsLogin'); $routeCollector->get('/getFriendRequests', '/Api/Friend/getFriendRequests'); $routeCollector->get('/dealFriendRequest', '/Api/Friend/dealFriendRequest'); $routeCollector->get('/getFriendList', '/Api/Friend/getFriendList'); // 测试URL /a $routeCollector->get('/a', function (Request $request, Response $response) { $response->write('this is write by router with not end '); $response->response(); }); // 测试URL /a2 $routeCollector->get('/a2', function (Request $request, Response $response) { $response->write('this is write by router2 with end '); $response->response(); }); $routeCollector->post('/a3', function (Request $request, Response $response) { $response->write('this is write by router2 with end '); $response->response(); }); // /user/1/index.html $routeCollector->get('/user/{id:\d+}', function (Request $request, Response $response, $id) { $response->write("this is router user ,your id is {$id}"); $response->response(); }); } public function getMethodNotAllowCallBack() { /* * //需要处理逻用回调函数 * return function () { * echo 111; * }; */ return null; } } ``` - 错误机制 错误捕捉通过Whoops插件 Whoops 是一个PHP库能够很容易处理错误和进行代码调试。该库提供了基于堆栈的错误处理,并提供一个好看的错误界面 - 数据库 MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements 基于easyswoole的spl库可以像java一样封装自己的bean ![输入图片说明](https://gitee.com/uploads/images/2018/0614/212703_020ccca9_1734595.png "屏幕截图.png") ``` key; } /** * @return the $value */ public function getValue() { return $this->value; } /** * @param field_type $key */ public function setKey($key) { $this->key = $key; } /** * @param field_type $value */ public function setValue($value) { $this->value = $value; } } ``` - 模板解析 Twig是一个灵活、高效并且安全的PHP模板引擎。 如果你使用过Smarty、Django或者Jinja这类基于文本的模板引擎的话,那么你会觉得Twig是很自然而然的事情。Twig严格遵守了PHP的信念,同时增加了在模板环境中很有用的函数,这些做法使得Twig不论是对设计师还是开发人员,都是非常友好的。 Twig的主要特征有: 高效:Twig将模板编译成了优化了的PHP文件,与原生的PHP代码比较而言,性能损耗非常小。 安全:Twig使用沙箱(sandbox)模式去运行模板中不被信任的代码。这使得我们可以选择Twig作为那些允许用户修改模板的应用的模板引擎。 灵活:Twig具有灵活的语法分析器和语法解析器,它允许开发人员定义自己的标签(tags)和过滤器(filters),并且创建自己的领域特定语言(DSL,domain specific language)。 - 模仿easyswoole遵循psr7的Response和Request类,在路由的之前通过DI容器注入,DI容器采用easyswoole的代码很好用。 依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。 控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。 依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。 IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)。 ``` static function registerDi() { $config = self::$config; // 通过DI 注入数据库$db = Di::getInstance()->get('mysql'); Di::getInstance ()->set ( 'mysql', MysqliDb::class, Array ( 'host' => $config ['database'] ['host'], 'username' => $config ['database'] ['username'], 'password' => $config ['database'] ['password'], 'db' => $config ['database'] ['db'], 'port' => $config ['database'] ['port'], 'charset' => $config ['database'] ['charset'], 'prefix' => $config ['database'] ['prefix'] ) ); // 通过DI 注入数据库视图 $twig = Di::getInstance()->get('twig'); Di::getInstance ()->set ( 'twig', TwigView::class, Array ( 'config' => $config ['view'] ) ); } ``` - 很感谢easyswoole的博主 通过他的easyswoolemvc让我更好的理解和规范的写出良好的的代码。 这是mvc的控制层的抽象层的实现。所有的controller实现类都写在如下图 ![输入图片说明](https://gitee.com/uploads/images/2018/0614/213702_69393a23_1734595.png "屏幕截图.png") ``` request = $request; $this->response = $response; $this->actionName = $actionName; if ($actionName == '__hook') { $this->response()->withStatus(Status::CODE_BAD_REQUEST); } else { $this->__hook($actionName); } } protected function actionNotFound($action): void { $this->response()->withStatus(Status::CODE_NOT_FOUND); } protected function afterAction($actionName): void {} protected function onException(\Throwable $throwable, $actionName): void { throw $throwable; } protected function onRequest($action): ?bool { return true; } protected function getActionName(): string { return $this->actionName; } protected function resetAction(string $action): void { $this->actionName = $action; } protected function __hook(?string $actionName): void { if ($this->onRequest($actionName) !== false) { $actionName = $this->actionName; // 支持在子类控制器中以private,protected来修饰某个方法不可见 $ref = new \ReflectionClass(static::class); if ($ref->hasMethod($actionName) && $ref->getMethod($actionName)->isPublic()) { try { $this->$actionName(); // 这里面会重复执行 $this->afterAction($actionName); } catch (\Throwable $exception) { $this->onException($exception, $actionName); } } else { throw new \Exception(static::class . "中没有找到" . $actionName); } } else { throw new \Exception("没有权限访问" . $actionName); } } protected function request(): Request { return $this->request; } protected function response(): Response { return $this->response; } protected function writeJson($statusCode = 200, $result = null, $msg = null) { $data = Array( "code" => $statusCode, "result" => $result, "msg" => $msg ); $this->response()->write(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); $this->response()->withHeader('Content-type', 'application/json;charset=utf-8'); $this->response()->withStatus($statusCode); } protected function twig(): TwigView { return Di::getInstance()->get('twig'); } /** * * 浏览器友好的变量输出 * @param mixed $var 变量 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 * @param string $label 标签 默认为空 * @param boolean $strict 是否严谨 默认为true * @return void|string */ /** * 浏览器友好的变量输出 * * @param mixed $var * 变量 * @param boolean $echo * 是否输出 默认为True 如果为false 则返回输出字符串 * @param string $label * 标签 默认为空 * @param boolean $strict * 是否严谨 默认为true * @return void|string */ protected function getNameSpace() { return self::class; } function __destruct() { $this->response->response(); } } ``` - 控制器层的代码实现 ``` response()->withHeader('Content-type', 'text/html; charset=gbk;'); $this->response()->withHeader('X-Powered-By', 'PHP/6.0.0'); echo "
";
		var_dump(1111);
		echo "
"; $this->twig ()->assign ( "aaaa", "111" ); $this->twig ()->assign ( "navigation", [ "aaaaa", "bbbbb", "ccccc" ] ); $this->twig ()->assign ( "navigation2", (new SettingModel ())->getSettings () ); $re = $this->twig ()->getTempLate ( "index" ); $this->response ()->write ( $re ); } protected function onRequest($action): ?bool { return true; } protected function afterAction($actionName): void { } } ``` 模拟POST与GET请求 httpcurl 支持文件上传等 ``` HttpCurl::request('http://example.com/', 'post', array( 'user_uid' => 'root', 'user_pwd' => '123456' )); ``` 高效的execl操作比传统的phpexecl要写,虽然没有phpexecl灵活。但是满足基本的execl操作 ![输入图片说明](https://gitee.com/uploads/images/2018/0614/214254_923a3d02_1734595.png "屏幕截图.png") 剩下会更加丰富自己的mvc框架,在逐渐考虑性能。