NotionCommotion Posted January 5, 2017 Share Posted January 5, 2017 How can I retrieve an object stored in SplObjectStorage based on a unique key? Is it possible to do so the way I am attempting to show in my 2 example? <?php class Foo { private $storage; private $map; public function __construct() { $storage = new SplObjectStorage(); $map=[]; } public function add(object $obj) { $this->storage->attach($obj, []); } public function assign1($obj,$id) { $this->storage[$obj] = $id; } public function findByID1($id) { $this->storage->rewind(); while($this->storage->valid()) { if($id == $this->storage->getInfo()) { return $this->storage->current(); } $this->storage->next(); } return false; } public function assign2($obj,$id) { $this->map[$id]=spl_object_hash($obj); } public function findByID2($id) { $hash=$this->map[$id]; return getObjectBasedOnHash($hash); } } $obj=(object)['foo' => 'bar']; $foo=new Foo(); $foo->add($obj); //Now this object's id is known $id=11111; $foo->assign1($obj,$id); $obj1=$foo->findByID1($id); $foo->assign2($obj,$id); $obj2=$foo->findByID2($id); Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/ Share on other sites More sharing options...
NotionCommotion Posted January 6, 2017 Author Share Posted January 6, 2017 (edited) Sorry, just realized that I did not enclose all the script in script tags... <?php class Foo { private $storage; private $map; public function __construct() { $this->storage = new SplObjectStorage(); $this->map=[]; } public function add($obj) { $this->storage->attach($obj, []); } public function assign1($obj,$id) { $this->storage[$obj] = $id; } public function findByID1($id) { $this->storage->rewind(); while($this->storage->valid()) { if($id == $this->storage->getInfo()) { return $this->storage->current(); } $this->storage->next(); } return false; } public function assign2($obj,$id) { $this->map[$id]=spl_object_hash($obj); } public function findByID2($id) { $hash=$this->map[$id]; //return getObjectBasedOnHash($hash); //How is this accomplished? } } $obj=(object)['foo' => 'bar']; $foo=new Foo(); $foo->add($obj); //Now this object's id is known $id=11111; $id=123321; //Option 1 $foo->assign1($obj,$id); $obj1=$foo->findByID1($id); //Option 2 $foo->assign2($obj,$id); $obj2=$foo->findByID2($id); Edited January 6, 2017 by NotionCommotion Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541078 Share on other sites More sharing options...
requinix Posted January 6, 2017 Share Posted January 6, 2017 SplObjectStorage is basically like an associative array that works with objects as keys. You are trying to use it as such, but you're also using these IDs as keys. Doing both doesn't make sense to me. If the IDs are unique then why not use them as the keys? And if that then why use Foo at all and not just an array? Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541083 Share on other sites More sharing options...
NotionCommotion Posted January 6, 2017 Author Share Posted January 6, 2017 SplObjectStorage is basically like an associative array that works with objects as keys. You are trying to use it as such, but you're also using these IDs as keys. Doing both doesn't make sense to me. If the IDs are unique then why not use them as the keys? And if that then why use Foo at all and not just an array? Because I don't know the key when the objects are added to SplObjectStorage. They are clients which make a connection to a server, and later communicate to the server and give the server its unique key. Later, the server might be given a specific client's unique key and told to send something to that client. I could iterate over the list of objects every time (as I showed in my option 1), but as a mater of principle, think I shouldn't. Yes, they are like associate arrays, but my understanding is the key is not really the object but a hash of that object. Why shouldn't I just store the hash which identifies the object? Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541084 Share on other sites More sharing options...
requinix Posted January 6, 2017 Share Posted January 6, 2017 Using the hash as the actual key is an implementation detail you shouldn't need to care about. If you use SplObjectStorage then just deal with the objects. 1. "Told to do something to that client" can't work until the client gives the key. Why does the client wait so long to give that? It should be giving that at the beginning of the process, as part of a sort of handshake protocol. 2. Since this code doesn't matter without the key being exchanged, you don't need to bother storing the client thing until that happens. Wait until you have the key and then store the object, which consequently removes the need for SplObjectStorage in the first place because you'll have the unique key (a scalar value) available. Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541086 Share on other sites More sharing options...
NotionCommotion Posted January 6, 2017 Author Share Posted January 6, 2017 Using the hash as the actual key is an implementation detail you shouldn't need to care about. If you use SplObjectStorage then just deal with the objects. And then iterate over SplObjectStorage to find a specific object which has a unique property? 1. "Told to do something to that client" can't work until the client gives the key. Why does the client wait so long to give that? It should be giving that at the beginning of the process, as part of a sort of handshake protocol. What handshake? 2. Since this code doesn't matter without the key being exchanged, you don't need to bother storing the client thing until that happens. Wait until you have the key and then store the object, which consequently removes the need for SplObjectStorage in the first place because you'll have the unique key (a scalar value) available. Wouldn't this require passing the key on every exchange? Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541103 Share on other sites More sharing options...
kicken Posted January 6, 2017 Share Posted January 6, 2017 I would ask why the clients are the ones generating these keys rather than the server? If you're going to be using them to identify individual clients then they would need to be unique and to guarantee they are unique the server should be the one generating them and assigning them to the client. If the server generates the key then you'd have it from the beginning. As for your option 2 method, why use a hash? You could just store the object into the map array. public function assign2($obj,$id) { $this->map[$id]=$obj; } public function findByID2($id) { return $this->map[$id]; } No need for SplObjectStorage or the hash for a simple id to object mapping like that. Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541113 Share on other sites More sharing options...
NotionCommotion Posted January 6, 2017 Author Share Posted January 6, 2017 I would ask why the clients are the ones generating these keys rather than the server? If you're going to be using them to identify individual clients then they would need to be unique and to guarantee they are unique the server should be the one generating them and assigning them to the client. If the server generates the key then you'd have it from the beginning. The clients are not generating these keys, but rather have been manually assigned a key such as 3512e089-861e-427f-a4eb-c9187f03a7d4. Care will be taken never to duplicate a key. As for your option 2 method, why use a hash? You could just store the object into the map array. public function assign2($obj,$id) { $this->map[$id]=$obj; } public function findByID2($id) { return $this->map[$id]; } No need for SplObjectStorage or the hash for a simple id to object mapping like that. Because I don't know the key when I first receive the object. The object is created when a client makes a connection, and it is saved using $this->clientList->attach($client, []);. Immediately after the client connects to the server, the client will send the server its GUID. The reason I do so are twofold: For every subsequent data receipt, the client does not need to send its GUID again. More importantly, another script which only know's a given clients GUID needs to be able to send data to that client. I am struggling on determining the best way to do this, however, it is outside of the scope of this post. Does this make any sense? <?php namespace MyServer; use React\EventLoop\Factory; use React\Socket\Server as SocketServer; use SplObjectStorage; require 'JSONStream.php'; class Server { private $app, //The main application $url_sockets, //Host and port for the socket $clientList; //SplObjectStorage public function __construct($url_sockets,$app) { $this->app = $app; $this->url_sockets=$url_sockets; $this->clientList = new SplObjectStorage(); } public function start() { $loop = Factory::create(); $socket = new SocketServer($loop); $socket->on('connection', function (\React\Socket\ConnectionInterface $client){ $client = new \Kicken\RLGL\JSONStream($client); $this->clientList->attach($client, []); $client->on('data', function($data) use ($client){ // The server doesn't know the client's GUID until the client sends this data to the server if($guid=$this->getConnectionID($client)) { $this->app->process($data, $guid, $client); } elseif($guid=$this->app->getGUID($data)) { $this->addConnection($client, $guid); } }); $client->on('close', function($conn) use ($client) { if($this->socketClients->contains($client)) { $this->socketClients->detach($client); } }); $client->on('error', function($conn) use ($client) { $client->close(); }); echo "New connection accepted.\r\n"; }); $foo->on('connection', function ($guid, $data){ /* I haven't really figured out this part. Another file such as index.php will receive $guid and $data via POST or GET. It then somehow needs to get it to this service so it could be sent to the approriate client. Options are: 1) redis queue 2) HTTP server located here and index.php sends it via cURL 3) Use the existing Sockets server here and index.php needs to somehow need to send it 4) ??? */ $client=$this->findConnectionByGuid($guid); $client->write($data); }); $socket->listen($this->url_sockets['port'],$this->url_sockets['host']); $loop->addPeriodicTimer(60, function() { //Initiate communication to local SOAP servers and save data $this->app->comm->soapClient(); }); $loop->run(); } private function addConnection($client, $guid) { $this->clientList[$client]['guid']=$guid; } private function getConnectionID($client) { return $this->clientList[$client]['guid']; } private function findConnectionByGuid($guid) { //There should be a better way to do this??? $this->socketClients->rewind(); while($this->socketClients->valid()) { if($guid == $this->socketClients->getInfo()) { return $this->socketClients->current(); } $this->socketClients->next(); } return false; } } Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541116 Share on other sites More sharing options...
Solution kicken Posted January 6, 2017 Solution Share Posted January 6, 2017 You could still make a guid map if you wanted to after you know what the GUID is. private function addConnection($client, $guid) { $this->clientList[$client]['guid']=$guid; $this->guidMap[$guid] = $client; } private function findConnectionByGuid($guid) { return isset($this->guidMap[$guid])?$this->guidMap[$guid]:null; } If there are not a lot of clients I'd probably just stick with the loop, but use a foreach to make it simpler. private function findConnectionByGuid($guid) { foreach ($this->socketClients as $client){ if ($this->socketClients[$client]['guid'] == $guid){ return $client; } } return null; } That way things are kept simple with only one member variable tracking the list of clients. Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541119 Share on other sites More sharing options...
NotionCommotion Posted January 6, 2017 Author Share Posted January 6, 2017 Of course. I wasn't thinking. There are not that many clients, however, I will probably go with the map approach just because... Quote Link to comment https://forums.phpfreaks.com/topic/302877-get-splobjectstorage-by-key/#findComment-1541120 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.