PHP Skip Function Variables When It Doesn't Exist - php

I have this code :
public function changeProfile ($first_name, $last_name, $email, $phone, $password,
$bank_name, $bank_account_number, $bank_account_name,
$gender, $birthday, $address, $area, $default_type) {
$this->connect();
$data = array ('first_name' => $this->escapeString($first_name),
'last_name' => $this->escapeString($last_name),
'email' => $this->escapeString($email),
'phone' => $this->escapeString($phone),
'password' => $this->escapeString($password),
'bank_name' => $this->escapeString($bank_name),
'bank_account_number' => $this->escapeString($bank_account_number),
'bank_account_name' => $this->escapeString($bank_account_name),
'gender' => $this->escapeString($gender),
'birthday' => $this->escapeString($birthday),
'address' => $this->escapeString($address),
'area' => $this->escapeString($area),
'default_type' => $this->escapeString($default_type));
$this->update('user', $data, 'email = "'.$email.'" AND phone = "'.$phone.'"');
$res = $this->getResult();
}
Now, I have a problem like this :
I want to 'skip' some variables on the function, for example $birthday and $gender, so that it won't be processed on SQL UPDATE and let the current data as it is.
I mean, if $birthday and $gender data doesn't exist, then don't update existing data on the table. because when I tried to use NULL as variables on the function, my data replaced with empty data.
how to manage this situation without having multiple if to check each variables?
thank you

If you have the option, you should replace your function's argument list with an array of arguments, for example:
public function changeProfile($variables)
{
$this->connect();
$data = array();
foreach ($variables as $key => $value) {
$data[$key] = $this->escapeString($value);
}
// Validation?
if (!isset($data['email'], $data['phone'])) {
die('Required fields missing.');
}
$this->update('user', $data, 'email = "' . $data['email'] . '" AND phone = "' . $data['phone'] . '"');
$res = $this->getResult();
}
This assumes that the SQL query is static. You could also add some more fields to it if you needed to.
You'd then call it like this:
$test->changeProfileUpdated([
'first_name' => 'john',
'last_name' => 'doe',
'email' => 'example#example.com',
'phone' => 12345,
'password' => 'password1',
'bank_name' => 'ANZ',
'bank_account_number' => '123-456',
'bank_account_name' => 'J DOE',
'gender' => 'M',
'birthday' => '1/2/13',
'address' => '12 Fake St',
'area' => 'Area 51',
'default_type' => 'Some default'
]);
Here's a demo comparing your code, this example and a validation failure.

If you cannot change the method signature to take an array instead you can naturally check each value with isset() or empty() depending on your data needs like:
if (!empty($gender) {
$data['gender'] => $this->escapeString(escapeString);
}
However this is tedious. A better way would be to take an array as an input and then have an array of valid and or required keys. Something like this:
class MyClass
{
private $valid_keys = [
"first_name", "last_name", "email", "phone", "password",
"bank_name", "bank_account_number", "bank_account_name",
"gender", "birthday", "address", "area", "default_type"
];
public function changeProfile($profile)
{
// Return valid keys
$profile = array_filter($profile, function ($key) {
return in_array($key, self::$valid_keys);
} , ARRAY_FILTER_USE_KEY);
// Escape values
$profile = array_map(function ($value) {
// .. your escape function
}, $profile);
// Do your stuff
$this->update('user', $profile, 'email = "'. $profile['email'].'" AND phone = "'.$profile['phone'].'"');
$res = $this->getResult();
}
}
That way you'll only set valid data and you have a way of escaping it generically.
Oh yeah and of course only the values in $profile will get send to your update function.
If you cannot change the method signature you can look into using func_get_args().
public function changeProfile($first_name, $last_name, $email, $phone, $password,
$bank_name, $bank_account_number, $bank_account_name,
$gender, $birthday, $address, $area, $default_type)
{
$args = func_get_args();
$profile = [];
// Important: $valid_keys should be the same as your function parameters and in the same order for this to work. If you want to go further you can look at `ReflectionMethod` to get the names through reflection.
foreach ($args as $index => $value) {
$key = self::$valid_keys[$index];
$profile[$key] = $this->escapeValue($value);
}
// Do your stuff
$this->update('user', $profile, 'email = "'. $profile['email'].'" AND phone = "'.$profile['phone'].'"');
$res = $this->getResult();
}

check if it is null or not then save it in an array as given below
function changeProfile ($first_name, $last_name,$email,$phone) {
$this->connect();
$data=array();
if($first_name!=""){
$data['first_name']= $this->escapeString($first_name);
}
if($last_name!=""){
$data['last_name']=$this->escapeString($last_name);
}
if($email!=""){
$data['email']=$this->escapeString($email);
}
if($phone!=""){
$data['phone']=$this->escapeString($phone);
}
$this->update('user', $data, 'email = "'.$email.'" AND phone = "'.$phone.'"');
$res = $this->getResult();
}

Related

How to insert a values into different table in a single php page?

I am inserting a record on my table after inserting to another table. This my sample code:
if(isset($_POST['submit'])){
$database = new Database();
$db = $database->getConnection();
$employee = new Employee($db);
if(!empty($first_name) && !empty($family_name) && !empty($first_name_arabic) && !empty($family_name_arabic)){
$emp_number = isset($_POST['emp_number']) && !empty($_POST['emp_number']) ? $_POST['emp_number'] : $employee->generateEmployeeNumber();
$fields = [
'reference' => $reference,
'emp_number' => $emp_number,
'first_name' => $first_name,
'middle_name' => $middle_name,
'third_name' => $third_name,
'family_name' => $family_name,
'nationality' => $nationality,
];
$employee->createOrUpdate($fields, '');
$result = $employee->selectOne('Reference', $reference);
if(!empty($_POST['passport_number']) && !empty($_POST['passport_place_issue']) && !empty($_POST['passport_date_issue']) && !empty($_POST['passport_date_expiry']) && !empty($result['id'])) {
$passport = new Passport($db);
$passport_fields = [
'passport_number' => $_POST['passport_number'],
'place_issue' => $_POST['passport_place_issue'],
'date_issue' => date_format(date_create($_POST['passport_date_issue']), 'Y-m-d'),
'date_expiry' => date_format(date_create($_POST['passport_date_expiry']), 'Y-m-d'),
'reference' => $result['reference'] ,
'employee_id' => $result['id'],
'status' => 'Active',
];
$passport->createOrUpdate($passport_fields, '');
}
}
}
but my problem is my insertion for passport table is not doing anything and no error is being return to me. As for the creatOrUpdate this is how i did:
function createOrUpdate($fields, $id){
if(is_null($id) || empty($id)){
$implodeColumns = implode(', ', array_keys($fields));
$implodePlaceholder = implode(", :", array_keys($fields));
$sql = "INSERT INTO " . $this->table_name. "($implodeColumns) VALUES(:".$implodePlaceholder.")";
echo "SQL ".$sql;
$stmt = $this->conn->prepare($sql);
foreach ($fields as $key => $value) {
$stmt->bindValue(":".$key,$value);
}
$stmt->execute();
}else{}
}
I don't know if creating a method with a same name is affecting the code, but createOeUpdate method for employee is from employee.php where createOrUpdate mehod for passport is from passport.php. Only employee is being saved in my database.
Any help is much appreciated
If the names are the same from different files you need to use namespaces like:
namespace name_of_your_main_file;
// Maybe need to add full path
// if it's not in the same folder.
use employee;
use passport;
// And use it with same names as:
employee::createOrUpdate(

Turn a array into a variable for send in PHPMailer

Im trying to turn a array that haves another array from a SQL select into a unique variable to send it for users by PHPMailer, I tried to place the array on variable of PHPMailer so didnt works, thats why Im trying this way that looks a little bit difficult
public static function getUsersByEmail($email) {
$sql = DB::prepare(
"SELECT username FROM users WHERE email=:email ORDER BY id LIMIT 10"
);
$sql->bindParam('email', $email);
$sql->execute();
$accounts = $sql->fetchAll(PDO::FETCH_ASSOC);
return $accounts; // its array
}
public function recoverUsername($email) {
if (User::emailHasAccounts($email) == true) {
$accounts = [User::getUsersByEmail($email)];
$str = implode(",", $accounts); // imploding array
$mail = new Mail([
'email' => $email,
'subject' => SITENAME,
'template' => 'accountslist',
'variables' => json_encode([
'email' => $email,
'accountList' => $str,
'date' => date('d/m/y h:i')
]),
'time' => time(),
'next_attemp' => time(),
'attemps' => 0,
'status' => 0
]);
// $mail->dbInsert();
return true;
} else {
echo "erro";
return false;
}
}
Solution (for PHP 5.5 <)
$accounts = getAccounts();
$rr = array_column($accounts, 'username');
$array = implode(',', $accounts);
$getaccounts = array_map(function ($accounts) {
return $accounts['username'];
}, $accounts);
$var = implode('<br>', $getaccounts);

How to format array data in more cleaner way?

I have this method:
private function formatCliendCardData($data) {
$formatedData = array();
$formatedData['first_name'] = trim($data['name']);
$formatedData['last_name'] = trim($data['surname']);
$formatedData['date_of_birth'] = $data['birth_year'] . '-' . sprintf("%02d", $data['birth_month_id']) . '-' . sprintf("%02d", $data['birth_day']); //[yyyy-mm-dd]
$formatedData['sex'] = ($data['sex_id'] == 's1'? 'm' : 'f');
$formatedData['county'] = 'Latvija'; //#TODO get real data
$formatedData['post_index'] = (int) preg_replace( '/[^0-9]/', '', $data['post_index']);
$formatedData['city'] = trim($data['city']);
$formatedData['street'] = trim($data['street']);
$formatedData['house_nr'] = trim($data['house_nr']);
$formatedData['phone'] = trim($data['phone']);
$formatedData['email'] = trim($data['email']);
return $formatedData;
}
I run in this problem from time to time. I have big method that just reformats data and returns it. It looks ugly. There is few other aproaches Im aware -- just make foreach loop, but there are exeptions, so i need make 'ifs' anyway. What is better way to reformat such data in your opinon?
I aggree with helloei,
create a class to handle all the formating and validation in the setter.
class Person
{
public function setName($name)
{
$this->name = trim($name);
}
...
}
and then create the object in your function:
private function formatCliendCardData($data) {
$person = new Person();
$person->setName($data['name`])
...
if you have highly custom condition to reformat some datas i think you don't have any other solution that apply this condition manually with some if/else or other custom loop.
if else, you have some unified condition to reformat you can aggregate this and apply in batch at your datas. In other word for my opinion the only other solution are: generalize conditions of your reformatting operations and apply this at your data.
this is Object Oriented approach
IMHO In those cases you have to reduce and clean your code. Often I use an helper function that allows me to split data and formatting rules.
// helper function (OUTSITE YOUR CLASS)
function waterfall($input=NULL,$fns=array()){
$input = array_reduce($fns, function($result, $fn) {
return $fn($result);
}, $input);
return $input;
}
// your formatting rules
$rules = array(
'first_name' => array('trim'),
'last_name' => array('trim'),
'date_of_birth' => array(
'f0' => function($x){
return sprintf("%s-%02d-%02d",
$x['birth_year'],
$x['birth_month_id'],
$x['birth_day']
);
},
'trim'
),
'sex' => array(
'f0' => function($x){
if($x['sex_id'] == 's1'){
return 'm';
}else{
return 'f';
}
}
),
'post_index' => array(
'f0' => function($x){
return (int) preg_replace('/[^0-9]/', NULL, $x);
},
'trim'
),
'city' => array('trim'),
'email' => array('strtolower','trim')
);
// your data
$data = array(
'first_name' => ' Andrea',
'last_name' => 'Ganduglia ',
'date_of_birth' => array(
'birth_year' => '1899',
'birth_month_id' => 5,
'birth_day' => 7
),
'post_index' => 'IT12100',
'city' => 'Rome',
'email' => 'USER#DOMAIN.tld '
);
// put all together
$formatedData = array();
foreach($data as $k => $v){
$formatedData[$k] = waterfall($v,$rules[$k]);
}
// results
print_r($formatedData);
/*
Array
(
[first_name] => Andrea
[last_name] => Ganduglia
[date_of_birth] => 1899-05-07
[post_index] => 12100
[city] => Rome
[email] => user#domain.tld
)
*/

Doctrine Repository accept array for getAll

In a repository, I need a custom getALL query which checks for items based on an array of data. e.g. I need to be able to send $params = [ 'type' => [ 'type1', 'type2' ], 'username' => $username ] but I can currently only send one parameter such as: $params = ['type' => 'type1', 'username' => $username].
What would be the best way of adding acceptance of an array (like the one above) to this getAll query?:
public function getAllQuery($params = [])
{
$query = $this->createQueryBuilder('c');
if(count($params))
{
foreach($params as $param => $value)
{
//todo need to make it accept an array of parameters
if(in_array($param, $this->getClassMetadata()->getFieldNames()) && $param != 'deleted')
{
$query
->andWhere(sprintf('c.%1$s LIKE :%1$s', $param))
->setParameter($param, sprintf('%%%s%%', $value));
}
/*code already exists here for checking other parameters
outside of 'type' (e.g. 'username') */
}
}
return $query->getQuery();
}
I am not able to comment so I will answer without to be sur that I've understand the question. Are you waiting something like this ? In this case it's more a PHP problem than Doctrine.
The results of the past code : here.
$params = array( 'type' => array( 'type1', 'type2' ), 'username' => 'flavien');
$requiredFields = array('type');
if(count($params))
{
foreach($params as $param => $value)
{
if(in_array($param, $requiredFields) && $param != 'deleted')
{
if(is_array($value))
{
echo "My param: {$param}" . PHP_EOL;
for($i=0; $i < count($value); $i++) {
echo $value[$i] . PHP_EOL;
}
}
}
}
}

UPDATE an array using PDO

I'm creating a multi-step form for my users. They will be allowed to update any or all the fields. So, I need to send the values, check if they are set and if so, run an UPDATE. Here is what I have so far:
public function updateUser($firstName, $lastName, $streetAddress, $city, $state, $zip, $emailAddress, $industry, $password, $public = 1,
$phone1, $phone2, $website,){
$updates = array(
'firstName' => $firstName,
'lastName' => $lastName,
'streetAddress' => $streetAddress,
'city' => $city,
'state' => $state,
'zip' => $zip,
'emailAddress' => $emailAddress,
'industry' => $industry,
'password' => $password,
'public' => $public,
'phone1' => $phone1,
'phone2' => $phone2,
'website' => $website,
);
Here is my PDO (well, the beginning attempt)
$sth = $this->dbh->prepare("UPDATE user SET firstName = "); //<---Stuck here
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
return $result;
Basically, how can I create the UPDATE statement so it only updates the items in the array that are not NULL?
I thought about running a foreach loop like this:
foreach($updates as $key => $value) {
if($value == NULL) {
unset($updates[$key]);
}
}
but how would I write the prepare statement if I'm unsure of the values?
If I'm going about this completely wrong, please point me in the right direction. Thanks.
First of all, use array_filter to remove all NULL values:
$updates = array_filter($updates, function ($value) {
return null !== $value;
});
Secondly, bind parameters, that makes your live a lot easier:
$query = 'UPDATE table SET';
$values = array();
foreach ($updates as $name => $value) {
$query .= ' '.$name.' = :'.$name.','; // the :$name part is the placeholder, e.g. :zip
$values[':'.$name] = $value; // save the placeholder
}
$query = substr($query, 0, -1).';'; // remove last , and add a ;
$sth = $this->dbh->prepare($query);
$sth->execute($values); // bind placeholder array to the query and execute everything
// ... do something nice :)
The below can be optimized:
$i = 0; $query = array();
foreach($updates as $key => $value) {
if ($value != NULL) {
$query[] = "{$key} = :param_{$i}";
$i++;
}
}
if (! empty($query)) {
$finalQuery = implode(",", $query);
$sth = $this->dbh->prepare('UPDATE user SET ' . $finalQuery);
$i = 0;
foreach($updates as $key => $value) {
if ($value != NULL) {
$sth->bindParam(':param_'.$i, $value, PDO::PARAM_STR);
$i++;
}
}
}

Categories