Least verbose way of defining a default array value - php

Is there a cleaner way to check for array values to prevent PHP notices? Currently I do this:
$email = (isset($_POST['user_email'])) ? $_POST['user_email'] : '';
$first_name = (isset($_POST['user_first_name'])) ? $_POST['user_first_name'] : '';
$last_name = (isset($_POST['user_last_name'])) ? $_POST['user_last_namel'] : '';
$birthday = (isset($_POST['user_last_name'])) ? $_POST['user_last_namel'] : '';
Is there a way to do something like JavaScript where you just provide a default, like this?
user.email = response.email || '';
I don't want to suppress notices, but these ugly checks clutter up my code. I'm on PHP 5.2.6.

You can create a function:
$email = getPost('user_email');
$first_name = getPost('user_first_name');
$last_name = getPost('user_last_name');
$birthday = getPost('user_birthday');
function getPost($key, $default = '')
{
if (isset($_POST[$key])) {
return $_POST[$key];
}
return $default;
}
Putting it in a function also let's you do additional sanitizing more easily, e.g., trim(), if desired.
You can also pass a default value that will be returned:
$flavor = getPost('flavor', 'vanilla'); // if $_POST['flavor'] is not set, 'vanilla' is returned

If you have a set of attributes, then one concise option is array_merge. Note that the defaults go first:
$post = array_merge(
array("email" => "", "first_name" => "", "last_name" => "", "birthday" => ""),
$_POST
);
Then just access them as is:
$email = $post["email"]; // it's assured there is some value
An even more compact way to localize a limited set of variables is extract() in combination with array_intersect_key(). But only in that combination - to prevent importing arbitrary variables:
extract(array_merge($defaults, array_intersect_key(array_filter($_POST), $defaults)));

I have seen at least three ways of doing this.
Adding array with defaults
$options = $_POST + $defaults;
where $options is an associative array having everything $_POST had, but with added keys and values from $defaults (unless there was a value in $_POST for specific key in $defaults, then this specific key/value pair from $defaults is ignored and value for this specific key in $_POST is not replaced).
Merging with array of defaults
As shown by #mario (use array_merge()):
$options = array_merge($defaults, $_POST);
Using helper functions...
...such as Kohana's Arr::get() helper:
/* ... */
public static function get($array, $key, $default = NULL)
{
return isset($array[$key]) ? $array[$key] : $default;
}
/* ... */
which has some advantage of easily replacing default value (which, by default is NULL). It can be used like that:
echo Arr::get($_POST, 'user_email');
or:
echo Arr::get($_POST, 'user_email', 'N/A');

function assure(&$a, $default=null) {
if (!isset($a)) $a=$default;
return $a;
}
$email=assure($_POST['user_email'],'');
$first_name=assure($_POST['user_first_name'],'');

You can use DefaultArray from NSPL:
$post = defaultarray('', $_POST);
$email = $post['user_email'];
$first_name = $post['user_first_name'];
$last_name = $post['user_last_name'];
$birthday = $post['user_birthday'];

Related

Could I automatically get a reference of arguments in a PHP function?

Currently, I am reviewing websites written ten years ago. These websites uses the old MySQL API for PHP. PHP hasn't been upgraded since version 5.3, that's why I need to rewrite each database request from the old API to PDO.
The original coder has create for each table an object that wraps INSERT,SELECT and UPDATE requests.
On tables with a lot of rows, it is very painful to quote for each object each argument of each wrapped request, and there a dozen of sites that I must revise !
So, I think about a way to reduce the time spent on quoting each argument of the function by getting these in a loop and quote each of them in two lines of code in each function...
After viewing PHP manual, it seems that there is no way to get a reference of a function arguments. I can copy or count them, but can't get any reference.
Have you got any ideas or tips that will make this job sucks less ?
Here is an example of what I shouldn't do :
public function insert($titre, $tva, $intra, $remise = 0,
$tx_remise = 0, $frais = 0, $code = 0, $nom = '',
$design = '', $adr = '', $cp = '', $ville = '',
$tel = '', $fax = '', $rcs = '', $marq = '',
$marq_g = '')
{
$ville = htmlspecialchars($ville);
$design = htmlspecialchars($design);
$nom = htmlspecialchars($nom);
$adr = htmlspecialchars($adr);
$marq = htmlspecialchars($marq);
$marq_g = htmlspecialchars($marq_g);
$titre = $this->db->quote($titre);
$tva = $this->db->quote($tva);
$intra = $this->db->quote($intra);
$remise = $this->db->quote($remise);
$tx_remise = $this->db->quote($tx_remise);
$frais = $this->db->quote($frais);
$code = $this->db->quote($code);
$cp = $this->db->quote($cp);
$tel = $this->db->quote($tel);
$fax = $this->db->quote($fax);
$rcs = $this->db->quote($rcs);
And what I approximately want to do :
public function insert(...)
{
foreach($function->argumentsReference as $ref)
$ref = quote($ref)
Of course $function isn't a real object, it is just a way to explain my idea with code.
Thanks.
You can use get_defined_vars to retrieve an associative array of all variables in scope, so as long as you use this at the top of your function then you'll effectively have a named copy of all the function arguments. Note that this is different to using func_get_args, which won't contain any default arguments if not provided in the call.
You can apply some logic to all the arguments (quoting, etc) using something like:
<?php
function foo($a, $b, $c) {
foreach (get_defined_vars() as $key => $value) {
${$key} = $value * 2;
}
echo implode(', ', [$a, $b, $c]);
}
foo(1, 2, 3);
// 2, 4, 6
If you took PDO you need to use PDO::prepare and you get that rid of that problem.
What about this (PHP 5.6 or higher required):
function insert(...$data){
var_dump($data); // This returns an array of all passed arguments.
array_map($data, function($datum){
return htmlspecialchars($datum);
}
// Boom, now all entries in the $data array are "htmlspecialcharsified".
list($titre, $tva, $intra, $remise, $tx_remise, $frais, $code, $nom, $design, $adr, $cp, $ville, $tel, $fax, $rcs, $marq, $marq_g) = $data;
// As long as all parameters are passed in the correct order, you now have the desired variables available.
// Do your magic here
}

Using variable to access multidimensional $_POST

Consider this code:
$var = 'test';
$_POST[$test]; // equals $_POST['test']
How can I access with the same method this variable:
$_POST['test'][0];
$var = 'test[0]'; clearly doesn't work.
EDIT
Let me give a bit more information. I've got a class that builds a form.
An element is added like this:
//$form->set_element(type, name, defaultValue);
$form->set_element('text', 'tools', 'defaultValue');
This results into :
<input type="text" name="tools" value="defaultValue" />
In my class I set the value: if the form is posted, use that value, if not, use the default:
private function set_value( $name, $value='' ) {
if( $_SERVER['REQUEST_METHOD'] == 'POST' )
return $_POST[$name];
else
return $value;
}
When I want to add multiple "tools", I would like to use:
$form->set_element('text', 'tools[0]', 'defaultValue');
$form->set_element('text', 'tools[1]', 'defaultValue');
$form->set_element('text', 'tools[2]', 'defaultValue');
But in the set_value function
that gives $_POST['tools[0]'] instead of $_POST['tools'][0]
Use any number of variables in [] to access what you need:
$test = 'test';
$index = 0;
var_dump($_POST[$test][$index]);
$test = 'test';
$index = 0;
$subkey = 'key'
var_dump($_POST[$test][$index][$subkey]);
And so on.
There's no special function to achieve what you want, so you should write something, for example:
$key = 'test[0]';
$base = strstr($key, '[', true); // returns `test`
$ob_pos = strpos($key, '[');
$cb_pos = strpos($key, ']');
$index = substr($key, $ob_pos + 1, $cb_pos - $ob_pos - 1);
var_dump($arr[$base][$index]);
Edit by LinkinTED
$key = 'test[0]';
$base = $n = substr($name, 0, strpos($key, '[') );
preg_match_all('/\[([^\]]*)\]/', $key, $parts);
var_dump($arr[$base][$parts[1][0]]);
See how when you did $_POST['test'][0]; you just added [0] to the end? As a separate reference.
You have to do that.
$_POST[$test][0];
If you need both parts in variables then you need to use multiple variables, or an array.
$var = Array( "test", "0" );
$_POST[$test[0]][$test[1]];
Each dimension of an array is called by specifying the key or index together with the array variable.
You can reference a 3 dimensional array's element by mentioning the 3 indexes of the array.
$value = $array['index']['index']['index'];
Like,
$billno = $array['customers']['history']['billno'];
You can also use variables which has the index values that can be used while specifying the array index.
$var1 = 'customers';
$var2 = 'history';
$var3 = 'billno';
$billno = $array[$var1][$var2][$var3];

PHP - Adding variables to an associative array with the variable names as keys

This is my first post so I'm sorry for any mistakes that I may not be aware of.
I've been fidddling with forms and POST for the past days now and I have a curious question on a certain situation.
I have this code in my basic web form. I declared some variables as shown below.
<?php
if (isset($_POST['submit'])) {
// Form submitted
$username = isset($_POST['username'])? $_POST['username'] : "";
$password = isset($_POST['password'])? $_POST['password'] : "";
$email = isset($_POST['email']) ? $_POST['email'] : "";
$country = isset($_POST['country']) ? $_POST['country'] : "";
}
?>
I wanted to create an array form_data with these variables as its elements, so I inserted the following:
<?php
$form_data = array();
$form_data['username'] = $username;
$form_data['password'] = $password;
$form_data['email'] = $email;
$form_data['country'] = $country;
print_r($form_data);
?>
My question is that is there any method in PHP that I don't know of in where I can get the same result? The variable name will be assigned as a key in the array and I prefer not to type in the keys' names manually like on that bit of code above.
So in short, if I have a variable named $number, I want to add its value into an array with 'number'(the variable name) as its key. Is there a method that does this automatically?
I hope I've made this question clear enough.
You could use compact:
$form_data = compact('username', 'password', 'email', 'country');
As long as you have the variables $username, $password, $email, and $country it will create the array you described.
compact() looks for a variable with that name in the current symbol table and adds it to the output array such that the variable name becomes the key and the contents of the variable become the value for that key.
Or, you could do a whitelist approach:
function array_whitelist($array, $whitelist = array()) {
return array_merge(array_flip($whitelist),
array_intersect_key($array, array_flip($whitelist)));
}
$form_data = array_whitelist($_POST, array('username', 'password', 'email', 'country'));
You can this with a loop. Create an array of variable names that you'll either white list (keep) or black list (remove) to help remove entries like submit from your array:
$blacklist = array('submit');
$form_data = array();
foreach($_POST as $key => $value) {
if(in_array($key, $blacklist))
continue; // skip unwanted entries
$form_data[$key] = $value;
}
Apply any trim() or other formatting during your loop.
Likewise, if you wanted to whitelist the variables you want to keep you can use a similar process:
$whitelist = array('username', 'password', 'email', 'country');
foreach($whitelist as $key) {
if(isset($_POST[$key]) && $_POST[$key] != '')
$form_data[$key] = $_POST[$key];
}
You can use array_keys function
$Keys=array_keys($_POST);
for($i=0;$i<count($Keys);$i++){
$form_data[$Keys[$i]]=$_POST[$Keys[$i]];
}
print_r($form_data);

Why does checking if a variable exists only return a 1 or 0 instead of the value?

I'm setting the following variables at the top of a page:
$pin = $_GET['Pin'];
$action = $_GET['action'];
$bookingref = $_GET['bookingref'];
$phone1 = $_GET['number1'];
$phone2 = $_GET['number2'];
I'm using WAMP to develop my site, and when the page loads, I get an 'Undefined Index' warning for each one.
So I thought I'll put them inside an isset, to check if they exist.
$pin = isset($_GET['Pin']);
$action = isset($_GET['action']);
$bookingref = isset($_GET['bookingref']);
$phone1 = isset($_GET['number1']);
$phone2 = isset($_GET['number2']);
But now when I try to echo the values I just get either a blank space or 1.
How can I echo the value of the variable, and keep the isset check?
Because you're assigning the return value of isset(), which is TRUE or FALSE.
You need to use isset() to check if they exist, then assign the variable if it does.
if(isset($_GET['Pin'])){
$pin = $_GET['Pin']
}
Or a shorthand ternary alternative
$pin = (!isset($_GET['Pin'])) ?: $_GET['Pin'];
isset returns true or false, not the value of the variable. That's its job, that's what it says on the can. The typical idiom is:
$pin = isset($_GET['Pin']) ? $_GET['Pin'] : null;
This is because isset() returns a boolean value (true or false), and not the value of the variable itself. There isn't a built-in way to achieve this, but you could easily mimic this behaviour with a user-defined function:
Taken from my answer here:
function ifsetor(&$value, $default = null) {
return isset($value) ? $value : $default;
}
Now you can simply use it like this:
$pin = ifsetor($_GET['Pin']);
$action = ifsetor($_GET['action']);
$bookingref = ifsetor($_GET['bookingref']);
$phone1 = ifsetor($_GET['number1']);
$phone2 = ifsetor($_GET['number2']);
You can even specify a default value using the second parameter, if you want.
isset return true or false based on variable is set or not. What you need is to do for all variables like below,
$pin = isset($_GET['Pin']) ? $_GET['Pin'] : '';
Definition: Determine if a variable is set and is not NULL
isset() returns a Boolean value that is True or False. It is the echo that displays "1" for true, or "" for false.
Here is I guess is the best method to use isset() is
<?php
$data =$_POST["firstname"];
if(isset($data))
{
trim($data);
echo $data;
}
else
{
$data="";
}
?>

Create an array of function arguments not equal to NULL?

I'll start with explaining what my end goal is as there may be better solutions to it.
I have a function called updateUser which accepts the following parameters:
function updateUser($password = NULL, $name = NULL, $lastname = NULL, $age = NULL, $email = NULL, $relation = NULL)
As you can see I've set them to NULL, so if they aren't passed through the function they become blank. Right? (I hope I got that right)
The problem is that each of those arguments (which are passed) contains info for a user that's going to be sent in to a database, and I only want to include the passed variables in the query as I don't want to set the ones that are not passed to (blank) in the database.
And so I came up with the idea to take all the passed arguments and shove them into an array. And then loop through every item in the array and generate a string like:
$string = "$password, $email";
I guess it would be more flexible if you just pass one array containing the property/value pairs that should be updated:
function updateUser($props) {
$names = array('password', 'name', 'lastname', 'age', 'email', 'relation');
$arr = array();
for ($names as $name) {
if (isset($props[$names])) {
$arr = "$name = '".mysql_real_escape_string($props[$names]).'"';
}
}
if (!empty($arr)) {
$query = "UPDATE … SET ".implode(',', $arr);
}
}
Then you call this function with an array with the properties that should be updated:
updateUser(array('name'=>'User A', 'password'=>'secret'))
Using the function call_user_func() (php.net docs), you can call your database INSERT or UPDATE commands depending on what data is passed to the function.
For example:
function updateUser($password = NULL, $name = NULL, $lastname = NULL,
$age = NULL, $email = NULL, $relation = NULL)
{
$array = array();
// Create an array with indices of passed parameters:
if($password !== NULL) // !== to check for NULL and not empty string.
$array["password"] = $password;
if($name !== NULL)
$array["name"] = $name;
// etc...
call_user_func("addToDb", $array);
}
function addToDb($detailsArray)
{
foreach($detailsArray as $detail)
{
// Add $detail's key with $detail's value to database.
}
}
Gets all arguments and filter variables away which are not a string.
$arguments = func_get_args();
array_filter($arguments, 'is_string');
//$arguments will be an array with numeric indices
I think the problem is that you might not call the function correctly. When you do it like this:
updateUser('pass', 'user', '', '', 'user#example.com');
than the values of $lastname and $age will not be null, but an empty string. But if you call it like this:
updateUser('pass', 'user', null, null, 'user#example.com');
they will remain null.

Categories