ThinkPHP之入门讲解

文章目录

  • [1 ThinkPHP](#1 ThinkPHP)
    • [1.1 框架](#1.1 框架)
      • [1.1.1 目录讲解](#1.1.1 目录讲解)
        • [1.1.1.1 5.x](#1.1.1.1 5.x)
        • [1.1.1.2 6.0以上](#1.1.1.2 6.0以上)
      • [1.1.2 配置文件](#1.1.2 配置文件)
        • [1.1.2.1 5.x](#1.1.2.1 5.x)
        • [1.1.2.2 6.0以上](#1.1.2.2 6.0以上)
      • [1.1.3 函数文件](#1.1.3 函数文件)
        • [1.1.3.1 5.x](#1.1.3.1 5.x)
        • [1.1.3.1 6.0以上](#1.1.3.1 6.0以上)
    • [1.2 控制器](#1.2 控制器)
      • [1.2.1 控制器的后缀](#1.2.1 控制器的后缀)
      • [1.2.2 框架中的命名空间](#1.2.2 框架中的命名空间)
      • [1.2.3 url访问](#1.2.3 url访问)
      • [1.2.4 调试模式](#1.2.4 调试模式)
        • [1.2.4.1 5.x](#1.2.4.1 5.x)
        • [1.2.4.2 6.0以上](#1.2.4.2 6.0以上)
    • [1.3 创建模块](#1.3 创建模块)
      • [1.3.1 创建前台和后台模块](#1.3.1 创建前台和后台模块)
      • [1.3.2 设置默认访问模块](#1.3.2 设置默认访问模块)
    • [1.4 Request请求类](#1.4 Request请求类)
      • [1.4.1 获取输入变量](#1.4.1 获取输入变量)
      • [1.4.2 参数绑定](#1.4.2 参数绑定)
        • [1.4.2.1 按名称绑定](#1.4.2.1 按名称绑定)
        • [1.4.2.1 按顺序绑定(6.0后不支持)](#1.4.2.1 按顺序绑定(6.0后不支持))
      • [1.4.3 依赖注入](#1.4.3 依赖注入)
        • [1.4.3.1 架构方法和方法注入](#1.4.3.1 架构方法和方法注入)
        • [1.4.3.2 invoke](#1.4.3.2 invoke)
    • [1.5 视图](#1.5 视图)
      • [1.5.1 视图模板定位](#1.5.1 视图模板定位)
        • [1.5.1.1 5.x](#1.5.1.1 5.x)
        • [1.5.1.2 6.0以上](#1.5.1.2 6.0以上)
      • [1.5.2 模板渲染](#1.5.2 模板渲染)

1 ThinkPHP

ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。
ThinkPHP 官网地址

1.1 框架

1.1.1 目录讲解

1.1.1.1 5.x

ThinkPHP 5.x 目录结构如下,默认是支持多模块

以下内容以5.0为基础讲解

project 应用部署目录

├─application 应用目录(可设置)

│ ├─common 公共模块目录(可更改)

│ ├─index 模块目录(可更改)

│ │ ├─config.php 模块配置文件

│ │ ├─common.php 模块函数文件

│ │ ├─controller 控制器目录

│ │ ├─model 模型目录

│ │ ├─view 视图目录

│ │ └─ ... 更多类库目录

│ ├─command.php 命令行工具配置文件

│ ├─common.php 应用公共(函数)文件

│ ├─config.php 应用(公共)配置文件

│ ├─database.php 数据库配置文件

│ ├─tags.php 应用行为扩展定义文件

│ └─route.php 路由配置文件

├─extend 扩展类库目录(可定义)

├─public WEB 部署目录(对外访问目录)

│ ├─static 静态资源存放目录(css,js,image)

│ ├─index.php 应用入口文件

│ ├─router.php 快速测试文件

│ └─.htaccess 用于 apache 的重写

├─runtime 应用的运行时目录(可写,可设置)

├─vendor 第三方类库目录(Composer)

├─thinkphp 框架系统目录

│ ├─lang 语言包目录

│ ├─library 框架核心类库目录

│ │ ├─think Think 类库包目录

│ │ └─traits 系统 Traits 目录

│ ├─tpl 系统模板目录

│ ├─.htaccess 用于 apache 的重写

│ ├─.travis.yml CI 定义文件

│ ├─base.php 基础定义文件

│ ├─composer.json composer 定义文件

│ ├─console.php 控制台入口文件

│ ├─convention.php 惯例配置文件

│ ├─helper.php 助手函数文件(可选)

│ ├─LICENSE.txt 授权说明文件

│ ├─phpunit.xml 单元测试配置文件

├─README.md README 文件

│ └─start.php 框架引导文件

├─build.php 自动生成定义文件(参考)

├─composer.json composer 定义文件

├─LICENSE.txt 授权说明文件

├─README.md README 文件

├─think 命令行入口文件

1.1.1.2 6.0以上

6.0以上,默认安装后的目录结构就是一个单应用模式,如下结构

www WEB部署目录(或者子目录)

├─app 应用目录

│ ├─controller 控制器目录

│ ├─model 模型目录

│ ├─ ... 更多类库目录

│ │

│ ├─common.php 公共函数文件

│ └─event.php 事件定义文件

├─config 配置目录

│ ├─app.php 应用配置

│ ├─cache.php 缓存配置

│ ├─console.php 控制台配置

│ ├─cookie.php Cookie配置

│ ├─database.php 数据库配置

│ ├─filesystem.php 文件磁盘配置

│ ├─lang.php 多语言配置

│ ├─log.php 日志配置

│ ├─middleware.php 中间件配置

│ ├─route.php URL和路由配置

│ ├─session.php Session配置

│ ├─trace.php Trace配置

│ └─view.php 视图配置

├─view 视图目录

├─route 路由定义目录

│ ├─route.php 路由定义文件

│ └─ ...

├─public WEB目录(对外访问目录)

│ ├─index.php 入口文件

│ ├─router.php 快速测试文件

│ └─.htaccess 用于apache的重写

├─extend 扩展类库目录

├─runtime 应用的运行时目录(可写,可定制)

├─vendor Composer类库目录

├─.example.env 环境变量示例文件

├─composer.json composer 定义文件

├─LICENSE.txt 授权说明文件

├─README.md README 文件

├─think 命令行入口文件

如果需要一个多应用的项目架构,目录结构可以参考下面的结构进行调整,但首先需要安装ThinkPHP的多应用扩展(命令:composer require topthink/think-multi-app),具体可以参考多应用模式

www WEB部署目录(或者子目录)

├─app 应用目录

│ ├─app_name 应用目录

│ │ ├─common.php 函数文件

│ │ ├─controller 控制器目录

│ │ ├─model 模型目录

│ │ ├─view 视图目录

│ │ ├─config 配置目录

│ │ ├─route 路由目录

│ │ └─ ... 更多类库目录

│ │

│ ├─common.php 公共函数文件

│ └─event.php 事件定义文件

├─config 全局配置目录

│ ├─app.php 应用配置

│ ├─cache.php 缓存配置

│ ├─console.php 控制台配置

│ ├─cookie.php Cookie配置

│ ├─database.php 数据库配置

│ ├─filesystem.php 文件磁盘配置

│ ├─lang.php 多语言配置

│ ├─log.php 日志配置

│ ├─middleware.php 中间件配置

│ ├─route.php URL和路由配置

│ ├─session.php Session配置

│ ├─trace.php Trace配置

│ └─view.php 视图配置

├─public WEB目录(对外访问目录)

│ ├─index.php 入口文件

│ ├─router.php 快速测试文件

│ └─.htaccess 用于apache的重写

├─extend 扩展类库目录

├─runtime 应用的运行时目录(可写,可定制)

├─vendor Composer类库目录

├─.example.env 环境变量示例文件

├─composer.json composer 定义文件

├─LICENSE.txt 授权说明文件

├─README.md README 文件

├─think 命令行入口文件

注意:多应用模式部署后,记得删除app目录下的controller目录(系统根据该目录作为判断是否单应用的依据)

1.1.2 配置文件

1.1.2.1 5.x

三个层级的配置文件:

  • 框架主配置文件(惯例配置文件) thinkphp/convention.php
  • 应用公共配置文件 application/config.php, application/database.php 对整个应用生效
  • 模块配置文件 application/模块目录/config.php 对当前模块生效

其他说明:

  • 配置文件格式 return array( 键值对 );
  • 加载顺序: 框架主配置文件->应用公共配置文件->模块配置文件
  • 配置文件生效顺序: 后加载的生效(后加载的配置项会覆盖之前配置项)
  • 如果要手动进行配置,一般不要修改框架本身的主配置文件,而是在应用或者模块配置文件中进行配置。
1.1.2.2 6.0以上

在 ThinkPHP 6以上,thinkphp/convention.php 这个配置文件确实已经不再存在了。ThinkPHP 6 相较于之前的版本有了较大的改动,特别是在配置文件的管理方面。具体来说:

  • 在 ThinkPHP 6 中,默认的配置文件被分散到了多个独立的配置文件中,放置在 config 目录下。每个配置文件针对不同的功能模块,例如 app.php、database.php、cache.php 等。这样的设计让配置更加模块化和清晰。
  • convention.php 的去除
    在 ThinkPHP 5.x 及之前的版本中,thinkphp/convention.php 用于存放框架的默认配置,这些配置在未被用户覆盖时会生效。
    从 ThinkPHP 6 开始,这种集中式的默认配置文件被取消,取而代之的是多个配置文件。
  • 配置优先级
    在 ThinkPHP 6 中,用户可以通过 config 目录中的文件来覆盖框架的默认配置。框架提供了一些默认配置,但这些配置是直接通过代码实现的,而不是放在一个单独的文件中。
  • 如何自定义配置
    如果需要自定义配置,可以在 config 目录中创建自己的配置文件,或者直接修改现有的配置文件。或者通过 config() 函数来获取和设置配置项。

1.1.3 函数文件

1.1.3.1 5.x

框架助手函数文件 thinkphp/helper.php,一般不建议直接修改thinkphp/helper.php

应用公共函数文件 application/common.php

模块函数文件 application/模块目录/common.php

1.1.3.1 6.0以上

移除thinkphp/helper.php

  • 在 ThinkPHP 5.x 中,thinkphp/helper.php 文件,主要用于定义一些常用的辅助函数。这些辅助函数在项目开发中可以直接调用,简化了开发工作。
    但是,在 ThinkPHP 6.x 及更高版本中,thinkphp/helper.php 文件被移除了。原因是框架开发团队希望简化核心代码,并且推荐开发者通过引入自己需要的库或工具来实现相应的功能,而不是依赖于框架内置的辅助函数。
    在 ThinkPHP 6.x 中的替代方案:
    • Composer 引入工具包:对于一些常用的功能,可以通过 Composer 引入第三方库来实现。例如,可以使用 symfony/var-dumper 来替代 dump 函数。
    • 自定义辅助函数:如果有一些常用的函数,可以在项目中创建自己的辅助函数文件,然后在项目的入口文件(如 app.php)中引入它。

移除app/模块目录/common.php

  • 在 ThinkPHP 6 中,app/模块目录/common.php 文件被移除是为了简化和灵活化项目结构。如果需要在模块中定义公共函数,可以在 app/common.php 中统一管理
    倡导将公共函数集中管理,通常放在 app/common.php 文件中,这样可以避免每个模块都定义自己的 common.php,从而减少冗余代码,并且使得跨模块调用更加便捷

1.2 控制器

1.2.1 控制器的后缀

打开配置文件application/config.php,有如下配置:'controller_suffix' => false,

表示默认情况下,控制器无特殊后缀。例如 Index控制器,文件名为Index.php

如果需要进行设置,可以设置为(我们不需要这么设置):'controller_suffix' => 'Controller',表示控制器以Controller为后缀。例如Index控制器,文件名为IndexController.php

定义位置及命名规则:

  • 定义位置:application/模块目录/controller/目录下(6.0以上默认是app了)
  • 命名规则:控制器名称(首字母大写) + (控制器后缀,默认没有) + .php
  • 默认:Index控制器 Index.php,User控制器 User.php,UserType控制器 UserType.php,Test控制器 Test.php

编写控制器:

  • 声明命名空间:namespace app\模块目录名\controller
  • 引入控制器基类(可选):use think\Controller;,其中think是命名空间 Controller是基类控制器
  • 定义当前控制器类,继承控制器基类(可选)

1.2.2 框架中的命名空间

命名空间本身是PHP就有的,用来防止命名冲突问题的。

TP框架中的命名空间,通常和目录挂钩。

原因:TP中的自动加载机制,会将类的命名空间作为加载路径的一部分。

TP中命名空间使用:

  • 声明命名空间 使用namespace关键字
  • 引入指定的类 使用use关键字 命名空间\类名称
  • 完全限定式访问 在使用类时,\完整命名空间\类名称(继承和实例化)
  • 如果一个类没有命名空间,使用 \类名

1.2.3 url访问

ThinkPHP5.0框架中,默认使用PATH_INFO方式的url进行访问。

示例:http://www.tpshop.com/index.php/Index/Test/index/page/10

格式:http://域名/入口文件/模块名/控制器名称/操作方法名称/参数名/参数值

隐藏入口文件写法:http://域名/模块名/控制器名称/操作方法名称/参数名/参数值

1.2.4 调试模式

1.2.4.1 5.x

默认情况下,如果代码有误(比如控制器名拼写有误),会出现比较模糊的错误

错误描述比较模糊,不方便进行错误调试。这种模式通常叫做部署模式(生产模式)。

开发阶段可以将框架设置为调试模式,便于进行错误调试:

修改 项目目录\application目录\config.phpapp_debug=>true

开启调试模式后,报错信息格式就会很清晰

1.2.4.2 6.0以上

调试模式配置在 config/app.php 文件中,通过 app_debug => true 设置

如果通过create-project默认安装的话, 会在根目录自带一个.example..env文件,你可以直接更名为.env文件中修改APP_DEBUG = true也可以

1.3 创建模块

1.3.1 创建前台和后台模块

一个典型的应用是由多个模块组成的(通常有前台网站模块和后台管理系统模块),这些模块通常都是应用目录下面的一个子目录,每个模块都有自己独立的配置文件、公共文件和类库文件。

我们给项目创建home(前台)和admin(后台)两个模块

1.3.2 设置默认访问模块

打开配置文件application/config.php,有如下配置:'default_module' => 'index',表示默认访问模块为index模块,可以更改默认模块为home模块
'default_module' => 'home'

在 6.0以上 中,可以通过修改配置文件来设置默认访问的模块。默认模块的配置通常在 config/app.php 文件中完成:'default_module' => 'admin'

1.4 Request请求类

1.4.1 获取输入变量

要获取当前的请求信息,可以使用\think\Request类

php 复制代码
$request = \think\Request::instance();
或者使用助手函数
$request = request();

也可以单独获取get变量或者post变量
Request::instance()->get();
Request::instance()->post();
input('get.');
input('post.');

特殊说明:路由变量与get变量

http://www.tpshop.com/home/test/index/id/100?page=10

  • param:能够获取所有参数(id, page)
  • get:只能获取?后面的请求字符串的参数(page)
  • route:只能获取到?前面的路由中的参数(id)

1.4.2 参数绑定

1.4.2.1 按名称绑定

方法参数绑定是把URL地址(或者路由地址)中的变量作为操作方法的参数直接传入。

php 复制代码
<?php
namespace app\index\Controller;

class Blog 
{
    public function read($id)
    {
        return 'id='.$id;
    }
    public function archive($year, $month='01')
    {
        return 'year='.$year.'&month='.$month;
    }
}

注意这里的操作方法并没有具体的业务逻辑,只是简单的示范。

URL的访问地址分别是:

http://serverName/index.php/index/blog/read/id/5

http://serverName/index.php/index/blog/archive/year/2016/month/06

两个URL地址中的id参数和year和month参数会自动和read操作方法以及archive操作方法的同名参数绑定。

1.4.2.1 按顺序绑定(6.0后不支持)

按照URL的参数顺序进行绑定的方式,合理规划URL参数的顺序绑定对简化URL地址可以起到一定的帮助。

还是上面的例子,控制器不变,还是使用:

php 复制代码
<?php
namespace app\index\Controller;

class Blog 
{
    public function read($id)
    {
        return 'id='.$id;
    }

    public function archive($year='2016',$month='01')
    {
        return 'year='.$year.'&month='.$month;
    }
}

我们在配置文件中添加配置参数如下:
// URL参数方式改成顺序解析
'url_param_type'         => 1,

接下来,访问下面的URL地址:

http://serverName/index.php/index/blog/read/5

http://serverName/index.php/index/blog/archive/2016/06

注意:按参数顺序绑定的话,参数的顺序不能随意调整,在使用路由定义的情况下不建议使用顺序绑定,而且按 顺序绑定参数的话,操作方法的参数只能使用路由变量或者PATHINFO变量,而不能使用get或者post变量。

1.4.3 依赖注入

依赖注入:简单的说,要在一个类A中使用另一个依赖类B时,不直接在类A中实例化类B,而是先实例化类B后再以参数的形式传入类A.

1.4.3.1 架构方法和方法注入

在控制器的架构方法中会自动注入当前请求对象,例如:

php 复制代码
namespace app\index\controller;

use think\Request;

class Index
{
	protected $request;
    
	public function __construct(Request $request)
    {
    	$this->request = $request;
    }
     public function hello(Request $request)
    {
        return 'Hello,' . $request->param('name') . '!';
    }    
}
  • 接收参数 获取请求对象,调用param方法;或者直接调用input函数
  • 参数绑定 在方法上声明形参,自动接收对应同名参数,主要针对id参数
  • 依赖注入 在方法上声明类型形参(Request $request),自动获取请求对象

可以找到任何一种方法 接收请求参数

php 复制代码
获取请求对象  
$request = request();
$request = \think\Request::instance();
$request = $this->request; //仅限于继承了底层控制器的情况下
public function save(Request $request)  //依赖注入

接收请求参数 param方法
$params = $request->param();
$params = input();
$params = request()->param();
$id = $request->param('id');
$id = input('id');
public function edit($id)//参数绑定
1.4.3.2 invoke

5.x中 invoke方法自动调用(v5.0.2)

5.0.2版本开始,如果依赖注入的类有定义一个可调用的静态invoke方法,则会自动调用invoke方法完成依赖注入的自动实例化。
invoke方法的参数是当前请求对象实例,例如:

php 复制代码
namespace app\index\model;

use think\Model;
class User extends Model
{
	public static function invoke(Request $request)
    {
    	$id = $request->param('id');
        return User::get($id);
    }
}

1.5 视图

1.5.1 视图模板定位

1.5.1.1 5.x

为了对模板文件更加有效的管理,ThinkPHP对模板文件进行目录划分,默认的模板文件定义规则是:视图目录/控制器名(小写)/操作名(小写)+模板后缀

默认的视图目录是模块的view目录,框架的默认视图文件后缀是.html

比如home模块 Index控制器index方法要调用的模板定义为view/index/index.html

渲染模板最常用的是继承系统的控制器基类后调用fetch方法,调用格式:fetch('[模板文件]'[,'模板变量(数组)'])

模板文件的写法支持下面几种:

用法 描述
不带任何参数 自动定位当前操作的模板文件
[模块@][控制器/][操作] 常用写法,支持跨模块
完整的模板文件名 直接使用完整的模板文件名(包括模板后缀)

下面是一个最典型的用法,不带任何参数:

php 复制代码
// 不带任何参数 自动定位当前操作的模板文件
return $this->fetch();

表示系统会按照默认规则自动定位模板文件,其规则是:当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html

但是从V5.0.16+版本开始,默认的模板文件名规则改为实际操作方法名的小写+下划线写法。例如,如果操作方法是 showPage,那么模板文件名将变成 show_page.html,但可以配置template.auto_rule的值为2 恢复之前的全小写规则。

如果有更改模板引擎的view_depr设置(假设 'view_depr'=>'_')的话,则上面的自动定位规则变成:
当前模块/默认视图目录/当前控制器(小写)_当前操作(小写).htmlview_depr是用于定义控制器名操作名之间在视图模板中的分隔符

php 复制代码
return $this->fetch('edit'); 
表示调用当前控制器下面的edit模板

return $this->fetch('member/read');
表示调用Member控制器下面的read模板。

return $this->fetch('admin@member/edit');
跨模块渲染模板

渲染输出不需要写模板文件的路径和后缀。这里面的控制器和操作并不一定需要有实际对应的控制器和操作,只是一个目录名称和文件名称而已,例如,你的项目里面可能根本没有Public控制器,更没有Public控制器的menu操作,但是一样可以使用

php 复制代码
return $this->fetch('public/menu');
输出这个模板文件。理解了这个,模板输出就清晰了。

fetch方法支持在渲染输出的时候传入模板变量,例如:
return $this->fetch('read', ['a'=>'a','b'=>'b']);

V5.0.4+版本开始,支持从视图根目录开始读取模板,例如:
$this->fetch('/menu');
表示读取的模板是:当前模块/默认视图目录/menu.html

如果你的控制器类没有继承系统的控制器基类,请使用系统提供的助手函数view进行渲染输出。

1.5.1.2 6.0以上

默认情况下,框架会自动定位模板文件路径,优先定位应用目录下的view目录,这种方式的视图目录下就是应用的控制器目录。

单应用模式

├─app

│ └─view(视图目录)

│ ├─index index控制器目录

│ │ └─index.html index模板文件

│ └─ ... 更多控制器目录

多应用模式

├─app

│ ├─app1 (应用1)

│ │ └─view(应用视图目录)

│ │ ├─index index控制器目录

│ │ │ └─index.html index模板文件

│ │ └─ ... 更多控制器目录

│ │

│ └─ app2... (更多应用)

第二种方式是视图文件和应用类库文件完全分离,统一放置在根目录下的view目录。

单应用模式

├─view 视图文件目录

│ ├─index index控制器目录

│ │ └─index.html index模板文件

│ └─ ... 更多控制器目录

多应用模式

如果是多应用模式的话,这种方式下view目录下面首先是应用子目录。

├─view 视图文件目录

│ ├─index(应用视图目录)

│ │ ├─index index控制器目录

│ │ │ └─index.html index模板文件

│ │ └─ ... 更多控制器目录

如果需要自定义view目录名称,可以通过设置view_dir_name配置参数:'view_dir_name' => 'template'

模板渲染的最典型用法是直接使用fetch方法,不带任何参数:

php 复制代码
<?php
namespace app\index\controller;
use think\facade\View;
class Index
{
    public function index()
    {
        // 不带任何参数 自动定位当前操作的模板文件
        return View::fetch();
    }
}

表示系统会按照默认规则自动定位视图目录下的模板文件,其规则是:控制器名(小写+下划线)/操作名.html

默认的模板文件名规则改为实际操作方法名的小写+下划线写法。但可以配置auto_rule参数的值来改变当前操作的自动渲染规则。
auto_rule配置:

  • 1:操作方法的小写+下划线
  • 2:操作方法全部转换小写
  • 3:保持和操作方法一致
php 复制代码
如果没有按照模板定义规则来定义模板文件(或者需要调用其他控制器下面的某个模板),可以使用:
指定模板输出
return View::fetch('edit'); 
表示调用当前控制器下面的edit模板

return View::fetch('member/read');
表示调用Member控制器下面的read模板。

跨应用渲染模板
return View::fetch('admin@member/edit');

支持从视图根目录开始读取模板,例如:
return View::fetch('/menu');
表示读取的模板是 menu.html

如果模板文件位置比较特殊或者需要自定义模板文件的位置,可以采用下面的方式处理。
return View::fetch('../template/public/menu.html');
这种方式需要带模板路径和后缀指定一个完整的模板文件位置,这里的../template/public目录是相对于当前项目入口文件位置。如果是其他的后缀文件,也支持直接输出,例如:

return View::fetch('../template/public/menu.tpl');
只要../template/public/menu.tpl是一个实际存在的模板文件。

1.5.2 模板渲染

在控制器方法中,使用assign方法进行模板赋值,使用fetch方法进行模板渲染。

使用助手函数view(),进行模板渲染并赋值。

注意:模板中输出变量值: {$模板变量名}

相关推荐
氤氲息1 小时前
Android 底部tab,使用recycleview实现
android
Clockwiseee2 小时前
PHP之伪协议
android·开发语言·php
小林爱2 小时前
【Compose multiplatform教程08】【组件】Text组件
android·java·前端·ui·前端框架·kotlin·android studio
小何开发3 小时前
Android Studio 安装教程
android·ide·android studio
开发者阿伟3 小时前
Android Jetpack LiveData源码解析
android·android jetpack
weixin_438150994 小时前
广州大彩串口屏安卓/linux触摸屏四路CVBS输入实现同时显示!
android·单片机
CheungChunChiu4 小时前
Android10 rk3399 以太网接入流程分析
android·framework·以太网·eth·net·netd
木头没有瓜5 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
键盘侠0075 小时前
springboot 上传图片 转存成webp
android·spring boot·okhttp
江上清风山间明月5 小时前
flutter bottomSheet 控件详解
android·flutter·底部导航·bottomsheet