PHP生成WordPress的Nginx跳转规则

建站初期总有一些事情考虑不周,前几天调整了固定链接,从/category/id.html调整为/archive/id,然后总觉得哪里不踏实。趁着周末去考试的时间想了一下,如果固定链接依赖于文章ID或分类,那么一旦ID或分类发生变化,文章的固定链接就会失效。再者,从长远来说,将来如果要改版或重构网站,基于ID或分类的链接将变得不稳定。

由此,可以得出结论,固定链接最好不要依赖文章ID和分类,而是要依赖于文章的内容。这样的固定链接显得更稳定,而且具有更好的可读性,有利于SEO优化,分享链接时,链接本身也变得更有意义。

所以,决定把本站的固定链接改成基于postname的形式。修改固定链接后,要把之前的文章链接做一个跳转,但是由于文章有点多,手动修改很费时间,于是动手写了一段PHP代码,用于生成Nginx的跳转规则,代码如下:

<?php
// 数据库连接设置
$servername = "localhost"; // 数据库主机
$username = "your_username"; // 数据库用户名
$password = "your_password"; // 数据库密码
$dbname = "your_database"; // 数据库名

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}

// 查询已发布的文章
$sql = "SELECT ID, post_title, post_name FROM wp_posts WHERE post_status='publish' AND post_type='post'";
$result = $conn->query($sql);

// 检查查询结果
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
        $id = $row['ID'];
        $post_name = $row['post_name'];
        // 生成 Nginx 重定向规则
        echo "rewrite ^/archives/$id$ /$post_name permanent;" . "<br>";
    }
} else {
    echo "没有找到已发布的文章。";
}

// 关闭连接
$conn->close();
?>

运行这段代码,就会在浏览器页面输出重定向规则,我们把它复制到nginx配置里就可以了。

location /archives/ {
    rewrite ^/archives/3681$ /letting-go-of-tech-obsession permanent;
    # 为了便于展示,这里只粘贴了一条规则...
}

后记:这种基于postname的permalink就是写文章的时候麻烦一点,写完后,还要再把标题翻译成英文,看个人取舍了。后面如果我忍受不了这多余的一步,也可能换成基于post_id的形式。使用postname还有一个好处理就是,如果要换成其它形式,WP可以自动实现跳转,而不用再另写跳转规则。

PHP获取当前用户的客户端IP

可以用以下函数来获取访客的客户端IP地址:

<?php
function get_client_ip() {
    $ip = $_SERVER['REMOTE_ADDR'];
    if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
        foreach ($matches[0] as $xip) {
            if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                $ip = $xip;
                break;
            }
        }
    }
    return $ip;
}

再来一个版本的代码,这个版本增加了对使用代理情况下的判断,根据需要选一个用就可以了:

<?php
/**
 * 获取客户端IP
 */
function getClientIp() {
    $ip = 'unknown';
    $unknown = 'unknown';

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)) {
        // 使用透明代理、欺骗性代理的情况
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];

    } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)) {
        // 没有代理、使用普通匿名代理和高匿代理的情况
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    // 处理多层代理的情况
    if (strpos($ip, ',') !== false) {
        // 输出第一个IP
        $ip = reset(explode(',', $ip));
    }

    return str_replace('.', '_', $ip);
}  

PHP处理用户名,中间用星号表示

有时需要将用户名进行隐私处理,可以用以下代码将用户名中间字母用星号遮盖:

<?php
//将用户名进行处理,中间用星号表示
function substr_cut($user_name){
    //获取字符串长度
    $strlen = mb_strlen($user_name, 'utf-8');
    //如果字符创长度小于2,不做任何处理
    if($strlen<2){
        return $user_name;
    }else{
        //mb_substr — 获取字符串的部分
        $firstStr = mb_substr($user_name, 0, 1, 'utf-8');
        $lastStr = mb_substr($user_name, -1, 1, 'utf-8')
        //str_repeat — 重复一个字符串
        return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($user_name, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr;
    }

}

PHP利用CURL实现 http post 和 get

PHP利用CURL实现HTTP GET和HTTP POST,用于HTTP请求,具体代码如下:

<?php
//初始化
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
//设置头文件的信息作为数据流输出,如果不想打印出http头,可以把这行去掉
curl_setopt($curl, CURLOPT_HEADER, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//执行命令
$data = curl_exec($curl);
//关闭URL请求
curl_close($curl);
//显示获得的数据
print_r($data);

HTTP POST:

<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$notify_url);
curl_setopt($ch, CURLOPT_POST, 1);


//curl_setopt($ch, CURLOPT_POSTFIELDS, "postvar1=value1&postvar2=value2&postvar3=value3");

$notifyData = [];

// In real life you should use something like:
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($notifyData));

// Receive server response ...
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

curl_exec($ch);

curl_close($ch);

// echo $server_output;

Debian12 安装 PHP8.3

当前 Debian12 官方源中带的 PHP 版本是8.2,而 PHP8.2 的 Active Support 到今年年底(31 Dec 2024),所以直接装8.3吧,可以用的时间长一点。

首先安装sury源

#!/bin/sh
# To add this repository please do:
if [ "$(whoami)" != "root" ]; then
    SUDO=sudo
fi
${SUDO} apt-get update
${SUDO} apt-get -y install lsb-release ca-certificates curl
${SUDO} curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
${SUDO} dpkg -i /tmp/debsuryorg-archive-keyring.deb
${SUDO} sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
${SUDO} apt-get update

注意,如果安装sury源时报错:

The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY B188E2B695BD4743

意思是系统缺少sury源的公钥。只要把公钥下载到系统就可以了,执行以下命令添加公钥:
wget -qO /etc/apt/trusted.gpg.d/sury-php.gpg https://packages.sury.org/php/apt.gpg
公钥添加完成后,执行apt update刷新包列表即可。

然后执行以下命令安装PHP8.3:

apt install -y php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-curl php8.3-xml php8.3-imagick php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath

如果需要支持 Laravel 框架,那么最后一个 bcmath 扩展是必须的。


同理,如果要安装php8.4,那么安装命令就是:

apt install -y php8.4-fpm php8.4-mysql php8.4-mbstring php8.4-curl php8.4-xml php8.4-imagick php8.4-zip php8.4-gd php8.4-intl php8.4-bcmath

Debian11 升级 Debian12

今天通过博客园首页链接购买了37块钱的天翼云,发现 Debian 最新版本只到11,那么就来升级一下吧。

1、更新当前系统apt updateapt full-upgrade,更新完后发现有一个包没有被升级0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.,执行apt list --upgradable -a看了一下,输出如下:

root@vm:~# apt list --upgradable -a
Listing... Done
base-files/oldstable 11.1+deb11u11 amd64 [upgradable from: 11.1+deb11u1]
base-files/now 11.1+deb11u1 amd64 [installed,upgradable to: 11.1+deb11u11]

应该是一个涉及核心系统的包,手动升级一下吧: apt-get install base-files。

2、更新完成后,更换 Debian12 的源,首先备份当前源 mv /etc/apt/sources.list /etc/apt/sources.list.old,然后写入 Debian12 的源,这里用的是清华的源:

cat > /etc/apt/sources.list << EOF
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware
EOF

3、继续更新系统apt updateapt full-upgrade,期间会有一些提示信息,根据需要选择。

更新完后,查看系统版本cat /etc/debian_version, 我这里显示的是12.7,嗯,最新版本 Debian 已经更新好了。

Debian 大版本升级还是一如既往的丝滑,从来没有让我失望过👍💖。

注:本文始发于我的博客园 https://www.cnblogs.com/art ,之后重新发于本站。

Debian 更换国内清华源

1、备份原文件 mv /etc/apt/sources.list /etc/apt/sources.list.old

2、写入新源,以下是 Debian 11 的:

cat > /etc/apt/sources.list << EOF
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
 
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
 
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
 
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security/ bullseye-security main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security/ bullseye-security main contrib non-free
EOF

如果是 Debian 12:

cat > /etc/apt/sources.list << EOF
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware

deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware
EOF

注:

deb 指向的是编译好的二进制软件包。
deb-src 指向的是软件的源代码包,可以使用apt source命令下载软件的源代码并自行编译。

注:本文始发于我的博客园 https://www.cnblogs.com/art ,之后重新发于本站。

PHP 常用代码片断

记录了一些PHP常用的代码片段,方便查阅使用。

<?php
// 判断请求类型
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
}

//php 判断是否为 ajax 请求
if (isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest") {
    // ajax 请求的处理方式 
} else {
    // 正常请求的处理方式 
}

// PHP设置页面编码:
header("Content-type:text/html; charset=utf-8");

header("Content-type:application/json;charset=utf-8");

// PHP获取当前时间:
date("Y-m-d H:i:s");

// PHP获取页面执行时间:
// 在脚本最后添加
echo microtime(TRUE) - $_SERVER['REQUEST_TIME_FLOAT'];

// PHP header跳转:
header("Location: http://www.baidu.com/");

// PHP清空所有session:
session_destroy();

// 获取昨天日期
date("Y-m-d", strtotime("-1 day"));

// 当前时间:
date('Y年m月d日 H点i分s秒', time());