单页网站是什么,wordpress缩略图不清晰怎么办,网站建设公司与前端,wordpress搜索功能调用1、mvc原理
# mvc 与框架## 1.mvc 是什么1. m:model,模型(即数据来源),主要是针对数据库操作
2. v:view,视图,html 页面。视图由一个一个模板构成(模板是视图的一个具体展现或载体,视图是模板的一个抽象)
3. c:controller,控制器,用于mv之间的数据交互## 2.最简单的 mvc
就是一…1、mvc原理
# mvc 与框架## 1.mvc 是什么1. m:model,模型(即数据来源),主要是针对数据库操作
2. v:view,视图,html 页面。视图由一个一个模板构成(模板是视图的一个具体展现或载体,视图是模板的一个抽象)
3. c:controller,控制器,用于mv之间的数据交互## 2.最简单的 mvc
就是一个可以显示数据库内容的模板## 3.分层后的mvc### 2.1 控制器(以下三个)1. 接受请求: 路由
2. 选择模型: CURD
3. 加载视图: 模板### 2.2 模型(功能是操作数据库)1. 查询构造器
2. 模型操作## 2.3 视图(以下两个)1. 模板赋值
2. 渲染视图
2、mvc的极简实现方式(一个页面)
?php
//!数据库查询(model)
//第一步:连接数据库
$db new PDO(mysql:dbnamephpedu,root,root);// 第二步:对数据库进行查询
$stmt $db-prepare(SELECT * FROM staff LIMIT ?);// 第三步:数据绑定,获取指定的数据,确定获取的数据条数
$stmt-bindValue(1,5,PDO::PARAM_INT);// 第四步:执行上述操作,如果不进行数据绑定就需要在execute里面加入参数
$stmt-execute();// 第五步:把查询到的数据集保存到一个变量里备用
$staffs $stmt-fetchAll(PDO::FETCH_ASSOC);
?!-- 视图(view) --
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title员工列表/title
/head
body!-- 第六步:foreach渲染数据 --h3员工列表/h3?php foreach ($staffs as $staff) :extract($staff) ?li?$id?:?$name? , ?$sex ? 女:男?(?$email?)/li?php endforeach?
/body
/html 上述代码中模型model和视图view都已经存在了而控制器controller实际上已经有了但是我们看不到因为我们上面的业务逻辑太简单直接把数据写进去了。没有通过controller让model和view进行数据交互。 3、分层的mvc 先写控制器controller控制器写完写模型model模型写完最后再写视图view。 其中core里面包含模型类(Model.php)视图类(View.php)控制器类(controller.php) Model.php
?php// 模型类// 命名空间遵循psr-4
// 类名与文件名同名
// 当前类的命名空间与当前类所在的路径应该是一一对应的
namespace core;use PDO;// 视图,控制器和模型不能直接使用,因为这是底层的业务逻辑
// 是框架源码的一部分,不要让用户直接用,因为框架一旦更新
// 新的框架源码会把core目录下的所有代码全部覆盖
// 所以视图,控制器和模型里面的内容和类尽量把它们转为抽象的
// 或者干脆写个接口,让用户来进行实例化
// 模型抽象化(每个用户一张表),只允许通过子类使用
abstract class Model
{// 要把连接对象写成属性,因为这个对象它会在当前的模型类中多个方法中使用protected $db null;// 1.连接数据库// 在实例化时能够自动连接,可以写在构造函数里public function __construct($dsn,$username,$password){$this-db new PDO($dsn,$username,$password);}// 2.内置一些基本的底层操作,供用户的自定义模型用// 自定义模型:与某一个或某一张数据表相关的类// 2.1获取全部数据public function select($num){$sql SELECT *FROM staff LIMIT ?;;$stmt $this-db-prepare($sql);$stmt-bindParam(1,$num,PDO::PARAM_INT); // !这种方法可以确保当出错时我们知道错误在哪里// if($stmt-execute()){// return $stmt-fetchAll(PDO::FETCH_ASSOC);// }else{// print_r($stmt-errorInfo());// }// !也可以用简化版,因为出错概率较低$stmt-execute();return $stmt-fetchAll(PDO::FETCH_ASSOC);}// 2.2获取某个数据(id)public function getOne($id){$sql SELECT *FROM user WHERE id ?;;$stmt $this-db-prepare($sql);$stmt-bindParam(1,$id,PDO::PARAM_INT); $stmt-execute();return $stmt-fetch(PDO::FETCH_ASSOC);}
} View.php
?php// 视图类namespace core;class view
{// 1.模板变量容器protected array $data [];// 2.模板赋值public function assign(string $key,$value){$this-data[$key] $value;}// 3.渲染视图// 渲染与传参可以同步完成// $path告诉数据显示在哪个页面中public function render(string $path,array $data []){if($data){foreach($data as $key$value){$this-assign($key,$value);}}// 将模板变量数组展开为独立的变量,以方便传入到模板中使用extract($this-data);// 渲染/加载模板文件file_exists($path) ? include $path : die(模板不存在);}
}
Controller.php
?php// 控制器类namespace core;abstract class Controller
{// 1.模型对象protected Model $model;// 2.视图对象protected View $view;// 3.实例化,初始化上面的模型对象,视图对象public function __construct(Model $model,View $view){$this-model $model;$this-view $view;}
}
autoload.php(自动加载器)
?php// 注册类的自动加载器方法
spl_autoload_register(function($class){// require str_replace(\\,/,$class) . php;// 为了系统的兼容性,可以使用require str_replace(\\,DIRECTORY_SEPARATOR,$class) . .php;// 这是一个可以代替 composer 的方法,参数是function,传入了一个类名,// 然后用str_replace这个函数,把类里面的命名空间,也就是反斜线替换成路径符,// 然后在后面加扩展名 .php 转变为类就行了// 这样就实现了了一个类的自动加载了(相当于require了一个命名空间类名)
}); 如果想要把这些类一个一个加载到项目中去则需要针对不同的业务类型创建不同的控制器和模型所以要创建一个controller文件夹 StaffController.php(用户自定义控制器) 虽然不是控制器基类但是要求必须继承自控制器基类(父类) ?php// 自定义控制器,必须继承自控制器基类(超类/父类)namespace controller;use core\Controller;
use core\Model;
use core\View;
use model\StaffModel;class StaffController extends Controller
{public function __construct(Model $model,View $view){// 里面这样写就冗余了// $this-model $model;// $this-view $view;//子类的构造函数直接调用父类的构造方法就可以了parent::__construct($model,$view);}// 自定义方法:默认方法// index():列出所有数据public function index($num 10){// 1.选择模型:获取数据$staff $this-model-getAll($num);// 2.加载视图// 路径约定:view/控制器/方法名.php// key值可以理解为变量名,相当于把$staff接收到的值赋给了名为staffs的变量$this-view-render(view/staff/index.php,[staffs$staff]);}
} 创建类文件夹里面都是自定义模型类 StaffModel.php(用户自定义模型类)
?php
// 自定义模型namespace model;use core\Model;class StaffModel extends Model
{public function __construct($dsn,$username,$password){parent::__construct($dsn,$username,$password);}// 获取全部数据public function getAll($num){return $this-select($num);}
} 创建视图文件夹在视图里再创建文件夹staff文件夹对应是当前的控制器里面的文件对应当前的方法。 staffindex.php
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title员工列表/title
/head
body!-- 第六步:foreach渲染数据 --h3员工列表/h3?php foreach ($staffs as $staff) :extract($staff) ?li?$id?:?$name? , ?$sex ? 女:男?(?$email?)/li?php endforeach?
/body
/html 在mvc2文件夹下创建测试文件index.php mvc2index.php
?php
namespace mvc2;use controller\StaffController;
use model\StaffModel;
use core\view;
// 入口文件:测试// 1.类的自动加载器
// 自动加载器主要用来加载间接用到的类但是直接用到的类还是需要用use
require __DIR__ . /core/autoload.php;// 路由解析// 2.实例化控制器
$model new StaffModel(mysql:dbnamephpedu,root,root);
$view new View();
// 实例化控制器对象
$staff new StaffController($model,$view);// 3.调用控制器中的方法
$staff-index(3);
上述运行结果 4、路由原理及应用
?php// 路由的本质:是从url中解析出控制器,控制方法,以及方法的参数// 1.controller:控制器类名
// 2.method:控制器中的某个方法名
// 3.parameter:参数列表,以数组形式// 以上三种数据在url中的展示方式有两种
// 1.queryString:查询字符串
// 2.PATH_INFO:路径信息// phpedu.io/one/two/demo1.php?查询字符串,以键值对方式,和分开
// !c:controller,m:method,p:parameter
// phpedu.io/one/two/demo1.php?chellommethodpaaa
// 得到这个查询字符串以后,我们可以通过一些方法,将该字符串解析成数组,从而得到控制器,方法和参数//! 在我们的脚本名称 phpedu.io/one/two/demo1.php 和查询字符串 chellommethodpaaa之间
// !如果又出现路径,我们用 PATH_INFO 表示 /user/index/100/200
// phpedu.io/one/two/demo1.php PATH_INFO ?chellommethodpaaa
// phpedu.io/one/two/demo1.php/user/index/100/200?chellommethodpaaa// /user/index/100/200:PATH_INFO
function p($data)
{echo is_array($data) ? sprintf(pre%s/pre,print_r($data,true)) : $data;
}
p([1,2,3]);
p(Hello);
echo hr;
// !QueryString: 查询字符串
// 超全局数组$_SERVER的QUERY_STRING键可以返回当前的查询字符串
p($_SERVER[QUERY_STRING]);
// 将查询字符串解析到数组里面
parse_str($_SERVER[QUERY_STRING],$request);
p($request);// 人为认定
// c controller, m:method,name:parameter
$controller array_shift($request);
$method array_shift($request);
$params array_shift($request);// 控制器类:测试专用
class HelloController
{public function world($name){return Hello , . $name;}
}// 生成控制器类名
$controller ucfirst($controller) . Controller;
echo (new $controller)-$method($params);
// 一般用回调的方式来调用
// echo call_user_func_array([new $controller(),$method],[$params]);
echo call_user_func([new $controller(),$method],$params);
echo hr;// ! 2.PATH_INFO:查询字符串与脚本之间的路径信息
//* http://phpedu.io/0824/router.php/hello/world/admin?chellomworldnamepeter
//* PATH_INFO:/hello/world/admin
p($_SERVER[PATH_INFO]);
p(explode(/,$_SERVER[PATH_INFO]));
// 但这样之后发现索引0对应的值为空
// p(array_filter(explode(/,$_SERVER[PATH_INFO])));
// 去除空字符也可以这样
$request explode(/,trim($_SERVER[PATH_INFO],/));$controller array_shift($request);
$method array_shift($request);
$params array_shift($request);$controller ucfirst($controller) . Controller;
echo call_user_func([new $controller(),$method],$params);
// 也可以 echo call_user_func_array([new $controller(),$method],[$params]);// !推荐使用PATH_INFO
// 通过url重写功能,可以将脚本的扩展名php隐藏,也可以在末尾自定义一个扩展名
//* 隐藏后的地址具有欺骗性:http://phpedu.io/0824/router/hello/world/admin.html/*** 总结:* 1.$_SERVER[QUERY_STRING]以键值对方式返回当前字符串,返回值是数组,需要用parse_str转换成字符串* 2.1.$_SERVER[PATH_INFO]返回带有/的字符串,返回值是字符串,需要用explode切割转换成数组*/
上述运行结果 在mvc3文件夹下创建测试文件index.php ?php
namespace mvc3;use model\UserModel;
use core\view;
use core\Router;
// 入口文件:测试// 1.类的自动加载器
require __DIR__ . /core/autoload.php;// 路由解析
$request Router::parse();$controller array_shift($request);
$method array_shift($request);
$params array_shift($request);// 生成控制器名称
$controller controller\\ . ucfirst($controller) . Controller;// echo $controller;
// die;// 2.实例化控制器
$model new UserModel(mysql:dbnamephpedu,root,root);
$view new View();
// 实例化控制器对象
$user new $controller($model,$view);// 3.调用控制器中的方法
call_user_func_array([$user,get],$params); mvc3corerouter.php
?phpnamespace core;// 路由器类
class Router
{public static function parse(): array{// 默认控制器,实际项目,应该来自配置文件,而不是在写死$controller Index;$action index;// 参数列表$params [];// 判断是否存在pathinfoif (array_key_exists(PATH_INFO, $_SERVER) $_SERVER[PATH_INFO] ! /) {// 为什么要判断 $_SERVER[PATH_INFO] ! / ?// 因为: admin.php/ 时,$_SERVER[PATH_INFO] /, 导致解析控制器失败$pathinfo array_filter(explode(/, $_SERVER[PATH_INFO]));// dump($pathinfo);// 考虑到index.php/ 情况, 这时pathinfo为空数组if (count($pathinfo) 2) {$controller array_shift($pathinfo);$action array_shift($pathinfo);$params $pathinfo;// $params array_shift($pathinfo);} else {$controller array_shift($pathinfo);}}// 查看控制器,方法,参数// dump($controller, $action, $params);// 将这些数据返回出去return [$controller, $action, $params];}
}mvc3modelUserModel
?php
// 自定义模型namespace model;use core\Model;class UserModel extends Model
{public function __construct($dsn,$username,$password){parent::__construct($dsn,$username,$password);}// 获取全部数据public function get($id){return $this-getOne($id);}
}
mvc3viewuserget
!DOCTYPE html
html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title员工信息/title
/headbody!-- 第六步:foreach渲染数据 --h3员工信息/h3?php if (is_array($user)) : ??php foreach ($user as $key $value) : ?!-- 如果不想拿 --?php// if($value null){// echo 该用户不存在;// }if ($key password || $key register_time) {continue;}?li[? $key ?] ? $value ?/li?php endforeach ??php endif ??php if (is_array($user) null) : ?h3此用户不存在/h3?php endif ?
/body/html 上述运行结果