4
\$\begingroup\$

Related to the question Verb conjugator for French, I was asked an question on whether one could summarize all the $exceptionIs<NAME_OF_EXCEPTION> = $exceptionmodel-> getValue() === ExceptionModel::NAME_OF_EXCEPTION lines. In other words, can one make dynamic variables out of the comparison of a value combined with all values of an enum?

As I'm a bit rusty in php, I made this version, and ask you whether this is a good solution, or if it needs major refactoring. To avoid posting other peoples code, I've mocked the ExceptionModel class, and replace the output of ExceptionModel::getConstants() with a predefined array. This to give you working code to review. The original code is located on github, as the classes ExceptionModel and Enum.

<?php
// A mockup of the original ExceptionModel inheriting from Enum
class ExceptionModel {
    const NO_EXCEPTIONS = 'no_exception';
    const ALLER = 'aller';
    const AVOIR_IRR = 'avoir_irr';
    const ETRE_IRR = 'etre_irr';

    // ... many more lines ...

    function getConstants() {
        // ... returns array of constants ...
    }
}


function myFunction($exception) {
    // In final version, it should use the following line
    // $exceptionModels = ExceptionModel::getConstants();

    // ... but for now, use this array
    $exceptionModels = array (
        "NO_EXCEPTIONS" => 'no_exception',
        "ALLER" => 'aller',
        "AVOIR_IRR" => 'avoir_irr',
        "ETRE_IRR" => 'etre_irr'
    );

    // Generate dynamic variables testing for equality of
    // of $exception and an Enum value from ExceptionModel
    foreach ($exceptionModels as $constName => $constValue) {
        ${'exceptionIs' . $constName} = $exception === $constValue;
    }

    if ($exceptionIsALLER) {
        echo "ExceptionModel is aller. ";
    }

    else if ($exceptionIsAVOIR_IRR) {
        echo "ExceptionModel is avoir_irr";
    } else {
        echo "ExceptionModel was neither, it is: " . $exception;
    }

    echo "\n";
}

echo "<pre>";
myFunction("none");
myFunction(ExceptionModel::ALLER);
myFunction(ExceptionModel::AVOIR_IRR);
echo "</pre>";
?>

This correctly produces the output:

ExceptionModel was neither, it is: none
ExceptionModel is aller. 
ExceptionModel is avoir_irr
\$\endgroup\$
2
\$\begingroup\$

PHP allows computed variable names, but it's nearly always a bad idea. Unless you are careful about variable naming conventions, you could easily trash a variable accidentally, possibly introducing a security vulnerability.

You would be better off using an associative array.

// Generate dynamic variables testing for equality of
// of $exception and an Enum value from ExceptionModel
foreach ($exceptionModels as $constName => $constValue) {
    $detected[$constName] = $exception === $constValue;
}

if ($detected['ALLER']) {
    echo "ExceptionModel is aller.";
} else if ($detected['AVOIR_IRR']) {
    echo "ExceptionModel is avoir_irr.";
} else {
    echo "ExceptionModel was neither, it is: " . $exception;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ In general I do agree with you, but in this particular case I see a point in doing this, or even doing automatically as suggested in my own answer. The risk of trashing a variable should be small as we're talking about constants within Enum classes. \$\endgroup\$ – holroy Nov 27 '15 at 0:28
1
\$\begingroup\$

An alternative approach to creating the temporary variables, is to use reflection and automatically define test function for equality to any given enum value.

If extending the base Enum class, or the ExtensionModel class with the following function:

function __call($func, $param) {
    $func_prefix = substr($func, 0, 2);
    $func_const = substr($func, 2);
    if ($func_prefix == "is") {
        $reflection = new ReflectionClass(get_class($this));
        return $this->getValue() === $reflection->getConstant($func_const);
    }
}

Then it is legal to do stuff like in the following test function:

function myFunction(ExceptionModel $exceptionModel, Tense $tense) {

    if ($exceptionModel->isALLER()
        && $tense->isPresent() ) {
        ... do something ...
    }

given that both ExceptionModel and Tense inherits from the Enum class. In other words, now you can do $enumobject->is<ENUM_VALUE>() for any enum value inheriting from Enum.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.