class - php: get variable type hint using reflection
Get the solution ↓↓↓class Expense {
/**
* @var int
*/
private $id;
}
I would like to obtain the type hint of a variable in my class, using reflection, because the default value is null.
Answer
Solution:
Try:
<?php
class Expense {
/**
* @var int
*/
private $id;
}
$refClass = new ReflectionClass('Expense');
foreach ($refClass->getProperties() as $refProperty) {
if (preg_match('/@var\s+([^\s]+)/', $refProperty->getDocComment(), $matches)) {
list(, $type) = $matches;
var_dump($type);
}
}
Output:
string(3) "int"
Answer
Solution:
For PHP 7.4
$reflection = new \ReflectionProperty('className', 'propertyName');
echo $reflection->getType()->getName();
Answer
Solution:
Obtain the complete Docblock:
$reflection = new ReflectionProperty('Expense', 'id');
$doc = $reflection->getDocComment();
Answer
Solution:
If PHPDoc comments prove to be missing or unreliable, you can type hint all the properties of a class provided they have a matching getter.
public function getClassPropertiesType(string $className): array {
$reflectionClass = new \ReflectionClass($className);
$reflectionProperties = $reflectionClass->getProperties();
$properties = [];
foreach ($reflectionProperties as $reflectionProperty) {
$properties[] = $reflectionProperty->getName();
}
$methods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
$results = [];
foreach ($properties as $property) {
foreach ($methods as $method) {
// get only methods that have 0 parameter and start with 'get'
if ($method->getNumberOfParameters() === 0 &&
strpos($method->getName(),'get') !== false &&
stripos($method->getName(), $property) !== false) {
$results[$property] = (string)$method->getReturnType();
}
}
}
return $results;
}
Logically, there should be only one getter for each property of the class.
If I dump the properties of some class:
0 => "id"
1 => "email"
2 => "password"
3 => "firstName"
4 => "lastName"
5 => "gender"
6 => "position"
7 => "isActive"
9 => "dateEmployedFrom"
10 => "dateEmployedTo"
11 => "dateOfBirth"
12 => "ssn"
13 => "mobilePhone"
14 => "homePhone"
15 => "address"
16 => "zipCode"
17 => "city"
18 => "country"
This is what you get:
"id" => "int"
"email" => "string"
"password" => "string"
"firstName" => "string"
"lastName" => "string"
"gender" => "bool"
"position" => "string"
"isActive" => "bool"
"dateEmployedFrom" => "DateTimeInterface"
"dateEmployedTo" => "DateTimeInterface"
"dateOfBirth" => "DateTimeInterface"
"ssn" => "string"
"mobilePhone" => "string"
"homePhone" => "string"
"address" => "string"
"zipCode" => "string"
"city" => "string"
"country" => "string"
Limitations + workaround
If a property doesn't have any getter, you can start looking for setters (or methods that start with 'add', 'is', 'remove'), provided the method's arguments are type hinted. You could also include private properties in your search$methods = $reflectionClass->getMethods(); // no filter
I suggest expanding like this, before returning:
$missingProperties = array_diff_key(array_flip($properties), $results);
if (!empty($missingProperties)) { // some properties are missing
foreach ($missingProperties as $missingProperty => $val) {
// get only methods that have 1 parameter and start with 'set'
if ($method->getNumberOfParameters() === 1 && strpos($method->getName(), 'set') !== false) {
$parameters = $method->getParameters();
// if not already in results, and parameter is required
// and is a class property
if(!array_key_exists($parameters[0]->getName(), $results) &&
!$parameters[0]->isOptional() &&
in_array($parameters[0]->getName(), $properties, true)) {
$string = $parameters[0]->__toString();
$string = substr($string, strlen('Parameter #0 [ <required> '));
$pos = strpos($string, ' '); // get first space after type
$string = substr($string, 0, $pos); // get type
$results[$parameters[0]->getName()] = $string;
}
}
}
}
Of course, this is not 100% bulletproof, but hopefully it will help. :-)
Last: PHP 7.4 introduces ReflectionParameter::getType So, you could drop the above string manipulation and just write:
$type = $parameters[0]->getType();
$results[$parameters[0]->getName()] = $type->__toString();
Answer
Solution:
A bit of a warning - PHP accelerators and some libraries themselves (i.e. symfony core) strip comments, quite often on the second run.
Answer
Solution:
You can use the ReflectionDocBlock.
Installation
composer require phpdocumentor/reflection-docblock
Usage:
$factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
$reflectionClass = new ReflectionClass(MyClass::class);
$property = $reflectionClass->getProperty('foo');
$docBlock = $factory->create($property->getDocComment());
//it returns an array, as a property might declare many types
//for example @var int|string|null
$types = $docBlock->getTagsByName('var')[0]->getType()
See the reference of ReflectionClass and ReflectionProperty
Answer
Solution:
In PHP7.4
public function getKeysAndTypes(): array
{
$return = [];
$reflectionClass = new \ReflectionClass(static::class);
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
if ($reflectionProperty->isPublic()) {
$return[$reflectionProperty->getName()] = $reflectionProperty->getType()->getName();
}
}
return $return;
}
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: script cache:clear returned with error code 255
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.