Setting a default value if a variable is empty

  • This is the pattern I've been using for "if the variable is empty, set a default value", and for variables like $muffin, it has all seemed well and good. But in the following real example, this pattern gives me a super long line which smells a bit to me. Is there a cleaner way to do this?



    $newsItems[0]['image_url']= $newsItems[0]['image_url']=='' ? '/img/cat_placeholder.jpg' : $newsItems[0]['image_url'];


    Maybe:



    $newsItems[0]['image_url']= $newsItems[0]['image_url']=='' ? 
    '/img/cat_placeholder.jpg' :
    $newsItems[0]['image_url']; //this doesn't look much better to me?

    Starting with PHP 7.0, Langen's answer is probably the best: `$newsItems[0]['image_url'] = $newsItems[0]['image_url'] ?? '/img/cat_placeholder.jpg';` http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.coalesce

  • Before dealing with your question, I'd like to point out that you probably want to use empty() instead of comparing with an empty string and that if you really want to compare to an empty string, use the === operator.



    Anyway, default initialization is a real problem in many languages. C# even has a ?? operator to solve this kind of issue! So, let's try to make it better to make your code better step by step.



    Ternary operator no more



    The one-liner is too long, and using the ternary operator on multiple lines is a bad idea: that's what if-statement are for:



    if (empty($newsItems[0]['image_url'])) {
    $newsItems[0]['image_url'] = '/img/cat_placeholder.jpg';
    }


    This is more readable for two reasons : it's easier to understand the syntax, but more importantly, it's easier to see that you simply want a default value when there's nothing. We don't need the 'else' part which is confusing with the ternary operator.



    Note: as mentioned by Simon Scarfe and corrected by mseancole, PHP also has some special ternary syntax to do this:



    $newsItems[0]['image_url'] = $newsItems[0]['image_url'] ?: 'img/cat_placeholder.jpg';


    Factorize it!



    If you're doing this only once or twice, then all is good, but otherwise you'd want to factorize it into a function, since you don't repeat yourself, right? The simple way is:



    function default_value($var, $default) {
    return empty($var) ? $default : $var;
    }

    $newsItems[0]['image_url'] = default_value($newsItems[0]['image_url'], '/img/cat_placeholder.jpg');


    (The ternary operator does make sense here since variable names are short and both branches of the condition are useful.)



    However, we're looking up $newsItems[0]['image_url'] when calling default_value, and this is possibly not defined, and will raise an error/warning. If that's a concern (it should), stick to the first version, or look at this other answer that gives a more robust solution at the expense of storing PHP code as a a string and thus cannot be checked syntactically.



    Still too long



    If we don't care about the warning/error, can we do better? Yes we can! We're writing the variable name twice, but passing by reference can help us here:



    function default_value(&$var, $default) {
    if (empty($var)) {
    $var = $default;
    }
    }

    default_value($newsItems[0]['image_url'], '/img/cat_placeholder.jpg');


    It's much shorter, and feels more declarative: you can look at a bunch of default_value calls and see what the default values are instantly. But we still have the same warning/error issue.


    The second two options presented here will raise an error and also (because of this) impact performance. I shouldn't have to mention the performance bit, though, as the fact that an error (Warning, in this case, undefined index) should simply be enough. Even if reporting/logging is turned off, the fact that the interpreter notices at all incurs more performance impact than `empty` and `isset` in conjunction with an `if`. Stick to the `if`, or use a solution like mine below.

    Thank you, upvoted. Of course, the performance does not matter here, unless it is proven that this code is part of a bottleneck.

    @MichaelJMulligan does my edit seem fair?

    @QuentinPradet, Fair. As for the syntactic check, can you elaborate on my answer? I'd be interested.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used