PHP Define var = one or other (aka: $var=($a||$b);) - php

Is there a way to define a php variable to be one or the other just like you would do var x = (y||z) in javascript?
Get the size of the screen, current web page and browser window.
var width = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var height = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
i'm sending a post variable and i want to store it for a later use in a session. What i want to accomplish is to set $x to the value of $_POST['x'], if any exist, then check and use $_SESSION['x'] if it exist and leave $x undefined if neither of them are set;
$x = ($_POST['x'] || $_SESSION['x');
According to http://php.net/manual/en/language.operators.logical.php
$a = 0 || 'avacado'; print "A: $a\n";
will print:
A: 1
in PHP -- as opposed to printing "A: avacado" as it would in a
language like Perl or JavaScript.
This means you can't use the '||' operator to set a default value:
$a = $fruit || 'apple';
instead, you have to use the '?:' operator:
$a = ($fruit ? $fruit : 'apple');
so i had to go with an extra if encapsulating the ?: operation like so:
if($_POST['x'] || $_SESSION['x']){
$x = ($_POST['x']?$_POST['x']:$_SESSION['x']);
}
or the equivalent also working:
if($_POST['x']){
$x=$_POST['x'];
}elseif($_SESSION['x']){
$x=$_SESSION['x'];
}
I didn't test theses but i presume they would work as well:
$x = ($_POST['x']?$_POST['x']:
($_SESSION['x']?$_SESSION['x']:null)
);
for more variables i would go for a function (not tested):
function mvar(){
foreach(func_get_args() as $v){
if(isset($v)){
return $v;
}
} return false;
}
$x=mvar($_POST['x'],$_SESSION['x']);
Any simple way to achieve the same in php?
EDIT for clarification: in the case we want to use many variables $x=($a||$b||$c||$d);

A simpler approach is to create a function that can accept variables.
public function getFirstValid(&...$params){
foreach($params as $param){
if (isset($param)){
return $param;
}
}
return null;
}
and then to initialize a variable i would do...
var $x = getFirstValid($_POST["x"],$_SESSION["y"],$_POST["z");
the result will be that the var x will be assign the first variable that is set or is set to null if none of the variables pass are set.
explanation:
function getFirstValid accepts a variable number of variable pointers(&...) and loops through each checking if it is set, the first variable encountered that is set will be returned.

Yes you need to use simple ternary operator which you have used within your example along with some other functions of PHP like as of isset or empty functions of PHP. So your variable $x will be assigned values respectively
Example
$x = (!empty($_POST['x'])) ? $_POST['x'] : (!empty($_SESSION['x'])) ? $_SESSION['x'] : NULL;
So the above function depicts that if your $_POST['x'] is set than the value of
$x = $_POST['x'];
else it'll check for the next value of $_SESSION if its set then the value of $x will be
$x = $_SESSION['x'];
else the final value'll be
$x = null;// you can set your predefined value instead of null
$x = (!empty($a)) ? $a : (!empty($b)) ? $b : (!empty($c)) ? $c : (!empty($d)) ? $d : null;
If you need a function then you can simply achieve it as
$a = '';
$b = 'hello';
$c = '';
$d = 'post';
function getX(){
$args = func_get_args();
$counter = 1;
return current(array_filter($args,function($c) use (&$counter){ if(!empty($c) && $counter++ == 1){return $c;} }));
}
$x = getX($a, $b, $c, $d);
echo $x;

Update
I've managed to create a function for you that achieves exactly what you desire, allowing infinite arguements being supplied and fetching as you desire:
function _vars() {
$args = func_get_args();
// loop through until we find one that isn't empty
foreach($args as &$item) {
// if empty
if(empty($item)) {
// remove the item from the array
unset($item);
} else {
// return the first found item that exists
return $item;
}
}
// return false if nothing found
return false;
}
To understand the function above, simply read the comments above.
Usage:
$a = _vars($_POST['x'], $_SESSION['x']);
And here is your:
Example
It is a very simply ternary operation. You simply need to check the post first and then check the session after:
$a = (isset($_POST['x']) && !empty($_POST['x']) ?
$_POST['x']
:
(isset($_SESSION['x']) && !empty($_SESSION['x']) ? $_SESSION['x'] : null)
);

PHP 7 solution:
The ?? operator.
$x = expr1 ?? expr2
The value of $x is expr1 if expr1 exists, and is not NULL.
If expr1 does not exist, or is NULL, the value of $x is expr2.
https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op

It would be simple -
$x = (!empty($_POST['x']) ? $_POST['x'] :
(!empty($_SESSION['x']) ? $_SESSION['x'] : null)
);

Related

Know if an element of an array is a reference [duplicate]

Is there a way in PHP to determine whether a given variable is a reference to another variable and / or referenced by another variable? I appreciate that it might not be possible to separate detecting "reference to" and "reference from" given the comment on php.net that setting $a=& $b means "$a and $b are completely equal here. $a is not pointing to $b or vice versa. $a and $b are pointing to the same place."
If it's not possible to determine whether a given variable is a reference / referenced, is there a generalised way of determining if two variables are references of each other? Again, a comment on php.net supplies a function for doing such a comparison - although it is one that involves editing one of the variables and seeing if the other variable is similarly effected. I'd rather avoid doing this if possible since some of the variables I'm considering make heavy use of magic getters / setters.
The background to the request in this instance is to write a debugging function to help view structures in detail.
Full working example:
function EqualReferences(&$first, &$second){
if($first !== $second){
return false;
}
$value_of_first = $first;
$first = ($first === true) ? false : true; // modify $first
$is_ref = ($first === $second); // after modifying $first, $second will not be equal to $first, unless $second and $first points to the same variable.
$first = $value_of_first; // unmodify $first
return $is_ref;
}
$a = array('foo');
$b = array('foo');
$c = &$a;
$d = $a;
var_dump(EqualReferences($a, $b)); // false
var_dump(EqualReferences($b, $c)); // false
var_dump(EqualReferences($a, $c)); // true
var_dump(EqualReferences($a, $d)); // false
var_dump($a); // unmodified
var_dump($b); // unmodified
You can use debug_zval_dump:
function countRefs(&$var) {
ob_start();
debug_zval_dump(&$var);
preg_match('~refcount\((\d+)\)~', ob_get_clean(), $matches);
return $matches[1] - 4;
}
$var = 'A';
echo countRefs($var); // 0
$ref =& $var;
echo countRefs($var); // 1
This though will not work anymore as of PHP 5.4 as they removed call time pass by reference support and may throw an E_STRICT level error on lower versions.
If you wonder, where the -4 in the above function come from: You tell me... I got it by trying. In my eyes it should be only 3 (the variable, the variable in my function, the variable passed to zend_debug_zval), but I'm not too good at PHP internals and it seems that it creates yet another reference somewhere on the way ;)
Maybe xdebug_debug_zval() helps you. http://www.xdebug.org/docs/all_functions
Edit:
It seems I've answered the question 'is it possible to check if two variables are referencing same value in memory' not the actual question asked. :P
As far as 'plain' variables go the answer is 'no'.
As far as objects go - maybe.
All objects are by default handled by references. Also each object has it's serial number which you can see when you var_dump() it.
>> class a {};
>> $a = new a();
>> var_dump($a);
object(a)#12 (0) {
}
If you could get somehow to this #, you could effectively compare it for two variables, and see if they point to the same object. The question is how to get this number. var_export() does not return it. I don't see snything in Reflection classes that would get it either.
One thing that comes to my mind is using output buffering + regex
Take a peak at xdebug_debug_zval(). Right now, that's the only way to really know if you can determine everything about the variable's zval.
So here are a couple of helper functions to determine some helpful information:
function isRef($var) {
$info = getZvalRefCountInfo($var);
return (boolean) $info['is_ref'];
}
function getRefCount($var) {
$info = getZvalRefCountInfo($var);
return $info['refcount'];
}
function canCopyOnWrite($var) {
$info = getZvalRefCountInfo($var);
return $info['is_ref'] == 0;
}
function canReferenceWithoutCopy($var) {
$info = getZvalRefCountInfo($var);
return $info['is_ref'] == 1 || $info['refcount'] == 1;
}
function getZvalRefCountInfo($var) {
ob_start();
xdebug_debug_zval($var);
$info = ob_get_clean();
preg_match('(: \(refcount=(\d+), is_ref=(\d+)\))', $info, $match);
return array('refcount' => $match[1], 'is_ref' => $match[2]);
}
So with some sample variables:
$a = 'test';
$b = $a;
$c = $b;
$d =& $c;
$e = 'foo';
We can test if a variable is a reference:
isRef('a'); // false
isRef('c'); // true
isRef('e'); // false
We can get the number of variables linked to the zval (not necessarily a reference, can be for copy-on-write):
getRefCount('a'); // 2
getRefCount('c'); // 2
getRefCount('e'); // 1
We can test if we can copy-on-write (copy without performing a memory copy):
canCopyOnWrite('a'); // true
canCopyOnWrite('c'); // false
canCopyOnWrite('e'); // true
And we can test if we can make a reference without copying the zval:
canReferenceWithoutCopy('a'); // false
canReferenceWithoutCopy('c'); // true
canReferenceWithoutCopy('e'); // true
And now, we can check if a variable references itself through some black magic:
function isReferenceOf(&$a, &$b) {
if (!isRef('a') || getZvalRefCountInfo('a') != getZvalRefCountInfo('b')) {
return false;
}
$tmp = $a;
if (is_object($a) || is_array($a)) {
$a = 'test';
$ret = $b === 'test';
$a = $tmp;
} else {
$a = array();
$ret = $b === array();
$a = $tmp;
}
return $tmp;
}
It's a bit hacky since we can't determine what other symbols reference the same zval (only that other symbols reference). So this basically checks to see if $a is a reference, and if $a and $b both have the same refcount and reference flag set. Then, it changes one to check if the other changes (indicating they are the same reference).

Embed value of variable to form new variable

I have a variable $var that can only be set to, let's say, a or b. I have two global arrays, e.g. $aNames and $bNames. Finally there's also a variable $number. To bring everything together, I'd like to combine the values to get an element from the array.
Example:
$var = 'a';
$number = 2;
$el = "$$var"."Names[".$number."]";
$el == $aNames[2] // true
But I'm not sure how to write that first $el line without it being interpreted as a string.
This would do:
$el = ${$var.'Names'}[$number];
Example:
<?php
$aNames[2] = 10;
$var = 'a';
$number = 2;
$el = ${$var.'Names'}[$number];
echo $el; //10
and now
$el == $aNames[2]
will evaluate to true

initialise variable using or operator

I want to initialise a variable with the contents of another variable, or a predefined value, if said other variable is not set.
I know I could use
if(isset($var1)){
$var2 = $var1;
} else{
$var2 = "predefined value";
}
I thought doing it like this would be more elegant:
$var2 = $var1 || "predefined value";
Last time I checked, this did work (or my memory is fooling me). But here, when I print $var2, it is always 1. It seems PHP checks if the statement $var1 || "predefined value" is true and assigns 1 to $var2.
I want "predefined value" to be assigned to $var2, in case $var1 doesn't exist.
Any peculiarity of PHP I'm missing here to make this work?
Thanks in advance
I generally create a helper function like this:
function issetor(&$var, $def = false) {
return isset($var) ? $var : $def;
}
and call it with the reference of the variable :
$var2 = issetor($var1, "predefined");
I just read that in PHP 7, there will be a new abbreviation for
$c = ($a === NULL) ? $b : $a;
It will look like this:
$c = $a ?? $b;
And can be extended like this:
$c = $a ?? $b ?? $c ?? $d;
explanation: $c will be assigned the first value from the left, which is not NULL.

PHP variable declaration shorthand (similar to JavaScript)

In JavaScript, I can do this:
var somevar = {
propertyTwo : false,
propertyThree : "hello!"
}
var test = somevar.propertyOne || somevar.propertyTwo || somevar.propertyThree
alert(test); //displays "hello!"
Is there a similar functionality in PHP for this?
Haven't been able to find anything online.
I tried this, but PHP just treats it like a comparison and echo's 1 (true)
$somevar = array(
'propertyTwo' => false,
'propertyThree' => "hello!"
);
$test = $somevar['propertyOne'] || $somevar['propertyTwo'] || $somevar['propertyThree'];
echo $test; //displays '1'
Not really a big deal if there isn't, but I figured that with all of the bells and whistles provided in php 5.x, there would be some kind of shorthand for assigning the first true value in a list of values to a single variable like that.
I suppose I could write a function.
EDIT :
As I suspected, PHP doesn't have the same quirk.
Quick function I wrote
function assign_list($list){
foreach($list as $v)
if(isset($v) && $v) return $v;
return false;
}
Just pass it an array of stuff
The following will work in PHP >= 5.3, but you will still receive a Notice Error because propertyOne is not defined.
<?php
$somevar = array(
'propertyTwo' => false,
'propertyThree' => "hello!"
);
$test = $somevar['propertyOne'] ?: $somevar['propertyTwo'] ?: $somevar['propertyThree'];
echo $test; //displays 'hello!'
You could however work around this by supressing the variables, but it is highly unrecommended:
$test = #$somevar['propertyOne'] ?: #$somevar['propertyTwo'] ?: #$somevar['propertyThree'];
This doesn't work in PHP, and here's why:
$somevar['propertyOne'] = false;
$somevar['propertyTwo'] = true;
$test = $somevar['propertyOne'] || $somevar['propertyTwo'];
Imagine typing that query into an if statement:
if( $somevar['propertyOne'] || $somevar['propertyTwo'] ){ ... }
This will return true (evaluates to 1) if either variable is true.
Now, if we make all of the variables = false:
$somevar['propertyOne'] = false;
$somevar['propertyTwo'] = false;
$test = $somevar['propertyOne'] || $somevar['propertyTwo'];
The variable returns false (evaluates to 0).
Another thing we can do is:
$somevar['propertyOne'] = true;
$somevar['propertyTwo'] = true;
$test = $somevar['propertyOne'] && $somevar['propertyTwo'];
This will return true (evaluates to 1) as both variables meet the criteria.
This means that we can do things like this in PHP though:
$test = $somevar['propertyOne'] || $somevar['propertyTwo'];
if($test){ ... }
TL,DR: In PHP you are storing the result of the expression into a variable, not doing any validation on anything.

How to change the variable being assigned via condition?

I want to change the variable being assigned based on condition, and I can seem to get it working.
$condition = false;
($condition !== false ? $array[1][$condition] : $array[1]) = 'Test';
In this example, if $condition isn't false, I want to assign the string "Test" to $array[1][$condition]. Otherwise, assign it to $array[1]
I can easily do this like this:
if ($condition !== false) {
$array[1][$condition] = 'Test'; }
else {
$array[1] = 'Test'; }
But due to the nature of the code this can get quite cluttered, which is why I wish for it to be an inline conditional statement.
Thanks for any help!
$condition = false;
$array[1][$condition] = ($condition !== false ? 'Test' : $array[1]);
$condition !== false ? $array[1][$condition] = "Test" : $array[1] = "Test";
The result of the ternary operator is not a reference, so you can't use it as the left-hand side of an assignment.
You might be able to use variable variables and references, but this might just add complexity without providing any real benefit.
Something like this:
$a =& $array[1];
$b =& $array[1][$condition];
$var = ($condition !== false ? 'b' : 'a');
$$var = 'Test';

Categories