Skip to main content
added 35 characters in body; deleted 1 character in body
Source Link
Hugues D
  • 352
  • 2
  • 10

If a property doesn't have any getter, you can start looking for setters - or(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

        $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;
                    }
                }
            }
        }

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.

        $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;
                    }
                }
            }
        }

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

        $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;
                    }
                }
            }
        }
deleted 46 characters in body; added 30 characters in body
Source Link
Hugues D
  • 352
  • 2
  • 10

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.

If I dump the properties of a Usersome class of mine:

This is what you get with the above function:

Limitations + workaround If

If a property doesn't have aany getter, you can start looking for setters - or methods that start with 'add', 'is', 'remove', provided the method's arguments are type hinted.

I suggest expanding like this, right before the returnreturning:

        $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 ($publicMethod$method->getNumberOfParameters() === 1 && strpos($publicMethod$method->getName(), 'set') !== false) { // get only methods that have 1 parameter and start with 'set'
                    $parameters = $publicMethod$method->getParameters(); 

                    // if not already in results, andparameterand 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;
                    }
                }
            }
        }
                $type = $parameters[0]->getType();
                $results[$parameters[0]->getName()] = $type;$type->__toString();

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.

If I dump the properties of a User class of mine:

This is what you get with the above function:

Limitations + workaround If a property doesn't have a getter, you can start looking for setters - or methods that start with 'add', 'is', 'remove', provided the method's arguments are type hinted.

I suggest expanding like this, right before the return:

$missingProperties = array_diff_key(array_flip($properties), $results);
        if (!empty($missingProperties)) { // some properties are missing
            foreach ($missingProperties as $missingProperty => $val) {
                if ($publicMethod->getNumberOfParameters() === 1 && strpos($publicMethod->getName(), 'set') !== false) { // get only methods that have 1 parameter and start with 'set'
                    $parameters = $publicMethod->getParameters();
                    // if not already in results, andparameter 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;
                    }
                }
            }
        }
                $type = $parameters[0]->getType();
                $results[$parameters[0]->getName()] = $type;

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.

If I dump the properties of some class:

This is what you get:

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.

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;
                    }
                }
            }
        }
                $type = $parameters[0]->getType();
                $results[$parameters[0]->getName()] = $type->__toString();
Source Link
Hugues D
  • 352
  • 2
  • 10

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 a User class of mine:

  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 with the above function:

  "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 a getter, you can start looking for setters - or methods that start with 'add', 'is', 'remove', provided the method's arguments are type hinted.

I suggest expanding like this, right before the return:

$missingProperties = array_diff_key(array_flip($properties), $results);
        if (!empty($missingProperties)) { // some properties are missing
            foreach ($missingProperties as $missingProperty => $val) {
                if ($publicMethod->getNumberOfParameters() === 1 && strpos($publicMethod->getName(), 'set') !== false) { // get only methods that have 1 parameter and start with 'set'
                    $parameters = $publicMethod->getParameters();
                    // if not already in results, andparameter 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;