Write the Code. Change the World.

分类目录
2月 18

做网站用 php,做自适应网站用 bootstrap。很早的时候,这是一个不错的组合。喜欢 laravel,那么现在用 laravel10 + bootstrap5 + vue 就不错。

创建一个 laravel 项目

laravel10 release 版本已经发布,可以这样创建

composer create-project laravel/laravel xxx10 --prefer-dist

### 查看当前版本(当前显示 10.0.3)
cd xxx10
php artisan --version

# git 初始化,方便版本管理
git init
git add .
git commit -m 'laravel initialize 10.0.3'

修改配置

这里我 homestead 配置的域名是 xr.com,数据库名是 xr

.env

vim .env
# 修改 APP_URL 以及数据库配置
APP_URL=http://xr.com
DB_DATABASE=xr
DB_USERNAME=homestead
DB_PASSWORD=secret

config/app.php

vim config/app.php

# 修改以下内容
'timezone' => 'Asia/Shanghai',
'locale' => 'zh-CN',
'faker_locale' => 'zh_CN',

添加辅助函数

加辅助函数集,用来安放无副作用的函数。增加到 app 下。

vim app/helpers.php

# 增加一个辅助测试函数
<?php 

    function test($str = 'world') {
        return 'Hello ' . $str;
    }

# 将该文件增加到 composer 的自动加载配置中。 autoload->files 就是需要 composer 自动帮我们加载的函数库(不含类)

vim composer.json

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        },
        "files": [
           "app/helpers.php" 
        ]
    },

# 然后 dump (这一步是不可少的)
composer dump-autoload

加好了之后,就可以来尝试一下了。这里打开 tinker 来试试。

php artisan tinker;

test();

test('bird')

最后,提交代码。

git  add .
git commit -m '修改基础配置以及创建辅助函数集'

安装 ui 包

composer require laravel/ui

php artisan ui bootstrap --auth

# 现在前端就用 pnpm + vite 组合
pnpm install 

pnpm run dev

如果报 System limit for number of file watchers reached 错误,请看 https://blog.vini123.com/837

这样就 ok 了。 注意看 resources/views/layouts/app.blade.php。如果站点效果都统一,可以其他页面都继承该模板。blade 模板真的很好用啊,可以继承,可以重写,可以插槽。

跟随时代的潮流,用上 vite 来构建前端项目。之前,laravel9 就开始使用 vite 来构建了。

因为是自己构建的,所以可以定义一些 bootstrap 的一些特征。比如 primary 的颜色。这样就很爽。

# resources/sass/_variables.scss 中,在尾部追加下边的代码(这样你的 primary 色就是红色了 。),当然还有更多的定义。

$primary: #f00;

https://v5.bootcss.com/docs/customize/color/

https://www.runoob.com/bootstrap5/bootstrap5-colors.html

相关

vite 中文文档 https://cn.vitejs.dev/guide/

bootstrap5 中文文档:https://v5.bootcss.com/docs/getting-started/introduction/

bootstrap5 教程 https://www.runoob.com/bootstrap5/bootstrap5-tutorial.html

11月 19

时间,日期相关的处理, carbon 的确是个好东西。感觉离不开呀。

Carbon 是对 PHP DateTime 模块的二次扩展;提供时间格式化,时间计算的功能;

官方主页:http://carbon.nesbot.com/;

github: https://github.com/briannesbitt/Carbon

参考

https://www.jianshu.com/p/7e45bc4d0006

https://www.php.cn/phpkj/laravel/484191.html

https://learnku.com/articles/62292

11月 11

只要 websocket 服务。最简单化的 websocket 服务。不需要其他基于 swoole 的其他框架应用。仅仅 swoole 扩展 + php + nginx 完成 websocket 的服务。就是想最简单简洁的实现。

就像官方的实例一样 https://wiki.swoole.com/#/start/start_ws_server,就这么些代码。

$ws = new Swoole\WebSocket\Server('0.0.0.0', 9502);

//监听WebSocket连接打开事件
$ws->on('Open', function ($ws, $request) {
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//监听WebSocket连接关闭事件
$ws->on('Close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

我们不喜欢用 ip 来连接,我们用域名。我们不喜欢用 http,我们用 https。我们不喜欢加端口号,我们用代理。这里我们用 nginx 来搞定。比如吧,我们自己的域名是: xx.com, nginx 就可以像下边这样配置:

map $http_upgrade $connection_upgrade {  
    default upgrade;  
    '' close;  
}

server 
{    
    listen 443 ssl http2; 
    server_name xx.com;

    ssl_certificate         /usr/local/server/nginx/conf/ssl/xx.com.pem;
    ssl_certificate_key     /usr/local/server/nginx/conf/ssl/xx.com.key;

    charset utf-8;
    index index.php index.html index.htm;
    root /www/xx/xx.com/public;

    location /wss {
        # 代理到上边的自定义的地址
        proxy_pass http://127.0.0.1:9502;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location / {
        try_files $uri $uri/  /index.php?$query_string; 
    }

    location ~ \.php($|/) {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param HTTPS $https if_not_empty;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

服务端的配置构建的重要部分就算好了。需要注意的是,创建 websocket 的时候,一定不要带上 ssl 相关的参数和证书。这样你 nginx 这边请求代理过去是 http 请求,就会出错。

websocket 这里没有心跳功能,可以手动模拟创建一个,去实现类似的业务。

还有,在服务端可以使用 swoole 自己的存储结构。 https://wiki.swoole.com/#/memory/table

旧的文章

https://blog.vini123.com/405

https://blog.vini123.com/482

https://blog.vini123.com/294

9月 30

使用 laravel 开发项目的时候, artisan 是个好东西。这个好东西是真的好。在做 command 的时候,您可以方便的输出想要的内容在终端上,比如警告,错误,选择等等。这是因为 command 它继承了Command 类,该类使用了 trait Illuminate\Console\Concerns\InteractsWithIO。而它最终实现了 Symfony\Component\Console\Output\OutputInterface 。 Symfony\Component\Console\Output\ConsoleOutput 是 cli output 的源头类。 只要我们做好 Symfony\Component\Console\Output\ConsoleOutput 的文章,不也可以输出吗。

ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.

来 123, 跟着步骤走起来

# 先生成一个 seeder
php artisan make:seeder TestSeeder

# 在该 seeder 的 run 函数中加入以下代码
    public function run()
    {
        $output = new \Symfony\Component\Console\Output\ConsoleOutput();
        $section = $output->section();
        $section->writeln('人生若只如初见,何事秋风悲画扇');
    }

# 那么开始测试一下
php artisan db:seed --class=TestSeeder

是不是就可以看见你想看见的东东了。当然你可以封装,搞出更多花样。也还有更多命令待使用。

8月 12

某些场景,需要用户的 openid 以及 unionid,如何获取和转换就很有必要。获取公众号所有用户的 openid,通过公众号 openid 获取用户的 unionid。

获取公众号 openid

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Getting_a_User_List.html

# 正常结果 json_decode 下的结构如下
{
  "total":23000,
  "count":10000,
  "data":{"
     openid":[
        "OPENID1",
        "OPENID2",
        ...,
        "OPENID10000"
     ]
   },
   "next_openid":"OPENID10000"
}

通过 openid 获取用户的 unionid

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId

8月 09

有些时候,对于并发,我们只想执行一次。多次并发请求就打破了你的想。这里我们用 redis 来弄就好。

操作一波

这里以 laravel 为例

use Illuminate\Support\Facades\Redis;

$time = 60;
$key = 'mimi' . $user->id;
// 如果不存在就 set 值,返回 0 或 1,set 成了返回 1,否则返回 0(表示已经锁住了,不要进去了)
$res = Redis::setnx($key,  $user->id);
if ($res) {
   # 设置 redis 过期(锁的时间秒)
   Redis::expire($key, $time);

   # 你的业务
   xxxxxx
}

laravel 并发处理,php 并发处理

7月 11

设计 API 授权,或者调用第三方 API 时,经常会接触到:

Authorization : Bearer Tokenxxxxxx

有没有疑惑为何不直接写成这样就得了:

Authorization : Tokenxxxxxx

这是因为 W3C 的 HTTP 1.0 规范,Authorization 的格式是:

Authorization: <type> <authorization-parameters>

所以 Bearer 是授权的类型,常见的授权类型还有:
- Basic 用于 http-basic 认证;
- Bearer 常见于 OAuth 和 JWT 授权;
- Digest MD5 哈希的 http-basic 认证 (已弃用)
- AWS4-HMAC-SHA256 AWS 授权
- …

6月 21

本地连接 redis, 出现 dial tcp 192.168.56.56:6379: connect: connection refused ,修改 redis 配置,重启就好了

操作

sudo vim /etc/redis/redis.conf

# 将 bind 127.0.0.1 ::1 改成 bind 0.0.0.0,然后重启

sudo service redis restart

# 查看
ps -ef | grep redis