phparraysforeachoperators

PHP Shorthand Addition Operator - Undefined Offset


I'm using the PHP shorthand addition operator to tally the number of times a specific id occurs within a multidimensional array:

$source['tally'] = array();

foreach ($items as $item) {
    $source['tally'][$item->getId()] += 1;
}

The first time it hits a new id, it sets its 'tally' value to 1 and then increments it each time it's found thereafter.

The code works perfectly (I get the correct totals), but PHP gives me an "Undefined Offset" notice each time it finds a new id.

I know I can just turn off notices in php.ini, but figured there must be a reason why PHP doesn't approve of my technique.

Is it considered bad practice to create a new key/offset dynamically like this, and is there a better approach I should take instead?

Please Note: To help clarify following initial feedback, I do understand why the notice is being given. My question is whether I should do anything about it or just live with the notice. Apologies if my question didn't make that clear enough.


Solution

  • If you simply want to defer the diagnostics (warning, notice), you can use an Immediately Invoked Function Expression (IIFE) that initializes return parameters:

    $source['tally'] = array();
    
    foreach ($items as $item) {
        (fn(&$_) => $_++)($source['tally'][$item->getId()]);
    }
    

    This has the benefit, that you would still get a warning on $source['tally'] if tally was not initialized.

    Which is not the case when using the error control operator, that eats all messages:

        @$source['tally'][$item->getId()]++;
    

    However, you should generally initialize your variables, in this case by adding the following code inside the loop (Null Coalesce assignment operation):

    if (!isset( $source['tally'][$item->getId()] ))
    {
       $source['tally'][$item->getId()] ??= 0;
       $source['tally'][$item->getId()]++;
    }
    

    Or perhaps in your case, map the ids and count:

    $source['tally'] = array_count_values(
        array_map(fn($item) => $item->getId(), $items)
    );