entry-header-eye-catch.html
entry-title-container.html

entry-header-author-info.html
Article by

ひっそりと佇むPhactory

こんにちは! pixiv事業本部Webエンジニアリングチームでアルバイトをしている、うすゆき(@usuyuki26)と申します!

今回は、ピクシブ百科事典のリファクタリングをしていく中で出会ったPhactoryについてお話しさせていただきます。

Phactoryとは

PhactoryのGitHubリポジトリA Database Factory for PHP Unit Testsと説明されている通り、ユニットテストでのデータベース作成やデータ挿入を支援するライブラリです。

テスト時はテスト対象のクラスにPDOとしてDIすることで、いとも容易くデータベースが絡むテストを実現できます。

self::phactory('pixpedia')->define('記事テーブル');

self::phactory('pixpedia')->create('記事テーブル', [
    'id' => 1,
    'tag_name' => 'テスト記事',
]);

これはとても偉大なことで、テスト時に外部のデータに依存することなく、実際にDBにデータが入っているかのようにテストを行うことができちゃいます。

このライブラリはpixiv.netとピクシブ百科事典の両方で利用しています。pixiv.netではユニットテストにて本物のMySQLのプロセスを複数起動、百科事典では『ピクシブ百科事典のテストにphp-mysql-engineを導入しました』にある通りピュアPHP製のPHP MySQL Engineを利用しています。

PhactoryはMySQL, PostgreSQL、SQLiteに対応していますが、基本的にシンプルにPDOを使っているだけなので、どのような環境でも問題なく動作します!

バグとの邂逅

そんなPhactoryを使ってテストを作っていく中で、バグと邂逅しました。
テスト用のデータを挿入する際、カラムの内容として null を渡すと正常に動作しないというものです。

PHP7.3では配列でない変数に配列アクセスしてもエラーは出ませんが、PHP7.4からはNotice、PHP8.0からはWarningを出してくれます。

このWarningにより原因を特定することができました。PHP8系の偉大さが垣間見れます。
さて、原因が分かったので†𝓞𝓢𝓢 𝓒𝓸𝓷𝓽𝓻𝓲𝓫𝓾𝓽𝓲𝓸𝓷…†の出番ですね!

PhactoryにPRを投げちゃいましょう…

……

………

…………

本家のPhactoryは2015年3月を最後に更新が途絶えています。公式ドキュメントのphactory.orgもすでにドメインが失効している状態です。

🍴

弊社にはPhacotryの社内フォーク版があります。
今回見つけたバグは社内フォーク版にパッチを当てることで、nullを含むカラムを用いたテストもできるようになりました。

From 2dc5839976947acf3e6fa1ef73596ea7d1921524 Mon Sep 17 00:00:00 2001
From: Usuyuki <usuyuki@pixiv.com>
Date: Thu, 2 Mar 2023 12:57:23 +0900
Subject: [PATCH] =?UTF-8?q?fix=20params=E3=81=AE=E5=80=A4=E3=81=8Cnull?=
 =?UTF-8?q?=E3=81=A0=E3=81=A3=E3=81=9F=E3=82=89where=20column=20=3D=20null?=
 =?UTF-8?q?=E3=81=A7=E3=81=AA=E3=81=8F=20is=20null=E3=82=92=E7=99=BA?=
 =?UTF-8?q?=E8=A1=8C=E3=81=99=E3=82=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/Sql/Row.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Sql/Row.php b/lib/Sql/Row.php
index cf85eb3..f2a158d 100644
--- a/lib/Sql/Row.php
+++ b/lib/Sql/Row.php
@@ -62,7 +62,7 @@ class Row {
                 $sql = "SELECT * FROM `{$this->_table}` WHERE";
 
                 for($i = 0, $size = sizeof($keys); $i < $size; ++$i){
-                    $sql .= " {$keys[$i]} = {$values[$i]} AND";
+                    $sql .= $params[$values[$i]] === null ? " {$keys[$i]} IS NULL AND" : " {$keys[$i]} = {$values[$i]} AND";
                 }
 
                 $sql = substr($sql, 0, -4);
-- 
GitLab

ピクシブでは社内フォークしたPhactoryにPHP8.1対応やバグ修正、不要コードの削除などを施すことで、現在も引き続きお世話になっています。

折角の機会ですので、いくつかの問題を解決した上で近代化改修したバージョンをGitHubで公開しようと準備を進めています…!

OSS

昨今OSS維持に関する問題は度々話題となっています。

弊社ではPhactoryのように開発が停滞したプロダクトを社内でフォークをすることで使い続ける事例、The PHP Foundationへの寄付のように財政的な支援を行う事例、他にも社内のエンジニアがOSSにPRを送る事例など、OSSに対して様々な向き合い方をしています。

Phactoryとの邂逅、そしてバグ修正は、私にとって昨今のOSS問題をとても身近に感じた瞬間でした。

宣伝

phperkaigi.jp

ピクシブ株式会社は本日3月23日から開催されるPHPerKaigiに協賛しています。 inside.pixiv.blog

Day 2ではTrack Dでピクシブ社員がライブコーディングしているので、pixivのインフラやコード、ピクシブ百科事典などについて気になることがある方はぜひお越しください!

また、私うすゆきも当日スタッフとして参加しています。この記事をお読みの方、ぜひ懇親会などでお話ししましょう!!

usuyuki
2022年5月アルバイト入社。PHPとSvelteとVTuberと百合で生きています。