tp5 (thinkphp 5) backend development

The compilation environment
is php 7.3.29. Windows may need to find a tutorial to install it.
The macOs system comes with apache. You only need to cancel the comments about php configuration in httpd.conf under the /etc/apache2 path.

insert image description here

Dependent package manager: composer, installation tutorial , common commands

Create project command:

composer create-project topthink/think 项目名称 --prefer-dist

Project directory structure
The editing tool I use is phpStorm .

Environment configuration of phpStorm.

insert image description here
insert image description here
insert image description here

to develop

The front-end and back-end separation projects first solve the problem of crossing
insert image description here
public/index.php : the entry file of the program

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
    
    
    //允许的源域名
    header("Access-Control-Allow-Origin: *");
    //允许的请求头信息
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
    //允许的请求类型
    header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
    exit;
}

Under the database configuration
application folder, there is a database.php file. It can be configured in it.

The next step is to create an object-relational map.
application creates a module. There are commands to create modules.
The module name can be any legal name.
Here I created an index module, under which three packages are established: controller, model, utils.
model
The model package is used to create object-relational mapping.
model/Users

<?php

namespace app\index\model;


use think\model;

class Users extends model
{
    
    
	// 只需要把表的名字声明好即可。
    protected $table = 'users';
}

controller
controller is used to implement business logic.
Here I have implemented, register, cancel account, change password, log in, obtain contact information of all users, and modify contact information of a user.
Among them, canceling the account, changing the password, and modifying the contact information of a certain user have been checked for authority, and only the account can be operated.
controller/User

<?php

namespace app\index\controller;

use app\index\utils\Token;
use think\Db;
use think\Request;
use think\Exception;
use app\index\model\Users;


class User
{
    
    
    /**
     * 注册
     * 校验函数还可以进行拆分
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function register(){
    
    

        // 获取 请求对象
        $request = Request::instance();
        // 从请求对象中 获取 phone,email, pwd 参数
        $phone = $request->param("phone");
        $email = $request->param("email");
        $pwd = $request->param("pwd");

        // 校验 phone, email, pwd 格式是否正确
        if (!preg_match(PhoneRule, $phone)) {
    
    
            return json(["msg"=>"error! phone 格式不正确"]);
        } elseif (!preg_match(EmailRule, $email)){
    
    
            return json(["msg"=>"error! email 格式不正确"]);
        } elseif (!preg_match(PwdRule, $pwd)){
    
    
            return json(["msg"=>"error! 密码至少包含数字和英文,长度6-20!"]);
        }

        // 查询 phone 或者 email 是否被注册过
        if(Users::where('phone', $phone)->find()){
    
    
            $user = Users::where('phone', $phone)->find();
            return json(["msg"=>"error! phone已被注册!"]);
        }elseif (Users::where('email', $email)->find()){
    
    
            return json(["msg"=>"error! email已被注册!"]);
        }

        // 经过上述的校验都没问题,校验函数返回一个 Users对象
        try {
    
    
            // 插入数据
            $newUser = new Users();
            $newUser->phone = $phone;
            $newUser->email = $email;
            // 对密码加密 ===========
            $newUser->pwd = md5($pwd);
            //========
            // 提交数据
            $newUser->save();

            // 注册:发不发放token?
            $token = 0;

            return json(["msg"=>"success! 注册成功!", "token"=>$token]);
        }catch (Exception $ex){
    
    
            return json(["error"=>$ex, "msg"=>"error! 注册失败!"]);
        }
    }

    /**
     * 登录
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function login(){
    
    
        $request = Request::instance();
        // 手机号码 或者 邮箱登陆
        // 获取 登录的方式 type
        $type = $request->param("type");
        if ($type == "0"){
    
    
            // type = 0, 手机号登录
            // 查询phone
            $phone = $request->param("phone");
            $user = Users::where('phone', $phone)->find();
            if(!$user){
    
    
                return json(["msg"=>"error! 用户不存在!"]);
            }
        }elseif ($type==="1"){
    
    
            // type = 1, 邮箱登录
            // 查询email
            $email = $request->param("email");
            $user = Users::where('email', $email)->find();
            if(!$user){
    
    
                return json(["msg"=>"error! 用户不存在!"]);
            }
        }else{
    
    
            // type 不对,直接返回提示
            return json(["msg"=>"error! 请选择登录方式!"]);
        }
        // 获取到用户的密码,直接加密
        $pwd = md5($request->param("pwd"));
        // 密码 密文比对
        // 根据手机号 查找 密码字段 的内容
        // 然后用户提交加密后的密码进行比对
        if ($user->pwd != $pwd){
    
    
            return json(["msg"=>"error! 密码错误!"]);
        }

        // 发放token
        $token = Token::getToken($user);

        return json(["msg"=>"success! 登录成功!", "token"=>$token]);
    }

    /**
     * 修改密码
     * 需要加token权限
     * 确保是在登录状态才能进行此操作
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function updatePwd(){
    
    
        $request = Request::instance();
        $checkRes = Token::checkToken($request);
        if($checkRes!==true){
    
    
            return json(["msg"=>$checkRes]);
        }
        {
    
    
            // 获取当前用户的 uid 或者 phone 或者 email
            // 根据这些信息查询数据库,获取数据库对象
            // 这里假设根据 phone 来获进行查找
            $phone = $request->param("phone");
            $user = Users::where("phone",$phone)->find();
            $pwd = $request->param("pwd");
            // 修改的密码也需要满足注册用户时的密码规则
            if (!preg_match(PwdRule, $pwd)){
    
    
                return json(["msg"=>"error! 密码至少包含数字和英文,长度6-20!"]);
            }
            $user->pwd = md5($pwd);
            // 保存提交
            $user->save();
            return json(["msg"=>"修改密码成功!"]);
        }

    }

    /**
     * 销毁账号
     * 需要加token权限
     * 确保是在登录状态才能进行此操作
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function destroyUser(){
    
    
        $request = Request::instance();
        // 获取当前用户的 uid 或者 phone 或者 email
        // 根据这些信息查询数据库,获取数据库对象
        // 这里假设根据 phone 来获进行查找

        $checkRes = Token::checkToken($request);
        if ($checkRes!==true){
    
    
            return json(["msg"=>$checkRes]);
        }

        $phone = $request->param("phone");
        $user = Users::where("phone",$phone)->find();
        // 删除提交
        $user->delete();
        return json(["msg"=>"success! 销毁成功!"]);
    }

    /**
     * 获取所有用户的联系信息
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getUsersContactInfo(){
    
    
        // select() 是选择全部, find() 是选择一条
        $result=Db::name('users')
            ->field('uid,phone,email')
            ->select();
        return json($result);
    }

    /**
     * 修改某用户的联系信息
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function updateUsersContactInfo(){
    
    
        // 获取 请求对象
        $request = Request::instance();

        $checkRes = Token::checkToken($request);
        if ($checkRes!==true){
    
    
            return json(["msg"=>$checkRes]);
        }

        // 从请求对象中 获取 phone,email, pwd 参数
        $phone = $request->param("phone");
        $email = $request->param("email");
        $uid = $request->param("uid");

        // 根据uid获取用户对象
        $user = Users::where('uid', $uid)->find();
        // 检查phone是否为空,为空则说明用户不需要修改phone
        if($phone != ""){
    
    
            // 检查 phone 的格式
            if (!preg_match(PhoneRule, $phone)) {
    
    
                return json(["msg"=>"error! phone 格式不正确"]);
            }
            // 修改用户的 phone
            $user->phone = $phone;
        }
        if($email != ""){
    
    
            // 检查 email 的格式
            if (!preg_match(EmailRule, $email)) {
    
    
                return json(["msg"=>"error! email 格式不正确"]);
            }
            // 修改用户的 email
            $user->email = $email;
        }
        // 保存提交
        $user->save();
        return json(["msg"=>"success! 修改成功!"]);
    }

    public function controllerTest(){
    
    
        test("llll");
    }
}

Token issuance and verification
I put Token issuance and verification in the utils folder, and regard it as a tool, encapsulated in the Token class, but I only need the processing functions inside, and do not need to create a Tokne object. The static method is used to issue tokens and verify tokens. Just use the class name to call it directly.
// I got stuck when writing this class, the idea is fine, but the result is different from my expectation, this is the most uncomfortable
// Why is it stuck?
// When verifying the token, the value of the token is passed by the user, which cannot be predicted, so putting the token passed by the user directly into JWT::decode for verification will cause an error, so an exception handling is required , but this exception is of \Exception type. I originally wrote think\Exception, but I have not been able to catch it. I have been looking for this bug for a long time. Therefore, the topmost level of exception should be \Exception.

<?php

namespace app\index\utils;

use app\index\model\Users;
use Firebase\JWT\JWT;

class Token
{
    
    
    // 生成token的方式不公开
    private static function generateToken($data){
    
    
        $key = 'key';   //秘钥:自定义
        $payload = array(
            'iss' => 'kary',                      //签发人(官方字段:非必需)
            'aud' => 'public',                    //受众(官方字段:非必需)
            'iat' => time(),                      //签发时间
            'nbf' => time(),                      //生效时间,立即生效
            'exp' => time() + 60*60*24*7,         //过期时间,一周
            'uid' => $data->uid,                        //自定义字段
        );
        //加密生成token
        return JWT::encode($payload, $key);
    }

    // 只公开获取token的方式
    public static function getToken($data){
    
    
        return self::generateToken($data);
    }

    public static function checkToken($request){
    
    
        $authorization = $request->header("authorization");
        // 获取token
        {
    
    
            // 异常捕获无效
            try {
    
    
                $token = substr($authorization,8,-1);
            }catch (\Exception $ex){
    
    
                $token = $authorization;
            }
        }

        try {
    
    
            // 1.如果当前时间大于 exp,或者小于nbf,token无效,进行拦截
            $key = 'key';
            JWT::$leeway = 60;//当前时间减去60,把时间留点余地
            $decode = JWT::decode($token, $key, array('HS256'));
            // 查数据库,用户不存在
            if(Users::where('uid', $decode->uid)->find()){
    
    
                // 比较当前时间大于 exp,或者小于nbf,token无效,进行拦截
                if($decode->nbf > time()){
    
    
                    return "权限伪造!";
                }elseif ($decode->exp < time()){
    
    
                    return "权限过期,请重新登录!";
                }
            }else{
    
    
                return "账户不存在!";
            }
        }catch (\Exception $ex){
    
    
            // token 无效
            return "权限不足!";
        }
        return true;
    }
}

When the user registers and logs in, it is necessary to verify the format of the mobile phone number, email address, and password submitted by the user. Regular expressions need to be used for discrimination. Regular expressions are too long. In order to make the code as concise as possible, Put the regular expression in the constant file to define it, and use the name of the expression directly when using it. The response body can also be encapsulated here.
application/common.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <[email protected]>
// +----------------------------------------------------------------------

// 应用公共文件

// 校验表达式
define('PhoneRule', "/^1[3456789]\d{9}$/");
define('EmailRule', "/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/");
define('PwdRule', "/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/");

// 响应体 统一封装
function writeJson($code, $data, $msg = 'ok', $errorCode = 0)
{
    
    
    $data = [
        'code' => $errorCode,
        'result' => $data,
        'message' => $msg
    ];
    return json($data, $code);
}

There
is a route.php under the public folder, and
there is also a route.php under the application folder.
The route.php under the public folder should be the main route, and the route.php under the application folder is a sub-route.
The relationship between these two routes will be reflected when the interface is requested.
Route.php under the public folder can be ignored, and focus on route.php under the application folder.

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

use think\Route;
// route参数的controller可以省略

// 增:注册
Route::post('/register','index/User/register');
// 删:注销账户
Route::post('/destroyUser', 'index/User/destroyUser');
// 改:修改密码
Route::post('/updatePwd', 'index/User/updatePwd');
// 查:登录
Route::post('/login', 'index/User/login');
// 查:获取所有用户的联系信息
Route::get('/getUsersContactInfo', 'index/User/getUsersContactInfo');
// 改:修改某用户的联系信息
Route::put('/updateUsersContactInfo', 'index/User/updateUsersContactInfo');


// 测试接口
Route::get('/controllerTest', 'index/User/controllerTest');


// 借口测试
Route::get('/test', function () {
    
    

    // find 查找只能找到一条记录
    $all = \app\index\model\IwalaCurrency::all();
    echo "\njust is one case!\n";
    return json($all);
});
Route::get(路由路径, 执行函数);

Recently, I am familiar with php and tp5 to do some things. share! ! !

Guess you like

Origin blog.csdn.net/wjl__ai__/article/details/124675856