Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Predis not Serializing Objects #29

Closed
stephenlb opened this issue May 19, 2011 · 7 comments
Closed

Predis not Serializing Objects #29

stephenlb opened this issue May 19, 2011 · 7 comments

Comments

@stephenlb
Copy link

It appears that this fails:

// Set Array
$redis->set( 'key', array(1,2,3) );

This is unanticipated with such a complete library. Where is the best place to put an object/array serializer for all Reids Commands?

@stephenlb
Copy link
Author

Rather the problem sits on reading with a GET command:

// Get Array
$data = $redis->get('key');

Recommendations?

@nrk
Copy link
Contributor

nrk commented May 19, 2011

This is an intended behaviour: Predis does not (and will not ever) handle any kind of serialization, it is completely up to developers how to serialize or deserialize values passed or stored in Redis. Behind the scenes of your example, the value passed to SET is casted to a string (string) array(1,2,3) which leads to the string value Array.

If you really want to handle (de)serialization for certain operations in a transparent way for the application's code, you should rely on Predis' extensibility and define your own commands like in the following example (I'm using json as a serialization format, but you can choose anything that best fits your application):

<?php

require 'autoload.php';

class StringSetJson
    extends Predis\Commands\StringSet {

    protected function filterArguments(Array $arguments) {
        $arguments[1] = json_encode($arguments[1]);
        return $arguments;
    }
}

class StringGetJson
    extends Predis\Commands\StringGet {

    public function parseResponse($data) {
        return json_decode($data);
    }
}

$client = new Predis\Client();

$profile = $client->getProfile();
// If you want, you can override SET or GET just like any other command, but I 
// think it's better to use different names for your serialization-aware commands:
$profile->defineCommand('jsonset', 'StringSetJson');
$profile->defineCommand('jsonget', 'StringGetJson');

$client->jsonset("json_key", array(1,2,3,4));
$value = $client->jsonget("json_key");

In this way you have complete control on which kind of serialization strategy to use (e.g. Igbinary) and how it should work depending on the data. It is probably worth to add this in the FAQ file and the new documentation that will be prepared once Predis v0.7 is released.

@nrk nrk closed this as completed May 19, 2011
@stephenlb
Copy link
Author

nrk,

Thank you for helping. This is disappointing since Memcache Clients support serialization automatically. PHP4+ supports object serialization: http://www.php.net/manual/en/function.serialize.php

@joeyhub
Copy link

joeyhub commented Mar 11, 2015

Hello,

I don't get what is with the profile thing in an OO world.

Why not provide a proxy class over the client class to intercept all the get set calls and serialize as necessary?

abstract class Predis\ProxyClient extends Predis\Client
    abstract method decode(string)
    abstract method encode(mixed)

    method get(string key)
        return $this->decode(parent::get(key))

If you separated your connection class this would work allowing difference client types for one connection.

I think the annoyance for me the the proposed solution here is that it is very granular where as the php redis extension lets us set the serializer globally (only problematic for strings as it adds a few bytes).

What you have looks like dependency injection but from the example I don't see it as being as convenient in this case as it could be.

Thanks.

@nrk
Copy link
Contributor

nrk commented Apr 15, 2015

@joeyhub you can indeed extend Predis\Client and implement both get() and set() methods to make them serialize / deserialize stuff, but that solution wouldn't work with pipelines, transactions and clustering due to how Predis is internally structured as these features work directly against the underlying connection.

@ryr
Copy link

ryr commented Sep 2, 2015

what about optional (like prefixing) variant to autoserialize (jsonify) all values, stored in redis?

$options = ['serialize' => 'json']

@tillkruss
Copy link
Member

Data serialization and compression will be added in #1084.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants