PHP之MVC
2021/11/8 22:10:27
本文主要是介绍PHP之MVC,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
PHP之MVC以及简单的封装
目录结构
各部分代码
config.php
return array( 'database'=>array( 'host'=>'127.0.0.1',//默认主机 'port'=>3306,//默认端口号 'dbname'=>'data',//默认数据库 'charset'=>'utf8',//默认字符编码集 'user'=>'root',//默认数据库的用户 'pwd'=>'root',//默认数据库的密码 'dbtype'=>'mysql',//默认数据库的类型 ), 'app'=>array( 'dp'=>'Admin',//默认平台 'dc'=>'User',//默认控制器 'dm'=>'Login',//默认方法 'dk'=>'',//加密密钥 'path'=>'./Public/Upload',//默认文件上传路径 'size'=>72345,//默认上传文件大小 'ftype'=>['image/jpeg','image/png','image/gif'],//默认文件上传类型 ) );
BaseController.php
namespace Controller\Admin; class BaseController extends \Core\Controller { use \Traits\Jump; public function __construct() { parent::__construct(); $this->checkLogin(); } private function checkLogin(){//验证是否登录 if (empty($_SESSION['user'])){ $this->error('index.php?m=login&c=user','请登录',2); } } }
ProductController.php
namespace Controller\Admin; use Core\Controller; class ProductController extends BaseController{ use \Traits\Jump; public function listMethod(){ $productmodel = new \Model\ProductModel(); $list = $productmodel->select(); require __VIEW__.'product.html'; } public function delMethod(){ $id = $_GET['id']; $id = (int)$id; if (is_numeric($id)&&is_int($id)){ $productmodel = new \Model\ProductModel(); if ($productmodel->delete($id)) $this->success('index.php?m=list&p=Admin','删除成功'); else $this->error('index.php?m=list&p=Admin','删除失败'); } } public function addMethod(){ if(!empty($_POST)){ $productmodel = new \Model\ProductModel(); if ($productmodel->insert($_POST)) $this->success('index.php?m=list&p=Admin','添加成功'); else $this->error('index.php?m=list&p=Admin','添加失败'); } } public function editMethod() { require __VIEW__.'product'.DS.'edit.html'; } }
UserController.php
namespace Controller\Admin; use Core\Controller; use Model\UserModel; class UserController extends Controller { use \Traits\Jump; public function loginMethod(){ $msg=''; if (!empty($_POST)){ $user = $_POST['username']; $password = $_POST['pwd']; $captcha = new \Lib\Captach(); if ($captcha->check($_POST['code'])==0) $this->error('index.php?m=login&c=user&p=Admin','验证码错误'); if ($user==''||$password==''){ $msg='请正确输入用户名或密码'; } $userobject = new \Model\UserModel('users'); $ulist = $userobject->checkUserNameAndPwd($userobject,$user,md5(md5($password.$GLOBALS['config']['app']['dk']))); if (!empty($ulist)){ $_SESSION['user']=$user; $_SESSION['iconpath']=$ulist[0]['filepath']; $this->success('index.php?m=list&p=Admin&c=Product','登录成功'); }else{ $this->error('index.php?m=login&p=Admin&c=User','登录失败'); } } require __VIEW__.'User'.DS.'login.html'; } public function registerMethod(){ $msg=''; $data=array(); if (!empty($_POST)){ $user = $_POST['username']; if ($user==''||$_POST['pwd']==''||$_FILES['face']==''){ $msg='用户名,密码或上传文件不能为空'; }else{ $usm = new UserModel('users'); if ($usm->isExist($usm,array('username'=>$user))==0){//存在sql注入的风险 $path = $GLOBALS['config']['app']['path']; $size = $GLOBALS['config']['app']['size']; $ftype = $GLOBALS['config']['app']['ftype']; $upload = new \Lib\Upload($path,$size,$ftype); if ($upload->uploadOne($_FILES['face'])){ $finalfilepath=$upload->getuploadfilepath(); if (!empty($finalfilepath)){ $img = new \Lib\Image($finalfilepath); $data['filepath']=$path.'/'.$img->filepath(); } $data['pwd'] = md5(md5($_POST['pwd'].$GLOBALS['config']['app']['dk']));//加入密钥 $data['username']=$user; if ($usm->insert($data)==1){ $_SESSION['user']=$user; $this->success('index.php?c=User&m=Login&p=Admin','注册成功'); }else{ $this->error('index.php?c=User&m=register&p=Admin','注册失败'); } }else{ $this->error('index.php?p=Admin&c=user&m=register',$upload->getError()); } }else{ $msg='用户名已存在'; } } } require __VIEW__.'User'.DS.'register.html'; } public function checkUserMethod(){ $model = new \Model\UserModel('users'); echo $model->isExist($model,array('username'=>$_GET['username'])); } public function verifyMethod(){ $captcha = new \Lib\Captach(); $captcha->entry(); } public function logoutMethod(){ session_destroy(); header('Location:index.php?m=login&c=user&p=Admin'); } }
ProductModel.php
namespace Model; class ProductModel extends \Core\Model { }
UserModel.php
namespace Model; class UserModel extends \Core\Model { public function isExist($userobject,$cond=array()){ if ($userobject->select($cond)){ $flag=1; }else{ $flag=0; } return $flag; } public function checkUserNameAndPwd($userobject,$username,$passwd){ return $userobject->select(array('username'=>$username,'pwd'=>$passwd)); } public function getusericonMethod(){ $user = new UserModel('users'); $ulist = $user->select(array('username'=>$_SESSION['user'])); return $ulist; } }
add.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> 商品名称:<input type="text" name="name"><br> 商品价格:<input type="text" name="price"><br> 评论数量:<input type="text" name="deal"><br> 店家名称:<input type="text" name="title"><br> <input type="submit" value="提交"> </form> </body> </html>
User/login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #msg{ color: red; } </style> </head> <script> window.onload=function () { var username=document.getElementById('username'); var passwd=document.getElementById('username'); var button=document.getElementById('button'); button.onclick=function adduser() { if (username.value==''||passwd.value==''){ document.getElementById('msg').innerHTML='请正确输入用户名或密码'; return false; }else { return true; } } } </script> <body> <form action="" method="post"> <span id="msg"><?=$msg ?></span><br> <input type="text" placeholder="请输入用户名" id="username" name="username"><br> <input type="password" placeholder="请输入密码" id="passwd" name="pwd"><br> <input type="text" name="code"><img src="index.php?m=verify&c=user&p=Admin" width="90" height="30" onclick='this.src="index.php?m=verify&c=user&p=Admin&"+Math.random()'><br> <a href="?m=register">注册</a> <button type="submit" id="button">提交</button> </form> </body> </html>
User/register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #msg{ color: red; } </style> </head> <script> window.onload=function () { var req=new XMLHttpRequest();//创建ajax对象 document.getElementById('username').onfocus=function(){ document.getElementById('msg').innerHTML=''; } document.getElementById('username').onblur=function () { req.open('get','/index.php?p=admin&c=user&m=checkUser&username='+this.value); req.onreadystatechange=function(){ if (req.readyState==4&&req.status==200){ if(req.responseText=='1'){ document.getElementById('msg').innerHTML='用户名已存在'; } } } req.send() } } </script> <body> <form action="" method="post" enctype="multipart/form-data"> <span id="msg"><?=$msg?></span> <br> <input type="text" placeholder="请输入用户名" name="username" id="username"><br> <input type="password" placeholder="请输入密码" name="pwd" id="pwd"><br> <input type="file" name="face"><br> <a href="?m=login">返回</a> <input type="submit" value="提交"> </form> </body> </html>
common.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .success{ color: green; } .error{ color: red; } </style> </head> <body> <div class="<?=$flag?>"><?=$info?></div> <div><span id="t"><?=$time?></span>秒后跳转</div> </body> <script> var t=document.getElementById('t').innerText; setInterval(function () { document.getElementById('t').innerHTML=t--; if (t==0){ location.href="<?=$url?>"; } },1000); </script> </html>
product.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎<?=$_SESSION['user']?><img src="<?=$_SESSION['iconpath']?>" width="50px" height="50px"></h1> <a href="/Application/View/Admin/product/add.html">加商品</a> <a href="index.php?c=user&p=Admin&m=logout">安全退出</a> <table> <tr> <th>商品名称</th> <th>商品价格</th> <th>评论数量</th> <th>商品店家</th> <th>操作过程</th> </tr> <?php foreach($list as $rows):?> <td><?=substr($rows['name'],0,20)?></td> <td><?=$rows['price']?></td> <td><?=$rows['deal']?></td> <td><?=$rows['title']?></td> <td><a href="?m=edit">修改</a> <a href="?m=del&p=Admin&id=<?=$rows['id']?>" onclick="return confirm('确认删除吗?')">删除</a></td> </tr> <?php endforeach;?> </table> </body> </html>
Controller.php
namespace Core; class Controller { public function __construct() { $this->initSession(); } private function initSession(){ new \Lib\Session(); } }
Framework.php
class Framework { //初始化常量 private static function initConst(){ define('DS',DIRECTORY_SEPARATOR);//定义目录分隔符 define('ROOT_PATH',getcwd().DS);//入口文件所在的目录 define('APP_PATH',ROOT_PATH.'Application'.DS);//application目录 define('CONFIG_PATH',APP_PATH.'Config'.DS);//Config目录 define('CONTROLLER_PATH',APP_PATH.'Controller'.DS);//Controller目录 define('MODEL_PATH',APP_PATH.'Model'.DS);//Model目录 define('VIEW_PATH',APP_PATH.'View'.DS);//View目录 define('FRAMEWORK_PATH',ROOT_PATH.'Framework'.DS);//Framework目录 define('CORE_PATH',FRAMEWORK_PATH.'Core'.DS);//Core目录 define('LIB_PATH',FRAMEWORK_PATH.'Lib'.DS);//Lib目录 define('TRAIT_PATH',ROOT_PATH.'Traits'.DS);//Traits } //引入配置文件 private static function initConfig(){ $GLOBALS['config']=require CONFIG_PATH.'config.php'; } //确定路由 private static function initRoutes(){ $p = isset($_GET['p'])?$_GET['p']:$GLOBALS['config']['app']['dp']; $c = isset($_GET['c'])?$_GET['c']:$GLOBALS['config']['app']['dc']; $m = isset($_GET['m'])?$_GET['m']:$GLOBALS['config']['app']['dm']; $p=ucfirst(strtolower($p)); $c=ucfirst(strtolower($c));//首字母大写 $m=strtolower($m);//转成小写 define('PLATFORM_NAME',$p);//平台名常量 define('CONTROLLER_NAME',$c);//控制器名常量 define('METHOD_NAME',$m);//方法名常量 define('__URL__',CONTROLLER_PATH.$p.DS);//当前请求的控制器地址 define('__VIEW__',VIEW_PATH.$p.DS);//当前视图的目录地址 } //自动加载 private static function initAutoLoad(){ spl_autoload_register(function ($class_name){ $namespace = dirname($class_name);//命名空间 $class_name= basename($class_name);//类名 if (in_array($namespace,array('Core','Lib'))) $path=FRAMEWORK_PATH.$namespace.DS.$class_name.'.php'; elseif ($namespace=='Model') $path=MODEL_PATH.$class_name.'.php'; elseif ($namespace=='Traits') $path=TRAIT_PATH.$class_name.'.php'; else $path=__URL__.$class_name.'.php'; if (is_file($path)&&file_exists($path)) require $path; }); } //请求分发 private static function initDispatch(){ $controller_name = DS.'Controller'.DS.PLATFORM_NAME.DS.CONTROLLER_NAME.'Controller';//拼接控制器 $method_name = METHOD_NAME.'Method'; $obj = new $controller_name(); $obj->$method_name(); } public static function run(){ self::initConst(); self::initConfig(); self::initRoutes(); self::initAutoLoad(); self::initDispatch(); } }
Model.php
namespace Core; class Model { protected $mypdo; private $table;//表名 private $pk;//主键 public function __construct($tabe='') { $this->initMyPDO(); $this->initTable($tabe); $this->getPrimaryKey(); } protected function initMyPDO(){ $this->mypdo=MyPDO::getInstance($GLOBALS['config']['database']); } private function initTable($table){ if ($table!=''){ $this->table=$table; }else{ //实例化子类模型 $this->table=substr(basename(get_class($this)),0,-5); } } //获取主键 private function getPrimaryKey(){ $rs = $this->mypdo->fetchAll("desc `{$this->table}`"); foreach($rs as $rows){ if ($rows['Key']=='PRI'){ $this->pk=$rows['Field']; break; } } } //万能的插入语句 public function insert($data){ $keys = array_keys($data); $keys = array_map(function ($k){ return "`{$k}`"; },$keys); $keys = implode(',',$keys); $values = implode(',',array_map(function ($v){ return "'{$v}'"; },array_values($data))); $sql = "insert into `{$this->table}` ({$keys}) values ({$values})"; return $this->mypdo->exec($sql); } //万能的修改语句 public function update($data){ $keys = array_keys($data); $index = array_search($this->pk,$keys); unset($keys[$index]); $keys = implode(',',array_map(function ($k) use($data){ return "`{$k}`='{$data[$k]}'"; },$keys)); $sql = "update `{$this->table}` set {$keys} where `{$this->pk}`='{$data[$this->pk]}'"; return $this->mypdo->exec($sql); } //万能的删除 public function delete($id){ $sql = "delete from `{$this->table}` where `{$this->pk}`='{$id}'"; return $this->mypdo->exec($sql); } //万能的查询语句 public function select($cond=array()){ $sql = "select * from `{$this->table}` where 1"; if (!empty($cond)){ foreach ($cond as $k=>$v){ if (is_array($v)){ switch ($v[0]){ case 'eq': $op='='; break; case 'lt': $op='<'; break; case 'gt': $op='>'; break; case 'lte': case 'elt': $op='<='; break; case 'gte': case 'egt': $op='>='; break; case 'neq': $op='<>'; break; } $sql.= " and `{$k}`{$op}'{$v[1]}'"; }else { $sql .= " and `{$k}`='{$v}'"; } } } return $this->mypdo->fetchAll($sql); } //查询返回一维数组 public function find($id){ $sql = "select * from `{$this->table}` where `{$this->pk}`='{$id}'"; return $this->mypdo->fetchRow($sql); } }
MyPDO.php
namespace Core; class MyPDO { private static $instance; private $host;//主机 private $port;//数据库端口号 private $dbname;//数据库名 private $charset;//数据库字符编码集 private $user;//数据库用户名 private $pwd;//密码 private $dbtype;//数据库类型 private $dns; private $mypdo; private function __construct($parma) { $this->initParma($parma); $this->initPDO(); $this->initException(); } private function __clone() { } //返回创建对象 public static function getInstance($parma){ if (!self::$instance instanceof self){ self::$instance = new self($parma); } return self::$instance; } //初始化参数 private function initParma($parma){ $this->host=$parma['host']; $this->port=$parma['port']; $this->dbname=$parma['dbname']; $this->charset=$parma['charset']; $this->user=$parma['user']; $this->pwd=$parma['pwd']; $this->dbtype=$parma['dbtype']; } //初始化PDO private function initPDO(){ try { $this->dns="{$this->dbtype}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}"; $this->mypdo=new \PDO($this->dns,$this->user,$this->pwd); }catch (\PDOException $ex){ $this->showException($ex); } } //初始化异常 private function initException(){ $this->mypdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION); } //执行增删改 public function exec($sql){ try { return $this->mypdo->exec($sql); }catch (\PDOException $ex){ $this->showException($ex,$sql); } } //返回最后一次插入的id public function lastinsertnum(){ return $this->mypdo-lastInsertId(); } //返回二维数组 public function fetchAll($sql,$type=''){ try { $rs = $this->mypdo->query($sql); $type = $this->getType($type);; return $rs->fetchAll($type); }catch (\PDOException $ex){ $this->showException($ex,$sql); } } //返回一维数组 public function fetchRow($sql,$type=''){ try { $rs = $this->mypdo->query($sql); $type = $this->getType($type); $rs->fetch($type); }catch (\PDOException $ex){ $this->showException($ex,$sql); } } //获取一行一列 public function fetchColumn($sql){ try { $stmt = $this->mypdo->query($sql); return $stmt->fetchColumn(); }catch (\PDOException $ex){ $this->showException($ex,$sql); } } //匹配数据的类型 private function getType($type){ switch ($type){ case 'num': return \PDO::FETCH_NUM; case 'obj': return \PDO::FETCH_OBJ; case 'both': return \PDO::FETCH_BOTH; default: return \PDO::FETCH_ASSOC; } } //显示异常 private function showException($ex,$sql=''){ if ($sql!=''){ echo 'SQL语句执行失败<br>'; echo '错误的SQL语句为'.$sql.'<br>'; } echo '错误编号为:'.$ex->getCode().'<br>'; echo '错误行号为:'.$ex->getLine().'<br>'; echo '错误信息为:'.$ex->getMessage().'<br>'; echo '错误文件为:'.$ex->getFile().'<br>'; } }
Captach.php
namespace Lib; class Captach { private $width; private $height; public function __construct($width=90,$height=30) { $this->width=$width; $this->height=$height; } //生成随机字符串 private function generalCode(){ $all_array = array_merge(range('a','z'),range('A','Z'),range(2,9)); //所有字符数组,array_merge():把多个数组连接起来,拼接成一个大的数组 $div_array = ['l','o','O','I'];//去除容易混淆的字符 $array = array_diff($all_array,$div_array);//剩余的字符数组 unset($all_array,$div_array);//销毁不需要使用的数组 $index=array_rand($array,6);//随机取6个字符,返回字符下标,按先后顺序排列 shuffle($index);//打乱字符 $code=''; foreach ($index as $i): $code.=$array[$i]; endforeach; $_SESSION['code']=$code;//保存在会话中 return $code; } //制作验证码图片 public function entry(){ $code = $this->generalCode(); $image = imagecreate($this->width,$this->height); imagecolorallocate($image,0,rand(0,255),255);//分配beijingse $color = imagecolorallocate($image,213,255,rand(0,255));//分配前景色 $font = 5;//内置5号字体 $x=(imagesx($image)-imagefontwidth($font)*strlen($code))/2; $y=(imagesy($image)-imagefontheight($font))/2; imagestring($image,$font,$x,$y,$code,$color); header('content-type:image/jpeg'); imagejpeg($image); } public function check($code){ return strtoupper($code)==strtoupper($_SESSION['code']);; } }
Image.php
namespace Lib; class Image { private $path; public function __construct($src_path,$w=50,$h=50,$prefix='small_') { $this->thumb($src_path,$w,$h,$prefix); } private function thumb($src_path,$w,$h,$prefix){ $dst_img = imagecreatetruecolor($w,$h); //设置缩略图的背景颜色 $color = imagecolorallocate($dst_img,rand(0,255),rand(20,45),rand(1,255)); //给目标图填充背景颜色 imagefill($dst_img,0,0,$color); //打开原图 $src_img = imagecreatefromjpeg($src_path); //复制原图拷贝到目标图上,并缩放大小 $src_w = imagesx($src_img); $src_h = imagesy($src_img); imagecopyresampled($dst_img,$src_img,0,0,0,0,50,50,$src_w,$src_h); $foldername = substr(dirname($src_path),-10); $filename = basename($src_path); $save_path = dirname($src_path).'/'.$prefix.$filename; //保存缩略图 imagejpeg($dst_img,$save_path); $this->path="{$foldername}/{$prefix}{$filename}"; } public function filepath(){ return $this->path; } }
Session.php
namespace Lib; class Session{ private $mypdo; public function __construct() { session_set_save_handler( array($this,'open'), array($this,'close'), array($this,'read'), array($this,'write'), array($this,'destory'), array($this,'gc') ); session_start(); } public function open(){ $this->mypdo=\Core\MyPDO::getInstance($GLOBALS['config']['database']); return true; } public function close(){ return true; } //读取会话 public function read($sess_id){ $sql = "select sess_value from sess where sess_id='{$sess_id}'"; return (string)$this->mypdo->fetchColumn($sql); } //写入会话 public function write($sess_id,$sess_value){ $sql = "insert into sess values('{$sess_id}','{$sess_value}',UNIX_TIMESTAMP()) on duplicate key update sess_value='{$sess_value}',sess_time=UNIX_TIMESTAMP()"; return $this->mypdo->exec($sql)!==false; } //销毁会话 public function destory($seess_id){ $sql = "delete from sess where sess_id='{$seess_id}'"; return $this->mypdo->exec($sql)!==false; } public function gc($lifetime){ $expires = time(); $sql = "delete from sess where sess_time<{$expires}"; return $this->mypdo->exec($sql)!==false; } }
Upload.php
namespace Lib; class Upload { private $error;//保存的错误消息 private $size;//上传的大小 private $path;//上传的路径 private $type;//允许上传的类型 private $finalfilepath;//文件最终路径 public function __construct($path,$size,$type) { $this->path=$path; $this->size=$size; $this->type=$type; } //返回错误信息 public function getError(){ return $this->error; } public function uploadOne($files){ if ($this->checkError($files)){//没有错误就上传 //文件上传,上传的文件保存到当天的文件中 $foldername=date('Y-m-d'); $folderpath="{$this->path}/{$foldername}";//文件夹路径 if (!file_exists($folderpath)){ mkdir($folderpath,0777,true); } $filename=uniqid('',true).strrchr($_FILES['face']['name'],'.');//文件名 $filepath="{$folderpath}/{$filename}";//文件路径 $this->finalfilepath=$filepath; if(move_uploaded_file($files['tmp_name'],$filepath)) return true; else{ $this->error='上传失败'; return false; } } } //验证上传是否有误 private function checkError($file){ //1.验证错误号 if ($file['error']!=0){ switch ($file['error']){ case 1: $this->error='文件大小超过了php.ini中允许的最大值,最大值是:'.ini_get('upload_max_filesize'); return false; case 2: $this->error='文件大小超过了表单允许的最大值'; return false; case 3: $this->error='只有部分文件上传'; return false; case 4: $this->error='没有文件上传'; return false; case 6: $this->error='找不到临时文件'; return false; case 7: $this->error='文件写入失败'; return false; default: $this->error='未知错误'; return false; } } //2.验证格式 $info=finfo_open(FILEINFO_MIME_TYPE); $mime=finfo_file($info,$file['tmp_name']); if (!in_array($mime,$this->type)){ $this->error='只能上传'.implode(',',$this->type).'格式'; return false; } //3.验证大小 if ($file['size']>$this->size){ $this->error='文件大小不能超过'.number_format($this->size/1024,1).'K'; return false; } //4.验证是否是HTTP上传 if (!is_uploaded_file($file['tmp_name'])){ $this->error='文件不是HTTP_POST上传的'; return false; } return true; } public function getuploadfilepath(){ return $this->finalfilepath; } }
Jump.php
namespace Traits; trait Jump{ //封装成功的跳转 public function success($url,$info){ $this->redirect($url,$info,2,'success'); } //封装失败的跳转 public function error($url,$info,$time=4){ $this->redirect($url,$info,$time,'error'); } /* * 作用跳转的方法 * @parma $url string 跳转的地址 * @parma $info string 显示信息 * @parma $time int 停留时间 * @parma $flag string 显示模式 */ private function redirect($url,$info,$time,$flag){ if ($info=='') header("Location:{$url}"); else require __VIEW__.'common.html'; } }
index.php
require './Framework\Core\Framework.php'; Framework::run();
数据库表结构
代码和数据库文件会上传。
这篇关于PHP之MVC的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-19php8的协程和hyperf的协程有什么区别?-icode9专业技术文章分享
- 2024-12-19php8 的fiber是什么?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-11-29使用PHP 将ETH账户的资产汇集到一个账户
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享