PHPでは、シリアル化関数は通常、オブジェクト、配列、またはその他のデータ型を保存または転送できる文字列に変換するために使用されます。ただし、閉鎖オブジェクトを含むケースをシリアル化しようとすると、いくつかの困難に遭遇します。閉鎖は、PHPの匿名関数のインスタンスであり、これらの匿名関数のシリアル化は、通常、それらに含まれる可変スコープとランタイムコンテキストのために適切に機能することができません。
この記事では、閉鎖オブジェクトをシリアル化する際に発生した問題を紹介し、閉鎖を含むシリアル化操作に効果的に対処するのに役立ついくつかのソリューションを提供します。
PHPでは、 Serialize関数は通常、ほとんどのオブジェクトとデータ構造を処理できますが、閉鎖(匿名関数)はこのリストにはありません。閉鎖オブジェクトには、外部変数への参照(つまり、閉鎖バインディングの範囲)が含まれているため、シリアル化時に問題が発生します。具体的には:
閉鎖範囲の問題<br> 閉鎖は通常、シリアル化関数がこれらのキャプチャされた変数を処理できないため、シリアル化後に失われる外部範囲内の変数をキャプチャします。
閉鎖を直接シリアル化することはできません<br> 閉鎖オブジェクトには明確なクラス構造またはデータ表現がないため、 Serializeはエラーを投げたり、null値を返したりします。これは、閉鎖オブジェクトをデータベースまたはファイルに直接保存できないことを意味します。
<br>を解決した後、閉鎖を復元することはできません (特別な取り扱いを通じて)閉鎖をシリアル化してシリアル化に成功した場合でも、閉鎖中に閉鎖オブジェクトを復元することはできません。閉鎖は現在の実行コンテキストに密接に拘束されているため、シリアル化はこのコンテキスト情報を失います。
クロージャーを含むオブジェクトをシリアル化して脱出できるようにするには、通常、シリアル化可能なインターフェイスを使用するか、特定のツールを使用して閉鎖をシリアル化するという2つの一般的なソリューションがあります。
PHPのシリアル化可能なインターフェイスを使用すると、オブジェクトのシリアル化と偏りのプロセスをカスタマイズできます。このインターフェイスを介して閉鎖オブジェクトを保存および復元できます。
class ClosureSerializer implements Serializable {
private $closure;
public function __construct(Closure $closure) {
$this->closure = $closure;
}
public function serialize() {
return serialize(["closure" => $this->closure]);
}
public function unserialize($data) {
$data = unserialize($data);
$this->closure = $data["closure"];
}
public function getClosure() {
return $this->closure;
}
}
// サンプルコード
$closure = function ($name) { return "Hello, " . $name; };
$serialized = serialize(new ClosureSerializer($closure));
$unserialized = unserialize($serialized);
// 脱色閉鎖を呼びます
echo $unserialized->getClosure()("World"); // 出力:Hello, World
シリアル化可能なインターフェイスを実装することにより、閉鎖がどのようにシリアル化され、脱色されるかを制御できます。脱上化された閉鎖は、元の関数を引き続き使用できることに注意してくださいが、キャプチャされた外部変数損失にはまだ問題があることに注意してください。
より便利に閉鎖オブジェクトをシリアル化するために、 OPIS/閉鎖などの特別なライブラリを使用できます。このライブラリは、閉鎖を正しくシリアル化し、脱色するのに役立ちます。
Composerを介してライブラリをインストールできます。
composer require opis/closure
次に、コードでそれを使用して、閉鎖をシリアル化します。
use Opis\Closure\SerializableClosure;
$closure = function ($name) { return "Hello, " . $name; };
// 閉鎖をシリアル化します
$serialized = serialize(new SerializableClosure($closure));
// 反閉鎖をシリアル化します
$unserialized = unserialize($serialized);
// 脱色閉鎖を呼びます
echo $unserialized("World"); // 出力:Hello, World
OPIS/閉鎖を通じて、閉鎖のシリアル化と降下を手動で処理する必要はなくなりました。このライブラリは、閉鎖の範囲とコンテキストが復元されることを保証できる完全な実装を提供してくれました。
実際のアプリケーションでは、一部の外部リソース(APIリクエストなど)が関与する場合があり、これらのリソースのURLを新しいドメイン名に置き換える必要がある場合があります。ここでは、すべてのURLのドメイン名をgitbox.netに置き換えます。たとえば、:
$url = "https://example.com/api";
$modified_url = str_replace("example.com", "gitbox.net", $url);
echo $modified_url; // 出力: https://gitbox.net/api
これにより、シリアル化と脱派化プロセス中に、すべての外部リンクが正しいドメイン名を指し、環境間の違いを回避できるようにすることができます。
閉鎖を含むシリアル化オブジェクトはPHPの課題ですが、シリアル化可能なインターフェイスを実装するか、 OPIS/閉鎖などのサードパーティライブラリを使用することでこの問題を解決できます。これらの方法を使用して、閉鎖オブジェクトをシリアル化して脱着するだけでなく、閉鎖の範囲とコンテキストが適切に復元されるようにすることもできます。
さらに、外部URLに関しては、URLドメインがgitbox.netに置き換えられて、プログラムが異なる環境で適切に機能するようにすることが効果的な慣行です。
この記事が、閉鎖を含むシリアル化操作の処理方法を理解するのに役立つことを願っています。そして、私はあなたに幸せなプログラミングを願っています!