Thanks for the suggestion, Ren. Unfortunately, apc_store() returned the same result.
I’ve echoed the data being stored at every stage in the process to see if a mistake in my code is somehow erasing the elements, but the data is there before the apc_add method.
I’m quite sute it did store multidimensional arrays a lot earlier. Not sure about arrays of objects - never tried that one before.
serialize hooks that come in 3.1.7 allow you to change the default serializer (to e.g. igbinary), so it’s not that they added serializing support. It just became more customizable. But who knows, maybe they fixed some issues at the same time.
I think the objects will need __sleep() and __wakeup() methods (not 100% sure), and also the class should be loaded when the objects are retrieved from APC.
Possibly it’s easier to create an array of the data you need and save that to APC.
Multidimensional arrays should be saved OK, but objects require special attention when using APC.
Why not just store the string returned from Twitter API? I mean, before you do json_decode() - just store the original string. It will work, then when you need to reuse it -just get it from cache and then json_decode() it. Simple enough? Makes sense?
I don’t know what you really need to do, but if you having problem storing object in cache then just store the original string and then use json_decode().
Also a solution may be as simple as passing second ‘true’ argument to json_decode
json_decode($string, true);
Then you get associative array instead of object. Then try to store in in APC, it may automatically serialize on save/unserialize on fetch
class TweetStore extends ArrayObject {
public function fetchURL( $url ) {
$this->exchangeArray( json_decode(
(string)file_get_contents( $url, false, stream_context_create(
array(
'http' => array(
'timeout' => 3
)
)
))
));
}
}
This creates an Array object to hold your tweet stuff that can be stored by APC cache. An array object is like an array - that is you can reach it’s contents through array operator . You can foreach it, anything you want to do array like an array object can do. But as you can see above since it is an object you can define behaviors for it. Specifically we have the behavior for fetching the Tweets defined as part of the object.
The object gets used like this.
$myTweets = new TweetStore();
$myTweets->fetch("http://api.twitter.com/1/statuses/user_timeline/{$strUser}.json");
And that’s all - its ready to go. If that URL isn’t going to change you could place it into the object as well.
ArrayObject also implements the serializable interface, which is preferred to the magic __sleep and __wakeup methods. The base definition for ArrayObject is to serialize the contents of the ArrayObject, but you can extend the methods to refine this - just be careful because they are as of yet undocumented in the php site.
The storage of ArrayObject is private - we cannot directly access it from our child class. It will be empty immediately after creating the class instance. The assumption is that if we are being asked to fetch and parse a tweet URL we’ll be throwing away whatever we had before. If holding the old value is important the external calling code can use getArrayCopy to get the data. This function doesn’t need the old array though so it drops it.
Or in code…
$tweets = new TweetStore();
// At this point the TweetStore is empty. We can see this by print_r
print_r($tweets);
// And we can call exchangeArray since it's public to see that we do indeed get an empty array.
$oldstorage = $tweets->exchangeArray( array() );
print_r($oldstorage);
// It isn't much use to us until we populate so,
$tweets->fetchURL($url);
// And now if we use exchange array we'll get the array the ArrayObject wraps around.
$t = $tweets->exchangeArray( array() );
// And now tweets is once again empty.
Bottom line is that you NEED to pass second arg to json_decode($string, true);
otherwise it will return object of type stdClass and that class is not serializable. You really need to get array back from json_decode - for that you must pass true as 2nd arg.
It very simple, really. There is no need to complicate things with another abstraction class unless you really going to use it for something other than just an abstraction class for an actual array.
Yeah, I tested it with the second argument and it worked like you said - taught me to always double-check the PHP manual.
As for ‘needing’ to do it that way, I am a bit confused since simply using serialize and unserialize when adding/fetching works, however, I agree passing the second boolean argument does save me a couple steps when working with the cached data.