# Seeking 'coalesce' php internal function

- Thread: https://externals.io/message/23101
- Original archive: https://news-web.php.net/php.internals/23101
- Started by D. Dante Lorenso on 2006-05-03T05:56:41+00:00
- Messages: 24
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #23101 — D. Dante Lorenso — 2006-05-03T05:56:41+00:00

URL: https://externals.io/message/23101#23101

All,

I'm sure this has been asked somewhere, but since I see requests for 
features for 5.2 or 6.0, I'd like to add a "simple" item to the list 
which would be quite useful to me and would simplify and clean up a lot 
of code out there:

    function coalesce(...)

This works much like in the SQL version of the same.  In SQL, the 
function returns the first non-null argument from an arbitrary list.  In 
our use, it should return the first non-empty value from the list:

Example:

    $x = "dante";
    $y = "";
    $z = "";

    $value = coalesce($z, $y, $x); // $value = "dante"

This function would ideally be built into the language and bypass 
warnings about undefined variables like 'empty' does.  It might be nice 
to have several varieties of this function:

    * return first parameter where empty() is `FALSE` 
    * return first parameter where isset() is `TRUE` 

I don't think something like this can NOT be written in userspace 
because the 'isset' and 'empty' checks need to be run before arguments 
can be passed to a user function or warnings will start flying.  A 
function like this simplifies code which used to look like this:

    if (!empty($_POST["postkey"])) {
        $value = $_POST["postkey"];
    }
    elseif (!empty($_GET["getkey"])) {
        $value = $_POST["getkey"];
    }
    elseif (!empty($default_value)) {
        $value = $default_value;
    }
    else {
        $value = "hard coded value";
    }

Into this:

    $value = coalesce($_POST["postkey"], $_GET["getkey"], 
$default_value, "hard coded value");

Can this be built and included?

Dante

---

## #23102 — D. Dante Lorenso — 2006-05-03T06:05:41+00:00

URL: https://externals.io/message/23101#23102 · In reply to: #23101

D. Dante Lorenso wrote:
> I don't think something like this can NOT be written in userspace 
> because the 'isset' and 'empty' checks need to be run before arguments 
> can be passed to a user function or warnings will start flying.  A 
> function like this simplifies code which used to look like this:
>
>    if (!empty($_POST["postkey"])) {
>        $value = $_POST["postkey"];
>    }
>    elseif (!empty($_GET["getkey"])) {
>        $value = $_POST["getkey"];
>    }
>    elseif (!empty($default_value)) {
>        $value = $default_value;
>    }
>    else {
>        $value = "hard coded value";
>    }
>
> Into this:
>
>    $value = coalesce($_POST["postkey"], $_GET["getkey"], 
> $default_value, "hard coded value");

I mean "I DON'T think like this CAN be written in userspace".  And, yes, 
there is a bug in that code up above (around $_GET testing), but the 
'coalesce' function removes the test/set with identical values so 
removes those kinds of careless bugs.

Dante

---

## #23103 — Johannes Schlueter — 2006-05-03T06:15:34+00:00

URL: https://externals.io/message/23101#23103 · In reply to: #23101

Hi,

please search the archives for "ifsetor".

johannes


> All,
>
> I'm sure this has been asked somewhere, but since I see requests for
> features for 5.2 or 6.0, I'd like to add a "simple" item to the list
> which would be quite useful to me and would simplify and clean up a lot
> of code out there:
>
>     function coalesce(...)
>
> This works much like in the SQL version of the same.  In SQL, the
> function returns the first non-null argument from an arbitrary list.  In
> our use, it should return the first non-empty value from the list:
>
> Example:
>
>     $x = "dante";
>     $y = "";
>     $z = "";
>
>     $value = coalesce($z, $y, $x); // $value = "dante"
>
> This function would ideally be built into the language and bypass
> warnings about undefined variables like 'empty' does.  It might be nice
> to have several varieties of this function:
>
>     * return first parameter where empty() is `FALSE` 
>     * return first parameter where isset() is `TRUE` 
>
> I don't think something like this can NOT be written in userspace
> because the 'isset' and 'empty' checks need to be run before arguments
> can be passed to a user function or warnings will start flying.  A
> function like this simplifies code which used to look like this:
>
>     if (!empty($_POST["postkey"])) {
>         $value = $_POST["postkey"];
>     }
>     elseif (!empty($_GET["getkey"])) {
>         $value = $_POST["getkey"];
>     }
>     elseif (!empty($default_value)) {
>         $value = $default_value;
>     }
>     else {
>         $value = "hard coded value";
>     }
>
> Into this:
>
>     $value = coalesce($_POST["postkey"], $_GET["getkey"],
> $default_value, "hard coded value");
>
> Can this be built and included?
>
> Dante

---

## #23104 — Steph Fox — 2006-05-03T06:16:01+00:00

URL: https://externals.io/message/23101#23104 · In reply to: #23102

D.

Please read the mailing list archives. And don't mention it again ;)

- Steph


----- Original Message ----- 
From: "D. Dante Lorenso" <dante@vocalspace.com>
To: <dante@lorenso.com>
Cc: <internals@lists.php.net>
Sent: Wednesday, May 03, 2006 8:05 AM
Subject: Re: [PHP-DEV] Seeking 'coalesce' php internal function


> D. Dante Lorenso wrote:
> > […]
> 
> I mean "I DON'T think like this CAN be written in userspace".  And, yes, 
> there is a bug in that code up above (around $_GET testing), but the 
> 'coalesce' function removes the test/set with identical values so 
> removes those kinds of careless bugs.
> 
> Dante
> 
> -- 
> 
> 
> 
> 
> __________ NOD32 1.1380 (20060125) Information __________
> 
> This message was checked by NOD32 antivirus system.
> http://www.eset.com

---

## #23111 — D. Dante Lorenso — 2006-05-03T07:13:44+00:00

URL: https://externals.io/message/23101#23111 · In reply to: #23103

Johannes Schlueter wrote:
> please search the archives for "ifsetor".
>   

I have completed this search and find:

    http://marc.theaimsgroup.com/?r=1&w=2&q=b&l=php-dev&s=coalesce
    http://marc.theaimsgroup.com/?l=php-dev&w=2&r=1&s=ifsetor&q=b

I am using PHP 5.1.2 currently and thought using pass-by-reference was 
frowned upon.  Assuming a mistaken assumption I move forward and see the 
following code which was presented to the list:

<?php
function ifsetor(&$var, $value) {
    return (isset($var)) ? $var : $value;
}
print ifsetor($x, "dante");
?>

This works as I'd like in my dev environment, however, this does not 
solve the problem of allowing variable number of parameters (variables 
and values).  So, I've whipped up this 10 variable version:

<?php
function ifsetor(&$var1, &$var2, &$var3, &$var4, &$var5, &$var6, &$var7, 
&$var8, &$var9, &$var10) {
    if (isset($var1)) return $var1;
    if (isset($var2)) return $var2;
    if (isset($var3)) return $var3;
    if (isset($var4)) return $var4;
    if (isset($var5)) return $var5;
    if (isset($var6)) return $var6;
    if (isset($var7)) return $var7;
    if (isset($var8)) return $var8;
    if (isset($var9)) return $var9;
    if (isset($var10)) return $var10;
    return false;
}
print ifsetor($x["notset"]->notset, $y["notset"]->notset, $z->notset, 
"dante");
?>

PHP Fatal error:  Only variables can be passed by reference in 
.../ifsetor.php on line 15
PHP Warning:  Missing argument 5 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
PHP Warning:  Missing argument 6 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
PHP Warning:  Missing argument 7 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
PHP Warning:  Missing argument 8 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
PHP Warning:  Missing argument 9 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
PHP Warning:  Missing argument 10 for ifsetor(), called in 
.../ifsetor.php on line 15 and defined in .../ifsetor.php on line 2

I can work around passing values by reference by calling the function 
like this:

    print ifsetor($x["notset"]->notset, $y["notset"]->notset, 
$z->notset, $temp = "dante");

But you have to admit that's getting ugly and still, there are undefined 
parameters declared ... so then I tried it by assigning default values:

<?php
function ifsetor(&$var1=null, &$var2=null, &$var3=null, &$var4=null, 
&$var5=null, &$var6=null, &$var7=null, &$var8=null, &$var9=null, 
&$var10=null) {
    if (isset($var1)) return $var1;
    if (isset($var2)) return $var2;
    if (isset($var3)) return $var3;
    if (isset($var4)) return $var4;
    if (isset($var5)) return $var5;
    if (isset($var6)) return $var6;
    if (isset($var7)) return $var7;
    if (isset($var8)) return $var8;
    if (isset($var9)) return $var9;
    if (isset($var10)) return $var10;
    return false;
}
print ifsetor($x["notset"]->notset, $y["notset"]->notset, $z->notset, 
$temp = "dante")."\n";
print_r($x);
?>

Now, $x, $y, and $z ARE set ...

    dante
    Array ( [notset] => stdClass Object ( [notset] => ) )

This is a nasty side-effect and can not be accepted.  I did not want to 
set these variables, just check their existance.

I am willing to go away and concede that this should be done in 
userspace IF you can show me that it is in fact possible.  The 2 
argument ifsetor is trivial in userspace, yes, but the variable case is 
more useful in a variety of situations and provides the most benefit to 
simplify code.  I did not find the answer in the archives.  Can you 
point me in the right direction?  I need to be able to do all of the 
following:

    * variable number of parameters
    * test 'isset' or 'empty'
    * testing variables and non-variable values (pass-by-reference won't
      work on values)
    * not have side-effect of defining values which are not already set
    * not trigger notices or warnings
    * returns value of first proper match

Dante

> johannes
>
> 
>   
> > […]

---

## #23112 — Eric Coleman — 2006-05-03T07:27:47+00:00

URL: https://externals.io/message/23101#23112 · In reply to: #23111

http://us3.php.net/func_get_args
http://us3.php.net/array

Enjoy.

Eric Coleman


Eric Coleman

http://aplosmedia.com
home: 412 399 1024
cell: 412 779 5176




> Johannes Schlueter wrote:
> > […]
>
> I have completed this search and find:
>
>    http://marc.theaimsgroup.com/?r=1&w=2&q=b&l=php-dev&s=coalesce
>    http://marc.theaimsgroup.com/?l=php-dev&w=2&r=1&s=ifsetor&q=b
>
> I am using PHP 5.1.2 currently and thought using pass-by-reference  
> was frowned upon.  Assuming a mistaken assumption I move forward  
> and see the following code which was presented to the list:
>
> <?php
> function ifsetor(&$var, $value) {
>    return (isset($var)) ? $var : $value;
> }
> print ifsetor($x, "dante");
> ?>
>
> This works as I'd like in my dev environment, however, this does  
> not solve the problem of allowing variable number of parameters  
> (variables and values).  So, I've whipped up this 10 variable version:
>
> <?php
> function ifsetor(&$var1, &$var2, &$var3, &$var4, &$var5, &$var6, & 
> $var7, &$var8, &$var9, &$var10) {
>    if (isset($var1)) return $var1;
>    if (isset($var2)) return $var2;
>    if (isset($var3)) return $var3;
>    if (isset($var4)) return $var4;
>    if (isset($var5)) return $var5;
>    if (isset($var6)) return $var6;
>    if (isset($var7)) return $var7;
>    if (isset($var8)) return $var8;
>    if (isset($var9)) return $var9;
>    if (isset($var10)) return $var10;
>    return false;
> }
> print ifsetor($x["notset"]->notset, $y["notset"]->notset, $z- 
> > […]
> ?>
>
> PHP Fatal error:  Only variables can be passed by reference in .../ 
> ifsetor.php on line 15
> PHP Warning:  Missing argument 5 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
> PHP Warning:  Missing argument 6 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
> PHP Warning:  Missing argument 7 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
> PHP Warning:  Missing argument 8 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
> PHP Warning:  Missing argument 9 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
> PHP Warning:  Missing argument 10 for ifsetor(), called in .../ 
> ifsetor.php on line 15 and defined in .../ifsetor.php on line 2
>
> I can work around passing values by reference by calling the  
> function like this:
>
>    print ifsetor($x["notset"]->notset, $y["notset"]->notset, $z- 
> > […]
>
> But you have to admit that's getting ugly and still, there are  
> undefined parameters declared ... so then I tried it by assigning  
> default values:
>
> <?php
> function ifsetor(&$var1=null, &$var2=null, &$var3=null, & 
> $var4=null, &$var5=null, &$var6=null, &$var7=null, &$var8=null, & 
> $var9=null, &$var10=null) {
>    if (isset($var1)) return $var1;
>    if (isset($var2)) return $var2;
>    if (isset($var3)) return $var3;
>    if (isset($var4)) return $var4;
>    if (isset($var5)) return $var5;
>    if (isset($var6)) return $var6;
>    if (isset($var7)) return $var7;
>    if (isset($var8)) return $var8;
>    if (isset($var9)) return $var9;
>    if (isset($var10)) return $var10;
>    return false;
> }
> print ifsetor($x["notset"]->notset, $y["notset"]->notset, $z- 
> > […]
> print_r($x);
> ?>
>
> Now, $x, $y, and $z ARE set ...
>
>    dante
>    Array ( [notset] => stdClass Object ( [notset] => ) )
>
> This is a nasty side-effect and can not be accepted.  I did not  
> want to set these variables, just check their existance.
>
> I am willing to go away and concede that this should be done in  
> userspace IF you can show me that it is in fact possible.  The 2  
> argument ifsetor is trivial in userspace, yes, but the variable  
> case is more useful in a variety of situations and provides the  
> most benefit to simplify code.  I did not find the answer in the  
> archives.  Can you point me in the right direction?  I need to be  
> able to do all of the following:
>
>    * variable number of parameters
>    * test 'isset' or 'empty'
>    * testing variables and non-variable values (pass-by-reference  
> won't
>      work on values)
>    * not have side-effect of defining values which are not already set
>    * not trigger notices or warnings
>    * returns value of first proper match
>
> Dante
>
> > […]

---

## #23114 — D. Dante Lorenso — 2006-05-03T07:40:57+00:00

URL: https://externals.io/message/23101#23114 · In reply to: #23112

Eric,

This reply is too basic and is not the answer.  The problem is more 
complex then you have grasped.

The only way to remove the notice and warning errors is by using 
pass-by-reference in the userspace function.  Pass-by-reference can not 
be done for literal values and will only work on variables.  All notices 
and warnings have been thrown long before func_get_args can be run.  
Besides, func_get_args will return an array and then isset() and empty() 
no longer apply to the original variables.

Dante

Eric Coleman wrote:
> http://us3.php.net/func_get_args
> http://us3.php.net/array
>
> Enjoy.
>
> Eric Coleman
>
>
> Eric Coleman
>
> http://aplosmedia.com
> home: 412 399 1024
> cell: 412 779 5176
>
>
> 
>
> > […]

---

## #23135 — Rick Widmer — 2006-05-03T08:37:51+00:00

URL: https://externals.io/message/23101#23135 · In reply to: #23114

D. Dante Lorenso wrote:

> Eric,
> 
> This reply is too basic and is not the answer.  The problem is more 
> complex then you have grasped.



function ifsetor()  {

$args = `func_get_args()`;
$count = count( $args );

for( $i=0; $i<$count; $i++ ) {
    if isset( $args[ $i ] )) {
       return $args[ $i ];
    }

return false;
}

---

## #23132 — D. Dante Lorenso — 2006-05-03T21:18:31+00:00

URL: https://externals.io/message/23101#23132 · In reply to: #23101

Dear Internals,

I'd like a white bikeshed, but until you can decide on a color, how 
about we just build the bikeshed already.  Please consider the following 
specification:

========== 8< ==================== 8< ==================== 8< ==========

filled

(PHP 5.2.0)

filled - Find first non-empty value in a variable list where empty() 
evaluates as FALSE.

Description
------------------------------

mixed filled ( mixed varname [, mixed ...] )

 `filled()` takes a variable number of parameters.  For each of these, 
*filled()* looks for a variable where !empty( varname ) evaluates as 
TRUE.  It returns the first non-empty value or `NULL` if all values are 
empty().

Note: `filled()` only checks variables as anything else will result in a 
parse error.  In other words, the following will not work: 
filled(trim($name)).
    `filled()` is the opposite of empty(), and no warning is generated 
when any one of the variables is not set.

Return Values
------------------------------

Returns first non-empty() value.

If all values are empty(), returns NULL.

Example
------------------------------
<?php
echo filled($x["somekey"], $_GET["getkey"], $default, "example");
echo filled("yes"); // prints yes
filled(false); // returns `NULL` 
echo filled($x["apple"], $y, "banana"); // prints banana
$y = "cat";
echo filled($x["apple"], $y, "banana"); // prints cat
$x["apple"] = "pear";
echo filled($x["apple"], $y, "banana"); // prints pear
unset($x["apple"]);
echo filled($x["apple"], $y, "banana"); // prints cat
?>

See also empty()

========== 8< ==================== 8< ==================== 8< ==========

Dante

---

## #23136 — D. Dante Lorenso — 2006-05-03T23:47:25+00:00

URL: https://externals.io/message/23101#23136 · In reply to: #23135

Rick Widmer wrote:
> D. Dante Lorenso wrote:
> > […]
> function ifsetor()  {
> $args = `func_get_args()`;
> $count = count( $args );
>
> for( $i=0; $i<$count; $i++ ) {
>    if isset( $args[ $i ] )) {
>       return $args[ $i ];
>    }
>
> return false;
> }
>


No, that doesn't address the problem.  See this:

---------- 8< -------------------- 8< -------------------- 8< ----------
<pre>
<?php
function ifsetor()  {
    $args = `func_get_args()`;
    $count = count($args);
    for ($i=0; $i<$count; $i++) {
        if (isset($args[$i])) {
            return $args[$i];
        }
    }
    return false;
}
print ifsetor($x, $y, $z, "dante")."\n";
?>
</pre>

PHP Notice:  Undefined variable: x in .../ifsetor.php on line 13
PHP Notice:  Undefined variable: y in .../ifsetor.php on line 13
PHP Notice:  Undefined variable: z in .../ifsetor.php on line 13
---------- 8< -------------------- 8< -------------------- 8< ----------

See my post regarding a specification for 'filled()' as a function.  An 
important feature is that warnings about unset variables should not 
occur.  Your suggestion does not qualify.  This problem can not be 
solved in userspace.

Dante

---

## #23137 — Rick Widmer — 2006-05-03T23:55:21+00:00

URL: https://externals.io/message/23101#23137 · In reply to: #23136

D. Dante Lorenso wrote:

> No, that doesn't address the problem.  See this:


print @ifsetor($x, $y, $z, "dante")."\n";

---

## #23138 — Jochem Maas — 2006-05-04T00:05:39+00:00

URL: https://externals.io/message/23101#23138 · In reply to: #23137

Rick Widmer wrote:
> D. Dante Lorenso wrote:
> 
> > […]
> 
> 
> print @ifsetor($x, $y, $z, "dante")."\n";

point 1: regardless of how people think there should be an ifsetor()
in the engine - the devs don't so there wont be one.

point 2: anything trying to implement this functionality in userspace
is a hack. (to stregethen that stance: Rasmus reiterated the point a few
days ago [can't remember which mailinglist] that people should be trying to
write *error free* code - ergo the error suppression is not a proper solution)

Dante, live with the hack. :-)

---

## #23139 — D. Dante Lorenso — 2006-05-04T00:08:14+00:00

URL: https://externals.io/message/23101#23139 · In reply to: #23137

Rick Widmer wrote:
> D. Dante Lorenso wrote:
> > […]
> print @ifsetor($x, $y, $z, "dante")."\n";

Usage of the shutup operator, @, in this context is a shameful coding 
habit and hides too much:

    print @ifsetor($x, fakefunction($y), $z, "dante")."\n";

Does not show any warnings or errors, but REALLY hides this:

PHP Notice:  Undefined variable: x in .../ifsetor.php on line 13
PHP Fatal error:  Call to undefined function fakefunction() in 
.../ifsetor.php on line 13

Ignoring the notice on $x is fine, but that fatal error shouldn't be 
ignored.

Dante

---

## #23140 — D. Dante Lorenso — 2006-05-04T00:26:15+00:00

URL: https://externals.io/message/23101#23140 · In reply to: #23138

Jochem Maas wrote:
> point 1: regardless of how people think there should be an ifsetor()
> in the engine - the devs don't so there wont be one.
Arrrrvvhggghh!  Don't you just want to scream!

> point 2: anything trying to implement this functionality in userspace
> is a hack. (to stregethen that stance: Rasmus reiterated the point a few
> days ago [can't remember which mailinglist] that people should be 
> trying to
> write *error free* code - ergo the error suppression is not a proper 
> solution)

Ok.  You CAN NOT implement 'ifsetor/coalesce/filled' in userspace.  And 
the devs don't want it to exist ... so, WTF?
> Dante, live with the hack. :-)
Translate to: Dante, you don't need PHP to be better, adequate is good 
enough.

<soap box>
Come on devs, I'm pleading with you.  Say it isn't so.  You force me to 
write so much extra code unless this functionality exists in the core.

Explain to me how every possible thing you might want to do to an array 
gets it's own function in the language, but something as trivial as this 
gets refused so strongly!

I mean really: array_change_key_case, array_chunk, array_combine, 
array_count_values, array_diff_assoc, array_diff_key, array_diff_uassoc, ...
    http://www.php.net/manual/en/ref.array.php

You can't tell me that most if not all of these functions could not have 
been implemented in userspace?  I might use 10% of all the array 
functions, but I'd use 'coalesce' and 'filled' daily.
</soap box>

Tell me at least this much.  Can these two functions be implemented as 
an extension? From what you know about PHP internals, does what WE want 
have to be a language construct?  If I can write coalesce() and `filled()` 
as extensions, I'll submit a new extension/patch.  Maybe it could join 
PECL and with popularity make it's way begrudgingly into the core?

Dante

---

## #23141 — Rasmus Lerdorf — 2006-05-04T01:14:53+00:00

URL: https://externals.io/message/23101#23141 · In reply to: #23140

Not sure what you guys are talking about.  ?: is on the roadmap.

-Rasmus

D. Dante Lorenso wrote:
> Jochem Maas wrote:
> > […]
> Arrrrvvhggghh!  Don't you just want to scream!
> 
> > […]
> 
> Ok.  You CAN NOT implement 'ifsetor/coalesce/filled' in userspace.  And 
> the devs don't want it to exist ... so, WTF?
> > […]
> Translate to: Dante, you don't need PHP to be better, adequate is good 
> enough.
> 
> <soap box>
> Come on devs, I'm pleading with you.  Say it isn't so.  You force me to 
> write so much extra code unless this functionality exists in the core.
> 
> Explain to me how every possible thing you might want to do to an array 
> gets it's own function in the language, but something as trivial as this 
> gets refused so strongly!
> 
> I mean really: array_change_key_case, array_chunk, array_combine, 
> array_count_values, array_diff_assoc, array_diff_key, array_diff_uassoc, 
> ...
>    http://www.php.net/manual/en/ref.array.php
> 
> You can't tell me that most if not all of these functions could not have 
> been implemented in userspace?  I might use 10% of all the array 
> functions, but I'd use 'coalesce' and 'filled' daily.
> </soap box>
> 
> Tell me at least this much.  Can these two functions be implemented as 
> an extension? From what you know about PHP internals, does what WE want 
> have to be a language construct?  If I can write coalesce() and `filled()` 
> as extensions, I'll submit a new extension/patch.  Maybe it could join 
> PECL and with popularity make it's way begrudgingly into the core?
> 
> Dante

---

## #23142 — D. Dante Lorenso — 2006-05-04T01:33:17+00:00

URL: https://externals.io/message/23101#23142 · In reply to: #23141

Rasmus Lerdorf wrote:
> Not sure what you guys are talking about.  ?: is on the roadmap.
> -Rasmus

Ok.  That has some signs of hope.  What is ?: exactly, though.  I 
searched '?:' and yeah, good luck with that in documentation.  It 
doesn't smell like it supports all the specifics that 'filled()' does.  
Am I supposed to do this:

    $value = $x ?: $y ?: $z ?: $default;

And no warnings will be thrown for $x, $y, and $z not existing?  Did you 
see my post about 'filled()'?

    http://news.php.net/php.internals/23132

Honestly, I'm happy to see '?:' because that's better than nothing, but 
I think `filled()` is more like empty() and would be a better 
implementation.  If you want to look at the language from a consistency 
point of view '?:' is very PERL-like whereas filled(...) is PHP-like:

PERL-like:

    $x ~= s/\s+//;
    $x = $a ?: $b ?: $c;

PHP-like:
  
    $x = preg_replace("/\s+/", "", $x);
    $x = filled($a, $b, $c);

In my PHP zen world, empty() and `filled()` are friends.  Ok, I've been 
selling 'filled()' for a while now.  Can we reverse the sell and try 
this .. why SHOULDN'T `filled()` be added to the language?

Dante

---

## #23143 — Jasper Bryant-Greene — 2006-05-04T01:44:40+00:00

URL: https://externals.io/message/23101#23143 · In reply to: #23142

D. Dante Lorenso wrote:
> Rasmus Lerdorf wrote:
> > […]
> 
> Ok.  That has some signs of hope.  What is ?: exactly, though.

Rasmus is referring to making the middle operand in the ternary operator 
optional, I believe.

Jasper

---

## #23144 — Rasmus Lerdorf — 2006-05-04T01:57:41+00:00

URL: https://externals.io/message/23101#23144 · In reply to: #23142

D. Dante Lorenso wrote:
> In my PHP zen world, empty() and `filled()` are friends.  Ok, I've been 
> selling 'filled()' for a while now.  Can we reverse the sell and try 
> this .. why SHOULDN'T `filled()` be added to the language?

Because it doesn't do enough.  Unlike empty(), when there actually is 
something there, you have to check the type before using it anyway.

eg.

   $a = filled($_GET['a'],$_GET['b']);

You still have to do:

   if(!is_array($a)) echo $a;

Because people could put ?a[]=1 in the GET args there and you have to 
check for that before using it.  That second type check defeats the 
purpose of `filled()` as far as I am concerned.  We need a quick way to do 
a check and default assignment without throwing a notice which is what 
?: provides, then we need a decent way to check input arguments which is 
what pecl/filter is being brought into the core for (among other things).

See: 
http://www.php.net/~derick/meeting-notes.html#ifsetor-as-replacement-for-foo-isset-foo-foo-something-else

By the way, the lack of array checks is rampant out there.  Pick just 
about any PHP site and find a page where it has arguments and add [] to 
one of them and watch it blow up.  In some cases where the developers 
were smart enough to send errors to their error log, you can't see that 
you made it blow up, but in surprisingly many you can:

http://en.wikipedia.org/w/index.php?title[]=Special:Userlogin&returnto[]=Main_Page

-Rasmus

---

## #23151 — D. Dante Lorenso — 2006-05-04T19:27:09+00:00

URL: https://externals.io/message/23101#23151 · In reply to: #23144

Rasmus Lerdorf wrote:
> D. Dante Lorenso wrote:
> > […]
> Because it doesn't do enough.  Unlike empty(), when there actually is 
> something there, you have to check the type before using it anyway.
> eg.
>   $a = filled($_GET['a'],$_GET['b']);
> You still have to do:
>   if(!is_array($a)) echo $a;

You are correct that `filled()` does not serve the purpose of proper user 
input filtering.

 `filled()` is not trying to solve the input filtering problem as much as 
it's trying to solve the problem of accessing array/object members in a 
cascading order of defaulting to a non-empty value.

Currently I have a 'hack' object called ObjArray() which I use to wrap 
"maybe" PHP arrays in order to access their array elements 'safely' (no 
 `E_NOTICE` thrown) with options of a default value.  I use code like this:

    $maybe_array = function_which_returns_array_or_false();

    $obj = new ObjArray($maybe_array);
    print $obj->array_key;
    print $obj->get("array_key", $default_value);

The ObjArray class makes use of __get and __set functions to avoid 
tripping the `E_NOTICE` warnings that would occur otherwise when trying to 
access array properties that are not set.  In turn, ObjArray allows 
arrays to be accessed like objects.  ObjArray, however, can't be used on 
multi-level array access, but `filled()` could.

    print filled($maybe_array["array_key"], $default_value);

That avoids having to wrap arrays inside objects and also allows more 
powerful accesses:

    print filled($maybe_array["array_key"]->maybe_some_property, 
$default_value);

And unlike the pass-by-reference hacks, 
'$maybe_array["array_key"]->maybe_some_property' will not magically come 
into existence after calling the `filled()` function.

INPUT FILTERING != `filled()`

The example of using $_GET and $_POST as arrays in my examples might be 
a bad idea.  In most cases, I plan to use `filled()` to set default values 
for arrays or objects which contain empty or non-set keys or 
properties.  Most times the variable being accessed is known to be a 
certain list of possible types and in one call to `filled()` I want to get 
the data I want or use a cascading set of defaults:

    define('HARD_CODED_CONSTANT', "HARD_CODED");
    $filtered_user_input = get_safely_filtered_user_input_as_object();
    $database_row = fetch_database_row_as_array();
    $config_settings = fetch_config_file_as_array();

    $value = filled($filtered_user_input->thekey, 
$database_row["thekey"], $config_settings["thekey"], HARD_CODED_CONSTANT);

This works WITH input filtering especially when the default value is not 
just a default for the user input, but is a default for the chain of 
search locations.  I have many lines of PHP code which deal with if 
(!$variable) ..., if (!isset($array["key"]) ..., if (empty($var))... 
trying to find defaults for data which does not exist or was not found.  
None of those deal with $_GET or $_POST user inputs.  Especially when 
moving into CLI development, $_GET and $_POST are irrelevant.

> Because people could put ?a[]=1 in the GET args there and you have to 
> check for that before using it.  That second type check defeats the 
> purpose of `filled()` as far as I am concerned.  We need a quick way to 
> do a check and default assignment without throwing a notice which is 
> what ?: provides, then we need a decent way to check input arguments 
> which is what pecl/filter is being brought into the core for (among 
> other things).

People CAN do a lot of things (and some maliciously do).  I don't 
believe `filled()` prevents the input filtering from being added to the 
core.  Input filtering and `filled()` shared some commonality (selecting 
alternate values under specific conditions), but do not nullify the need 
for one or the other.

Detracting from my goal of having 'filled()' included in core, I'd have 
to say that as I see input filtering defined, that could be entirely 
written as part of Zend Framework in PHP and doesn't need to exist as 
part of the language core.  `filled()`, OTOH, must be written in 'zend' 
core because it simply can not be written as an extension or in 
userspace without triggering errors (undefined variables) or creating 
unwanted variables (pass by reference).

Dante

---

## #23152 — D. Dante Lorenso — 2006-05-04T19:38:40+00:00

URL: https://externals.io/message/23101#23152 · In reply to: #23132

The default value for 'filled()' if all values test `TRUE` for empty() 
should be FALSE, not NULL.  This is more consistent with the return 
values of empty().

Since `filled()` returns the first non-empty() value in the list of 
parameters provided, it works well when cast into a boolean context 
because the non-empty() value should evaluate as TRUE.  Example:

    filled("testing") // returns testing
    if (filled("testing")) {} // true
    filled(87) // returns 87
    (boolean) filled(87) // true

    $x["apple"] = "42";
    filled($x["apple"]) // returns 42
    filled($x["pear"]) // returns false
    if (filled($x["apple"]) !== false) {} // true
    if (filled($x["pear"]) !== false) {} // false

Just wanted to chime in with an update in case 'filled()' can actually 
be considered.  I'd like everyone to consider this one function to be 
evaluated on it's merits alone and apart from any other functions which 
also might be wanted.  `filled()` is the opposite of empty() and is not 
dealing with tests for 'isset()'.  Another function should be proposed 
to solve that problem if it would still be needed after `filled()` is 
implemented.

Do I have any power to call a vote on this?

Dante


D. Dante Lorenso wrote:
> Dear Internals,
>
> I'd like a white bikeshed, but until you can decide on a color, how 
> about we just build the bikeshed already.  Please consider the 
> following specification:
>
> ========== 8< ==================== 8< ==================== 8< ==========
>
> filled
>
> (PHP 5.2.0)
>
> filled - Find first non-empty value in a variable list where empty() 
> evaluates as FALSE.
>
> Description
> ------------------------------
>
> mixed filled ( mixed varname [, mixed ...] )
>
> `filled()` takes a variable number of parameters.  For each of these, 
> *filled()* looks for a variable where !empty( varname ) evaluates as 
> TRUE.  It returns the first non-empty value or `NULL` if all values are 
> empty().
>
> Note: `filled()` only checks variables as anything else will result in a 
> parse error.  In other words, the following will not work: 
> filled(trim($name)).
>    `filled()` is the opposite of empty(), and no warning is generated 
> when any one of the variables is not set.
>
> Return Values
> ------------------------------
>
> Returns first non-empty() value.
>
> If all values are empty(), returns NULL.
>
> Example
> ------------------------------
> <?php
> echo filled($x["somekey"], $_GET["getkey"], $default, "example");
> echo filled("yes"); // prints yes
> filled(false); // returns `NULL` 
> echo filled($x["apple"], $y, "banana"); // prints banana
> $y = "cat";
> echo filled($x["apple"], $y, "banana"); // prints cat
> $x["apple"] = "pear";
> echo filled($x["apple"], $y, "banana"); // prints pear
> unset($x["apple"]);
> echo filled($x["apple"], $y, "banana"); // prints cat
> ?>
>
> See also empty()
>
> ========== 8< ==================== 8< ==================== 8< ==========
>
> Dante

---

## #23153 — Pierre — 2006-05-04T21:06:04+00:00

URL: https://externals.io/message/23101#23153 · In reply to: #23151

On Thu, 04 May 2006 14:27:09 -0500
dante@vocalspace.com ("D. Dante Lorenso") wrote:

> Detracting from my goal of having 'filled()' included in core, I'd
> have to say that as I see input filtering defined, that could be
> entirely written as part of Zend Framework in PHP and doesn't need to
> exist as part of the language core.  `filled()`, OTOH, must be written
> in 'zend' core because it simply can not be written as an extension
> or in userspace without triggering errors (undefined variables) or
> creating unwanted variables (pass by reference).

I think it is time for you to do two things. The first is to read this
list archive about ifsetor (and other names it has), it will spare you
some ink and us some bandwidth. The second is to actually try the
filter extension and get some knowledge about what can be done where
and why. There is eventually a third one, try to imagine than the Z
Framework has nothing to do with php.net.

It is not an attack, but it seems you are putting so much effort on
this topic without actually having read what has been said and decided.

-- Pierre

---

## #23157 — Jared White — 2006-05-05T01:18:16+00:00

URL: https://externals.io/message/23101#23157 · In reply to: #23153

> On Thu, 04 May 2006 14:27:09 -0500
> dante@vocalspace.com ("D. Dante Lorenso") wrote:
>
> > […]
>
> I think it is time for you to do two things. The first is to read this
> list archive about ifsetor (and other names it has), it will spare you
> some ink and us some bandwidth. The second is to actually try the
> filter extension and get some knowledge about what can be done where
> and why. There is eventually a third one, try to imagine than the Z
> Framework has nothing to do with php.net.
>
> It is not an attack, but it seems you are putting so much effort on
> this topic without actually having read what has been said and  
> decided.

Well, from where I'm setting, Dante has brought up excellent points  
that were never covered before according to my look at the list  
archives. In fact, I find this situation indicative of a larger  
problem, which is that extremely important discussions of major  
issues with the language get breezed by far too quickly just because  
someone decides it's not interesting enough or it's time to move on  
(*cough* named parameters *cough*). I think the concept behind filled 
() is sound, has merit, and is worth talking about seriously.

Jared

---

## #23158 — Brian Moon — 2006-05-05T03:41:13+00:00

URL: https://externals.io/message/23101#23158 · In reply to: #23157

> Well, from where I'm setting, Dante has brought up excellent points that 
> were never covered before according to my look at the list archives. In 
> fact, I find this situation indicative of a larger problem, which is 
> that extremely important discussions of major issues with the language 
> get breezed by far too quickly just because someone decides it's not 
> interesting enough or it's time to move on (*cough* named parameters 
> *cough*). I think the concept behind `filled()` is sound, has merit, and 
> is worth talking about seriously.
> 
> Jared

+1

Dante's discussion has nothing to do with ifsetor() or the filter 
extension IMO.

Brian Moon
dealnews.com

---

## #23159 — Pierre — 2006-05-05T05:44:22+00:00

URL: https://externals.io/message/23101#23159 · In reply to: #23158

Jared, Brain,



> Dante's discussion has nothing to do with ifsetor() or the filter
> extension IMO.

His last answer has obviously something to do with both.

My answer answer is to his last post, which has obviously something to
do with that. My answer is also about his wrong statement (must be in
ZE2). Also did I take his point unserioulsy? no. I only told Dante to
read the list archives and to get the required knowledge before to
continue arguing.

--Pierre
