自己动手写PHP MVC框架
ccwgpt 2024-11-22 11:34 20 浏览 0 评论
PHP的框架众多,对于哪个框架最好,哪个框架最烂,是否应该用框架,对于这些争论在论坛里面都有人争论,这里不做评价,
个人觉得根据自己需求,选中最佳最适合自己MVC框架,并在开发中能够体现出敏捷开发的效果就OK了,作为一个PHPer要提高自己的对PHP和MVC的框架的认识,所以自己写一个MVC框架是很有必要的,
即使不是很完善,但是自己动手写一个轻量简洁的PHP MVC框架起码对MVC的思想有一定的了解,而且经过自己后期的完善会渐渐形成一个自己熟悉的一个PHP框架。
来写一个PHP MVC框架开发的简明教程,首先声明,教程里面的框架不是一个完善的框架,只是一种思路,当然每个人对MVC框架实现的方法肯定是有差异的,希望高手多提意见多指正,和我一样的菜鸟多讨论多交流,刚接触MVC的PHPer多学习。
首先,我们在项目中建立如下目录和文件:
app
|-controller 存放控制器文件
|-model 存放模型文件
|-view 存放视图文件
|-lib 存放自定义类库
|-config 存放配置文件
|--config.php 系统配置文件
|-system 系统核心目录
|-index.php 入口文件
PHP进阶架构资料,学完还怕拿不到30K?
点击进人暗号:知乎
新件的index.php为入口文件,我们这里采用单一入口,入口文件的内容很简单:
<?php
/**
* 应用入口文件
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
require dirname(__FILE__).'/system/app.php';
require dirname(__FILE__).'/config/config.php';
Application::run($CONFIG);
入口文件主要做了2件事,第一引入系统的驱动类,第二是引入配置文件,然后运行run()方法,传入配置作为参数,具体这2个文件是什么内容,我们接下来继续看。
先看一下config/config.php文件,里面其实是一个$CONFIG变量,这个变量存放的全局的配置:
<?php
/**
* 系统配置文件
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
/*数据库配置*/
$CONFIG['system']['db'] = array(
'db_host' => 'localhost',
'db_user' => 'root',
'db_password' => '',
'db_database' => 'app',
'db_table_prefix' => 'app_',
'db_charset' => 'urf8',
'db_conn' => '', //数据库连接标识; pconn 为长久链接,默认为即时链接
);
/*自定义类库配置*/
$CONFIG['system']['lib'] = array(
'prefix' => 'my' //自定义类库的文件前缀
);
$CONFIG['system']['route'] = array(
'default_controller' => 'home', //系统默认控制器
'default_action' => 'index', //系统默认控制器
'url_type' => 1 /*定义URL的形式 1 为普通模式 index.php?c=controller&a=action&id=2
* 2 为PATHINFO index.php/controller/action/id/2(暂时不实现)
*/
);
/*缓存配置*/
$CONFIG['system']['cache'] = array(
'cache_dir' => 'cache', //缓存路径,相对于根目录
'cache_prefix' => 'cache_',//缓存文件名前缀
'cache_time' => 1800, //缓存时间默认1800秒
'cache_mode' => 2, //mode 1 为serialize ,model 2为保存为可执行文件
);
我这里有意识的定义$CONFIG['system']数组表示是系统的配置文件,当然你可以在里面定义$CONFIG['myconfig']为表示在定义的配置,以后在程序的控制器,模型,视图中来调用,都个很自由。
具体配置值代表什么意思注视很清楚了,下面的如果程序中有详细注释的我就不解释啦,呵呵
PHP进阶架构资料,学完还怕拿不到30K?
再来看一下system/app.php文件,主要是干嘛的:
<?php
/**
* 应用驱动类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
define('SYSTEM_PATH', dirname(__FILE__));
define('ROOT_PATH', substr(SYSTEM_PATH, 0,-7));
define('SYS_LIB_PATH', SYSTEM_PATH.'/lib');
define('APP_LIB_PATH', ROOT_PATH.'/lib');
define('SYS_CORE_PATH', SYSTEM_PATH.'/core');
define('CONTROLLER_PATH', ROOT_PATH.'/controller');
define('MODEL_PATH', ROOT_PATH.'/model');
define('VIEW_PATH', ROOT_PATH.'/view');
define('LOG_PATH', ROOT_PATH.'/error/');
final class Application {
public static $_lib = null;
public static $_config = null;
public static function init() {
self::setAutoLibs();
require SYS_CORE_PATH.'/model.php';
require SYS_CORE_PATH.'/controller.php';
}
/**
* 创建应用
* @access public
* @param array $config
*/
public static function run($config){
self::$_config = $config['system'];
self::init();
self::autoload();
self::$_lib['route']->setUrlType(self::$_config['route']['url_type']);
$url_array = self::$_lib['route']->getUrlArray();
self::routeToCm($url_array);
}
/**
* 自动加载类库
* @access public
* @param array $_lib
*/
public static function autoload(){
foreach (self::$_lib as $key => $value){
require (self::$_lib[$key]);
$lib = ucfirst($key);
self::$_lib[$key] = new $lib;
}
//初始化cache
if(is_object(self::$_lib['cache'])){
self::$_lib['cache']->init(
ROOT_PATH.'/'.self::$_config['cache']['cache_dir'],
self::$_config['cache']['cache_prefix'],
self::$_config['cache']['cache_time'],
self::$_config['cache']['cache_mode']
);
}
}
/**
* 加载类库
* @access public
* @param string $class_name 类库名称
* @return object
*/
public static function newLib($class_name){
$app_lib = $sys_lib = '';
$app_lib = APP_LIB_PATH.'/'.self::$_config['lib']['prefix'].'_'.$class_name.'.php';
$sys_lib = SYS_LIB_PATH.'/lib_'.$class_name.'.php';
if(file_exists($app_lib)){
require ($app_lib);
$class_name = ucfirst(self::$_config['lib']['prefix']).ucfirst($class_name);
return new $class_name;
}else if(file_exists($sys_lib)){
require ($sys_lib);
return self::$_lib['$class_name'] = new $class_name;
}else{
trigger_error('加载 '.$class_name.' 类库不存在');
}
}
/**
* 自动加载的类库
* @access public
*/
public static function setAutoLibs(){
self::$_lib = array(
'route' => SYS_LIB_PATH.'/lib_route.php',
'mysql' => SYS_LIB_PATH.'/lib_mysql.php',
'template' => SYS_LIB_PATH.'/lib_template.php',
'cache' => SYS_LIB_PATH.'/lib_cache.php',
'thumbnail' => SYS_LIB_PATH.'/lib_thumbnail.php'
);
}
/**
* 根据URL分发到Controller和Model
* @access public
* @param array $url_array
*/
public static function routeToCm($url_array = array()){
$app = '';
$controller = '';
$action = '';
$model = '';
$params = '';
if(isset($url_array['app'])){
$app = $url_array['app'];
}
if(isset($url_array['controller'])){
$controller = $model = $url_array['controller'];
if($app){
$controller_file = CONTROLLER_PATH.'/'.$app.'/'.$controller.'Controller.php';
$model_file = MODEL_PATH.'/'.$app.'/'.$model.'Model.php';
}else{
$controller_file = CONTROLLER_PATH.'/'.$controller.'Controller.php';
$model_file = MODEL_PATH.'/'.$model.'Model.php';
}
}else{
$controller = $model = self::$_config['route']['default_controller'];
if($app){
$controller_file = CONTROLLER_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Controller.php';
$model_file = MODEL_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Model.php';
}else{
$controller_file = CONTROLLER_PATH.'/'.self::$_config['route']['default_controller'].'Controller.php';
$model_file = MODEL_PATH.'/'.self::$_config['route']['default_controller'].'Model.php';
}
}
if(isset($url_array['action'])){
$action = $url_array['action'];
}else{
$action = self::$_config['route']['default_action'];
}
if(isset($url_array['params'])){
$params = $url_array['params'];
}
if(file_exists($controller_file)){
if (file_exists($model_file)) {
require $model_file;
}
require $controller_file;
$controller = $controller.'Controller';
$controller = new $controller;
if($action){
if(method_exists($controller, $action)){
isset($params) ? $controller ->$action($params) : $controller ->$action();
}else{
die('控制器方法不存在');
}
}else{
die('控制器方法不存在');
}
}else{
die('控制器不存在');
}
}
}
我叫它框架驱动类,也许不合适,但是我是这样理解的,它用来启动这个框架,做好一些初始化的工作,下面我来详细分析一下每个方法的功能:
1.首先时定义了一些常量,很明了,不解释了
2.setAutoLibs 这个方法其实就是设定那些是系统启动时自动加载的类库,类库文件都存放在SYS_LIB_PATH下面,以lib_开头的,当然这里你可以根据自己的规则来命名
3.autoload 这个方法就是用来引入你要自动加载的类,然后来实例化,用$_lib数组来保存类的实例,比如$lib['route']是system/lib/lib_route.php中lib_route类的实例
4.newLib 这个方法是用来加载你自定义的类的,自定义类存放在根目录下的lib中,但是自定义的类的文件前缀是你自己定义的,看系统配置文件里面有,我定义的是my,这样我就可以在lib
目录下新建一个自定义的类了,比如 my_test.php
<?php
class MyTest {
function __construct() {
echo "my lib test";
}
}
为什么类名这样命名,看下newLib方法的实现就知道,其实这些你完全可以定义自己的规则,这个方法会首先去着lib下面有没有这个类,如果有就会引入实例化,如果没有就去找系统目录下面的类,有就实例化
5.init 就是一个初始化的方法,里面其实就是加载自动加载的类,以及引入核心控制器和核心模型,这个2个核心文件过会我们再来分析
6.run 方法就是启动这个框架的了,里面的最后2步很重要,就是获取URL然后拆分成一个数组的形似,然后由routeToCm来分发到Controller和Model
7.routeToCm 很重要,根据URL分发到Controller和Model,这个我们过会来说
在run方法中
self::$_lib['route']->setUrlType(self::$_config['route']['url_type']); //设置url的
类型
$url_array = self::$_lib['route']->getUrlArray(); //将url转发成数组
好吧,我们来看下route的系统类到底做了说明
<?php
/**
* URL处理类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
final class Route{
public $url_query;
public $url_type;
public $route_url = array();
public function __construct() {
$this->url_query = parse_url($_SERVER['REQUEST_URI']);
}
/**
* 设置URL类型
* @access public
*/
public function setUrlType($url_type = 2){
if($url_type > 0 && $url_type <3){
$this->url_type = $url_type;
}else{
trigger_error("指定的URL模式不存在!");
}
}
/**
* 获取数组形式的URL
* @access public
*/
public function getUrlArray(){
$this->makeUrl();
return $this->route_url;
}
/**
* @access public
*/
public function makeUrl(){
switch ($this->url_type){
case 1:
$this->querytToArray();
break;
case 2:
$this->pathinfoToArray();
break;
}
}
/**
* 将query形式的URL转化成数组
* @access public
*/
public function querytToArray(){
$arr = !empty ($this->url_query['query']) ?explode('&', $this->url_query['query']) :array();
$array = $tmp = array();
if (count($arr) > 0) {
foreach ($arr as $item) {
$tmp = explode('=', $item);
$array[$tmp[0]] = $tmp[1];
}
if (isset($array['app'])) {
$this->route_url['app'] = $array['app'];
unset($array['app']);
}
if (isset($array['controller'])) {
$this->route_url['controller'] = $array['controller'];
unset($array['controller']);
}
if (isset($array['action'])) {
$this->route_url['action'] = $array['action'];
unset($array['action']);
}
if(count($array) > 0){
$this->route_url['params'] = $array;
}
}else{
$this->route_url = array();
}
}
/**
* 将PATH_INFO的URL形式转化为数组
* @access public
*/
public function pathinfoToArray(){
}
}
注意querytToArray方法,将将query形式的URL转化成数组,比如原来是localhost/myapp/index.php/app=admin&controller=index&action=edit&id=9&fid=10 这样的url就会被转发成如下的数组
array(
'app' =>'admin',
'controller' =>'index',
'action' =>'edit',
'id' =>array(
'id' =>9,
'fid' =>10
)
)
这下再耐心来看下我写的笨拙的routeToCm,来通过数组参数来分发到控制器,找到控制器以后还要引用相应的模型,然后就实例化控制器和模型,呵呵,貌似有点成型了。
下面就要开始实现 控制器-模型-视图了 我们的思路是这样的,建立一个核心模型和核心控制器,在以后自己的模型和控制器中来继承核心模型和控制器,核心模型和控制器中主要可以是一些通用的方法和必须的组建的加载,下面我们先来写核心控制器, 新建system/core/controller.php
<?php
/**
* 核心控制器
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
class Controller{
public function __construct() {
// header('Content-type:text/html;chartset=utf-8');
}
/**
* 实例化模型
* @access final protected
* @param string $model 模型名称
*/
final protected function model($model) {
if (empty($model)) {
trigger_error('不能实例化空模型');
}
$model_name = $model . 'Model';
return new $model_name;
}
/**
* 加载类库
* @param string $lib 类库名称
* @param Bool $my 如果FALSE默认加载系统自动加载的类库,如果为TRUE则加载非自动加载类库
* @return object
*/
final protected function load($lib,$auto = TRUE){
if(empty($lib)){
trigger_error('加载类库名不能为空');
}elseif($auto === TRUE){
return Application::$_lib[$lib];
}elseif($auto === FALSE){
return Application::newLib($lib);
}
}
/**
* 加载系统配置,默认为系统配置 $CONFIG['system'][$config]
* @access final protected
* @param string $config 配置名
*/
final protected function config($config){
return Application::$_config[$config];
}
/**
* 加载模板文件
* @access final protect
* @param string $path 模板路径
* @return string 模板字符串
*/
final protected function showTemplate($path,$data = array()){
$template = $this->load('template');
$template->init($path,$data);
$template->outPut();
}
}
注释都写的很清楚了吧,其实很简单,这里的加载模板的方法中load了一个系统自动加载的模板类,这个类我们在建立视图的时候再来讲,然后我们再来建核心模型的文件
system/core/model.php
<?php
/**
* 核心模型类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
class Model {
protected $db = null;
final public function __construct() {
header('Content-type:text/html;chartset=utf-8');
$this->db = $this->load('mysql');
$config_db = $this->config('db');
$this->db->init(
$config_db['db_host'],
$config_db['db_user'],
$config_db['db_password'],
$config_db['db_database'],
$config_db['db_conn'],
$config_db['db_charset']
); //初始话数据库类
}
/**
* 根据表前缀获取表名
* @access final protected
* @param string $table_name 表名
*/
final protected function table($table_name){
$config_db = $this->config('db');
return $config_db['db_table_prefix'].$table_name;
}
/**
* 加载类库
* @param string $lib 类库名称
* @param Bool $my 如果FALSE默认加载系统自动加载的类库,如果为TRUE则加载自定义类库
* @return type
*/
final protected function load($lib,$my = FALSE){
if(empty($lib)){
trigger_error('加载类库名不能为空');
}elseif($my === FALSE){
return Application::$_lib[$lib];
}elseif($my === TRUE){
return Application::newLib($lib);
}
}
/**
* 加载系统配置,默认为系统配置 $CONFIG['system'][$config]
* @access final protected
* @param string $config 配置名
*/
final protected function config($config=''){
return Application::$_config[$config];
}
}
因为模型基本是处理数据库的相关内容,所以我们加载了mysql类,这个mysql类就不在这里写了,你可以自己根据习惯写自己的mysql的操作类,如果你想支持其他的数据库,完全可以自己灵活添加。
核心模型控制器已经有了,其实里面还可以添加其他你觉得必要的全局函数,这样我们开始新建一个自己的控制器和模型,来实例运用一下
新建controller/testController.php
<?php
/**
* 测试控制器
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
class testController extends Controller {
public function __construct() {
parent::__construct();
}
public function index() {
echo "test";
}
public function testDb() {
$modTest = $this->model('test'); //示例化test模型
$databases = $modTest->testDatebases(); //调用test模型中 testDatebases()方法
var_dump($databases);
}
}
testController 继承我们的核心控制器,其实在以后的每个控制器中都要继承的,现在我们通过浏览器访问 http://localhost/myapp/index.php?controller=test ,哈哈,可以输出 test 字符串了
然后我们再新建一个模型model/testModel.php
<?php
/**
* 测试模型
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
class testModel extends Model{
function testDatabases(){
$this->db->show_databases();
}
}
其实就是定义了一个获取所有的数据库的方法,打开浏览器访问 http://localhost/myapp/index.php?controller=test&action=testDb,不管你信不信,反正我的浏览器是输出了所有的数据库了
现在就差视图了,其实在核心控制器的controller.php文件中已经有了一个showTemplate方法,其实就是实现了加载模板类,$data就是我们要传递给模板的变量,然后输出模板
/**
* 加载模板文件
* @access final protect
* @param string $path 模板路径
* @param array $data 模板变量
* @return string 模板字符串
*/
final protected function showTemplate($path,$data = array()){
$template = $this->load('template');
$template->init($path,$data);
$template->outPut();
}
下面我们来看一下template类
<?php
/**
* 模板类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuansir-web.com>
* @version 1.0
*/
final class Template {
public $template_name = null;
public $data = array();
public $out_put = null;
public function init($template_name,$data = array()) {
$this->template_name = $template_name;
$this->data = $data;
$this->fetch();
}
/**
* 加载模板文件
* @access public
* @param string $file
*/
public function fetch() {
$view_file = VIEW_PATH . '/' . $this->template_name . '.php';
if (file_exists($view_file)) {
extract($this->data);
ob_start();
include $view_file;
$content = ob_get_contents();
ob_end_clean();
$this->out_put = $content;
} else {
trigger_error('加载 ' . $view_file . ' 模板不存在');
}
}
/**
* 输出模板
* @access public
* @return string
*/
public function outPut(){
echo $this->out_put;
}
是不是简单,就是引入你的静态模版文件,放在缓冲区,然后输出,其实如果你想静态化某个模版,那个这个放在缓冲区的$this->out_put就有用了,你可以在里面添加一个静态化的方法。
好了,现在我们来在新建一个视图文件 view/test.php
<html>
<body>
这是<?php echo $test; ?>,呵呵
</body>
<html>
然后修改一些我们的testController.php中的index()
public function index() {
$data['test'] = "yuansir-web.com";
$this->showTemplate('test', $data);
}
再来浏览 http://localhost/myapp/index.php?controller=test ,可以输出 “这是 http://yuansir-web.com,呵呵”,那么显然我们的视图也完成了。
这样我们的自己写PHP的MVC的框架就完成了,再补充一下,有人可能疑惑如果我是想建立前台后台的,单一入口怎么办呢,其实你要是从头就看我的这个教程,看下代码就会发现,其实只要在 controller目录下新建
一个admin目录就可以在里面写控制器了,比如controller/admin/testController.php 模板引用也是同样的道理,建立 view/admin/test.php ,然后模板加上路径就可以了,$this->showTemplate('admin/test', $data);
是不是很简单,很灵活。
好了,这样我们《自己动手写PHP MVC框架》的教程就结束了,你可以模仿自己写一个,也可以根据自己的思路来写一个,我教程中的可以自己扩增成一个完善的框架,再次申明一下,教程中的代码不完善,没有做过任何基准测试,效率神马的不考虑,便捷性神马的看个人,呵呵
喜欢我的文章就关注我吧,持续更新中.....
相关推荐
- VUE3前端开发入门系列教程二:使用iView框架辅助开发
-
1、安装iView新框架,支持VUE3npminstallview-ui-plus2、编辑src/main.js,添加以下内容,导入js和css到项目importViewUIPlusfrom...
- 万能前端框架uni app初探03:底部导航开发
-
前言本节我们使用uniapp的底部导航功能,点击不同tab会显示不同页面,这个功能在实际项目开发中几乎是必备的。一、基础知识1.tabBar如果应用是一个多tab应用,可以通过tabBar配...
- Rust Web 开发框架,前端你可以选择哪个?
-
Rust构建一切。在如今流行的语言中,Rust可谓是将构建和高效作为自己优美的身姿在大众视野中脱颖而出。它是一门赋予每个人构建可靠且高效软件能力的语言。它有什么特性呢?高性能。Rust速度惊人且内...
- 连载:前端开发中纠结的Javascript框架(上)
-
如今,前端开发有着许许多多的框架和库。其中一些好用,一些却不尽人意。通常我们会习惯性运用某一概念,模块或句法。事实上,并没有什么万能工具。这篇文章是关于未来框架的发展趋势——那就是没有框架!我从以下几...
- 前端开发框架的演进架构:提升用户体验和开发效率
-
前端开发框架是现代Web应用开发的重要工具,它不仅可以帮助开发者构建复杂的用户界面,还能够提升用户体验和开发效率。随着Web技术的不断发展,前端开发框架也在不断演进,为开发者提供了更丰富、更高效的工具...
- Google应用Mesh-TensorFlow框架,让CNN也能处理超高分辨率图像
-
为了要处理超高分辨率医疗图像数据,Google开发了一种空间数据分区(SpatialPartition)技术,在不牺牲图像分辨率的条件下,分析超高分辨率图像。Google使用Mesh-TensorF...
- 大模型安全挑战加剧:框架层漏洞成新靶心
-
近日,360数字安全集团发布了一份关于大模型安全漏洞的报告,揭示了当前大模型及围绕其构建的框架和应用中存在的严重安全问题。报告显示,360近期研究发现了近40个大模型相关的安全漏洞,其中既包括二进制内...
- Keras 3.0正式发布:可用于TensorFlow、JAX和PyTorch
-
机器之心报道编辑:陈萍经过5个月的更新迭代,Keras3.0终于来了。「大新闻:我们刚刚发布了Keras3.0版本!」Keras之父FrancoisChollet在X上激动的...
- TensorFlow和Keras入门必读教程(tensorflow与keras版本对应)
-
导读:本文对TensorFlow的框架和基本示例进行简要介绍。作者:本杰明·普朗什(BenjaminPlanche)艾略特·安德烈斯(EliotAndres)来源:华章科技01TensorFlo...
- 谷歌官方回应“TensorFlow遭弃”:还在投资开发,将与JAX并肩作战
-
鱼羊发自凹非寺量子位|公众号QbitAI终于,谷歌出面回应“TensorFlow遭弃”传闻:我们将继续致力于将TensorFlow打造为一流机器学习平台,与JAX并肩推动机器学习研究。这段时...
- 2025 年的PHP :现代 Web 开发的强大引擎
-
程序员还在吐槽PHP过时?2025年的PHP8.4直接封神了。看看最近更新的属性钩子、强类型系统,加上Laravel这些框架,老语言早就脱胎换骨。十年前说PHP弱类型容易崩代码的,现在脸疼不?联合类...
- 前端内卷终结者?htmx如何让开发者告别200行JS只做一个按钮
-
当你用React写一个点赞按钮需要引入3个状态管理库、编写80行JSX和120行钩子函数时,htmx只需要一行HTML:<buttonhx-post="/like"hx-sw...
- NativePHP桌面版V1.0正式发布(元气桌面电脑版下载)
-
导读:各位小伙伴,使用PHP构建桌面级系统的利器,NativePHP来了。概述NativePHP是一个用于使用PHP构建桌面应用的框架。它允许PHP开发人员使用熟悉的工具和技术创建跨平台的原生应用...
- PHP Laravel框架底层机制(php基本框架)
-
当然可以,Laravel是最受欢迎的PHP框架之一,以优雅的语法和丰富的生态而闻名。尽管开发体验非常“高端”,它的底层其实是由一系列结构清晰、职责分明的组件构成的。下面我从整体架构、核心流程、...
- PHP框架之Laravel框架教程:2. 控制器、路由、视图简单介绍
-
2.控制器、路由、视图简单介绍我们先建立控制器,目录是:app/Http/Controllers,新建控制器Ding.php,代码如下:Ding.php:<?phpnamespaceA...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- VUE3前端开发入门系列教程二:使用iView框架辅助开发
- 万能前端框架uni app初探03:底部导航开发
- Rust Web 开发框架,前端你可以选择哪个?
- 连载:前端开发中纠结的Javascript框架(上)
- 前端开发框架的演进架构:提升用户体验和开发效率
- Google应用Mesh-TensorFlow框架,让CNN也能处理超高分辨率图像
- 大模型安全挑战加剧:框架层漏洞成新靶心
- Keras 3.0正式发布:可用于TensorFlow、JAX和PyTorch
- TensorFlow和Keras入门必读教程(tensorflow与keras版本对应)
- 谷歌官方回应“TensorFlow遭弃”:还在投资开发,将与JAX并肩作战
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)