1

In the context of the following tutorial:

An easy way to allow a variable number of parameters is to set defaults for all but the first two:

function my_add( $val1, $val2, $val3 = '', $val4 = '', $val5 = '' ){
     return $val1 + $val2;
}

You can try something like below to make sure the values are numeric, otherwise return 0:

function my_add( $val1, $val2, $val3 = '0', $val4 = '0', $val5 = '0' ){
     if( !is_numeric( $val1 ) || !is_numeric( $val2 )){ // add checks for all the values
          return 0;  
     }
     return $val1 + $val2;
}

I have attempted to adapt the above code for my own purposes - though the code may be erroneous, I believe the intention is clear:

function sum_warehouses_stock( $warehouse1, $warehouse2, $warehouse3 = '0', $warehouse4 = '0', $warehouse5 = '0' ){
         if( !is_numeric( $warehouse1 ) {
               $warehouse1 = 0;
         }
         if( !is_numeric( $warehouse2 ){
               $warehouse2 = 0;  
         }
         if( !is_numeric( $warehouse3 ){
               $warehouse3 = 0; 
         }
         if( !is_numeric( $warehouse4 ){
               $warehouse4 = 0;   
         }
         if( !is_numeric( $warehouse5 ){
               $warehouse5 = 0;   
         }
         return $warehouse1 + $warehouse2 + $warehouse3 + $warehouse4 + $warehouse5;
    }

But I get:

Parse error: syntax error, unexpected ';' in your code on line 26

  1. Can you help me correct the error?
  2. How can I improve my code to be more efficient as I realise there is a lot of repetition?

Edit 1: to spell out the intention the function should check all of these variables and ensure for each variable that if their value is not numerical, redefine their values to zero. Then sum the values of the variables.

Edit 2: The solution needs to be in the format function ($warehouse1, $warehouse2, $warehouse3) but such that it is expressed in a more generally as: function (/* array of a variable number of warehouses*/)

Edit 3 - this is the solution I've been running with based on kojow7's answer:

function ld_sum_warehouses_stock($a, $b, $c, $d, $e, $f){
$warehouses = array( $a, $b, $c, $d, $e, $f );
    $total = 0;
    foreach($warehouses as $warehouse){
        $warehouse = str_replace(["+","<",">"], "", $warehouse);
        if (is_numeric($warehouse)){
             $total += $warehouse;
        }
     }
     return $total;
}

It allows me to call on a single function and pass the relevant variables in a single call - which is a constraint of the plugin I'm using.

However, at this stage the code is inflexible and forces me to commit to fixed number of variables. If the above code can be re-written accommodate a variable number of variables $a, $b to $n, then the solution will finally be consummated.

4
  • 1
    its missing closing parenthesis ) on the if blocks, time to get some coffee Commented Oct 10, 2018 at 1:41
  • 1
    regarding the arguments, you could probably use an array instead, then use an array map then array sum, no need to code warehouse...n Commented Oct 10, 2018 at 1:45
  • @Ghost Feel free to post an explicit solution Commented Oct 10, 2018 at 1:46
  • You're not closing the parenthesis of !is_numeric(). It (they) should be if ( !is_numeric($warehouseN) ) (two final parenthesis). Commented Oct 10, 2018 at 1:46

5 Answers 5

4

As mentioned by another user, using an array to pass all the variables in and mapping them to get the results is good.

Another solution if you'd like to keep the arguments in the function is as follows: Note that $c, $d, $e, $f, $g etc are not present.

function add($a, $b)
{
    $total = 0;

    // gets all args passed to this function, including those not listed.
    $args = func_get_args();

    foreach($args as $arg) {
        // check if argument value is numeric.
        if (is_numeric($arg)) {
            // ...if it is, add it to the running total.
            $total += $arg;
        }
    }

    return $total;
}

func_get_args is a way to retrieve all args given to the function as an array. With this in mind, you have to strip the first 2 out if you want them to be ignored. array_slice($args, 2) would remove the first 2 items ($a and $b) from the args array.

What I'm doing here is iterating over all the arguments given to the function including the first two and adding them all together. There is no reason to 0 a value if you still plan on adding it to the total. You may as well check the opposite, make sure the value IS numeric and only then, add it to the total.

Call it like this:

$result = add(1, 5, 77, 45, 885, 2456, 3, 5);

Note the following would also work, and ignore the strings:

$result = add(1, 5, 'ignores', 45, 'these', 2456, 'strings', 5);
Sign up to request clarification or add additional context in comments.

Comments

1

As others have said, you are missing the closing parenthesis on each of your if statements. You open two, but only close one.

While Ghost's answer is more elegant, it is also a bit more advanced. Here is a simpler way that might be more clear as to how it works:

function sum_warehouses_stock($warehouses){

    $total = 0;
    foreach($warehouses as $warehouse){
        if (is_numeric($warehouse)){
             $total += $warehouse;
        }
     }
     return $total;
}

This one will accept an array of numbers. It will then loop through each of those. If it is numeric, it will add it to the total. The total will then be returned.

To call the function, you need to pass it an array of values such as:

sum_warehouses_stock([5,0,20]);

or possibly based on your situation:

$warehouses = array(qldstocklevel[1], vickstocklevel[1], wastocklevel[1]);
sum_warehouses_stock($warehouses);

There's probably a better way to do this, because this fixes it to only three warehouses every time. It's better to make it more generic by allowing a variable number of warehouses.

Update

If you are unable to create an array of values outside of the function, then you are better off using the func_get_args() function as follows:

function sum_warehouses_stock(){

    $total = 0;
    $warehouses = func_get_args();

    foreach($warehouses as $warehouse){
        if (is_numeric($warehouse)){
             $total += $warehouse;
        }
     }
     return $total;
}

Then you can call it with a variable amount of warehouses:

sum_warehouses_stock(1, 5, 9);

or

sum_warehouses_stock(qldstocklevel[1], vickstocklevel[1], wastocklevel[1]);

This answer is now very similar to simonw16's answer.

Comments

1

Just like what's been said in the comments, you have a typo on the if blocks, it's missing the ) closing parenthesis.

As for the summation of the variables, why not use an array instead.

Here's the idea:

function sum_warehouses_stock($warehouses) {
    return array_sum(array_map(function($w) {
        return !is_numeric($w) ? 0 : $w;
    }, $warehouses));
}

If you're expecting a series of numbers, just load them up as array, then add your usual is_numeric then finally array_sum them. Then you won't need to declare warehouse...n.

So to use it:

echo sum_warehouses_stock([1, 2, 3, 0, 'a']);

1 Comment

Possible to annotate this code for a rookie so he can follow?
1

You're missing closing parenthesis. For your current code, this would fix your problem:

function sum_warehouses_stock( $warehouse1, $warehouse2, $warehouse3 = '0', $warehouse4 = '0', $warehouse5 = '0' ){
    if( !is_numeric( $warehouse1 ) ){
        $warehouse1 = 0;
    }
    if( !is_numeric( $warehouse2 ) ){
        $warehouse2 = 0;
    }
    if( !is_numeric( $warehouse3 ) ){
        $warehouse3 = 0;
    }
    if( !is_numeric( $warehouse4 ) ){
        $warehouse4 = 0;
    }
    if( !is_numeric( $warehouse5 ) ){
        $warehouse5 = 0;
    }

    return $warehouse1 + $warehouse2 + $warehouse3 + $warehouse4 + $warehouse5;
}

However, you should probably just be passing an array parameter instead of adding an arbitrary number of $warehouseX into it.

This would probably be the most succinct:

function sum_warehouses_stock( $warehouses = array() ){
    return array_sum( $warehouses );
}

Then, no matter how you get your warehouse values, even if they return an empty string or null, they'll basically be treated like zero.

$warehouses = array( 1, 7, 0, '', null );

echo sum_warehouses_stock( $warehouses ); // Result: "8"

5 Comments

Does this function work even if the original value was a text string? i.e. it gets converted to zero first before summing?
With this function, $warehouses needs to be an array, or it will give you an error - but any value inside it can be a a string or integer. 3 and '3' are both treated as three, while null, 0, '0', 'some string', '', etc. will all evaluate to zero. So like in the example, [1, 7, 0, '', null]` would be evaluated as [1, 7, 0]. If you need those values defined as zero for other purposes, a more robust solution like @Ghost's would be appropriate.
In this interpretation you would get your variables and add them to an array, $warehouses = array(); $warehouses[] = $warehouse_1_value; $warehouses[] = $warehouse_2_value;, etc.
How would the value "Call for more information", or "No stock" be treated? As zero also?
Correct, they will effectively be treated as zero. Check out this link: sandbox.onlinephpfunctions.com/code/… You can use that site or phptester.net to test relatively simple PHP scripts to evaluate results. Any non-numeric value gets treated as zero with array_sum()
1
     if( !is_numeric( $warehouse1 ) ){
           $warehouse1 = 0;
     }
     if( !is_numeric( $warehouse2 ) ){
           $warehouse2 = 0;  
     }
     if( !is_numeric( $warehouse3 ) ){
           $warehouse3 = 0; 
     }
     if( !is_numeric( $warehouse4 ) ){
           $warehouse4 = 0;   
     }
     if( !is_numeric( $warehouse5 ) ){
           $warehouse5 = 0;   
     }

You should be careful in closing open symbol like (, {, [.

The usual problem in closing these is on open parenthesis ( especially when your working with method inside these controlled statements. Always remember the the count of open parenthesis ( is always the number of closing parenthesis ).

the code should be:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.