在农历生日的时候,我为自己写下了「写在 26 岁」,而今天,是我的阳历 26 岁。
在上一篇文章当中,写的很丧气,我自己都很焦虑。在这一篇文章,希望能给自己打打气。
26岁在人生漫长的八十多年里,并不能算得上特殊。不过,自己选择的路线确实会让这一年显得特殊一些。新的一年,祝你能够心想事成。在做的事情能够有一个好的结果。
如果可以的话,今年做一个大胆的选择,去试一试过去可能没试过的东西,体验一个不一样的生活。
别浪费了自己的 26 岁。

在农历生日的时候,我为自己写下了「写在 26 岁」,而今天,是我的阳历 26 岁。
在上一篇文章当中,写的很丧气,我自己都很焦虑。在这一篇文章,希望能给自己打打气。
26岁在人生漫长的八十多年里,并不能算得上特殊。不过,自己选择的路线确实会让这一年显得特殊一些。新的一年,祝你能够心想事成。在做的事情能够有一个好的结果。
如果可以的话,今年做一个大胆的选择,去试一试过去可能没试过的东西,体验一个不一样的生活。
别浪费了自己的 26 岁。

最近观察到一个现象,我认为一个非常「理性」,拥有着「理工科思维」的前辈,他的配偶却显得「贪小利」、「情绪不稳定」,这似乎是很奇怪的事情。难道「理工科思维」、「沉稳」的前辈不应该是找一个很稳重的配偶么?
但随时时间的流逝,我又有了新的看法。
作为一个普通人,当我们掌握了「理工科思维」和使用理性指导生活的方式和方法后,我们的生活可以非常容易走上正轨。我们在做各种选择会比依靠「情绪」来指导我们的生活的人会更加稳健、更加轻松、更加富有确定性。
但理工科思维未免过于范式固定,在这种情况下,我们的生活可能是一成不变的,朝着一个确定的目标上走着,在一个明确的轨道上行驶。
一个不那么稳定的配偶,可以为他的生活中添加一些变量和变化,让生活变得不那么枯燥。从这个角度来说,也挺好的。
这篇文章也是在试图用理性的逻辑来分析一个现实生活中的问题。但可能我说的全都是错的。

在使用 Laravel Livewire 的时候一个常见问题是生成的 Livewire.js 文件会报错。
一般来说,解决思路有两种
在 Livewire 的配置当中,存在一个 asset_url 选项,这个选项会用于在页面中嵌入 Livewire.js 文件的功能,因此。如果你在使用过程中,修改了这个值,导致生成的地址是错误的,就有可能报错。
这个问题往往会导致报错的页面是 Nginx 的 404 页面。
在你的 Nginx 配置当中,如果你针对 JS 文件或 CSS 文件有单独处理,你需要将对应的处理注释掉,确保所有请求转发给 Laravel 进行处理。
# location ~ .*\.(js|css)?$ {
# expires 7d;
# access_log off;
# }
Code language: PHP (php)
最近在读《如何成为顶级记者》,总体来说,不同的记者有不同的切入视角,但如果要找一个能够综述所有人的关键点就是 —— 「离事情发生的地点足够近」。无论是通过自己的数据分析找到真正的事情发生点,还是和当事人建立更加友好、更加深入的联系,都是为了达成「离事情发生的地点足够近」这个诉求。
而当我总结到这里时,我突然在思考一个问题:我的问题真的是如何成为一个顶级记者么?
显然不是,我必然是会在编程和工程师的路上越走越远的,我的目的其实是:「如何录制好一档访谈类型的播客」,而这个问题如果细化的话,其实真正的问题应该是「如何提出一个正确的问题」。
当我明确了正确的问题之后,那就知道正确的 Action 应该是什么 —— 「学习提出正确的问题」。
回到这个事情本身,我其实在初期也进行了思考:从做一个好的访谈播客出发,推导出我需要具备优秀的访谈能力,而优秀的访谈能力往往出现在优秀的主持人和优秀的记者身上,因此我推导出了需要去学习顶级记者的思路。但是,问题的思考还不够深入,如果进一步推导和抽象,才能得到正确的答案 — 「提出一个正确的问题」。

在 Laravel 9 当中,引入了新的 Mailer 组件,随之而来的是一些过去没有的 Bug。
如果你在开发过程中出现了 An email must have a "From" or a "Sender" header 的报错,需要在 PHPUnit 当中配置 MAIL_FROM_ADDRESS 属性,用于通过测试。
<env name="MAIL_FROM_ADDRESS" value="from@example.com" />
Code language: HTML, XML (xml)
自 WordPress 5.0 开始, Gutenberg 编辑器(后文称为古腾堡编辑器)开始存在于 WordPress 当中,为普通用户所用。而得益于古腾堡编辑器带来的卓越的使用体验(用户不需要再记录晦涩难懂的短代码、无须忍受 TinyMCE 的界面),用户使用 WordPress 的方式也开始变得多种多样。
如果你还没有用过古腾堡编辑器,那你可以访问 WordPress 官方提供的在线预览工具来试用:https://wordpress.org/gutenberg/
古腾堡的出现,让作者可以更加接近于我一直描述的 WordPress 所能够提供的最大的价值 —— 让写作变得更加简单,易实现。不仅如此,古腾堡带来的新的编辑体验,让除了工程师、Geek 以外的人也可以很轻松的实现一个更好看、更易读、更加丰富的界面。
而从 WordPress 开发团队的态度来看,也是更加推荐作者们更多的使用古腾堡编辑器:从Twenty Nineteen 开始,古腾堡的支持就成为了默认,并不断的通过官方主题的用法,让作者们看到 WordPress 原来还可以是这样。今年的 Twenty Twenty Two 更是从写作者变为了艺术家 —— 你可以十分简单的建造一个线上的画廊。
过去,WordPress 开发整体来说,可以分为两条线:一条是主题开发,你需要与 PHP、HTML、CSS、Javascript 共同战斗;另一条线则是插件开发,你需要与PHP 为伍。
搞插件开发的,你对于前端开发不甚了解也无所谓。WordPress 提供了大量的 helper function 。比如,我在「开发一个短代码插件」中,不使用一行前端代码就实现了 TinyMCE 的功能新增。
而在新的古腾堡编辑器生态下,开发者如果希望对于古腾堡进行拓展,一方面依然可以使用之前的方式,接入各种短代码来实现各种不同的用户体验,另一方面,则可以借助与前端技术栈来实现一个更加丰富的用户体验。
你可以使用 JQuery 和 WordPress 为你绑定的全局对象来修改古腾堡编辑器实现你的目标,更是可以借助前端的开发体系,诸如 Webpack、React 来开发一个强交互,体验佳的用户体验。
WordPress 的开发不再是 PHP 工程师自己的事情,它将更多的人卷入 WordPress 的开发过程中。而对于 WordPress 开发工程师来说,则有了更高的要求,来完成插件的开发、主题的开发。
自古腾堡的推出,这样的趋势就开始渐显。但直到我真正开始开发一款古腾堡插件,我才真正意识到 —— WordPress 在内容创作领域的价值,无可替代。纵然他有众多的历史包袱,但对于每一个创作者来说,他都是最好的选择。

WordPress 支持设定多级分类,如果你需要在页面中展示最顶级的分类,则需要获取到最顶级的分类,具体实现的方式如下:
使用如下代码获取到自定义分类
$tax = wp_get_post_terms($post->ID,array('part'))
Code language: PHP (php)获得的结果如下
Array
(
[0] => WP_Term Object
(
[term_id] => 7
[name] => 目录1
[slug] => category1
[term_group] => 0
[term_taxonomy_id] => 7
[taxonomy] => part
[description] =>
[parent] => 6
[count] => 2
[filter] => raw
)
)
Code language: PHP (php)这里的 term_id 则代表你设定的自定义分类的 ID
因为分类是多级的,我们需要找到祖先节点,因此需要用到函数 get_ancestors ,执行如下代码
$tree = get_ancestors($tax[0]->term_id)
Code language: PHP (php)会获得如下结果
Array
(
[0] => 6
[1] => 8
)
Code language: PHP (php)这个返回结果则是从你当前分类向上查找,查找到最顶级的分类的结果。需要注意的是,这个数组的最后一个元素才是你最终最顶级的分类。
当你知道了最后一个才是最顶级的分类,只需要使用 end() 函数来获取最后一个。
end($tree)
Code language: PHP (php)这样,就能拿到最终目录的 ID,接下来要做的就是在你的界面上展示这些数据。

自打上次为我的博客加入了 Redis 缓存后,博客站点访问速度明显变快,几乎可以达到秒开的效果。剩下的需要在网络层面进行进一步的优化。
不过,我还在思考如何才能更好的优化我的 WordPress 性能。很显然,我需要一个指标来帮助我做决策。这让我想到了一个东西 —— HTTP 标准中的 Server-Timing Header。
来自 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Server-Timing
Server-Timing标头传达在一个给定请求-响应周期中的一个或多个参数和描述。它用于在用户浏览器的开发工具或PerformanceServerTiming(en-US) 接口中显示任何后端服务器定时参数(例如,数据库读/写、CPU 时间、文件系统访问等)。
Server Timing 可以帮助我们记录服务端到底在哪些步骤中消耗了哪些时间,可以方便我进行性能的查询。
我在 WordPress 的 Plugin Directory 目录进行了搜索,并没有找到支持这个功能的插件,不过我在 Github 上找到了这个插件 —— https://github.com/ocReaper/wp-server-timing。
有了这个插件,我就可以无需自己手动添加相应的能力。
使用插件也非常简单,在页面上下载压缩包,并在 WordPress 后台安装并启用这个插件。

安装完成后,你接下来要做的就是重新在浏览器中打开你的网站,并按下 F12 打开开发者工具,选择文档 Tab(英文是 Document),刷新当前页面,就可以看到列表中出现了一个你博客地址对应的文档,点击文档,并在弹出的窗口中切换到「时间」Tab,就可以在下方看到服务器计时了。

按照上图的结果,可以看到,我的 WordPress 耗时最长的是 Template Processing ,我需要针对这个属性进行定向优化。
以下是 WordPress 的加载顺序图,你可以对比着参考


在写测试的时候,如果你需要对大量的数据进行 compare 处理的时候,你大概率不会把所有需要对比的对象都列出来,而是选择直接循环处理。
在测试中如果有循环处理的时候,很有可能会出现的一个问题是你可能无法在测试无法通过时快速定位道具体是循环中的哪一个元素出现的问题。这个时候的定位就会比较麻烦。
一个比较好的办法是,可以在 Jest 中加入 try/catch 中来处理错误,这样可以在出现错误的时候,打印一些辅助信息来快速定位,比如
it('test-error-catch-example',() => {
let needTestData = [1,2,3,4]
needTestData.foreach( item => {
let result = doSomething(item)
// 这里开始是新增的
try{
expect(result).toBe(true)
}catch(e){
console.log("error key",item)
throw e;
}
// 新增的错误处理结束
})
})
Code language: JavaScript (javascript)通过添加一个自定义的 try catch ,可以在出现问题的时候,一方面将 Error 按照常规的方式抛出,等待 Jest 处理,另一方面,可以在 catch 时输出自定义的信息,方便我们进行排查和修复。

从去年开始,我就开始定投 Crypto 领域的主流货币,比如 BTC、ETH 等,每月少量入金,用一笔不会影响我正常生活的钱来完成 Crypto 领域的投入。
而最近大火的 NFT,我除了参与一些 NFT 的开发意外,并没有参与市场化的交易。
对我来说,原因其实非常简单:
虽然 NFT 确实可以一夜暴富( 0.1 Eth 入,5 个 Eth 出)也是很正常的,但对于身在其中的玩家来说,消耗的精力也是 BTC、ETH 等主流币的定投者无法比拟的。
至少,买 BTC 和 ETH 我可以每天安稳的睡觉,不用担心需要实时盯盘,在一个好的时候卖出。