WordPress的最佳固定链接

WordPress提供了六种固定链接结构,前五种是固定结构,最后一种是可以自定义的结构。既然提供了不同的选择,自然就有不同的适用场景,这两天我一直在思考这个问题。

第一种类型,朴素型,https://example.com/?p=123,这种类型以前是WordPress的默认类型。这种结构的固定链接,没有任何语义性,人类和搜索引擎都无法理解链接中包含的信息,所以不建议使用。

第二种类型,日期和名称型,链接结构如下https://example.com/2019/12/28/sample-post/,这种类型强调日期。一天发布多篇文章的网站可以使用这种,比如新闻性质的网站或企业博客等,可以通过日期来判断文章的时效性。WordPress目前默认的固定链接就是这种类型。使用这种链接类型的企业博客网站之一微软官方博客(用的是WordPress),因为一天可能发布多篇文章,所以使用了这种类型。

第三种类型, 月份和名称型 ,https://example.com/2019/12/sample-post/,这种类型的固定链接和第二种差不多,强调月份,用于发布不是特别频繁并且需要明确大体日期的站点,例如个人博客、技术网站等。WordPress创始人Matt Mullenweg的博客就是使用的这种类型。

第四种是数字型,即https://example.com/archives/123,这种类型如同第一种,不过把URL参数变成了目录结构的形式。由于链接没有任何语义,不推荐这种。

第五种是文章名型,即https://example.com/sample-post/,链接只有postname一种元素,这种类型不强调时间,不强调时效性,只注重文章的关键信息。而且修改文章的发布时间、目录等属性不影响固定链接的构成,同时由于只有一个层级,对搜索引擎的权重相对高,方便提取关键信息,对于人类也很容易读懂。注重SEO和营销类型的网站可以使用这种。

第六种,自定义类型,通过使用不同的标记来自定义链接的结构。

总体来说,对于个人博客,比较适合的类型是第五种和第三种。个人博客,适合使用年月进行归档,就像按年份和月份建立文件夹一样,把某年某月的文章整理到一起。在做外链或者做记录的时候,看到链接就能知道文章的发布年月和标题,做到心中有数,虽然有时候并不希望这样。 第五种也不错,简单纯粹,除了post-name,再无其它干扰,并且URL更短,层级最小,更利于搜索引擎抓取,修改文章的一些属性不会影响固定链接。

最后一点,固定链接一旦确定下来,就不要换来换去。一但更改,对于站内链接和站外链接的修复都很麻烦,如果注重SEO的话,对于SEO也是灾难。当然这些问题都有应对的办法,不过为了不折腾,选择了就坚持下去,只管写文章,再不用考虑这个问题。

修改wordpress twentytwenty主题的中文显示效果

今天没什么事,把博客主题的文字显示效果做了修改。之前默认的字体和行距是为英文优化的,显示英文很完美,但是显示中文就不怎么好看,字体粗行距小,看起来糊成了一片。

修改样式有三种方式,一种是直接修改主题的样式文件style.css,但这种方式有缺点,在主题更新后,自己所做的修改就被覆盖了,每次更新都要改一次,麻烦了点。好处是在后台编辑器里面也能实现和前台看到的相同的文字效果。

第二种方式是使用“自定义—额外CSS”功能,把自定义样式写进额外CSS里就能实现想要的效果了,而且更新主题无影响。缺点是后台编辑器还是默认字体,无法实现和前台一致的效果。不过这也无所谓,后台只有自己在看,前台阅读体验好就行了。

还有另外一种方式是使用子主题功能,既能做到更新无影响又能实现前后台文字显示效果一致,但我感觉,这个还是有点过于麻烦了,不想折腾,就没有尝试。

CentOS7.3编译安装PHP7.4.1

PHP最近发布了最新版本7.4.1,这几天早就想把博客升级到最新版本了,但一直没时间弄。今晚正好没事,就想升级一下,于是开启了一晚上的折腾之路,一直折腾到凌晨3点多才弄好,下面把过程记录一下。


一、编译前准备

PHP7.4.1的libzip依赖要求0.11版本以上,由于CentOS7.3自带的是libzip-0.10.1,不满足要求, 所以要先升级libzip。本来在编译PHP7.3的时候,已经源码编译安装过libzip-1.2.0,在PHP7.3的时候可以正常编译通过,但是到了PHP7.4就会报错找不到libzip这个包No package 'libzip' found,怎么编译都不行,试过修改环境变量PATH,试过1.5.2最新版,统统都不行。在这个问题上浪费了大量的时间,通过大量的搜索摸索,最后通过使用第三方源才安装成功。第三方源使用的是remi源,在搜索的过程中,知道这个源用的还挺多的,使用方式如下:

这种使用remi源升级libzip的这一部分已不是最佳做法,请查看后面2020年3月20的更新。使用remi源安装只能解决这一个版本的问题,到了PHP7.4.2版本以后就编译不通了。

  1. 添加remi源

    rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm
  2. 使用yum安装libzip5-devel-1.5.2,–enablerepo=remi表示启用remi源

    yum --enablerepo=remi install libzip5-devel-1.5.2-1.el7.remi.x86_64

    经网友留言提示,这里最好使用:

    yum --enablerepo=remi install libzip5-devel

    因为上面那句会由于会更新导致失效。

这样就安装好了libzip的最新版本,这版本应该足够以后升级PHP使用了。


2020年3月20日更新:

可以通过源码安装的形式升级libzip,而不必使用第三方的源,因为到了PHP7.4.2以后,使用remi源安装的libzip,在编译PHP代码的时候,会报错。而使用源码安装的libzip则没有问题。使用源码安装方式如下:

wget https://nih.at/libzip/libzip-1.2.0.tar.gz
tar -xvf libzip-1.2.0.tar.gz
cd libzip-1.2.0
./configure && make && make install

这样安装好了之后,在PHP configure的时候还是找不到我们安装的libzip,解决这个问题的方法有两种:

第一种,在PHP configure命令的参数最后添加一项PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ 即:

// 这里只是演示,省略了中间的参数
./configure ... PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

第二种,在编译完libzip-1.2.0之后,紧接着执行一句:

export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/"

这两种都是告知系统,要到/usr/local/lib/pkgconfig/路径中寻找依赖,因为我们编译好的libzip就在这个路径中。到这里,升级libzip完成。


由于这台服务器之前编译过PHP7.3,一些基础的依赖都已经安装好了,所以这里只针对PHP7.4.1安装两个必要的依赖库,命令如下:
yum install -y libsqlite3x-devel.x86_64 oniguruma-devel

基础编译环境的配置完成。


二、编译

PHP7.4的configure配置参数有些已经更改,在网上查到已知的变动如下:

--with-gd 改为 --enable-gd
--with-freetype-dir 改为 --with-freetype
--with-jpeg-dir 改为 --with-jpeg
--with-webp-dir 改为 --with-webp
--with-xpm-dir 改为 --with-xpm
--with-libxml-dir 改为  --with-libxml 
--enable-zip 改为 --with-zip
--enable-zlib-dir 改为 --with-zlib

最终的configure命令修改如下:

./configure \
--prefix=/usr/local/php/php74 \
--enable-gd \
--with-curl \
--enable-fpm \
--enable-cgi \
--with-openssl \
--enable-mbstring \
--with-pdo-mysql \
--with-zlib \
--with-zip \
--with-mysqli \
--enable-opcache \
--enable-mysqlnd \
--with-libxml \
--with-jpeg \
--with-freetype \
--with-pdo-sqlite \
--with-sqlite3 \
--enable-cli \
--enable-shared \
--enable-exif \
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

如果之前执行过
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/",
那么最后一句可以去掉。

configure完成之后,执行make && make install

编译安装完成。


三、配置

把php.ini拷贝到php7.4目录下,当前目录是在PHP7.4.1的源代码目录下。

cp php.ini-development /usr/local/php/php74/lib/php.ini
#下面是为了使用service命令来管理 
cd sapi/fpm
cp init.d.php-fpm /etc/init.d/php74-fpm
chmod 755 /etc/init.d/php74-fpm

这样配置好之后,就可以正确使用service php74-fpm xxx命令了。php74-fpm开机自启动通过编辑/etc/rc.d/rc.local实现:
vi /etc/rc.d/rc.local

#!/bin/bash
touch /var/lock/subsys/local
/usr/bin/setterm -blank 0 || true
/etc/init.d/php56-fpm start
/etc/init.d/php73-fpm start
/etc/init.d/php74-fpm start
/etc/init.d/nginx start

最后需要执行一下ldconfig。

如果使用systemd来管理,可以参照下面的做法:

cd sapi/fpm
cp php-fpm.service /lib/systemd/system/php74-fpm.service
vi /usr/lib/systemd/system/php74-fpm.service
ProtectSystem=full 改成 ProtectSystem=false 改完后保存退出
#上面修改了系统服务,要使用这个命令重载系统服务
systemctl daemon-reload  
#加入开机启动
systemctl enable php74-fpm.service
#启动服务
systemctl start php74-fpm.service

配置PHP-FPM:

cd /usr/local/php/php74/etc
cp php-fpm.conf.default php-fpm.conf
cd  /usr/local/php/php74/etc/php-fpm.d
cp www.conf.default www.conf

在我的环境中,因为装了多个PHP版本,所以还需要修改下php-fpm的端口,编辑www.conf:
vi /usr/local/php/php74/etc/php-fpm.d/www.conf

listen = 127.0.0.1:9000 
改为 
listen = 127.0.0.1:9074 

php.ini的配置,把时区改为东八区,编辑php.ini:
vi /usr/local/php/php74/lib/php.ini

date.timezone = "Asia/Shanghai"

配置mysql的socket,不然连不上数据库

mysqli.default_socket =
改为
mysqli.default_socket = /var/lib/mysql/mysql.sock
pdo_mysql.default_socket= 
改为
pdo_mysql.default_socket= /var/lib/mysql/mysql.sock

四、扩展安装

wordpress需要用到imagick扩展,这个扩展之前已经编译过。

这里再简单记录一下,进入imagick的源代码目录
cd ~/imagick-3.4.4

因为以前编译过,所以这里要清除编译缓存重新生成:make clean,不然编译完,执行php -m会看到如下警告信息

[root@104 bin]# ./php -m
PHP Warning:  PHP Startup: imagick: Unable to initialize module
Module compiled with module API=20180731
PHP    compiled with module API=20190902
These options need to match in Unknown on line 0

编译安装,以下命令在 ~/imagick-3.4.4下执行

/usr/local/php/php74/bin/phpize
./configure --with-php-config=/usr/local/php/php74/bin/php-config --with-imagick=/usr/local/imagemagick
make && make install

make install后有个路径要记录下,用于配置php.ini中的extension_dir

Installing shared extensions:/usr/local/php/php74/lib/php/extensions/no-debug-non-zts-20190902/

在php.ini中配置启用扩展

extension_dir = "/usr/local/php/php74/lib/php/extensions/no-debug-non-zts-20190902/"
extension=imagick.so

最后,启动php74-fpm:service php74-fpm start

修改本站的nginx的配置文件,把php-fpm的端口改为9074,并重新加载nginx配置文件:service nginx reload

至此,PHP7.4.1编译安装全部完成,网站可以访问了。

灰度屏清屏

<?xml version="1.0" encoding="utf-8"?>
<config.boo>
  <content>
    <channel setSize="0" />
  </content>
</config.boo>

发这个xml过去,把节目都清了

然后133.xml这个文件里面的 <channel action=”add” guid=”xxx”>

现在的channel标签没有带guid属性, 就相当于每次都会往配置文件里面添加一个节目了, 所以会有问题

Windows安装自己开发的.NET Windows服务全攻略

在日常开发中,我们经常会遇到需要将.NET应用程序注册为Windows服务的场景。本文将手把手教你如何通过InstallUtil工具完成服务的安装与卸载,并附赠避坑指南。(搓手期待脸)

一、准备工作

在开始操作前,请确认以下三点:

  1. 已安装对应版本的.NET Framework(示例使用v4.0.30319)
  2. 服务程序myservice.exe已生成且经过测试
  3. 建议将服务文件存放在非系统目录(如D:\MyServices\)

💡小贴士:右键点击解决方案生成时,记得选”Release”模式哦~

二、详细安装步骤

第一步:启动管理员命令行

按住Win + X键,在弹出菜单中选择【Windows Terminal(管理员)】,就像开启魔法权限一样~

第二步:执行安装咒语

%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe C:\Windows\service\myservice.exe

当看到这两句魔法生效提示时,说明安装成功啦:

正在提交安装阶段...

安装已成功完成。

三、验证服务安装

方法1:可视化检查

按下Win + R输入services.msc,在服务列表里找找你的服务名称,就像在人群中找老朋友一样~

方法2:命令行确认

sc query myservice

看到STATE显示为STOPPED就说明服务已经在乖乖待命啦!


四、卸载服务指南

当需要更新服务时,先来段优雅的卸载舞蹈:

%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u C:\Windows\service\myservice.exe

成功时会收到这样的友好通知:

正在开始卸载的安装阶段...
卸载已成功完成。

五、避坑宝典

  1. ​权限不足:看到”拒绝访问”提示?请检查是否以管理员身份运行CMD
  2. ​路径陷阱:若出现”找不到文件”,请检查路径中的空格是否用双引号包裹
  3. ​依赖缺失:安装失败时记得检查是否缺少.dll文件
  4. ​版本迷思:使用.NET Core开发的服务请改用sc create命令

六、知识扩展

对于使用新版本.NET的同学,可以试试这个现代咒语:

sc create "myservice" binPath="D:\Services\myservice.exe"

希望这篇指南能像贴心助手一样,帮你顺利完成服务部署。如果在实践中遇到任何魔法失灵的情况,欢迎在评论区召唤技术支持哦!(ง •̀_•́)ง

IIS配置MP4格式MIME类型终极指南

一、血泪故事会:为什么你的视频播不了?

昨天隔壁工位老王的旅游网站突然被客户投诉,所有风光展示视频都变成「白屏黑洞」。最后发现是IIS把.mp4文件当成二进制流推给浏览器,导致视频无法解析。今天我们就用5分钟根治这个顽疾!(╯‵□′)╯︵┻━┻


二、MIME类型急救知识包

1. 什么是MIME类型?

就像文件身份证,告诉浏览器「我是谁,该怎么打开」。当IIS遇到不认识的文件类型时,会默认使用application/octet-stream(二进制流),这就是视频无法播放的元凶!

2. MP4的正确打开方式

  • ​正确姿势:video/mp4(推荐!浏览器自动调用播放器)
  • ​备胎方案:application/mp4(部分老系统兼容)
  • ​错误示范:application/octet-stream(默认导致播放失败的罪魁祸首)

📌 行业冷知识:根据RFC 4337标准,MP4官方MIME类型是video/mp4


三、图形界面配置四步曲(附灵魂图解)

步骤1:召唤IIS管理器

Win + R 输入inetmgr,就像打开阿拉丁神灯一样~

步骤2:定位MIME设置

步骤3:添加新条目

点击右侧【添加】按钮,填写魔法参数:

文件扩展名: .mp4
MIME类型: video/mp4

步骤4:重启大法好

操作完成后一定要右键选择【重新启动】站点,就像给服务器做心肺复苏!


四、命令行高手模式(批量部署必备)

# 添加MP4类型
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/staticContent" -name "." -value @{fileExtension='.mp4';mimeType='video/mp4'}

# 立即生效咒语
iisreset /noforce

五、疑难杂症急诊室

症状1:配置后仍然无法播放

  • 检查清单:
    • 清除浏览器缓存(Ctrl + Shift + Del)
    • 检查文件权限(右键文件→属性→安全)
    • 查看HTTP响应头(F12开发者工具)

症状2:服务器报404错误

<!-- 在web.config中加入 -->
<system.webServer>
  <staticContent>
    <remove fileExtension=".mp4" />
    <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
  </staticContent>
</system.webServer>

六、安全加固小课堂

危险操作预警!

⚠️ 不要图省事添加<mimeMap fileExtension=".*" ... />,这相当于给黑客开后门!

推荐白名单策略

<staticContent>
  <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
  <mimeMap fileExtension=".webm" mimeType="video/webm" />
  <!-- 显式声明允许的视频格式 -->
</staticContent>

七、跨版本兼容指南

IIS版本特殊说明
IIS 7.x需要安装静态内容模块
IIS 8+原生支持H.264编码
IIS 10支持HTTP/2视频流

🎯 实战演练:访问你的视频地址,用https://tools.keycdn.com/curl检查MIME类型是否显示为video/mp4,看到绿色的正确标识就可以开香槟啦!🍾

如果还有任何悬案未破,欢迎在评论区召唤技术支援小队! (•̀ᴗ•́)و ̑̑

jquery easyui datagrid 全选、反选、清除

//全选
function allselectRow(tableName) {
    $('#' + tableName).datagrid('selectAll');
}
//反选
function unselectRow(tableName) {
    var s_rows = $.map($('#' + tableName).datagrid('getSelections'),
            function(n) {
                return $('#' + tableName).datagrid('getRowIndex', n);
            });
    $('#' + tableName).datagrid('selectAll');
    $.each(s_rows, function(i, n) {
        $('#' + tableName).datagrid('unselectRow', n);
    });
}
//全清
function clearSelections(tableName) {
    $('#' + tableName).datagrid('clearSelections');
}
var grid = $('#tt1');
        var options = grid.datagrid('getPager').data("pagination").options;
        //当前页数
        var currentPage = options.pageNumber;
        //总条数
        var total = options.total;
        //当前页记录数
        var rows = options.pageSize;
        //总页数
        var max = Math.ceil(total / options.pageSize);


//全选选择
function checkAll() {
    $("input[name='menuid']").each(function() {
        $(this).attr("checked", true);
    });
};
//反向选择
function reversal() {
    $("input[name='menuid']").each(function() {
        $(this).attr("checked", !this.checked);
    });
}
//取消选择
function clearCheck() {
    $("input[name='menuid']").each(function() {
        $(this).attr("checked", false);
    });

PHP日志类

新建Log.class.php,复制以下代码放入其中:

<?php
interface ILogHandler {
    public function write($msg);
}

// PHP日志类
class CLogFileHandler implements ILogHandler {
    private $handle = null;

    public function __construct($file = '') {
        $this->handle = fopen($file, 'a');
    }

    public function write($msg) {
        fwrite($this->handle, $msg, 4096);
    }

    public function __destruct() {
        fclose($this->handle);
    }
}
class Log {
    private $handler = null;
    private $level = 15;

    private static $instance = null;

    private function __construct() {
    }
    private function __clone() {
    }

    public static function Init($handler = null, $level = 15) {
        if (!self::$instance instanceof self) {
            self::$instance = new self();
            self::$instance->__setHandle($handler);
            self::$instance->__setLevel($level);
        }
        return self::$instance;
    }


    private function __setHandle($handler) {
        $this->handler = $handler;
    }

    private function __setLevel($level) {
        $this->level = $level;
    }

    public static function DEBUG($msg) {
        self::$instance->write(1, $msg);
    }

    public static function WARN($msg) {
        self::$instance->write(4, $msg);
    }

    public static function ERROR($msg) {
        $debugInfo = debug_backtrace();
        $stack = "[";
        foreach ($debugInfo as $key => $val) {
            if (array_key_exists("file", $val)) {
                $stack .= ",file:" . $val["file"];
            }
            if (array_key_exists("line", $val)) {
                $stack .= ",line:" . $val["line"];
            }
            if (array_key_exists("function", $val)) {
                $stack .= ",function:" . $val["function"];
            }
        }
        $stack .= "]";
        self::$instance->write(8, $stack . $msg);
    }

    public static function INFO($msg) {
        self::$instance->write(2, $msg);
    }

    private function getLevelStr($level) {
        switch ($level) {
            case 1:
                return 'debug';
                break;
            case 2:
                return 'info';
                break;
            case 4:
                return 'warn';
                break;
            case 8:
                return 'error';
                break;
            default:
        }
    }

    protected function write($level, $msg) {
        if (($level & $this->level) == $level) {
            $msg = '[' . date('Y-m-d H:i:s') . '][' . $this->getLevelStr($level) . '] ' . $msg . "\n";
            $this->handler->write($msg);
        }
    }
}

调用方式:

<?php
require 'Log.class.php'; // 导入日志类文件
define('DS', DIRECTORY_SEPARATOR); // 设置目录分隔符
define('LOG_PATH', dirname(__FILE__) . DS . 'log' . DS); // 日志文件目录

$logHandler = new CLogFileHandler(LOG_PATH . date('Y-m-d') . '.log');
$log = Log::Init($logHandler, 15);

Log::DEBUG('111111');

centos 编译安装apache httpd

wget http://mirror.bit.edu.cn/apache/httpd/httpd-2.4.39.tar.gz
wget http://mirror.bit.edu.cn/apache/apr/apr-1.7.0.tar.gz
wget http://mirror.bit.edu.cn/apache/apr/apr-util-1.6.1.tar.gz

解压缩:

tar -xvf httpd-2.4.39.tar.gz
tar -xvf apr-1.7.0.tar.gz
tar -xvf apr-util-1.6.1.tar.gz

一点文件操作:

mv apr-1.7.0 httpd-2.4.39/srclib/apr
mv apr-util-1.6.1 httpd-2.4.39/srclib/apr-util
cd httpd-2.4.39

编译前安装 :

yum -y install gcc make zlib-devel pcre-devel expat-devel

mkdir /web

mkdir /web/httpd

mkdir  /web/php

编译命令:

./configure --prefix=/web/httpd --with-included-apr --enable-nonportable-atomics=yes --with-z

编译完成后:

make

make install

service httpd start