Automatically apply isset() each time $arr['KEY'] is called - php

Not sure if this is possible. For example:
$color = isset($product['color']) ? $product['color'] : '';
$size = isset($product['size']) ? $product['size'] : '';
$qty = isset($product['qty']) ? $product['qty'] : '';
***
***
I use isset() pretty much everywhere I need to get a value from array that I am not sure if its set. I am using my own custom framwork so I was wondering if I can add some kind of way to check automatically if its set or not.
So I want something like this:
//if its not set, do not throw warning message just return blank
$color = $product['color'];
$size = $product['size'];
$qty = $product['qty'];
Basically similar to what PHP magic function __isset does for the class but I need it for any array that is not a class.
I added a function to my BaseController that is used in every controller but it is still an extra function call:
$color = $this->isSet($product, 'color', '');
$size = $this->isSet($product, 'size', '');
$qty = $this->isSet($product, 'qty', '');
and function:
public function isSet(array $data, $key, $return) {
return isset($data[$key]) ? $data[$key] : $return;
}
My question is, is there a better way of doing this without functions?

$color = #$product['color'];
$size = #$product['size'];
$qty = #$product['qty'];

Related

Although I use isset, I get an undefined index error

I know it asks too many time. But the isset function is not solve my problem.
$get = (isset($this->settings[$set['id']])) ? $this->settings[$set['id']] : '';
Notice: Undefined index: id in \public_html\settings.php on line 419
Try to check if the variable is set before using it as an argument.
$get = isset( $set['id']) ? $this->settings[$set['id']] : '';
Maybe, $set['id'] must check, like this:
$set_ = isset($set['id']) ? $set['id'] : '';
$value = isset($this->settings[$set_]) ? $this->settings[$set['id']] : '';
I would simply add it to the isset call
$get = isset( $set['id'],$this->settings[$set['id']]) ? $this->settings[$set['id']] : '';
You can use multiple arguments in isset. This is roughly equivalent to doing this:
$get = isset($set['id']) && isset($this->settings[$set['id']]) ? $this->settings[$set['id']] : '';
This can be easily tested with this code:
$array = ['foo' => 'bar'];
$set = []; //not set
#$set = ['id' => 'foo']; //uncomment to test if set
#using [] to add an element to a string not an array
$get = isset($set['id'],$array[$set['id']]) ? $array[$set['id']] : '';
echo $get;
When $set = ['id' => 'foo'] the output is bar if you leave that commented then the output is an empty string.
Sandbox

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
}

$_POST better writing quality

I have this code :
if(isset($_POST['prenom2'])){
$t['prenom2'] = $_POST['prenom2'];
}else{
$t['prenom2'] = '';
}
if(isset($_POST['nom2'])){
$t['nom2'] = $_POST['nom2'];
}else{
$t['nom2'] = '';
}
if(isset($_POST['prenom3'])){
$t['prenom3'] = $_POST['prenom3'];
}else{
$t['prenom3'] = '';
}
etc (there are 5 or 6 fields I need to test).
There must be a better way of doing this, like if a given index of POST isn't set, that index is...
Thanks
You can use foreach.
$indexes = array('prenom2', 'nom2', ...);
$t = array();
foreach ($indexes as $i) {
$t[$i] = isset($_POST[$i]) ? $_POST[$i] : '';
}
print_r($t);
If you don't want to use if..else.. condition then you can use ternary : operator as
$t['prenom2'] = (isset($_POST['prenom2'])) ? $_POST['prenom2'] : '';
$t['nom2'] = (isset($_POST['nom2'])) ? $_POST['nom2'] : '';
Basically the same as the answer from Matei but moved in a function to reduce duplicate code.
Parameter $t is your final array and $key is a string representing the array index. The final $t array is also returned so there is no need for passing a reference.
function setT($t, $key)
{
$t[$key] = isset($_POST[$key]) ? $_POST[$key] : '';
return $t;
}
$t = setT($t, 'prenom1');
$t = setT($t, 'prenom2');
$t = setT($t, 'prenom3');
Based on your real problem, you may choose one of these:
for($i=1; $i<6; $i++){
$t['prenom'.$i] = (isset($_POST['prenom'.$i])) ? $_POST['prenom'.$i] : '';
$t['nom'.$i] = (isset($_POST['nom'.$i])) ? $_POST['nom'.$i] : '';
}
or
$indexes = array('prenom2'=>'', 'nom2'=>'', ...);
$t = array_merge($indexes,$_POST);

methods of declaring multiple variables

I have the following blocks of code:
$ship = $this->get_address($this->dealer_num);
$bill = $this->get_address($this->bill_to_num);
$this->ship_name = $ship['CMNAME'];
$this->ship_address1 = $ship['CMLNE1'];
$this->ship_address2 = $ship['CMLNE2']!='' ? $ship['CMLNE2'] : NULL;
$this->ship_address3 = $ship['CMLNE2']!='' ? $ship['CMLNE3'] : NULL;
$this->ship_city = $ship['CMCITY'];
$this->ship_state = $ship['CMST'];
$this->ship_zip = $ship['CMZIP'];
$this->ship_country = $ship['CMCTRY'];
$this->bill_name = $bill['CMNAME'];
$this->bill_address1 = $bill['CMLNE1'];
$this->bill_address2 = $bill['CMLNE2']!='' ? $bill['CMLNE2'] : NULL;
$this->bill_address3 = $bill['CMLNE3']!='' ? $bill['CMLNE3'] : NULL;
$this->bill_city = $bill['CMCITY'];
$this->bill_state = $bill['CMST'];
$this->bill_zip = $bill['CMZIP'];
$this->bill_country = $bill['CMCTRY'];
Here is the definition of get_address:
private function get_address($key) {
$result = db_query('SELECT CMNAME, CMLNE1, CMLNE2,
CMLNE3, CMCITY, CMST, CMZIP, CMCTRY
FROM myTable
WHERE C1STKY = :key;',
array(':key' => $key));
$info = $result->fetch(PDO::FETCH_ASSOC);
return $info;
}
What are my alternatives for declaring these variables? I hate the big long lists of just variable declarations. Is there a more elegant way to declare these?
The way I ultimately fixed this problem was changing my class definition. Rather than having class properties for each address component, I simply changed my class definition to store the address as an associative array. It felt much cleaner that way.
Thus, the above code became
$this->shipping_address = $this->get_address($this->dealer_num);
$this->billing_address = $this->get_address($this->bill_to_num);

Least verbose way of defining a default array value

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'];

Categories