实力进阶,教你使用thinkphp6开发一款商城系统

0.开篇

你好!很高兴你能点开这个教程,相信你对这个教程有了那么一点点兴趣,接下来占用你一点点时间,邀你浏览一下本章内容,希望能够让你更加有兴趣去学完这个教程。

作者我是一名九零后程序员,搬砖了好几年,主要使用PHPJava作为开发语言,另外也懂些前端,毕竟刚工作那会写了不少htmlcssjs,到后面也学习了vue。作为一名开发人员,自己喜欢看一些技术文章,也喜欢分享一些东西,这样才能提高自己的技术。

为什么要写这个教程?

其实前两年就想写了,可能是因为项目的原因,也可能是自己还没想好写些什么。不过今年还是下定决心要写一下,一来是能够学习和巩固自己的知识,二来也是分享一下自己的经验。

课程简介

本教程打算以一个商城项目为例,会实现后台权限管理、会员管理、商品管理、商品团购、抢购……反正是一些常用的功能都给它实现了。

本教程不同于网上的一些视频教程,只是为了实现而实现,说真的网上的一些教程,都是按部就班的实现功能,很少会提及为什么要这样做,这样做的好处是啥,更不用说会踩到什么坑了,因此有些人自学了,效果也好不到哪去。

在这个教程中模块与功能的代码实现是次要的,更重要的是我们是如何去规划、设计这些模块,我们要站在一个架构师的角度实现我们的系统。

你能学到什么?

第一、进一步掌握Thinkphp,让你知道如何阅读文档,让你知道在学习了thinkphp后如何快速的掌握其它框架。

第二、数据库的设计,如何合理的设计数据表,表设计的越合理,sql就会写得越简单,让你轻松应对上千万的数据。

第三、如何搭建自己的系统,完善基础架构。

第四、在实际工作中是如何处理需求,积累经验。

其实你学到的东西远不止这些,每个模块中所涉及到的知识就很多了。但这些不是重点,重点你是怎么实现的,比如说手机验证码,我要分享的是你要如何阅读第三方的文档,快速提取有效的信息,快速实现手机发送验证码功能。最终的目的是你在掌握了接入阿里云短信功能的同时,自己能够阅读其它第三方短信平台的文档而接入短信发送的功能,例如百度。

总之本教程重在引导。

适合人群

工作一两年的,有接触thinkphp的同学即可

最后

如果说对你有帮助,记得点个赞~~~~

因为篇幅过长,大家可以访问,里面教程会一直更新
https://gitee.com/myha/demo-shop

1.技术选型

1.1环境搭建

环境版本
语言PHP7.3.4
数据库mysql5.7
缓存redis3.0.5

这里推荐使用phpstudy集成环境

1.2框架选型

到目前为止,国内使用最多的PHP框架当属ThinkphpLaravel,这两款框架很相似,文档也是比较齐全。作为一个PHP程序员至少要掌握其中一个,当然最好都掌握。

本教程的项目使用了Thinkphp6.1的版本,是当前最新版本。

官方文档链接:https://www.kancloud.cn/manual/thinkphp6_0/1037479

安装

composer create-project topthink/think demo-shop

默认是单应用模式的,这里我们开发的项目是多应用,因此还需执行以下命令

composer require topthink/think-multi-app

本项目有后台模块、提供给web端的API模块,因此就需要用到多应用模型、这样有利于我们后期项目的管理和维护

目录结构

把框架下载下来后,我们认识一下里面的一些目录,下面是官网给出的目录结构,实际上下载下来的目录比较简洁

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                 命令行入口文件

在这里插入图片描述

稍微留意一下框起来的部分,后面会用到

URL重写

重写url主要是为了隐藏入口index.php,我们可以发现很多网站的地址并没有带上入口文件,比如说tp的官网

https://www.kancloud.cn/manual/thinkphp6_0/1037479 而不是

https://www.kancloud.cn/index.php/manual/thinkphp6_0/1037479

官网文档里面也提到了,它也给出了重写的规则,但是最后会发现有点问题,因此做了一下调整

<IfModule mod_rewrite.c>
  Options +FollowSymlinks -Multiviews
  RewriteEngine On

  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
#####RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]  这是官网的
  RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
</IfModule>

注意上面是基于Apache的规则,我们在根目录(入口文件所在的目录),新建一个.htaccess文件,把规则写进里面去即可

2.完善架构

我们下载下来的代码结构是非常简单的,对于实际项目,我们需求对框架的某些功能进行一些封装以及开启框架的某些功能。

2.1接口的结构

本教程是php+vue前后分离的一个项目,因此接下来都会讲接口的实现。

<?php
namespace app\controller;

class User 
{
    public function login()
    {
        return 'login';
    }
}

如上面的代码,这就是一个登录接口。对于一个新手来说,可能会把所有逻辑都写在控制器(controller)里面,这种做法对于我来说是绝对禁止的,因为这样做会使你的代码非常臃肿,并且复用性差,因此如何设计代码结构,成为你程序简洁、高效的关键。

本教程的接口的代码结构主要分为三层:控制层、业务层、模型层

控制层:接口名的定义,主要负责参数的过滤及结果的返回

业务层:实现业务功能的具体核心代码

模型层:负责与数据库交互

每个应用都拥有独立的控制层,这个很好理解,因为你总不可能两个不同的应用使用同一个接口。

每个应用也可以拥有独立的业务层,因为不同应用可能业务代码不一样,但不管是哪个应用都离不开对数据库的增删改查,因此我们这里封装一个核心的业务层,只提供增删改查的逻辑,所有应用都可以直接调用它,做到最大程度的复用性

模型层我们可以把它比作数据表,每个应用都可以使用同一个模型

或许你还不理解,不过没关系,有个印象就行,后面具体开发按照这个结构来,你就会明白了

2.2基础控制器

在文档中https://www.kancloud.cn/manual/thinkphp6_0/1067000,这里提到了基础控制器,它提供了数据验证功能 ,这里我们后面会讲到。

app目录下我们会发现框架生成的BaseController.php基础控制器,我们可以把它当作最底层的控制器。前面我们说过,我们这个项目是一个多应用项目,因此这里为每个应用都建一个基础控制器,让其继承BaseController.php,这样每个应用即可使用底层控制器提供的方法,又可以定制开发一些当前应用共用的方法。

app下新建一个admin目录,作为后台应用。接着新建controller-->AdminController.php,内容如下

<?php
// +----------------------------------------------------------------------
// | 应用基础控制器
// +----------------------------------------------------------------------
namespace app\admin\controller;

use think\App;
use app\BaseController;

class AdminController extends BaseController
{   
    public function __construct(App $app)
    {
        parent::__construct($app);
    }

    protected function initialize()
    {
        
    }
}

initialize()为初始化方法,在BaseController构造函数里面调用了它,每次请求都会执行该方法,因此我们可以在这个方法里封装一些公用信息。

2.3返回值的封装

在文档https://www.kancloud.cn/manual/thinkphp6_0/1037526中会讲到响应输出

在这里插入图片描述

一般来说比较常见的是渲染模板输出JSON输出 ,在一些外包公司为了节省开发成本,前后端都是混到一起,他们一般才采用渲染模板输出,这也要求后端开发人员要了解html,现在随着vue前端框架的崛起,后端开发只需把数据以 JSON输出返回给前端即可。

返回给前端的数据需要固定的格式,你不能随便返回一些乱七八糟的东西,一般来说会返回给前端下面三个基本字段:

响应码描述
code响应码,成功返回200,异常返回500
msg响应信息
data响应数据

当然你还可以加别的字段,只要统一就行。

另外Thinkphp框架为止也提供了一个助手函数 json(),一般来说我们是这样使用它的

json(['code'=>200, 'msg'=>'操作成功','data'=>$data]);
json(['code'=>500, 'msg'=>'服务器异常~']);  
json(['code'=>1000, 'msg'=>'请输入用户名!']);

不知道你们有没有发现,假如说查询列表数据,每次返回成功,你都要写'code'=>200, 'msg'=>'操作成功',这样很繁琐,因此这里我们简单封装一下。

打开app目录下的全局函数文件common.php,这里面新增的函数可以全局调用

/**
 * 返回值-成功
 * @param string $code    错误码
 * @param string $msg     提示信息
 */
function success($data = []){
    return json(['code'=>200, 'msg'=>'操作成功','data'=>$data]);
}

/**
 * 返回值-失败
 * @param string $code    错误码
 * @param string $msg     提示信息
 */
function failure($code=201, $msg='操作失败'){
    return json(['code'=>$code, 'msg'=> $msg]);
}

/**
 * 返回值-异常
 * @param string $code    错误码
 * @param string $msg     提示信息
 */
function error(){
    return json(['code'=>500, 'msg'=>'服务器异常~']);
}

我们就可以这样调用:

//返回列表数据
return success($data);
//新增一条数据成功
return success();
//新增一条数据失败
return failure();
//新增一条数据,请输入用户名
return failure(1000,'请输入用户名!');
//异常只返回500
return error();

这里的话我们还需求做个小小优化,当然很多人在开发过程中并没有这样做,这也是情有可原,毕竟时间紧迫的话就会忽略掉。

一般来说我们定义一些错误码及对应信息的常量,例如本项目会在app->config下新建一个error.php

return [
    'er1'    =>['code'=>'1000','msg'=>'请输入用户名!'],
];

最后我们这样调用

return failure(config('error.er1')['code'],config('error.er1')['msg']);

2.4表单验证器

前面我们在基础控制器里面提到了验证器,实际上文档中有专门的栏目介绍它https://www.kancloud.cn/manual/thinkphp6_0/1037624

它的主要用途就是新增或修改数据对数据进行合法性验证,一般来说前端会传一些数据给后端接口,比如新增一条管理员数据,那此时就必须验证账号和密码这两个字段,这两个字段不能为空,同时密码还需要满足一定的条件,此时框架提供的验证器就派上用场了。

打开底层控制器BaseController.php,我们会发现框架已经给我们创建了一个验证码方法,非常的好用

/**
     * 验证数据
     * @access protected
     * @param  array        $data     数据
     * @param  string|array $validate 验证器名或者验证规则数组
     * @param  array        $message  提示信息
     * @param  bool         $batch    是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
protected function validate(array $data, $validate, array $message = [], bool $batch = false){
    //内容省略
}

接下来看看调用示例

$data = $this->request->post();
//验证规则
$validate = [
    'account' => 'require',
    'password'  => 'require|regex:/^[a-zA-Z0-9_]{8,20}$/',
];
//提示信息
$message = [
    'account.require' => '账号不能为空!',
    'password.require' => '密码不能为空!',
    'password.regex' => '密码长度8~20位,包含字母数字下划线!',
];
$this->validate($data, $validate, $message);

如果输入的账号为空,运行这段代码后你会发现抛出以下异常

在这里插入图片描述

2.5异常接管

上一节讲验证器的时候,抛出了一个账号不能为空的异常,很显然这种提示方式对于前端很不友好,前端无法获取到相应的信息,因此我们要想办法捕抓到这个异常,将提示信息json的格式返回给前端

我们打开文档https://www.kancloud.cn/manual/thinkphp6_0/1037615,文档有讲解相关异常的处理。

框架也为我们生成了app/ExceptionHandle.php,打开看看里面的内容,其中有这样的一个函数

render($request, Throwable $e),我们在里面新加参数验证码错误的代码

public function render($request, Throwable $e): Response
{
     // 参数验证错误
    if ($e instanceof ValidateException) {
        return failure(1004,$e->getError());
    }
    return parent::render($request, $e);
}

这时如果参数验证码错误的话,就会被捕抓到,同时返回json格式的数据给前端,如下

{
	"code": 1004,
	"msg": "账号不能为空!"
}

同样的我们需要接管其它的异常

// 参数验证错误
if ($e instanceof ValidateException) {
    return failure(1004,$e->getError());
}

// 其它异常
if ($e instanceof RouteNotFoundException || $e instanceof Exception 
    || $e instanceof HttpException || $e instanceof HttpResponseException || $e instanceof ModelNotFoundException
    || $e instanceof DataNotFoundException || $e instanceof RouteNotFoundException) 
{
    return error();
}

我们统一返回这样的格式给前端

{
	"code": 500,
	"msg": "服务器异常~"
}

为什么要这样返回?

因为在生产环境,我们一般不会把系统产生的异常信息返回给用户的,因为这是一种很危险的信号。

那有些人可能会问,如果都这样提示,那不是不知道哪里出问题了吗?

别慌,在app/ExceptionHandle.php中,开头有这样的一段代码

/**
     * 不需要记录信息(日志)的异常类列表
     * @var array
*/
protected $ignoreReport = [
    // HttpException::class,
    // HttpResponseException::class,
    // ModelNotFoundException::class,
    // DataNotFoundException::class,
    // ValidateException::class,
    // RouteNotFoundException::class,
    // Exception::class,
];

我们注释掉它,这样错误信息会被日志记录下来

日志一般记录在runtime下面的log目录里的xxx.log文件

[2023-11-17T11:21:39+08:00][error] [255]账号不能为空1111
[2023-11-17T11:22:36+08:00][error] [255]账号不能为空1111[F:\phpstudy_pro\WWW\demo.shop\app\common.php:84]
[2023-11-17T11:25:57+08:00][error] [8]未定义变量: c[F:\phpstudy_pro\WWW\demo.shop\app\admin\controller\SysUser.php:172]

这样我们就很容易找到问题了

生产环境也一样,运维一般会在某个地方输出这些日志,这样我们可以方便的通过浏览器可以看到这些异常信息

2.6开启Redis缓存

在文档https://www.kancloud.cn/manual/thinkphp6_0/1037634中介绍了有关缓存的使用,框架默认的缓存是基于本地文件,这里我们只需配置一下,把它改成基于redis

打开全局的config/cache.php,新增以下内容

'redis' => [
    // 驱动方式
    'type' => 'redis',
    //服务地址
    'host' => env('cache.host'),
    //端口
    'port' => env('cache.port'),
    //密码
    'password' => env('cache.password'),
    //节点
    'select' => env('cache.select'),
    // 缓存前缀
    'prefix' => env('cache.prefix'),
    // 缓存有效期 0表示永久缓存
    'expire' => env('cache.expire')
],

打开.env,新增以下内容

[CACHE]
DRIVER = redis
HOST = 127.0.0.1
PORT = 6379
PASSWORD = 
SELECT = 0
PREFIX = 
EXPIRE = 0

一般本地的redis配置信息都默认是这样,如果发现你的连接不上,就看看密码是否正确

框架给我们提供了助手函数 cache(),看看它的使用方式

//设置缓存,且缓存时间是永久,因为配置EXPIRE = 0,标识永久
cache("user_id",1);
//缓存10秒
cache("user_id",1,10);
//获取缓存
cache("user_id");

2.7路由配置

路由能做的东西很多,文档非常详细的介绍https://www.kancloud.cn/manual/thinkphp6_0/1037495

为什么要使用路由?个人认为主要是有下面两个好处:

  1. 访问地址写到一个地方,方便管理
  2. 使用路由中间件,可以提前过滤接口

打开config/route.php,把以下的配置项设置为true,开启强制路由

// 是否强制使用路由
'url_route_must'        => true

另外我们在admin应用下新建route/app.php,每个应用可设置单独的路由,例如

<?php
// +----------------------------------------------------------------------
// | 后台应用路由
// +----------------------------------------------------------------------
// | Author: myh
// +----------------------------------------------------------------------
use think\facade\Route;
//图片验证码
Route::get('login/verify','sysUser/verify');

使用任何一个框架,做任何一个项目都可以按照这样的思路来开发,做一些开放前的准备工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/160895.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux网络】从原理到实操,感受PXE无人值守自动化高效批量网络安装系统

一、PXE网络批量装机的介绍 1、常见的三种系统安装方式 2、回顾系统安装的过程&#xff0c;了解系统安装的必要条件 3、什么是pxe 4、搭建pxe的原理 5、Linux的光盘镜像中的isolinux中的相关文件学习 二、关于实现PXE无人值守装机的四大文件与五个软件的对应关系详解 5个…

OpenCV图像处理、计算机视觉实战应用

OpenCV图像处理、计算机视觉实战应用 专栏简介一、基于差异模型模板匹配缺陷检测二、基于NCC多角度多目标匹配三、基于zxing多二维码识别四、基于tesseract OCR字符识别 专栏简介 基于OpenCV C分享一些图像处理、计算机视觉实战项目。不定期持续更新&#xff0c;干货满满&…

vulnhub靶机Momentum

下载地址&#xff1a;https://download.vulnhub.com/momentum/Momentum.ova 主机发现 目标192.168.21.129 端口扫描 端口版本扫描 漏洞扫描 扫出来点目录简单看看 发现js里面有一点东西 这里面告诉了我们了web文件有id传值&#xff0c;而且有aes加密还有密钥 跟二没有啥区别&…

庖丁解牛:NIO核心概念与机制详解

文章目录 Pre输入/输出Why NIO流与块的比较通道和缓冲区概述什么是缓冲区&#xff1f;缓冲区类型什么是通道&#xff1f;通道类型 NIO 中的读和写概述Demo : 从文件中读取1. 从FileInputStream中获取Channel2. 创建ByteBuffer缓冲区3. 将数据从Channle读取到Buffer中 Demo : 写…

Redis维护缓存的方案选择

Redis中间件常常被用作缓存&#xff0c;而当使用了缓存的时候&#xff0c;缓存中数据的维护&#xff0c;往往是需要重点关注的&#xff0c;尤其是重点考虑的是数据一致性问题。以下是维护数据库缓存的一些常用方案。 1、先删除缓存&#xff0c;再更新数据库 导致数据不一致的…

LLM大模型4位量化实战【GPTQ】

权重量化方面的最新进展使我们能够在消费类硬件上运行大量大型语言模型&#xff0c;例如 RTX 3090 GPU 上的 LLaMA-30B 模型。 这要归功于性能下降最小的新型 4 位量化技术&#xff0c;例如 GPTQ、GGML 和 NF4。 在上一篇文章中&#xff0c;我们介绍了简单的 8 位量化技术和出…

算法通关村第十关-青铜挑战快速排序

大家好我是苏麟,今天带来快速排序 . 快速排序 单边快速排序(lomuto 洛穆托分区方案) 单边循环 (lomuto分区) 要点 : 选择最右侧元素作为基准点j 找比基准点小的&#xff0c;i 找比基准点大的&#xff0c;一旦找到&#xff0c;二者进行交换。 交换时机: 找到小的&#xff0c…

魔术《4 Kings 折纸》的三重境界(四)——魔术效果的突破

‍ ‍早点关注我&#xff0c;精彩不错过&#xff01; 在前三篇文章里&#xff0c;我们解释清楚了分别基于奇偶性&#xff0c;集合和群论来解释《4 Kings 折纸》这个魔术的过程&#xff0c;详情请戳&#xff1a; 魔术《4 Kings 折纸》的三重境界&#xff08;三&#xff09;——群…

【限时免费】20天拿下华为OD笔试之 【前缀和】2023B-最大子矩阵和【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录 题目描述与示例题目描述输入描述输出描述示例输入输出说明 解题思路如何表示一个子矩阵暴力解法二维前缀和优化二维前缀和矩阵的构建 代码解法一&#xff1a;二维前缀和PythonJavaC时空复杂度 解法二&#xff1a;暴力解法&#xff08;不推荐&#xff09;PythonJavaC时…

Springboot 项目启动类放置位置

文章目录 Springboot 项目启动类放置位置springboot 默认包扫描机制启动类放在特定位置springboot 启动注解理解配置启动类扫描特定的包1、 ComponentScan2、利用 SpringBootApplication 注解的 scanBasePackages 属性 Springboot 项目启动类放置位置 如果我们使用 IDEA 或者 …

常见面试题-MySQL的Explain执行计划

了解 Explain 执行计划吗&#xff1f; 答&#xff1a; explain 语句可以帮助我们查看查询语句的具体执行计划。 explain 查出来的各列含义如下&#xff1a; id&#xff1a;在一个大的查询语句中&#xff0c;每个 select 关键字都对应一个唯一的 id select_type&#xff1a;…

jdk1.8配置tomcat9教程

文章目录 前言报错&尝试解决运行 前言 最近在学习SpringMVC框架&#xff0c;但是里面需要用到Tocmat服务器。作为0基础Java选手&#xff0c;直接找了个视频里面的tomcat包下载。 里面的版本是apache-tomcat-8.5.68-windows-x64.zip的&#xff0c;然后就开始疯狂的各种博客…

巧用SqlServer数据库实现邮件自动发送功能

使用数据库发送邮件需要三个步骤&#xff0c;配置数据库的邮件服务、编写存储过程、设置SQL作业&#xff0c;接下来开始逐步分享&#xff1a; 配置数据库邮件&#xff1a; 在SqlServer左侧菜单栏中&#xff0c;找到管理页签中数据库邮件选项&#xff1a; 接下来开始配置数据库…

wpf devexpress自定义编辑器

打开前一个例子 步骤1-自定义FirstName和LastName编辑器字段 如果运行程序&#xff0c;会通知编辑器是空。对于例子&#xff0c;这两个未命名编辑器在第一个LayoutItem(Name)。和最终用户有一个访客左右编辑器查阅到First Name和Last Name字段&#xff0c;分别。如果你看到Go…

验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码)

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信你对这篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc;表白墙/留言墙 —— 中级SpringBoot项目&#xff0c;MyBatis技术栈MySQL数据库开发&#xff0c;练手项目前后端开发(带完整源码) 全方位全步骤手…

力扣每日一题-数位和相等数对的最大和-2023.11.18

力扣每日一题&#xff1a;数位和相等数对的最大和 开篇 这道每日一题还是挺需要思考的&#xff0c;我绕晕了好久&#xff0c;根据题解的提示才写出来。 题目链接:2342.数位和相等数对的最大和 题目描述 代码思路 1.创建一个数组存储每个数位的数的最大值&#xff0c;创建一…

OpenShift 4 - 就地调整 Pod 资源使用量

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.14 的环境中验证 文章目录 为什么需要就地调整 Pod 资源启动 InPlacePodVerticalScaling 特性实现就地调整 Pod 资源参考 为什么需要就地调整 Pod 资源 以往在 Kubernetes 中调整 Pod 的 …

CentOS 7搭建Gitlab流程

目录 1、查询docker镜像gitlab-ce 2、拉取镜像 3、查询已下载的镜像 4、新建gitlab文件夹 5、在gitlab文件夹下新建相关文件夹 6、创建运行gitlab的容器 7、查看docker容器 8、根据Linux地址访问gitlab 9、进入docker容器&#xff0c;设置用户名的和密码 10、登录git…

如何从回收站恢复已删除的文件

我们在各个领域都使用计算机。无论是专业工作还是个人工作&#xff0c;我们在生活中总能找到计算机的用途。因此&#xff0c;我们在很大程度上依赖于我们的计算机。计算机是办公室和企业部门使用的高效机器。 人们使用个人计算机发送电子邮件、创建文档、听音乐和观看视频等等…

企业要做大模型落地?建议进来看看这个榜单

机器幻觉问题&#xff0c;可能是未来相当长一段时间内悬浮在大模型领域上方的两片乌云之一。遥记半年前&#xff0c;LeCun 就曾断言&#xff1a;“单纯根据概率生成自回归的大语言模型&#xff0c;根本解决不了幻觉、错误的问题&#xff0c;GPT模型活不过5年”。 当然&#xff…