I sometimes have variables that might not be set and I would like to use a default parameter instead. Like here:
if ($p == "a") doSomething();
If $p is not defined PHP throws Notice: Undefined variable. To avoid this I often I used this construct in such a case:
$p = (isset($p) ? $p : "");
But that is ugly if you have to use it a lot. So I wrote a function for it:
function getIfSet(&$value, $default = '')
{
return isset($value) ? $value : $default;
}
// Example
if (getIfSet($p) == "a") doSomething();
I wonder if there is a PHP function for this or how you solve this.
Just a little improvement, prefer passing null value to $default, passing empty string can be confusing, cause correct value can be empty string.
function getIfSet(&$value, $default = null)
{
return isset($value) ? $value : $default;
}
$p = getIfSet($p);
isset() is about as clean as it gets. Although I must admit that I'm not too fond of defaulting to an empty string, simply because a variable could be an empty string, yet still "be set". I think that a default of bool false or null would be truer to the behavior of isset:
function getIfSet(&$value, $default = false)
{
return isset($value) ? $value : $default;
}
$p = getIfSet($p);
if($p !== false){
//insert or whatever
}
else{
header('Location: error.php');
exit;
}
Depending on what kind of values you're checking (maybe REQUEST data?), consider using classes. They are fun and they could be available anywhere.
Assuming you're checking POST data (if you don't, well, take this as an idea), create a class that checks this array:
class Post
{
public function __get($index)
{
if (isset($_POST[$index]))
return $_POST[$index];
else
return null;
}
}
As simple as that. You know that __get() will trigger when you try to access a non-existant property. In this case, if the property (actually, the index in the $_POST array) doesn't exist, null will be returned and no errors are generated.
Now you can do:
$params = new Post();
$foo = $params->name ?: ''; // of course this doesn't make much sense.
if (!$params->password) ...
// instead of
if (isset($_POST['password'])) ...
// you'll still have to use isset for cases like:
if (isset($_POST['user']['password']) ...
if (isset($params->user['password'])) ...
// but still looks neater I'd say
A problem you'll find soon is that $params isn't a super global variable, while $_POST are. How to solve this? Create it in the constructor of your controller class and use Dependency Injection for all other objects your are using.
I tried to make renocor's answer more clean and OOP when I came up with this solution:
class NiceArray implements ArrayAccess {
protected $array;
public function __construct(&$array) {
$this->array =& $array;
}
public function offsetExists($offset) {
return true;
}
public function offsetGet($offset) {
if (isset($this->array[$offset]))
{
return $this->array[$offset];
}
else
{
return null;
}
}
public function offsetSet($offset, $value) {
$this->array[$offset] = $value;
}
public function offsetUnset($offset) {
unset($this->array[$offset]);
}
}
Usage:
$get = new NiceArray($_GET);
if ($get['p'] == "a") doSomething();
I know the class is kind of big but this way you still have an array and you can easily use it for every array you want. You do not need to change any code you may had before. You can still access and change the data. It will even change the original array.
Related
in the flat php I can just writing this line like that
if(isset($_POST['MoveString'])){
//code here
}
but in symfony when I write my code like that
if(isset($request->get('MoveString'))){
//my code here
}
I get this error
Compile Error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead)
so what's the wrong aren't they the same result ?
according to this part of isset documentation :
Warning
isset() only works with variables as passing anything else will result
in a parse error.
and where is the result of expression in your code ?
to figure out this, take a quick look at the implementation of Request\get method :
public function get($key, $default = null)
{
if ($this !== $result = $this->attributes->get($key, $this)) {
return $result;
}
if ($this !== $result = $this->query->get($key, $this)) {
return $result;
}
if ($this !== $result = $this->request->get($key, $this)) {
return $result;
}
return $default;
}
and as you can see, for example from the ParameterBag object which is called via $this->attributes property, and you can check the other properties [ query, request ]'s objects too.
$result is returning a result of an expression
public function get($key, $default = null)
{
return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default;
}
so you simply needs to -as the error explains- to use your statement as follows:
if($request->get('MoveString') !== null){
//my code here
}
or even simpler :
if($request->get('MoveString')){
//my code here
}
In case you want to know if the parameter exists, even with a null value, you can use the has() method instead of get():
if ($request->has('MoveString')){
//my code here
}
If I do a post, I can get content by doing $payload = json_decode($app->request->getBody());
But I cannot understand how request->getBody works in slim.
First, there's a magic method :
public function __get($name)
{
return $this->container->get($name);
}
This will return a Slim\Http\Request object. That's fine for now.
$this->container is the Slim\Helper\Set, and this is the get function :
public function get($key, $default = null)
{
if ($this->has($key)) {
$isInvokable = is_object($this->data[$this->normalizeKey($key)]) && method_exists($this->data[$this->normalizeKey($key)], '__invoke');
return $isInvokable ? $this->data[$this->normalizeKey($key)]($this) : $this->data[$this->normalizeKey($key)];
}
return $default;
}
$this->data[$this->normalizeKey($key)] is the same as $this->data['request'], which is something of type "Closure" (not sure to understand this).
$isInvokable is true, so this is called :
$this->data[$this->normalizeKey($key)]($this)
What is this line doing ? Why the ($this) (Slim\Helper\Set) at the end ?
Especially, why the next function to be called is this :
public function singleton($key, $value)
{
$this->set($key, function ($c) use ($value) {
static $object;
if (null === $object) {
$object = $value($c);
}
return $object;
});
}
Why singleton($key, $value) ?
It has never been called !
$key is not defined at the start of the function. Also what makes $c a Slim\Helper\Set, and $value a closure ?
And why the execution of only static $object makes the $object goes from unitialized to one of type Slim\Http\Request ?
Disclaimer: I'm not familiar with Slim. I'm just going by what you've posted.
Well, the Set->get() method tests, if the value in the data property array with the key $key can be invoked, and then does it, if true.
So $this->data[$this->normalizeKey($key)]($this) is calling a method with $this given as parameter and then Set->get() returns that method's return value.
A closure is also often called an "anonymous function", which is a new feature as of PHP 5.3. Using an array as variable to call a function is available since PHP 5.4.
It allows you to pass around functions/methods as values, which is arguably the distinctive feature in functional programming.
Function singleton is called before in the initialization.
It is setting all $key to a function.
So, $this->data[$this->normalizeKey($key)]($this) is that function !
I am in need of a PHP function to check that a variable exist or not outside of function. If it does not exist, then assign a default value to it.
The function will be something like: function if_exist($argument, $default = '') where $argument will be any variable outside the function. It can be a variable's variable, and $default will be the default value of the variable if the variable doesn't exist.
Please avoid using global scope in the function, because I heard that it's not good for a site's security.
You can make $argument pass-by-reference:
function if_exist(&$argument, $default="") {
if(!isset($argument)) {
$argument = $default;
return false;
}
return true;
}
DEMO
I don't see why you want a function for this at all.
$a = isset($a) ? $a : "my default string";
Everybody will understand what your code does without resorting to little-known "features" of PHP and having to look at your functions body to see what it does.
Even though it may look like a function call, it's not. isset() is a language construct! That's why it will not raise a Notice.
There are two ways of going at this. You may be looking for the first non-null value or if the actual variable is set or not...
The first use-case is easy... To get the value of the first variable that isn't null, define a function as such:
function coalesce() {
$args = func_get_args();
if(is_array($args))
return null;
foreach($args as $arg) {
if($arg !== null)
return $arg;
}
return null;
}
Using this function is easy. Simply call coalesce() with a number of different arguments and it will always return the first non-null value it encounters.
$myVar = coalesce($myVar, null, 'Hello There', 'World');
echo $myVar; // Hello there
However, if you are looking for a function to check if a variable is defined, and if it isn't define it, then you need to create a function which forces the first argument to be a reference.
function set_default(&$variable, $defaultValue = null) {
if(!isset($variable)) {
$variable = $defaultValue;
return false;
}
return true;
}
Use this:
function setGlobalIfNotSet( $variableName, $defaultValue = false ) {
if ( ! isset( $variableName )) {
global $$variableName;
$$variableName = $defaultValue;
}
}
You can make a function to use isset:
function isset_default($v, $default = '') {
return isset($v) ? $v : $default;
}
Usage:
$v = isset_default($v, 'somedefaultvalue');
Alrighty, I'm getting quite frustrated, namely because I thought I had this issue solved, or had accomplished this successfully before.
Quick preliminary:
PHP 5.3.6.
Error reporting cranked to 11. (-1 actually; future safe, all errors/notices)
I have a class, it aggregates request parameters. For giggles here is a stripped down version:
class My_Request{
private $_data = array();
public function __construct(Array $params, Array $session){
$this->_data['params'] = $params;
$this->_data['session'] = $session;
}
public function &__get($key){
// arrg!
}
}
Anyways, the reason for arrg! is, no matter what I try, I always get an error whenever the $key doesn't exist. I've tried:
// doesn't work
$null = null;
if(isset($this->_data[$key])){ return $this->_data[$key]; }
return $null;
// doesn't work
return $this->_data[$key];
I've been told ternary operators cannot result in a reference, ergo, that of course doesn't work, but we know that from the if condition attempt anyways. What happens, for example:
// params will have foo => bar, and session hello => world
$myRequest = new My_Request(array('foo' => 'bar'), array('hello' => 'world'));
// throws an error - Undefined index: baz
echo $myRequest->params['baz'];
I'm losing my mind here; perhaps I hallucinated a scenario where I achieved this. Is it not possible to (without throwing a notice) successfully do this?
Clarification: Things I've tried
The aforementioned:
// no check, no anything, just try returning : fails
public function &__get($key){
return $this->_data[$key];
}
// null variable to pass back by reference : fails
public function &__get($key){
$null = null;
if(isset($this->_data[$key])){
return $this->_data[$key];
}
return $null;
}
Other attempts:
// can't work - can't return null by reference nor via ternary : fails
public function &__get($key){
return isset($this->_data[$key])
? $this->_data[$key]
: null;
}
echo $myRequest->params['baz'];
The isset check in your __get function will look up "params" from $this->_data and return the array. The notice you get is from outside the class and about a key "baz" in the returned array - which in your example was never actually defined.
I realize this question is stale, but I just stumbled on it via Google while looking for the answer (which I have since found).
class My_Request{
private $_data = array();
public function __construct(Array $params, Array $session){
$this->_data['params'] = $params;
$this->_data['session'] = $session;
}
public function &__get($key){
if (array_key_exists($key, $this->_data)) {
return &$this->_data[$key]; // Note the reference operator
} else {
$value = null; // First assign null to a variable
return $value; // Then return a reference to the variable
}
}
}
$this->_data[$key] is an operation that returns a value, so returning the value will result in an error because it's not a reference. To make it return a reference instead, you have to use the reference: &$this->_data[$key].
Haven't tried this because I avoid __get and __set, but maybe this would work for you:
public function __get($key){
if(!isset($this->_data[$key]))
return false;
return $this->_data[$key];
}
Totally untested, but it looks like it could maybe do the job.
In my PHP class I have
public $a;
public $b;
public $c;
public $d;
and I set there values in the construct.
I am now attempting to write a update function, and i'm trying to check if they are updating, say $a, to be the same as it is.
function update($what, $to) {
if ($to == $this->what) return false;
...
}
$updated = $instance->update($a, "Foobar");
if ($updated) echo "Updated";
else echo "You didn't change the value";
but since I know this line
if ($to == $this->what) return false;
is invalid, i'm seeking a new way to write it.
Ideas?
Thanks in advance
The solution to your dilemma are variable variables. Your update function must assign it like this:
$this->{$what} = $to;
The if-check would be correspondingly:
if ($to == $this->{$what}) return false;
And you cannot actually invoke the update() method with a variable $a. You must give it a variable name as string:
$instance->update("a", "Foobar");
You can do something like:
if ($to == $this->$what) return false;
And call it like this:
update("a", "Foobar");
This uses variable variables ( http://php.net/manual/en/language.variables.variable.php ).
You could also pass by reference:
function update(&$what, $to) {
if ($to == $what) return false;
...
}
And call it like you did in your example.
$this->$what should do the trick, if $what = 'a'
You generally want to avoid doing that though.