Search code examples
phpnoticeautovivification

How can I pre-increment at an empty array index without throwing a notice?


I'd like to do this:

$matched_tags[$tag]++

As a simple way of keeping track of how many times a given $tag is found during a loop.

This appears to be throwing a NOTICE the first time any new $tag is encountered, because the index is undefined. PHP kindly autovivifies it, sets it to 0 and post-increments it, but throws the NOTICE anyway.

Now I like to develop with Notices on as a best practice, so I don't want to suppress them. But to me what I'm doing isn't notice-worthy.

Do I really have to:

if ( ! isset ( $matched_tags[$tag] ) ) $matched_tags[$tag] = 0;
$matched_tags[$tag]++;

Oh that is so painful. Please tell me there's a more elegant way, or I swear I'll switch to Perl so help me.


Solution

  • I found another way to increment undefined array items. It looks like a kind of a hack, but it's obvious and still short.

    Suppose you need to increment a leaf value of the few nested arrays. Using isset() it may be too annoying:

    <?php
    error_reporting(E_ALL);
    
    $array['root']['node'][10]['node'][20]['leaf'][30]['totalCount'] = 
        isset($array['root']['node'][10]['node'][20]['leaf'][30]['totalCount'])
        ? ($array['root']['node'][10]['node'][20]['leaf'][30]['totalCount'] + 1)
        : 1;
    

    Name of an array item repeated there three times, rippling in your eyes.

    Try to use & operator to get an array item reference. Acting with a reference not causing any notices or errors:

    <?php
    error_reporting(E_ALL);
    
    $item = &$array['root']['node'][10]['node'][20]['leaf'][30]['totalCount'];
    // $item is null here
    $item++;
    unset($item);
    
    echo $array['root']['node'][10]['node'][20]['leaf'][30]['totalCount']; // 1
    

    It works just fine, but you can also avoid null to 0 casting:

    <?php
    error_reporting(E_ALL);
    
    $item = &$array['root']['node'][10]['node'][20]['leaf'][30]['totalCount'];
    // $item is null here
    $item = isset($item) ? ($item + 1) : 1;
    unset($item);
    
    echo $array['root']['node'][10]['node'][20]['leaf'][30]['totalCount']; // 1
    

    If you're already on PHP7, use coalesce operator instead of isset():

    $item = ($item ?? 0) + 1;