I'm using symfony and doctrine.
The server gets a HTTP PATCH request for the URL /company/{id} containing the property of a model and its value like {"name": "My new name"}
The new value needs to be persisted into the DB.
$request = Request::createFromGlobals();
$requestContentJSON = $request->getContent();
$requestContentObj = json_decode($requestContentJSON);
$repository = $this->getDoctrine()->getRepository('MyBundle:Company');
$company = $repository->find($id);
Now I could just enter $company->setName($requestContentObj[0]);
but the property being received will vary. Right now I'm using the following code to be able to handle every property:
foreach($requestContentObj as $key => $value){
switch($key){
case 'name':
$company->setName($value);
break;
case 'department':
$company->setDepartment($value);
break;
case 'origin':
$company->setOrigin($value);
break;
case 'headquarters':
$company->setHeadquarters($value);
break;
case 'email':
$company->setEmail($value);
break;
case 'twitterid':
$company->setTwitterId($value);
break;
case 'description':
$company->setDescription($value);
break;
}
}
But this doesn't look very smart especially because I know that I will have other entities like news, products, users, etc that will have their properties updated in the same manner. I'd like to do something like this:
$company->set("property", "value");
First thought that crossed my mind was to put this switch statement inside the company class inside this set function and also inside all the other entity classes I have. But is there a better way? Maybe symfony/doctrine has the solution already built-in, but I didn't find anything that would suit me.
I still want to use setters and getters as a long-term investment.
Thank you.
Assuming you'll have the property names similar to method names.
You can do something like this. To set multiple properties.
Class customer {
protected $_email;
public function __construct(array $config = array()){
$this->setOptions($config);
}
public function getEmail(){
return $this->_email;
}
public function setEmail($email){
$this->_email = $email;
}
public function setOptions(array $options)
{
$_classMethods = get_class_methods($this);
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (in_array($method, $_classMethods)) {
$this->$method($value);
} else {
throw new Exception('Invalid method name');
}
}
return $this;
}
public function setOption($key, $value){
return $this->setOptions(array($key, $value));
}
}
Now you can simply do this:
$array = array('email' => '[email protected]');
$customer = new Customer($array);
echo $customer->getEmail();
My inital thought would be to add a merge
method to your class, like so:
<?php
// example Company entity
class Company
{
private $name;
function setName($name)
{
$this->name = $name;
}
function getName()
{
return $this->name;
}
function merge(\stdClass $obj)
{
// get the object vars of the passed object
// iterate, and replace matching properties
foreach (get_object_vars($obj) as $prop => $val) {
if (property_exists($this, $prop)) {
$this->$prop = $val;
}
}
}
}
$company = new Company();
// mocking your request object
$requestContentObj = new stdClass();
$requestContentObj->name = 'acme';
$company->merge($requestContentObj);
var_dump($company);
Yields:
class Company#1 (1) {
private $name =>
string(4) "acme"
}
This silently dumps any passed values that do not match any properties in your Company
class, which may or may not be what you want. Hope this helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With