I'm working on some code to sync the state of models between client (being a javascript application) and server. Often I end up writing redundant code to track the client and server objects so I can map the client supplied data to the server models.
Below is some code I am thinking about implementing to help. What I don't like about the below code is that this method won't handle nested relationships very well, I would have to create multiple object trackers.
One work around is for each server model after creating or loading, simply do $model->clientId = $clientId; IMO this is a nasty hack and I want to avoid it. Adding a setCientId method to all my model object would be another way to make it less hacky, but this seems like overkill to me. Really clientIds are only good for inserting/updating data in some scenarios. I could go with a decorator pattern but auto generating a proxy class seems a bit involved. I could use a generic proxy class that uses a __call function to allow for original object data to be accessed, but this seems wrong too. Any thoughts or comments?
$clientData = '[{name: "Bob", action: "update", id: 1, clientId: 200}, {name:"Susan", action:"create", clientId: 131} ]';
$jsonObjs = json_decode($clientData);
$objectTracker = new ObjectTracker();
$objectTracker->trackClientObjs($jsonObjs);
$query = $this->em->createQuery("SELECT x FROM Application_Model_User x WHERE x.id IN (:ids)");
$query->setParameters("ids",$objectTracker->getClientSpecifiedServerIds());
$models = $query->getResults();
//Apply client data to server model
foreach ($models as $model) {
$clientModel = $objectTracker->getClientJsonObj($model->getId());
...
}
//Create new models and persist
foreach($objectTracker->getNewClientObjs() as $newClientObj) {
$model = new Application_Model_User();
....
$em->persist($model);
$objectTracker->trackServerObj($model);
}
$em->flush();
$resourceResponse = $objectTracker->createResourceResponse();
//Id mappings will be an associtave array representing server id resources with client side
// id.
//This method Dosen't seem to flexible if we want to return additional data with each resource...
//Would have to modify the returned data structure, seems like tight coupling...
//Ex return value:
//[{clientId: 200, id:1} , {clientId: 131, id: 33}];