Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@hareku

PHPでSimpleXMLElementを持ったオブジェクトをキャッシュしたい時

結論:sleep()とwakeup()を使う

以下のようなSimpleXMLElementをプロパティとして持ったクラスのオブジェクトを、Serializeしてキャッシュしたい場合があります。

MyClass.php
<?php
namespace App;
use SimpleXMLElement;

class MyClass
{
    /**
     * @var SimpleXMLElement
     */
    public $xml;

    /**
     * @param  SimpleXMLElement  $xml
     * @return void
     */
    public function __construct(SimpleXMLElement $xml)
    {
        $this->xml = $xml;
    }
}

例えばこのクラスのオブジェクトをLaravelでそのままキャッシュしようとすると、「SimpleXMLElementをシリアライズできないよ」というエラーで怒られます。

解決策としてPHPのマジックメソッドであるsleep()とwakeup()を使用します。
先ほどのMyClassに以下のメソッドを追記。

    public function __sleep()
    {
        $this->xml = $this->xml->asXml();

        return ['xml'];
    }

    public function __wakeup()
    {
        $this->xml = simplexml_load_string($this->xml);
    }

シリアライズされる前にsleep()が呼ばれ、その中ではSimpleXMLElementをXML文字列に変換しています。
そしてアンシリアライズされる時に
wakeup()の中で再度SimpleXMLElementに変換するような形。

参考:PHP: マジックメソッド - Manual
http://php.net/manual/ja/language.oop5.magic.php

Laravelの時の注意点

Laravelではrememberというキャッシュがなければオリジンを取得し、そして保存して返すというメソッドがあります。
保存して返すというところがミソですが、これは以下のような問題を引き起こします。

  1. MyClassをキャッシュへ保存しようとする
  2. 保存する際に__sleep()メソッドによりxmlプロパティがstringへ変換される
  3. xmlプロパティがstringであるオブジェクトがrememberメソッドより返される

このように、初回(オリジンを取得する際)に__wakeup()が呼ばれないという事態に陥ってしまいます。
これは以下のように対処します。

$item= Cache::remember('item', 30, function () {
    return new MyClass($someSimpleXMLElement);
});

if (is_string($item->xml)) {
   $item->__wakeup();
}

return $item;
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?