Reputation: 2639
In PHP, undeclared class properties/variables will default to "public" visibility.
Is there a way (for certain classes, but not all) to change the default visibility to "protected" (or private)?
I know it's good practise to declare them all normally. However in this case I have lots layers of model classes sourced from SQL views with lots of columns. I'd like these to default to "protected" (to prevent my frontend devs from using raw values without HTML escaping), and when "public" access is needed, I'll declare them as so. i.e. Seeing it's security related, I want to "whitelist public" rather than "blacklist protected/private".
Upvotes: 2
Views: 1769
Reputation: 58444
No. There isn't.
But your classes shouldn't actually use undefined properties. In most cases that would be an indication of a "problem" (if not a full blown "mistake") in your code.
As for your actual problem: I personally use code like this in my data mappers:
public function applyValues($instance, array $parameters)
{
foreach ($parameters as $key => $value) {
$method = 'set' . str_replace('_', '', $key);
if (method_exists($instance, $method)) {
$instance->{$method}($value);
}
}
}
Since the method names in PHP are not case-sensitive, this approach works with both camelCase
and under_score
naming convention for SQL.
And this method will essentially work as "whitelist". If the setter is defined in your domain object, the value will be applied. If not, then it will be ignored. And, if you are using Twig (which you probably should), then having <p>{{ entity.content }}</p>
will attempt to call $entity->getContent()
.
Upvotes: 0
Reputation: 467
You have to use Reflection to accomplish what you are asking.
<?php
class MyClass {
private $myProperty = true;
}
$class = new ReflectionClass("MyClass");
$property = $class->getProperty("myProperty");
$property->setAccessible(true);
$obj = new MyClass();
echo $property->getValue($obj); // Works
echo $obj->myProperty; // Doesn't work (error)
?>
See PHP Manual for ReflectionProperty::setAccessible
In that case, you'll probably have to use magic methods. Something along these lines.
class Person {
private $properties = [
'first_name' => ['visibility'=>'public','value'=>null]
'last_name' => ['visibility'=>'public','value'=>null],
'income' => ['visibility'=>'private','value'=>null]
];
function __get($name) {
if (array_key_exists($name, $this->properties) && $this->properties[$name]['visibility'] == 'public')
return $this->properties[$name];
}
function __set($name, $value) {
if (array_key_exists($name, $this->properties) && $this->properties[$name]['visibility'] == 'public')
$this->properties[$name] = $value);
}
}
Upvotes: 1
Reputation: 932
If you need that level of visibility control you MUST declare a class. Directly to your question, no, there is no way to set visibility dynamically.
Despite the documentation not having a specific session to stdClass
object type, whatever array you convert using (object)
will be a stdClass
object with the non numeric indexes added as public properties. http://php.net/manual/en/language.types.object.php#language.types.object.casting
A generic solution would be you have a class with a protected
property that would be and array and it would hold the values. You would have to write an access method too expecting a index and returning either the raw or escaped value.
Upvotes: 3