普里戈任不知道真挂还是假挂,但老夫想起了一个人,和他很像,那就是曾经手握北府军的猛人刘牢之。他们的最大问题是没有基本盘,北府军的补剂牢牢的被东晋掌权者控制。这支部队说到底是谢玄的遗产,刘牢之和手下大将更多上下属关系,不是完全利益一致的行动人。当手握北府军的刘牢之碰到选择题时,也会思考到底跳哪边,听朝廷怕功高盖主,不听怕换代后被鸟尽弓藏。但即使这样,刘牢之还是跳对两次,卖了王恭和司马元显,可惜没有第三次。但有一个好消息,汲取了刘牢之的经验,他的继任者成功了,宋武帝刘裕!
分类: 大杂烩
-
出梅了
沿海城市天气状况里,最讨厌的莫过于黄梅天,所有环境都是湿漉漉的,人容易乏力,而东西容易发霉变质。今天广播报道,上海出梅了!直接来个户外40度,其实温度并没有上周高,但是太阳直射体感温度起来了,这也标志着,真正的夏天到来了!
-
上海夏天稳了睡凉席了
根据我自己的笔记,上个月4月22日的时候白天来到过30度,也就是可以穿短袖的温度。今年整个上海4月5月温度都不是很理想。终于,在5月的最后一周,天开始热了!晚上短袖吹着凉风,非常舒服,这也是上海夏天的开始,一直到十月中旬结束。好好享受夏天带来野蛮生长的感觉,今天立即把凉席也拿出来铺了起来,晚上睡觉26度感觉挺不错,真的喜欢天暖和的感觉!
-
Symfony6生产环境Twig导致构建失败小记录
最近把Symfony4升级到6,php版本也跟着升到8.2.5,体验了把新版本好处,但发现几个问题。
默认的构建命令,
symfony new my_project_directory --version="6.2.*"
,这是一个典型的API项目,也是我创建的类型。在API环境下,生产环境显然是不用任何模板功能的,但因为开发环境需要模板做展示,所以上线时候产生了一个BUG。当你加入
composer.phar require --dev profiler
为dev环境添加调试条的时候,你会发现一个问题,所有基于Profiler的依赖,例如Twig确实在composer.json的dev里。但是,在config/Bundles.php
里却把因为Profiler依赖而加入的Twig模板引擎标记为全环境都需要Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true]
,这里要改成Symfony\Bundle\TwigBundle\TwigBundle::class => ['dev' => true, 'test' => true]
。但这时候还没有完,
config/packages/twig.yaml
也需要删除,否则Symfony启动的时候检查到配置文件会自动调用,而导致报错。顺便把templates
目录删除,这个是Twig默认加入的模板文件。最后,记得一点,
composer install --no-dev --no-ansi --no-interaction --no-progress --classmap-authoritative --no-scripts --prefer-dist
在你的composer安装命令中,千万不要--no-plugins
,这会导致/vendor/autoload_runtime.php
无法生成! -
做了一个PHP8的Docker镜像
花了大概30分钟时间,做了一个PHP8的自用镜像,为什么那么快呢?因为是基于以前的PHP7修改而来的呀,这下就有JIT的支持了!
docker hub官方地址:https://hub.docker.com/r/nickzhuo/phpallinone
源代码地址:https://github.com/nickzhuo/phpallinone -
Windows下Docker Build发生的入口报错问题
用docker很久很久,但build都是放在服务器执行,一方面是拉代码有缓存,另外一方面服务器是linux的,会快点点。在本地run的时候目前用的是WSL内核的Windows版本docker,但是我发现一个奇怪的问题。在linux上build一切正常,但是windows上build出来的镜像不能用,即使是在WSL环境下build的,也是启动入口报错。
/usr/local/bin/docker-php-entrypoint: exec: line 9: /start.sh: not found
乍一推测还以为是win下面斜杠的问题,但其实不是,这个问题需要把镜像中启动文件
start.sh
,从文件CRLF改成LF格式,这样在win下build就顺利成功了。说来也挺奇怪的,WSL应该是纯linux了,但是也是有这一问题。 -
上海这天气开始舒服了
四月头里几天还是冷的不行,出门要穿的严严实实,尤其晚上风大有点冷。现在这天气绝了,晚上室内温度20以上,白天的太阳更是暖洋洋,开到种的柠檬树长新叶子了,非常开心。
-
PS4重新安装DLC的方法
给PS4重新安装了GT SPORT,但是进入游戏的时候发现首发版赠送的赛车不能用,游戏内提示请再次下载追加内容,原本以为很简单的事情,结果发现不简单,PSN的设计有点反人类。
需要进入PS首页选择內容保存庫然后可能很多搜索结果说在这里可以找到DLC的聚合页面,但其实没有,要进一步选择游戏,例如我选的是GT SPORT,进入游戏详情页面之后,往下选择Platstation Store然后在右侧就能重新安装DLC。
-
利用Attribute特性和ValueResolverInterface为Symfony注入IP
PHP8发布之后越发爱不释手,尤其Attribute比Annotation强大不少,Attribute可以对单个参数进行控制,这个功能很强大。演示一下控制器中通过Attribute描述字段来获得当前IP,其实一般解析器都是用来denormalize客户端POST过来的参数,但是为了用到Attribute,我用IP来举例。
<?php namespace App\Resolver; use Attribute; #[Attribute(Attribute::TARGET_PARAMETER)] final class IP { }
先设计一个Attribute申明,注意TARGET_PARAMETER标识作用在参数范围。
<?php namespace App\Resolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; class IPValueResolver implements ValueResolverInterface { public function resolve(Request $request, ArgumentMetadata $argument): iterable { $argumentType = $argument->getType(); // 检查IP的Attribute $attributes = $argument->getAttributes(IP::class); if (count($attributes) == 0 || $argumentType !== 'string') { return []; } yield $request->getClientIp(); } }
其次,编写一个解析器,注意,Symfony 6.2开始提供ValueResolverInterface,之前版本用ArgumentValueResolverInterface。
public function resolver(#[IP] string $ip): Response
最后,便是在任何控制器的方法中,只要使用了
#[IP] string $ip
就能方便的取得IP了。正确使用解析器,可以大大降低控制器中和Request对象耦合的重复代码,将预处理的流程都放在解析中! -
从PHP 7.4升级到PHP 8.2是惊人的变化
一直工作在PHP7的版本下,最近把环境都挪到了PHP8下面,具体用的是最新的8.2.3版本。不得不说,这个变化是天翻地覆的,有很多专门的文章写了PHP8的特点,我也稍微记录下自己角度的观察。
- 支持更多强类型,这个在php7里其实也可以有,叫做标量,打开严格模式即可,但问题是提供的类型不多。PHP8就基本支持了完整的类型,包括方法的返回值,这样的写法对内存的使用处置肯定有极大好处的。
public function weibo(WeiboService $weiboService):Response
- 支持使用问号?的null的返回,虽然php是脚本语言,但这个东东其实在现在语言里很有用,可见未来会有更完整的nullable支持,但历史代码库肯定要做大规模升级,同时也需要java里optional类的支持。
public function share(string $text, string $ip, ?string $pic = null): void
- 有了枚举,让代码阅读起来更清晰更清晰,同时作为形参可以限制范围,而不是要判断int取值的范围。
enum PlatformConfig: int { case TENCENT = 1; case BAIDU = 2; case ALIPAY = 3; case APP_ANDROID = 4; case APP_IOS = 5; }
- readonly关键字,提升代码效率,8.2支持class级别的readonly。也就是说在写构造函数的时候,可以用readonly确认类对象的只读属性,用private来控制访问级别,简化类对象的初始化,唯一有个小缺点,既然都干净了,为什么不把body的{}花括号一起省略掉呢,代码可以更美观。
readonly class LoginSubscriber implements EventSubscriberInterface { public function __construct(private TokenStorageInterface $storage, private JWTService $manager, private LoginRepository $loginRepository) { } }
- readonly进阶带来一个特性,简单来说就是immutable风格对象,例如在跨平台前段Flutter框架里,所有的对象都是不可变的。这种风格的写法带来一个好处就是可以方便计算对象是否变化,但如果要改变某个属性,要做的是为类提供一个类似copyWith的方法,改变内部值并且返回一个新的对象,新对象肯定有有新的hashcode。Flutter因为是基于Dart的,Dart没有反射,但PHP又反射,所以可以用第三方的包来实现这种设计风格。
class Post { use Cloneable; public readonly string $title; public readonly string $author; public function __construct(string $title, string $author) { $this->title = $title; $this->author = $author; } }
总结就是,PHP8是划时代的,更具有方向性的,我们可以知道PHP团队走在一条正确的道路上。:D
-
舟哥康复了
22年真的不太平,圣诞节晚上感觉发冷喉咙痛,果不其然,新冠了。这个病毒有延迟性,当天用抗原无法测出,第三天用抗原可以从痰液中测出两条杠。
基本症状第一天是发冷,全身发冷,只要温度不够就非常难受。需要大量进食高热量食物,然后对我来说比较明显的两个症状是喉咙难受,当然没有吞刀片的地步,但也很难受,其次就是眼压高。我的体温只有前两天有点烧,其他时候都很正常。肌肉很痛,尤其是训练的最后一个部位,痛得很,然后就是手肘老伤的地方有点痛。
终于大概六天的样子我又恢复健康了,感觉不冷了,体温彻底恢复了,但目前还是有些咳嗽。这个新冠还是很痛苦的,远比一般感冒痛苦,传染性尤其强大,身边周围的人没有不阳的。
-
WIN10下HDR设置让人捉摸不透
和MAC直接用相比,WIN下的HDR有点琢磨不透,我的显示器是KOIOS 3221UD,播放器是POTPLAYER。之前因为都是维持着MAC下设置,看HDR视频总是发暗,经过不懈努力我终于发现。
- 保持WIN显示设置HDR开启状态
- KOIOS设置里HDR选项设置成自动(这点很重要)
- 如果用了madvr可以在显示器hdr设置中选择第二项,让hdr信号直接输出到显示器。
- 如果用N卡,控制面板中视频项颜色由播放器决定,不要覆盖了播放器选项。
-
上海的秋天终于到来了
刚刚过去的上海夏天的温度应该是历年体感最高的,黄梅天都没能成功占领这个城市,每天的白天都被40多的温度占领,到了午夜时分,也是36,37能让人中暑的温度,上海的夏天越来越难过了。
秋天终于来了,虽然还处于不稳定状态,但是大自然让身体是瞬间舒服起来,人的活力也被激发了,白天的户外活动也开始解锁。
-
macOS Monterey 12.5更新终于把外接HDR显示器重启后没有HDR的bug修复了
只要是外接HDR显示器,只要系统没有重启,是从睡眠中唤醒的,那么在youtube中的HDR选项就会没有,这时候只有重启或者重新插拔DP线。
现在12.5更新了,唤醒后再youtube中也有HDR选项了,方便了。再次测试了下,bug还在,重启后外接显示器还是会丢失youtube里hdr选项。
-
尝试使用高德官方flutter插件amap_flutter_map
之前一直在用
amap_map_fluttify
,但我发现国内开源太容易半途而废了,当然不去说对错,这东东算是完了,就算以后再发新版本我也不敢用了。高德官方的flutter插件早就出了,这次小试了下,感觉不错。
- 支持Null-Safety和新版本flutter完美兼容。
- 配置方便,可以在native端配置key,也可以直接在代码中配置。
- 最新版本完成了工信部的合规!这个很重要!
- 官方版本,更新更及时,可以单独配置SDK版本。
相较于以前版本的复杂配置,高德官方版本配置很方便,flutter可以搭配不同的native端!只要在
android/app/build.gradle
配置,就可以选择你要的SDK版本。dependencies { implementation('com.amap.api:3dmap:9.2.1') implementation('com.amap.api:location:6.1.0') }
就可以完美使用了,不用自己去加载lib和so,很方便,当然缺点也有。
- 高德对于商用授权都要收费了,没有免费这一说了。
- 只有地图和定位两大类包,不过这个也没关系,可以使用web api获得其他接口。
- 没有官方讨论区,也只有商业授权用户才能得到官方的技术支持。