Write the Code. Change the World.

5月 01

虽然有 docker , 但还是喜欢用 homestead 开发环境。这个时候,一些旧的项目可能会用到比较低版本的 php,这个时候切换 php 版本就是一个常用的操作。

使用 php 版本

homestead 环境中,项目使用 php 的哪个版本,可以在 Homestead.yaml 文件中进行配置。比如:

sites:
    - map: work.xiangrong.com
      to: /home/vagrant/code/zhoulin/work.xiangrong.com/public
      php: "7.4"

这里指定好 php 版本就好。

但是,当 homestead 环境中当前使用的 php 版本是 php 8php 5.6 这些。使用 composer 或项目本身就有可能报错。这个时候,我们就需要将 homestead 环境的 php 版本切换的和项目所配置的一样。

补充

如果切换成对应的 php 版本还会出 badgateway 这样的错误,可以试着重启 php 看看。

# 这里以 php 7.4 为例
sudo /etc/init.d/php7.4-fpm restart

操作

# 查看当前环境中的 php 版本
php -v

# 查看所有 php 版本和当前版本
sudo update-alternatives --display php

# 执行后,会列出当前 php 所有版本和编号,输入编号,切换到执行的版本
sudo update-alternatives --config php

其实

其实,想切换到某个 php 版本。直接输入就可以了,也不用向上边那样敲那么长的命令。 比如,想切换到 php7.4 版本。直接输入 php74 回车即可。同理,想切换到 php8.2 版本,直接输入 php82 回车即可。这些命令,可以在 Homestead 目录下的 aliases 文件中找到。

function php73() {
    sudo update-alternatives --set php /usr/bin/php7.3
    sudo update-alternatives --set php-config /usr/bin/php-config7.3
    sudo update-alternatives --set phpize /usr/bin/phpize7.3
}

function php74() {
    sudo update-alternatives --set php /usr/bin/php7.4
    sudo update-alternatives --set php-config /usr/bin/php-config7.4
    sudo update-alternatives --set phpize /usr/bin/phpize7.4
}

function php80() {
    sudo update-alternatives --set php /usr/bin/php8.0
    sudo update-alternatives --set php-config /usr/bin/php-config8.0
    sudo update-alternatives --set phpize /usr/bin/phpize8.0
}

function php81() {
    sudo update-alternatives --set php /usr/bin/php8.1
    sudo update-alternatives --set php-config /usr/bin/php-config8.1
    sudo update-alternatives --set phpize /usr/bin/phpize8.1
}

function php82() {
    sudo update-alternatives --set php /usr/bin/php8.2
    sudo update-alternatives --set php-config /usr/bin/php-config8.2
    sudo update-alternatives --set phpize /usr/bin/phpize8.2
}

今天五月一日。

阅读全文 >>

4月 16

在项目中,我们通常会用到 mysql、redis 数据库。有时候再额外使用 sqlite 数据库也不错。 那就开搞。

centos 一般会默认安装了 sqlite 数据库。只是版本都比较落后。

# 查看 sqlite3 的版本
sqlite3 --version

# 如果没有安装那就更好。如果安装了,就先卸载这玩意

yum remove sqlite3

安装最新版本的 sqlite3

https://www.sqlite.org/download.html

官网列出了 sqlite3 的下载地址。我们选择最新的版本地址,是包含 includes a "configure" script 的版本。当前最新版本是 3.41.2。

开始安装吧。

# 喜欢将一些需要编译安装的包放在这里
cd /usr/local/src/service

wget https://www.sqlite.org/2023/sqlite-autoconf-3410200.tar.gz

tar -xzvf sqlite-autoconf-3410200.tar.gz

cd sqlite-autoconf-3410200

./configure --prefix=/usr/local

make && make install

# 建立软链
ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3

# 查看版本
sqlite3 --version

到此 sqlite3 最新版本已经安装完成了。

阅读全文 >>

4月 15

css 是没有父元素选择器的。可是现在有伪选择器 has,这个可以实现父选择器的愿望。通过 has 这个词,也很容易记住和理解。就像一个反向思维一样,本来需要一个父级,那如果我父级就在那,我判断是否有子集不就通了吗。而 css 从来都是从父到子到兄的。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/:has

为什么要搞这玩意呢。还是因为在使用 element-ui 的上传组件时,当用户选择了一张图片后,上传按钮还是显示在那地方。这样体验很差也不好看。即使你加了 limit:1 的控制也不行。不知道为啥会这样(我没找到对应的 api 还是就是这样呢)。

既然这样了,那总得处理。最直接的一种方式是通过 js + css 的方式。对于 html,只要 js + css 是没有搞不定的。可是这样代码不好看了啊,也增加了多余的逻辑。通过观察组件的 dom 结构,可以发现,不管是否有选择的图片,上传按钮的兄弟级存在一个 li标签。 只要选择了图片或默认存在的图片,都会存在一个
样式为 .el-upload-list__item的 div。那好,这个时候就想到,如果存在父选择器,再通过父选择器的兄弟选择,通过 display:none,不就可以隐藏了吗。
可是,可是就是没有父选择器啊。可是,可是 has 伪选择器就是可以实现这样一个场景就是父选择器。

下边是 element ui 的上传组件的结构(精简模拟的)

# 没选择图片的
<div class="upload-card">
    <li></li>
    <div class="upload-btn">

    </div>
</div>

# 选择图片的
<div  class="upload-card">
    <li>
    <div class="el-upload-list__item"></div>
    </li>
    <div class="upload-btn">

    </div>
</div>

通过 has 就可以实现隐藏了。

.upload-card:has(.el-upload-list__item) .upload-btn {
    display:none;
}
 ```

 ### 真实 code

 ```
 #template
 <el-form-item label="封面" prop="cover">
 <el-upload ref="coverUpload" class="upload-card" action="#" :multiple="false"  list-type="picture-card" :file-list="image.cover" :http-request="uploadCover" :auto-upload="false">
 <i class="el-icon-plus" />
 </el-upload>
</el-form-item>

# scss
::v-deep .upload-card:has(.el-upload-list__item) .el-upload--picture-card {
  display: none !important;
}

阅读全文 >>

4月 07

如果发现配置了定时任务,却发现没有执行到。可以先看看日志。

# 看日志
tail -f /var/log/cron

# 查看日志文件
ll /var/log/cron*

# 看哪些用户在使用定时任务
ls /var/spool/cron/

# 查看某个用户的任务详情。比如 nginx
more /var/spool/cron/nginx

# 开机自启动
systemctl enable crond

如果没有日志,请查看下边的方法

情况是这样的。本来是有日志的。如果把日志删除了,即使重启 crontab 服务也是没有日志的。还有一种就是以前根本就没打开日志。这两种情况下边的方法都可以搞定。还有说在 /etc/rsyslog.d 下建立 50-default.conf。那还不如下边的方法。 下边的方法是通过 chatGPT 查询到的。有时候还是很方便的。

要查看CentOS 8 crontab的日志,您可以按照以下步骤进行处理:

  1. 打开 /etc/rsyslog.conf 文件并找到以下行:

cron.* /var/log/cron

  1. 将上述行的注释符号(“#”)移除,以启用cron日志记录功能。保存并关闭该文件。

  2. 重新启动 rsyslog 服务,以确保更改生效:

$ sudo systemctl restart rsyslog

  1. 检查 /var/log/cron 文件,以查看生成的 cron 日志。

如果上述方法不起作用,则您可以尝试在 crontab 命令中将日志记录级别设置为更高的级别。例如,将以下行添加到 crontab 文件的顶部:

MAILTO=user@domain.com

          • /path/to/script > /dev/null 2>&1

在上述命令中,将 MAILTO 设置为您的邮件地址,以接收有关 crontab 任务运行情况的通知。将脚本路径替换为实际的脚本路径,并将输出重定向到 /dev/null,以避免在终端中看到任何输出。将 "> /dev/null 2>&1" 去掉就可以在/var/spool/mail用户文件夹下查看cron任务的执行情况了。

阅读全文 >>

3月 30

瀑布流是一种展现方式。无论 h5 还是小程序,在一定场景下会需要。可以通过把数据分组,再 flex-column 布局。也可以用过计算浮动来实现布局。这些搞起来,还是比较麻烦,而且代码不好看。现在微信小程序实现瀑布流都新的方式。还有吸顶等操作。

开始

https://developers.weixin.qq.com/community/develop/article/doc/000ae631788f400c9a7f151f65b013

https://developers.weixin.qq.com/community/develop/article/doc/000a088c5c471062bf0f0af1a5b813

文章尾部,有代码测试片段。打开,就可以尝试。不过,需要将渲染方式切换到 Skyline 。

切换操作看这里 https://developers.weixin.qq.com/miniprogram/dev/framework/runtime/skyline/migration/#%E5%BF%AB%E6%8D%B7%E5%88%87%E6%8D%A2%E5%85%A5%E5%8F%A3

计算的方式

https://juejin.cn/post/7066778804827619364

阅读全文 >>

3月 20

小白一枚,从前端开始,开发区块链项目。

需要知道的事情

  1. chrome 浏览器,先要安装 metaMask 插件。
  2. 代码中,检测 metaMask 插件是否已经安装,并是可行的状态。
    
    # 不需要任何引入,就是这样直接判断
    if (window.ethereum != null)  {

}

阅读全文 >>

3月 20

通过给 div 定义 id 属性,然后在 a 标签中 href 设置定义好的 id,用户点击 a 标签,页面就可以滑到目标位置。只是这样,点击的时候,url 会出现变化。这里了还有一种方法。

html 跳转到指定的位置

 const goView = function() {
    document.querySelector("#roll_user").scrollIntoView(true);
 }

这种,是通过 js 调用方法来实现。优点是 url 地址不变,还可以设置更多的参数。显得安静丝滑。缺点是,如果刷新浏览器,位置会变化。

当然,还可以通过 js 用其他方式实现这种结果。只是不划算。

阅读全文 >>

3月 14

使用 vite 来作为构建前端的工具,是有一些缺陷的。

However, it lacks some features that Laravel Mix supports, such as the ability to copy arbitrary assets into the build that are not referenced directly in your JavaScript application.

https://laravel.com/docs/10.x/vite

相关

https://github.com/laravel/vite-plugin/blob/main/UPGRADE.md#migrating-from-vite-to-laravel-mix

多语言相关

注册,登录这些页面,以及 request 错误的提示,都是英文的。想要中文的,就得有对应的语言配置。

https://laravel-lang.com/installation/

composer require laravel-lang/common --dev

php artisan lang:add zh_CN

php artisan lang:update

然后,在 config/app.php 中,将 lang 设置成 'zh_CN' 即可。

阅读全文 >>

3月 12

Inertia 是为希望构建整体应用程序的人而构建的。他们通常更喜欢控制器和视图之间的紧密结合,但又希望使用现代客户端框架来构建其应用程序。

上边这个描述,的确是很贴切。比如 laravel 框架,自身使用的是 blade 模板来渲染页面。所有处理都是服务端完成。也可以在其中部分使用 vue、react这些。

Laravel 提供了两全其美的解决方案。Inertia 可以桥接您的 Laravel 应用程序和现代 Vue 或 React 前端,使您可以使用 Vue 或 React 构建完整的现代前端,同时利用 Laravel 路由和控制器进行路由、数据注入和身份验证 - 所有这些都在单个代码存储库中完成。使用这种方法,您可以同时享受 Laravel 和 Vue / React 的全部功能,而不会破坏任何一种工具的能力。

https://laravel.com/docs/10.x/frontend

而 Inertia.js ,则是可以作为一个胶水的目的,就是服务端还是那个服务端,使用 vue,react,svelte 还是一样使用。但这些都是服务端来完成的。传统的 vue, react,svelte 这些(非 ssr 实现的),都是在前端处理,比如状态,页面 dom等都是在前端实现的。

官网: https://inertiajs.com/who-is-it-for

几年前构建的 demo: http://demo.inertiajs.com/login

中文文档(这个文档太旧了,当前最新版本是 1.0 版本):https://learnku.com/docs/inertia/0.11

相关

https://learnku.com/laravel/t/41051

阅读全文 >>

3月 11

文本形式的一问一答,公众号这种场景还是不错。今天就尝试用 laravel10 接入一个 chatgpt 的功能。并使用到公众号上。

使用 chatgpt,我们需要使用下边这个包。

https://packagist.org/packages/geekr/openai-laravel

开始

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

# 查看当前 laravel 版本 (Laravel Framework 10.3.3)
php artisan --version

# 添加到版本控制
git init -b main
git add .
git commit -m 'laravel initialize'

# 安装 geekr/openai-laravel
composer require geekr/openai-laravel

如果报 Could not find a version of package geekr/openai-laravel matching your minimum-stability (stable). Require it with an explicit version constraint allowing its desired stability. 这个错误。 可以这么操作。这个包对框架版本限定的死死的,通过这个方式来安装。

rm -rf composer.lock

# 在 composer.json 中增加配置
"require": {
        …
        "geekr/openai-laravel": "dev-master"
    },

composer install

# 添加到版本控制
git add .
git commit -m '安装 geekr/openai-laravel'

如果上边步骤都 ok 了,继续。

# 生成配置文件
php artisan vendor:publish --provider="GeekrOpenAI\Laravel\ServiceProvider"

上边命令,会在 config 目录下,生成一个 openai.php 的配置文件。

然后要配置 OPENAI_API_KEY 。这个 key, 我们在 https://platform.openai.com/account/api-keys 这里申请。

到写这里,已经过去了 2 个多小时。饭也没吃,好难啊。不仅要绿色上网,还要有一些特定国家的手机号码接收短信。接受短信后,询问你用这个来干啥,然后就一直 502,死活过不去。后来用 postman,将 token 以及 body 复制过去请求还是不行。再后来快要放弃的时候,尝试着将 postman body 里边的中文改成字母,竟奇迹般的创建成功了。再然后进入首页,进入 keys 列表。点击创建,马上就可以生成 key 了。


话说为了接受短信,还花了 7 块人民币。

关于接受短信

https://www.hztdst.com/9514.html

https://sms-activate.org/getNumber

上边这种方式是花钱的,花钱的果然好使,好用。后来找啊找,好像也有免费这种服务的。
https://sms24.info/en/messages/OpenAI

https://onlinesim.io/

既然拿到了 key。那就继续。我们在 .env.example 中创建 keyurl 的配置。这样做是因为 .env.example 参与版本控制,.env 是不参与的。

# chatgpt 配置
OPENAI_API_KEY=
OPENAI_BASE_URI=open.aiproxy.xyz/v1

然后,我们在 .env 中配置好上边的配置。填入 keyurl

先用 tinker 进行调试。有问有答就好。

# 打开 tinker
php artisan tinker

# 敲入下边的命令
use GeekrOpenAI\Laravel\Facades\OpenAI;

$content = '中国有多少个王朝,最古老的王朝是哪个王朝';

$messages[] = ['role' => 'user', 'content' => $content];

$response = OpenAI::chat()->create([
    'model' => 'gpt-3.5-turbo',
    'messages' => $messages
]);

坐等结果。看到是有结果返回的。如下图所示。

这仅仅是一个测试,需要多多测试。不过总得持有怀疑的态度。这个接口接的就是 chatgpt,不是其他的接口。给个错误的 key 试试,看是否能有正常的反馈。

只要有问有答,接入公众号就简单的。用户给公众号输入文本信息(如果所有文本信息都用 chatgpt来处理),那就在服务端将接到的信息作为 GeekrOpenAI\Laravel\Facades\OpenAI 的请求参数来直接请求,再将请求结果解析,再处理,拿到结果。然后按照公众号的规则,输出给用户就可以了。

如果你的文本信息还有其他用途。那就得让用户带上标志了。比如让用户在问之前加上前缀 gpt xxxx 这样的。服务端拿到后,再做特殊处理。

话是这么说,可是真正做起来又会出现意外。

gpt 的请求时间太长了。复杂的问题会超出 10 秒,简单的问题也比较久。这个就会引发微信公众号里的异常机制。

腾讯个坑爹货,用户给服务端发送消息,只要 5 秒内,没回复,腾讯会再继续调用,一直调用三次。三次后,还没返回或有错误解构都会显示 “该公众号提供的服务出现故障,请稍后再试”。 网上也有很多解决方法,说直接返回一个空字符串或”success“字符串或使用客服消息。都试过,没有用。空字符串和”success“是没有用,客服消息是有用,只是这玩意不能阻止它连续请求三次的问题。

一直在挣扎。在入口那,用 redis 对请求做一次记录,下次重复请求过滤掉。只是这样做,太不好看了。

还是使用 Redis::setex($key, 20, $key) 来标记。哎。

体验效果如下图。

参考

https://geekr.dev/posts/chatgpt-website-by-laravel-10

阅读全文 >>