Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function assign a parameter that isn't null

This is the follow up question on my previous question.

Run a function without a parameter but needed a variable outside of the function - PHP

I recieved this answer

function foo($arg1 = null, $arg2 = null) {
    // if they are not set retrieve from a session
    $arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1'];
   // rinse repeat.
}

So I've thought, maybe I can reduce the line of codes by preventing to call the same variable on every single function.

I've come up with this one.

function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) {
     //do something
}

Unfortunately, I recieved this error.

Parse error: syntax error, unexpected T_VARIABLE

Is there a reason why it results to this one? I just replaced the null ones with a variable that has a value in it.

Is there any way to assign a function with parameter that has already a value instead of assigning a null ones?

P.S.

I'm trying to output the data using echo $campaign->getName(), so there's no parameter provided when calling the function.

So I'm trying to call a function something like this

function foo($arg1 = $_SESSION['user_id'], $arg2 = $_SESSION['campaign_id']) {
     //do something
}

If there's any way to do it without calling the same variable over and over again.

Any help would be appreciated. :)

like image 634
Wesley Brian Lachenal Avatar asked Apr 11 '14 06:04

Wesley Brian Lachenal


People also ask

Can I define a function that accepts no arguments?

You can define a function that doesn't take any arguments, but the parentheses are still required. Both a function definition and a function call must always include parentheses, even if they're empty.

Can we use a function as a parameter of another function?

You can use function handles as input arguments to other functions, which are called function functions. These functions evaluate mathematical expressions over a range of values.

What type of parameter can be given a default value?

Default Parameter Data TypesAny primitive value or object can be used as a default parameter value.

Can I call a function without parameter?

You can use a default argument in Python if you wish to call your function without passing parameters. The function parameter takes the default value if the parameter is not supplied during the function call.


3 Answers

tl;dr

Don't try that (it doesn't really even work as you see), use proper DI (dependency injection) and pass your external (global) variables as parameters:

// functions should be deterministic — require the arguments in favour of using dynamic defaults
function foo($arg1 /* require it */, $arg2 = 1 /* static scalars as default is no problem */) {
    // your code
}
foo($_SESSION["user_id"]); // always pass dynamic arguments, don't fetch them in the function

Intro

It isn't possible to use anything else as default as the so called static scalars. These are literals (strings, integers etc.), constants and (since PHP 5.6) operations on these literals/constants.

So...

I had the same great idea more than two years ago and filed a bug report ... https://bugs.php.net/bug.php?id=60544

Today I think it's a not-so-great idea. Default values are supposed to be static by the language. I doubt the ones who designed PHP hadn't had their reasons.

But there's still a way...

How you can do it (not recommended)

The only workaround here is to use constants.

function foo($arg = ARG) {
    var_dump($arg);
}

At the moment where you're sure that the value won't change anymore, define the constant before the first call of the function:

define("ARG", $_SESSION["user_id"]);

Then you can later just call it via foo();.

That's possible due to lazy evaluation of constants here.

The drawback of this method is that you have to define the constant once and then it'll remain immutable for the rest of the scripts run-time.

But I still strongly not recommend it. It's hackish and has major disadvantages.

How you could do it better

You have shown us a way how to do it:

$arg1 = ($arg1 !== null) ? $arg1 : $_SESSION['arg1'];

That absolutely is the correct way. If you really want to do it.

But you still shouldn't do that. You're accessing global scope (superglobals) from a function.

How you should do it

There's one reason why the language designers didn't implement this possibility and it's the same why we shouldn't try to circumvent that in any way by constants or global scope access in the functions.

You really should properly use dependency injection and pass external (global) values to the functions via parameter. (see example in tl;dr section)

This genre of code you're proposing can easily lead to hardly debuggable code as people might not expect that global state is accessed by genuine functions.

That's why functions should have deterministic output for a given input (except if they're explicitly supposed to be non-deterministic, e.g. a function to read a file), that dramatically increases testability and portability.

like image 61
bwoebi Avatar answered Oct 02 '22 15:10

bwoebi


You can't.

You can only assign literals to function defaults, constant values that cannot change in runtime. That means, "actual strings", numbers (42), hardcoded arrays ([1, 2, 3]), NULL. And not $variables, function() {} or anything else that may be changed at runtime.

Nor you should.

If you function depends on a user ID and a campaign ID, you should pass them into your function, and not rely on them being in SESSION because you can't know if they actually are in there!.

Do not rely on globals.


Why not pass the parameters to the function? It needs them, doesn't it? Would you expect the following function to work without parameters?

add($x, $y)

And just because those parameters are brought from SESSION, database, or the world beyond?

No. The function needs two parameters, and as such, it should ask for and given two parameters.

like image 34
Madara's Ghost Avatar answered Oct 02 '22 13:10

Madara's Ghost


I have bad news for you, in the form of shorter isn't always better. This is mainly because you're referring to the $_SESSION values as constants, and that's not really good. A good, solid code is longer because of all the checking and validation that helps avoid unnecessary errors. This is basically what you need to do:

function foo($arg1 = null, $arg2 = null) {
    // if condition
    if (!$arg1 && isset($_SESSION['arg1']))
        $arg1 = $_SESSION['arg1'];

    // tenary condition
    $arg2 = (!$arg2 && isset($_SESSION['arg2'])) ? $arg2 : $_SESSION['arg2'];
}

If you really want to, you can look for something that will shorten this code by a few letters but it won't really be much different. All those validations are a must and shouldn't be ignored.

like image 25
Gil Avatar answered Oct 02 '22 15:10

Gil