Skip to content

Loading…

DDC-29: ProxyClassGenerator does not correctly override methods with type-hinted array or default values or pass by reference #3657

Closed
doctrinebot opened this Issue · 2 comments

1 participant

@doctrinebot

Jira issue originally created by user itoijala:

The ProxyClassGenerator does not take into account array type-hinting, default values or pass by reference.

Example:

public function exampleMethod(array $array, &$c, $a = 'foo', array $b = array('b'))
{
    /** ... **/
}

Creates the follwing code:

public function exampleMethod($array, $c, $a, $b) 
{
    $this->_load();
    return parent::exampleMethod($array, $c, $a, $b);
}

and the following warning:

Strict Standards: Declaration of Doctrine\Generated\Proxies\Model*User_UserAProxy::exampleMethod() should be compatible with that of Model\User\User::exampleMethod() in C:\Windows\Temp\Model_User*UserAProxy.g.php on line 200

I am not sure about the consequences other than the warning when using E_STRICT.

The fix seems to be relatively simple:

Modify the _generateMethods method in ProxyClassGenerator

OLD:

private function _generateMethods(ClassMetadata $class)
    {
        $methods = '';

        foreach ($class->reflClass->getMethods() as $method) {
            if ($method->isConstructor()) {
                continue;
            }

            if ($method->isPublic() && ! $method->isFinal() && !$method->isStatic()) {
                $methods .= PHP_EOL . 'public function ' . $method->getName() . '(';
                $firstParam = true;
                $parameterString = $argumentString = '';

                foreach ($method->getParameters() as $param) {
                    if ($firstParam) {
                        $firstParam = false;
                    } else {
                        $parameterString .= ', ';
                        $argumentString  .= ', ';
                    }

                    // We need to pick the type hint class too
                    if (($paramClass = $param->getClass()) !== null) {
                        $parameterString .= '\\' . $paramClass->getName() . ' ';
                    }

                    $parameterString .= '$' . $param->getName();
                    $argumentString  .= '$' . $param->getName();
                }

                $methods .= $parameterString . ') {' . PHP_EOL;
                $methods .= '$this->*load();' . PHP*EOL;
                $methods .= 'return parent::' . $method->getName() . '(' . $argumentString . ');';
                $methods .= '}' . PHP_EOL;
            }
        }

        return $methods;
    }

NEW:

private function _generateMethods(ClassMetadata $class)
    {
        $methods = '';

        foreach ($class->reflClass->getMethods() as $method) {
            if ($method->isConstructor()) {
                continue;
            }

            if ($method->isPublic() && ! $method->isFinal() && !$method->isStatic()) {
                $methods .= PHP_EOL . 'public function ' . $method->getName() . '(';
                $firstParam = true;
                $parameterString = $argumentString = '';

                foreach ($method->getParameters() as $param) {
                    if ($firstParam) {
                        $firstParam = false;
                    } else {
                        $parameterString .= ', ';
                        $argumentString  .= ', ';
                    }

                    // We need to pick the type hint class too
                    if (($paramClass = $param->getClass()) !== null) {
                        $parameterString .= '\\' . $paramClass->getName() . ' ';
                    }
                    _* else if ($param->isArray())
                    {
                        $parameterString .= 'array ';
                    } *_

                    _* if ($param->isPassedByReference())
                    {
                        $parameterString .= '&';
                    } *_
                    $parameterString .= '$' . $param->getName();
                    _* if ($param->isDefaultValueAvailable())
                    {
                        $parameterString .= ' = ' . var_export($param->getDefaultValue(), true);
                    } *_
                    $argumentString  .= '$' . $param->getName();
                }

                $methods .= $parameterString . ') {' . PHP_EOL;
                $methods .= '$this->*load();' . PHP*EOL;
                $methods .= 'return parent::' . $method->getName() . '(' . $argumentString . ');';
                $methods .= '}' . PHP_EOL;
            }
        }

        return $methods;
    }

EDIT: forgot to add the fix for pass by reference.
EDIT2: fixed typo.

@doctrinebot

Comment created by romanb:

formatting

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.0-ALPHA2 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.