PHP: Rewriting switch as class - php

So, I have a switch statement inside a foreach loop that checks the value of a field in the array and uses the value to build a named array and email address variable for each unique value. Question is below example code.
As an example, if the values are foo, bar, and foobar, then the following occurs:
switch($value['value']) {
case 'foo':
if(!isset($foo)){
$foo = array();
}
if(!isset($email_foo)){
$email_foo = convert_to_email($value['value']);
}
array_push($foo, $value);
break;
case 'bar':
if(!isset($bar)){
$bar = array();
}
if(!isset($email_bar)){
$email_bar = convert_to_email($value['value']);
}
array_push($bar, $value);
break;
case 'foobar':
if(!isset($foobar)){
$foobar = array();
}
if(!isset($email_foobar)){
$email_foobar = convert_to_email($value['value']);
}
array_push($foobar, $value);
break;
default:
if(!isset($default)){
$default = array();
}
if(!isset($email_default)){
$email_default = 'this#isemail.com';
}
array_push($default, $value);
}
Resulting in 4 different email addresses:
$email_foo = 'foo#isemail.com';
$email_bar = 'bar#isemail.com';
$email_foobar = 'foobar#isemail.com';
$email_default = 'default#isemail.com';
and 4 different arrays of data:
$foo = array(
0 => array(
'value' => 'F Oo',
'name' => 'Janet',
'age' => 23
),
1 => array(
'value' => 'F Oo',
'name' => 'Doug',
'age' => 42
)
)
$bar = array(
0 => array(
'value' => 'B Ar',
'name' => 'James',
'age' => 23
),
1 => array(
'value' => 'B Ar',
'name' => 'Donald',
'age' => 42
)
)
etc...
So, here is the question:
Is it possible to write a class that can be used to create all of the named arrays and email variables? Sort of something like this:
class Account_Manager_Build
{
public function __construct()
{
if(!isset($this)){
$this = array();
}
if(!isset("email_$this")){
"email_$this" = convert_to_email($this->value['value']);
}
array_push($this, $this->value);
}
}
For testing purposes, here is the function convert_to_email that is used throughout the examples:
function convert_to_email($input){
$returned = strtolower(substr($input, 0, 1)).strtolower(end(str_word_count($input, 2))).'#ismail.com';
return $returned;
}

Actually, you can create dynamically variables using the $$ notation:
$variable = "email_$name";
$$variable = "something";
However I'm not sure of what you're trying to do
What's the point of computing $email_something if it can be easily computed from something?
Why do you create those variables instead of just storing this in an array?

Related

Update Array If Value Found Multidimensional Array

Is there a way to update a part of a multidimensional array if a value is found? For example I have an array $foo with an updated chunck of $foo called $bar. I'd like to merge $bar into $foo when some_id = 123.
Unfortunately I can't change some_id and the some_id key is the same for all arrays. The bar key unfortunately must also stay the same.
$foo = array(
0 => array(
bar => array(
some_id => 123,
a => 1
)
),
1 => array(
bar => array(
some_id => 234,
a => 5
)
)
)
$update_bar = array(
some_id => 123,
a => 10
)
Simpliest way is:
foreach ($foo as $key => $value) {
if ($value['some_id'] == 123) {
$foo[$key] = $updated_bar;
break;
}
}
And if some_id value is really important and unique, it's better to rebuild $foo like:
$foo = array(
// use some_id as key
123 => array(
a => 1
),
234 => array(
a => 5
)
);
// and update without any `foreach`
$foo[123] = array(a => new_val)
Solution 1:
You can use reference variable in the foreach loop that will assign to the looping variable itself.
foreach ($multifoo as &$foo) {
$foo['bar']['a'] = ($update_bar['some_id'] == $foo['bar']['some_id']) ? $update_bar['a'] : $foo['bar']['a'];
}
print_r($multifoo);
Solution 2:
You can use array_map function and return it the changed variable.
$multifoo = array_map(function ($foo) use ($update_bar) {
if ($update_bar['some_id'] == $foo['bar']['some_id']) {
$foo['bar']['a'] = $update_bar['a'];
}
return $foo;
}, $multifoo);
print_r($multifoo);
Demo link: https://3v4l.org/u7uL4

PHP Find a value in a key and get the value of another key in a multi-dimentional array

Might be a newbie question but I've been trying to figure this problem and it's doing my head in.
I have the following array :
[0] => Array
(
[provisionalBookingRoomID] => 1
[totalSpecificRoomCount] => 2
)
[1] => Array
(
[provisionalBookingRoomID] => 2
[totalSpecificRoomCount] => 5
)
I need a php function that searches through the array for the value of 'provisionalBookingRoomID' and returns the value of 'totalSpecificRoomCount'
basically something like the following
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms);
// getProvisionalTotalRoomsCount('1', $arrayOfRooms) should return 2;
Any ideas?
Check this:
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms){
foreach($arrayOfRooms as $key=>$value){
if($value['provisionalBookingRoomID'] == $currentRoom){
return $value['totalSpecificRoomCount'];
}
}
}
For anyone looking for a generic function :
function findValueInArray($array, $searchValue, $searchKey, $requiredKeyValue) {
foreach($array as $key=>$value){
if($value[$searchKey] == $searchValue){
return $value[$requiredKeyValue];
}
}
}
// Usage : findValueInArray($provisionalBookedRoomsArray, '1', 'provisionalBookingRoomID', 'totalSpecificRoomCount');
If you are likely to work with more than one value, you could build a new array with a 1->1 map for those attributes.
<?php
$items = array(
array(
'name' => 'Foo',
'age' => 23
),
array(
'name' => 'Bar',
'age' => 47
)
);
// Php 7
$name_ages = array_column($items, 'name', 'age');
echo $name_ages['Foo']; // Output 23
// Earlier versions:
$name_ages = array();
foreach($items as $value)
{
$name_ages[$value['name']] = $value['age'];
}
echo $name_ages['Foo']; // Output 23
$value = 0;
$array = array(array("provisionalBookingRoomID"=>1,"totalSpecificRoomCount"=>2),array("provisionalBookingRoomID"=>2,"totalSpecificRoomCount"=>5));
array_map(
function($arr) use (&$value) {
if($arr['provisionalBookingRoomID']==1) {
$value = $arr['totalSpecificRoomCount'];
}
},$array
);
echo $value;

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
)
*/

Delete/unset from a global array using a function / method

I have an GLOBAL array that keeps all the configurations, it looks like this:
$_SOME_ARRAY = array(
'some_setting' => array(
'some_value' => '1',
'other' => 'value'
),
'something_else' => 1,
);
How can I delete keys from this array, using some function like:
deleteFromArray('some_setting/other')
I have tried different things, but can't seem to find a way, to delete it without manually calling unset($_SOME_ARRAY['some_setting']['other'])
EDIT
I have tried working on with it. The only solution I see so far, is by "rebuilding" the original array, by looping through each value and verify. The progress:
public static function delete($path) {
global $_EDU_SETUP;
$exploded_path = explode('/', $path);
$newConfig = array();
$delete = false;
foreach($exploded_path as $bit) {
if(!$delete) {
$loop = $_EDU_SETUP;
} else {
$loop = $delete;
}
foreach($loop as $key => $value) {
if($key == $bit) {
echo 'found first: ' . $key . '<br />'; // debugging
if(!$delete) {
$delete = $_EDU_SETUP[$key];
} else {
$delete = $delete[$key];
}
} else {
$newConfig[$key] = $value;
}
}
}
$_EDU_SETUP = $newConfig;
}
The array could look like this:
$array = array(
'a' => array(
'a',
'b',
'c'
),
'b' => array(
'a',
'b',
'c' => array(
'a',
'b',
'c' => array(
'a'
),
),
)
);
And to delete $array['b']['c'] you would write Config::delete('b/c'); - BUT: It deletes whole B. It is only supposed to delete C.
Any ideas?
This what you can do, assuming the array has 2 levels of data.
$_SOME_ARRAY = array(
'some_setting' => array(
'some_value' => '1',
'other' => 'value'
),
'something_else' => 1,
);
function deleteFromArray($param){
global $_SOME_ARRAY ;
$param_values = explode("/",$param);
if(count($param_values) == 2 ){
unset($_SOME_ARRAY[$param_values[0]][$param_values[1]]);
}else{
unset($_SOME_ARRAY[$param_values[0]]);
}
}
deleteFromArray('some_setting/other');
print_r($_SOME_ARRAY);
You can modify the function to add more strict rules by checking if the key exists before doing unset using the function array_key_exists()
how do you like this ?
$_SESSION = $_SOME_ARRAY; // Btw it should be session from beginning...
function deleteFromArray($string)
{
$array = explode("/",$sting);
foreach($array as $arrA)
{
foreach($array as $arrB)
{
unset($_SESSION[$arrA][$arrB]);
}
}
}
now you could delete more than one entry like
deleteFromArray('some_setting/some_value/a_other_value')
but take care of using dim1array names in dim2array...
of corse you could add more foreach or make a recursiv function out of it to get deep in the array
do you want to delete particular array using a unique index(like a primary id)?, i would use a for loop to look for that particular index then delete that array...E.g delete array where the index = 1 , pls check above
foreach ($_SOME_ARRAY as $a => $key)//get all child arrays of '$_SOME_ARRAY '
{
foreach($Key as $b => $key2)//get values of the child arrays
{
if($Key[0] == 1)// if the index at[0] equals 1
{
unset($arr[$a][$b]); //delete that array
}
}
}

PHP - good practice reading POST variables

I am thinking of a good practice to read the client submitted POST data.
For example if I have a post variable that should have the following structure:
array(
[0] => array(
['test'] => array(1, 2, 3),
['test2'] => "string"
),
[1] => array(
['test'] => array(),
['test2'] => "string2"
),
)
Where the indices 'test' and 'test2' should always be present but their values may be empty (array() and "");
The functions that handle the POST data are expecting the correct format, so I have to make sure that the data has not been manipulated.
I could do the following:
$result = array();
if(isset($_POST['myVar']) && is_array($_POST['myVar'])) {
foreach($_POST['myVar'] as $array) {
$new = array('test' => array(), 'test2' = "");
if(isset($array['test']) && is_array($array['test'])) {
foreach($array['test'] as $expectedInt) {
$new['test'][] = (int)$expectedInt;
}
}
if(isset($array['test2']) && is_string($array['test2']))
$new['test2'] = $array['test2'];
}
$result[] = $new;
}
I think you get the idea what I mean. I wonder if there is a better practice of reading the POST data into the expected format.
I usually do this to assure I have default indices:
$par = $_POST;
$par += [
'key' => 'default',
'other' => 'default',
]
If $par doesn't contain those keys, they are set.
In your case, your could do this:
$ready = [];
foreach($_POST as $k => $v){
$v += [
'test' => [],
'test2' => "string2",
];
// Validate if needed
$v['test'] = (array)$v['test'];
$v['test2'] = (string)$v['test2'];
$ready[$k] = $v;
}
Later you can be sure, that $ready will contain values with test and test2 keys.
This is very useful in functions, where you replace a lot of arguments with one parameter array, and then later set default values,

Categories