What I'm trying to do is write one function to reuse vs writing out an if statement every time.
If statement:
if (!isset($value)){ echo 'null';}else{ echo $value;}
Function:
function isSetTest($value){
if ( !isset($value)){
$value = NULL;
}
return $value;
}
echo'name'.isSetTest($value);
Function works but I still get the "undefined" error message which is what i'm trying to avoid.
Pass by reference instead, so that no processing of the variable is done until you want it:
function isSetTest(&$value) { // note the &
if (!isset($value)) {
$value = NULL;
}
return $value;
}
You can shorten this a bit:
function isSetTest(&$value) {
return isset($value) ? $value : null;
}
I have a function that does something similar, except you can provide an optional default value in the case that the variable is not set:
function isset_or(&$value, $default = null) {
return isset($value) ? $value : $default;
}
The problem in your code is, that you still pass an undefined variable to your function, so that's why you still get your undefined error.
One way to solve this now, is that you pass your variable name as a string and then use variable variables, to check if it exists, e.g.
function isSetTest($value){
global $$value;
if ( !isset($$value)){
$$value = NULL;
}
return $$value;
}
echo'name'.isSetTest("value");
Demo
Related
I have a bunch of optional settings and I'm sick of checking for isset and property_exists.
In Laravel, if I ask for a property that does not exist on a model or request, I get null and no complaints (errors). How can I do the same for my data structure.
If I try array, I can't do simple $settings['setting13'], I have to either pre-fill it all with nulls or do isset($settings['setting13']) ? $settings['setting13'] : '' or $settings['setting13'] ?? null. If I try an object (new \stdClass()), $settings->setting13 still gives me a warning of Undefined property.
How can I make a class such that it responds null or an empty string whenever it is asked for a property that it doesn't have?
Simply do what Laravel does, create a class that deals with your data structure which returns a value if key exists, and something else if it doesn't.
I'll illustrate with an example class (this class supports the "dot notation" of accessing array keys):
class MyConfigClass
{
protected $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function get($path = '', $default = null)
{
if(!is_string($path))
{
return $default;
}
// There's a dot in the path, traverse the array
if(false !== strpos('.', $path))
{
// Find the segments delimited by dot
$segments = explode('.', $path);
$result = $this->data;
foreach($segments as $segment)
{
if(isset($result[$segment]))
{
// We have the segment
$result = $result[$segment];
}
else
{
// The segment isn't there, return default value
return $default;
}
}
return $result;
}
// The above didn't yield a result, check if the key exists in the array and if not - return default
return isset($this->data[$path]) ? $this->data[$path] : $default;
}
}
Use:
$my_structure = [
'url' => 'www.stackoverflow.com',
'questions' => [
'title' => 'this is test title'
]
];
$config = new MyConfigClass($my_structure);
echo $config->get('url'); // echoes www.stackoverflow.com
echo $config->get('questions.title'); // echoes this is test title
echo $config->get('bad key that is not there'); // returns null
There is also a possibility to create wrapper as Jon Stirling mentioned in a comments. This approach will allow to keep code clean and also add functionality via inheritance.
<?php
class myArray implements ArrayAccess {
private $container;
function __construct($myArray){
$this->container = $myArray;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
$settings = array("setting1"=>1,"setting2"=>2,"setting3"=>3);
$arr = new myArray($settings);
echo $arr['setting1'];
echo "<br>";
echo $arr['setting3'];
echo "<br>";
echo $arr['setting2'];
echo "<br>";
echo "------";
echo "<br>";
echo $arr['setting4'] ?:"Value is null";
!empty($settings['setting13']) ? $settings['setting13'] : ''
can be replaced with
$settings['setting13'] ?: ''
as long as whatever you want to print and whatever you want to check exists is the same expression. It's not the cleanest thing ever - which would be to check the existence of anything - but it's reasonably clear and can be chained :
echo ($a ?: $b ?: $c ? $default ?: '');
However, you are not the first who are "sick of checking for isset and property_exists, it's just that we still have to do it, or else we get unexpected results when we expect it the least.
It's not about saving time typing code, it's about saving time not debugging.
EDIT : As pointed in the comments, I wrote the first line with isset() instead of !empty(). Since ?: returns the left operand if it's equal to true, it's of course uncompatible with unchecked variables, you have at least to check for existence beforehand. It's emptiness that can be tested.
The operator that returns its left operand if it exists and is different from NULL is ??, which can be chained the same way ?: does.
Admittedly not the best way to do this, but you can use the error suppressor in php like this:
$value = #$settings['setting13'];
This will quitely set$value to NULL if $settings['setting13'] is not set and not report the undefined variable notice.
As for objects, you should just calling for attributes that are not defined in class.
function valueFromGetOrPost($parameter)
{
$shvalue=NULL;
if ($_GET[$parameter])
{
$shvalue=$_GET[$parameter];
}
else if (isset($_POST[$parameter]))
{
$shvalue=$_POST[$parameter];
}
return $shvalue;
}
say by using filter_input
Basically the code check whether a parameter exist either in GET or POST. And then return the value of the parameter.
I think this must be so common it should be there by some built in function already
Use $_REQUEST (documentation).
An associative array that by default contains the contents of $_GET, $_POST and $_COOKIE.
So your code will look like:
function valueFromGetOrPost($parameter)
{
$shvalue=NULL;
if ($_REQUEST[$parameter])
{
$shvalue=$_REQUEST[$parameter];
}
return $shvalue;
}
You could use fast return to simplify it a bit, i.e
function valueFromGetOrPost($parameter){
$shvalue=NULL;
if (isset($_GET[$parameter])){
return $_GET[$parameter];
} else if (isset($_POST[$parameter])){
return $_POST[$parameter];
}
}
Or, you could use a ternary operator, since you're returning NULL anyway if neither are set:
function valueFromGetOrPost($parameter){
$shvalue = (isset($_GET[$parameter]) ? $_GET[$parameter] : $_POST[$parameter]);
return $shvalue;
}
Here is my proposal, using the filter_input() function:
function valueFromGetOrPost($parameter)
{
$value = ($getValue = filter_input(INPUT_GET, $parameter))
? $getValue
: filter_input(INPUT_POST, $parameter);
return ($value) ? $value : NULL;
}
I get a lot of array from some API and I need to check weither some variable exist or not.
I have a lot of block that look like that :
if (isset($var))
$varToSet = $var;
else
$varToSet = '';
So I've decided to make a function for that. I came with that:
function setVar($var)
{
if (isset($var))
return $var;
return '';
}
But as I would expected I got the error Undefined variable, I figured out I needed to passe the argument by reference so I would get the following prototype :
function setVar(&$var);
And It was working perfectly until now, here's an example of my problem :
// works fine
$var = "test";
$varToSet = setVar($var);
// works fine
$var = "test";
$varToSet = setVar($doesNotExist);
// works fine
$var = "test";
$varToSet = setVar($doesNotExist['index']);
// doesn't work
$var = "test";
$varToSet = setVar($var['index']);
In the last example I get Illegal string offset 'index and Only variables can be passed by reference PHP errors.
I know why I got those errors, I just can't figure out how overcome this problem.
i mainly use property_exists to check if a value exist on a json object.
function getFromJson($json,$value)
{
if (property_exists(json, $value)) {
return $json->$value;
}
return null;
}
function get($var,$value = null)
{
if (is_null($value)) {
return $var;
}
if (is_object($var) && property_exists($var, $value)) {
return $json->$value;
}
if (is_array($var)) {
return $var[$value];
}
return $var;
}
The error gives you the answer. Your variable is a string. But you are trying to access an array element by using brackets [ ].
And the second is caused by invalid refference.
This is passing by reference:
$variable = 'test';
myFunction($variable);
and this is passing by value:
myFunction('test');
That's a big difference!
You can't call string as array
$varToSet = setVar($var['index']);
You can change the line to:
echo $var['index'];
and you will still have the same error/warning.
If you want to validate if array variable is set use
isset($var['index'])
but it returns value, not a refference
I'm writing quite often this line of code:
$myParam = isset($params['myParam']) ? $params['myParam'] : 'defaultValue';
Typically, it makes the line very long for nested arrays.
Can I make it shorter?
function getOr(&$var, $default) {
if (isset($var)) {
return $var;
} else {
return $default;
}
}
$myParam = getOr($params['myParam'], 'defaultValue');
Be sure to pass the variable by reference though, otherwise the code will produce a E_NOTICE. Also the use of if/else instead of a ternary operator is intentional here, so the zval can be shared if you are using PHP < 5.4.0RC1.
PHP 7 will contain ?? operator that does exactly that.
See https://wiki.php.net/rfc/isset_ternary, example:
// Fetches the request parameter user and results in 'nobody' if it doesn't exist
$username = $_GET['user'] ?? 'nobody';
// equivalent to: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
Yes, by making a proxy function, but is it really worth it?
Also, isset is a language construct, so wrapping it in a proxy function will degrade performance, although the degradation will likely be less than trivial (not even really worth mentioning.)
This is what I use:
function getindex($arr, $index, $default = null) {
return isset($arr[$index]) ? $arr[$index] : $default;
}
As of PHP 5.3 you can use:
$myParam = $params['myParam'] ?: 'defaultValue';
Note, however, that $params['myParam'] and isset($params['myParam']) are not 100% the same.
I'm using little this little magic class which works as variable
class Post() {
private $post = Array();
public function __construct() {
$this->post = $_POST;
}
public function __get($name) {
return #$this->post[$name];
}
public function __set($name, $value) {
return $this->post[$name] = $value;
}
public function __call($function, $params) {
if(isset($this->post[$function])) {
return $this->post[$function];
} else {
$this->post[$function] = $params[0];
return $params[0];
}
}
}
$post = new Post();
then in document you can use it easily as any other variable so for example $post->name $post->somelist[2] or with default value $post->name("John Doe") and after that you got it returned as well as stored.
I know this doesn't shorten anything up for you but thought I'd just share this, I use this alot in my applications to make sure something is set and has a value.
function is_blank($var = NULL){
return empty($var) && !is_numeric($var) && !is_bool($var);
}
function chk_var($var = NULL){
return (isset($var) && !is_null($var) && !is_blank($var));
}
Then...
if(chk_var($myvar)){ ... }
No. Unfortunately, you can't. Not in a decent way. You'll at least have to give in on performance.
Update: since PHP7, ?? will do just that. See https://wiki.php.net/rfc/isset_ternary
You if you have to do it often, you are probably missing the point.
In fact, variables should be defined before use.
So, there oughtn't be a case when you have your param undefined.
Just create a default params file, and initialize every your variable.
$params['myParam'] = 'defaultValue';
later it can be changed under some circunstances but it never be undefined.
Got the idea?
I find in my PHP pages I end up with lines and lines of code that look like this:
$my_id = isset($_REQUEST['my_id']) ? $_REQUEST['my_id'] : '';
$another_var = isset($_REQUEST['another_var']) ? $_REQUEST['another_var'] : 42;
...
Is there a better, more concise, or more readable way to check this array and assign them to a local variable if they exist or apply a default if they don't?
EDIT: I don't want to use register_globals() - I'd still have the isset problem anyway.
How about wrapping it in a function?
<?php
function getPost($name, $default = null) {
return isset($_POST[$name]) ? $_POST[$name] : $default;
}
a better method might be to create a singleton/static class to abstract away the details of checking the request data.
Something like:
class Request {
private $defaults = array();
private static $_instance = false;
function getInstance () {
if (!self::$_instance) {
$c = __CLASS__;
self::$_instance = new $c;
}
return self::$_instance;
}
function setDefaults($defaults) {
$this->defaults = $defaults;
}
public function __get($field) {
if (isset($_REQUEST[$field]) && !empty($_REQUEST[$field])) {
return $_REQUEST['field'];
} elseif (isset($this->defaults[$field])) {
return $this->defaults[$field];
} else {
return ''; # define a default value here.
}
}
}
you can then do:
# get an instance of the request
$request = Request::getInstance();
# pass in defaults.
$request->setDefaults(array('name'=>'Please Specify'));
# access properties
echo $request->name;
echo $request->email;
I think this makes your individual scripts loads cleaner and abstracts away the validation etc. Plus loads of scope with this design to extend it/add alternate behaviours, add more complicated default handling etc etc.
First, use $_POST for POSTed variables. $_REQUEST is a mashup of many different incoming variables, not just $_POST and could cause problems.
One solution for your question would be to create a function that handles the isset() logic.
function ForceIncomingValue($Key, $Default) {
if (!isset($_POST[$Key]))
return $Default;
else return $_POST[$Key];
}
first of all, NEVER use the $_REQUEST variable, it'll lead to bugs and other problems during development
function getPOST($key) {
if(isset($_POST[$key])) {
return $_POST[$key];
}
}
note that this code leaves the variable empty when $_POST[$key] was not set
you could also adapt that code to enable you to instead provide you with a (sensible) default when the value could not be loaded.
function getPOST($key, $default = NULL) {
if(isset($_POST[$key])) {
return $_POST[$key];
} else {
return $default;
}
}
Is the set of variables you're expecting known at the time of the script's writing, or do you want to do this for an arbitrary set of values? If the former is true, you could do something like this:
# This array would hold the names of all the variables you're expecting
# and a default value for that variable name
$variableNames = array (...);
foreach ($variableNames as $key => $default) {
if (isset ($_REQUEST[$key])) $$key = $_REQUEST[$key];
else $$key = $default;
}
Basically, this takes advantage of PHP's ability to evaluate variables to create other variables (hence the double-dollar for $$key--this means create a new variable whose name is the value of $key).
I haven't yet come up with a good solution to the latter situation.
PHP's null coalescing operator!
$username = $_GET['user'] ?? 'nobody';
For a lot of variables, with a requirement check, anyone is free to use my expect function.