Write the Code. Change the World.

分类目录
12月 11

docker 的确是个好东西。该早一点就用起来。当下还在熟悉和练习中。

渐渐去丰富和完善。

.env

# 时区
TZ=Asia/Shanghai

# 项目对应文件夹
SOURCE_DIR=./www

# nginx https://nginx.org/
NGINX_NAME=nginx
NGINX_VERSION=1.25.3
NGINX_HTTP_HOST_PORT=80
NGINX_HTTPS_HOST_PORT=443
NGINX_CONFD_DIR=./conf/nginx/conf.d
NGINX_CONF_FILE=./conf/nginx/nginx.conf
NGINX_SSL_CERTIFICATE_DIR=./conf/nginx/ssl
NGINX_LOG_DIR=./logs/nginx

# php8.3
PHP_LOG_DIR=./logs/php8.3

# mysql
MYSQL_DATA=./data/mysql8.2-data
MYSQL_PORT=3306

# redis
REDIS_PORT=6379

继续阅读

10月 13

很久很久以前,第三方授权登录就开始流行。比如 qq、微博、github、微信这些。如果有一个大的平台来做这个服务的确是很方便的一个事情。在这些授权后都会有一个回调页面,就是从自己的网页跳转到授权页面,再跳转回来。但是,小程序是没提供这个服务的。但是自己可以构造类似的方式。
整个环节,代码都是由自己控制,可以很灵活的视线需求。仅仅是生成小程序码和扫码登录上小程序是腾讯那边做的。

示例:https://www.zeipan.com/admin

步骤

关键点:这里以 jwt 的认证方式来实现授权登录。

  • 登录页获取并展示生成携带参数的小程序码
  • 登录页面轮询获取登录状态(这里是 token)
  • 手机微信扫描小程序码并授权同意登录

继续阅读

9月 10

该后台使用 vite + ts + pnpm + vue3 + element-plus + tailwindcss 等技术栈构成。没有添加任意可视化图标等插件。以最小功能,最基础功能展现。用户可以额外添加可使用的插件逻辑。

该后台后端使用 php8.2 + laravel 10 + mysql

该后台后端 go 语言版本开发中。将使用 gframe2.5.2

源码: https://github.com/vini123/simpleAdmin

在线体验: https://www.zeipan.com/admin

权限以及密码一键复位: https://v3test.yuepaibao.com/admin/api/reset

测试账号以及密码: zhoulin@xiangrong.pro、 111111 (如果发现登录不了,可一键复位谢谢)

继续阅读

9月 06

既然 go 的迁移、seeder 等不好用,还是用 laravel 来搞吧。

开始

composer create-project laravel/laravel youme.com --prefer-dist

这样就创建了一个最新的 laravel 项目,项目文件在 youme.com 里。在本地,做了 host 映射。通过 youme.com 就可以打开。

上边就是默认的。

创建 git 版本控制,提交。

git init -b main
git add .
git commit -m 'laravel initialize'

继续阅读

8月 14

前端本地测试,mock 可以先用着。终究还是得和真实的服务环境对接。这个时候请求接口,往往就会遇到跨域的问题。对于 laravel框架,对于 laravel10,只需要建立一个中间件,在中间件中对请求进行处理就好。需要的时候,带上中间件,不需要的时候,去掉它就可以。还是很方便的。

Do

php artisan make:middleware EnableCrossRequestMiddleware

# 完整代码如下
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnableCrossRequestMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);
        $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
        $allow_origin = [
            'http://localhost:5173',
        ];

        if (in_array($origin, $allow_origin)) {
            $IlluminateResponse = 'Illuminate\Http\Response';
            $SymfonyResopnse = 'Symfony\Component\HttpFoundation\Response';
            $headers = [
                'Access-Control-Allow-Origin' => $origin,
                'Access-Control-Allow-Methods' => 'POST,GET,OPTIONS,PUT,PATCH,DELETE',
                'Access-Control-Allow-Headers' => 'Accept,Content-Type,Referer,User-Agent,Origin,X-Requested-With,X-XSRF-TOKEN,X-CSRF-TOKEN,Authorization,Time'
            ];

            if ($response instanceof $IlluminateResponse) {
                foreach ($headers as $key => $value) {
                    $response->header($key, $value);
                }
                return $response;
            }

            if ($response instanceof $SymfonyResopnse) {
                foreach ($headers as $key => $value) {
                    $response->headers->set($key, $value);
                }
                return $response;
            }
        }
        return $response;
    }
}

然后,在 ./app/Http/Kernel.php 的 $middleware 中添加一个配置。

    protected $middleware = [
        …
        \App\Http\Middleware\EnableCrossRequestMiddleware::class,
    ];

这样就完事了。

本来是想将中间件放在中间件组里(middlewareGroups)或使用 alias (放在 $middlewareAliases)的方式来使用,但都失败了。暂时还没找到原因。

之所以想这样弄,是因为不是所有的请求都需要设置请求头。

继续阅读

7月 12

A VirtualBox machine with the name 'homestead' already exists.
Please use another name or delete the machine with the existing
name, and try again.

Do

之前在mac上安装laravel/homestead vagrant虚拟机环境时由于参照的教程是: 每次都必须在~/Homestead目录下边运行vagrant up/halt命令,觉得实在是不方便,于是乎按照另外一个教程(在任何目录下可以通过homestead up来启动虚拟机)来配置环境,但是当键入homestead up时,却报出

==> default: Importing base box 'laravel/homestead'...

==> default: Matching MAC address for NAT networking...

A VirtualBox machine with the name 'homestead' already exists.

Please use another name or delete the machine with the existing

name, and try again.

这样的错误

stackoverflow上好几个人说通过vagrant global-status 查看虚拟器,然后在vagrant destroy {id}删除对应名称的虚拟机可以解决问题,但是重复n遍homestead up或者到~/Homestead下运行vagrant up之后,还是会报出上边的错误,后来通过VBoxManage list vms获取虚拟机列表,然后在通过运行

VBoxManage unregistervm homestead --delete

之后,重新运行homestead up之后 一切回归正常

参考

https://www.cnblogs.com/huangye-dream/p/4604973.html

7月 04

# 在 mysql 中,先查询出 sql_mode
show variables like 'sql_mode';

# 编辑修改
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

# 没有就追加,有就修改
# 先备份一个全的
# sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

sql_mode =这里你填需要的

# 重启
sudo service mysql restart
6月 28

https://learnku.com/docs/laravel/10.x/octane/14909#swoole

https://segmentfault.com/a/1190000040673969

https://chriswhite.is/coding/swoole-vs-roadrunner-for-laravel-octane/

composer require laravel/octane

# 选择 swoole
php artisan octane:install

# 安装 swoole
pecl install swoole

# 查找 php.ini 文件位置
php -i grep | php.ini

# vim 编辑,并配置
extension=swoole.so

# 重启 php
sudo /etc/init.d/php-fpm restart

# 查看扩展
php -i |grep swoole

继续阅读

5月 04

laravel orm 的多态有的时候是真的好用。比如,我们在设计一个消息表的时候,这个多态就很有用。消息对于整个项目,是一个基础的统称。比如,有人注册账号了,给他一个欢迎的消息。 有人充值了一个会员,给他一个充值消息。有人参加了一个活动,给他一个参加的消息。就这样一个场景。在消息表里边,我们仅仅需要构建这些字段 user_id、content、messageable_id、messageable_type、status、updated_at、created_at 就可以了。是不是很干净,是不是很舒适。后端的东西往往是给前端服务的。我们要会联想到前端的一个场景。有一个消息列表,我们点击消息,应该可以查看到消息的详情。比如会员消息详情、充值详情(当然有的时候是不需要详情,比如欢迎语。)这个时候,多态一对一在这个场景就很符合。这个多态和面向对象里的多态(继承、接口)不一样,但有相似的意境。

开始

多态的重要信息是 xxxable_id、和 xxxable_type。一个对应的是目标对象的 id,一个对应的是目标对象的类名(比如 App\Models\Topic)。

在 xxx 模型中。我们要定义一个 xxxable 方法。这里以 Message 模型为例。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Message extends Model
{
    use HasFactory;

    protected $fillable = ['user_id', 'content', 'messageable_id', 'messageable_type'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * 获取父级的对象
     */
    public function messageable(): MorphTo
    {
        return $this->morphTo();
    }
}

在父级对象中,你也可以定义相对应的关系。当然也可以不定义。在这个场景中,我们重要的是消息列表以及消息对应的对象。所以仅仅在消息中定义 morph 就好。

使用

比如: Message::query()->take(10)->with('messageable')->get();

一个完整的过程。我们有这三个模型:Message(消息)、Topic(话题)、Member(会员)。

$user = $request->user();
$data = [xxx];
$topic = Topic::create($data);

# 获取类名
$topicClass = get_class($topic);

# 创建消息
Message::create([
    'user_id' => $user->id,
    'content' => '您的话题已创建,请等待审核',
    'messageable_id' => $topic->id,
    'messageable_type' => $topicClass
 ]);

---------------------------------------
$member = Member::create($data);

Message::create([
    'user_id' => $user->id,
    'content' => '您已成为会员,请愉快的玩耍吧',
    'messageable_id' => $member->id,
    'messageable_type' => get_class($member)
 ]);

再啰嗦一点点

上边说了,前端是要点击消息,做对应的跳转的。既然后端是动态绑定(多态算是动态的一种绑定吧),那么前端就是一个强制的硬性的绑定了,可以理解为是枚举。可以用 if 来搞定。因为消息的种类就那么多,不像数据库,有成千上万百万千万的数据。

if (消息类型一) {
    跳转到一
} else if (消息类型二) {
    跳转到二
}

因为有了 messageable_id,我们就可以通过接口来请求各自所想要的信息了。

对于消息列表。如果没有特殊的要求 messageable 我们也是不需要在这里就请求上的。因为请求了,就需要数据库去查询。查询了又不用,那不是浪费。这里看具体情况哈。

中文文档

https://learnku.com/docs/laravel/10.x/eloquent-relationshipsmd/14889#5981a6