Validate array, then return it - php

Im trying to get more into arrays.
Im passing an array to a class which should validate the input ant convert it into uppercase.
class Input {
public function clean(array $variable)
{
$count = 0;
$input = array();
foreach($variable as $row)
{
$variable = strtoupper(trim(stripslashes(strip_tags($row))));
$input[$count]['input'] = $variable;
$count++;
}
return $input;
}
}
$input = new Input;
$array = array('John', 'Marie', 'Alice');
$input->clean($array);
What is the way to validate the entire array and return each result, so i could echo it out?
Thanks!
P.S. is this a good approach? Or should I rather keep on validating every variable separately?

$result = $input->clean($array);
var_dump($result);

Related

php access to specific position of multidimensional array by its keys and set it

In PHP we can do things like these:
Class Example {
...
}
$example = 'Example';
$object = new $example();
Or the use of variable variables:
$hour = 18;
$greets = array('Good morning','Good afternoon','Good evening');
$values = array(13,21,23);//people is sleeping at 23PM, so they don't greet.
$n = count($values);
$greet = 'greets';
for($i=0;$i<$n;$i++){
if($hour < $values[$i]){
echo 'hello, '.${$greet}[$i];
break;
}
}
And others..
I wonder if it would be possible to access directly to a specific index of a multidimensional array in a similar way. Something like:
$array = array(...); //multidimensional array.
$position = '[0][4][3]';
print_r($array$position);
Thanks in advance.
UPDATE
I'm so sorry because I finished my question in a wrong way.
I need to set the multimesional array and add a value. i.e:
$array$position = $data;
You could implement it yourself with a custom function:
function getValueFromMultiDimensionalArray( array $array, string $key )
{
$keys = explode('][', $key);
$value = $array;
foreach ($keys as $theKey) {
// remove the opening or closing bracket if present
$theKey = str_replace([ '[', ']' ], '', $theKey);
if (!isset($value[$theKey])) {
return null;
}
$value = $value[$theKey];
}
return $value;
}
You can define path as dot separated , check the following solution
function getValueByKey($a,$p){
$c = $a;
foreach(explode('.',$p) as $v){
if(!array_key_exists($v, $c)) return null;
$c = $c[$v];
}
return $c;
}
You can use this function as
$path = '1.2.3.0';
$indexValue = getValueByKey($array, $path);
Nope, this is not possible.
The only thing you can do is to implement ArrayAccess interface, which allows to access instances with [] operator. But you will have to define the logic yourself.
class MyClass implements ArrayAccess
{
...
}
$x = new MyClass([0=>[4=>[3=>'hello world']]]);
$position = '[0][4][3]';
echo $x[$position]; //hello world

Filtering a Multidimensional Array based of another array

I'm creating a PHP class that manipulates csv files.
As part of the class I have a function that allows the data to be filtered showOnlyWhere. However I get this error Invalid argument supplied for foreach() on line 331 (the line with the foreach statement). I tried adding global $arr; but that didn't work. How would i fix it?
$this -> rows is a multi-dimensional array that contains all the csv data.
$arr is in the format:
$key=>$val array(
$key = Column Name
$val = value that column should contain
)
Below is the showOnlyWhere function
function showOnlyWhere($arr)
{
if($this->showOnlyWhere == true){
$rows = $this->filteredRows;
}
else{
$rows = $this->rows;
}
$filter = function ($item){
global $arr; // didn't work
foreach($arr as $chkCol => $chkVal){
if ($item[$arr[$chkCol]] != $chkVal ){
return false;
break(3);
}
}
return true;
};
$this->filteredRows = array_filter($rows,$filter);
$this->showOnlyWhere = true;
}
I think the error might have something to do with the Anonymous function - but I'm not really sure.
instead of using global $arr you can make $arr available to the anonymous function via use
$filter = function ($item) use ($arr) {
//global $arr; // didn't work
foreach($arr as $chkCol => $chkVal){
if ($item[$arr[$chkCol]] != $chkVal ){
return false;
}
}
return true;
};
Also, I noticed that you are assigning $rows = $this->filteredRows; before you populate $this->filteredRows. I'm not sure if that's intentional?
Format for your $arr is wrong.
this is wrong:
$key=>$val array(
$key = Column Name
$val = value that column should contain
)
You cannot supply class objects to foreach, it should be a valid array.
It should be like this:
$arr=array(
$key => 'Column Name',
$val = 'value that column should contain'
);
So first convert your object to a valid array.

Looping through PHP object members and assign a value to members

I know I can loop through a PHP object and obtain the values of it's members like so:
class MyObject {
public $one = 1;
public $two = 2;
public $three = 3;
function getMemberValues() {
foreach($this as $memb => $value) {
echo $value." ";
}
}
}
$o = new MyObject();
$o->getMemberValues();
// prints 1 2 3
but what I want to be able to do is loop through the members and assign a value to each one.
I can't figure out the syntax for it though.
$this[$memb] = 111;
doesn't work because you get a
Cannot use object of type MyObject as array
error, and
$this->$memb
obviously isn't valid either.
Is this possible?
Many thanks
Yes, $this->$memb is valid.
You can assign to a property like this:
$memb = 'one';
$this->$memb = 1;
This also works for functions, and this is documented here
and
$this->$memb
obviously isn't valid either.
Have you tried it? It looks perfectly valid to me.
foreach ($this as $memb => $val) {
$this->$memb = 'toto';
}
The code above should work perfectly.
Maybe
function getMemberValues() {
foreach($this as &$value) {
$value = $newval;
}
}
http://php.net/manual/en/function.get-object-vars.php
function getMemberValues()
{
echo implode(' ', get_object_vars($this));
}

How to dynamically set array keys in php

I have some logic that is being used to sort data but depending on the user input the data is grouped differently. Right now I have five different functions that contain the same logic but different groupings. Is there a way to combine these functions and dynamically set a value that will group properly. Within the function these assignments are happening
For example, sometimes I store the calculations simply by:
$calcs[$meter['UnitType']['name']] = ...
but other times need a more specific grouping:
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] =...
As you can see sometimes it is stored in a multidiminesional array and other times not. I have been trying to use eval() but without success (not sure that is the correct approach). Storing the data in a temporary variable does not really save much because there are many nested loops and if statements so the array would have to be repeated in multiple places.
EDIT
I hope the following example explains my problem better. It is obviously a dumbed down version:
if(){
$calcs[$meter['UnitType']['name']] = $data;
} else {
while () {
$calcs[$meter['UnitType']['name']] = $data;
}
}
Now the same logic can be used but for storing it in different keys:
if(){
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
while () {
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
}
}
Is there a way to abstract out the keys in the $calc[] array so that I can have one function instead of having multiple functions with different array keys?
You can use this if you want to get&set array values dynamically.
function getVal($data,$chain){
$level = $data;
for($i=0;$i<count($chain);$i++){
if(isset($level[$chain[$i]]))
$level = $level[$chain[$i]];
else
return null; // key does not exist, return null
}
return $level;
}
function setVal(&$data,$chain,$value){
$level = &$data;
for($i=0;$i<count($chain);$i++){
$level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object
}
$level = $value;
}
How it works:
Calling getVal($data,array('foo','bar','2017-08')) will return the equivalent of $data['foo']['bar']['2017-08'].
Calling setVal($data,array('foo','bar','2017-08'),'hello') will set value as if you called
$data['foo']['bar']['2017-08'] = 'hello'. non-existent keys will be created automatically by php magic.
This can be useful if you want to build the structure of the array dynamically.
Here's a function I wrote for setting deeply nested members on arrays or objects:
function dict_set($var, $path, $val) {
if(empty($var))
$var = is_array($var) ? array() : new stdClass();
$parts = explode('.', $path);
$ptr =& $var;
if(is_array($parts))
foreach($parts as $part) {
if('[]' == $part) {
if(is_array($ptr))
$ptr =& $ptr[];
} elseif(is_array($ptr)) {
if(!isset($ptr[$part]))
$ptr[$part] = array();
$ptr =& $ptr[$part];
} elseif(is_object($ptr)) {
if(!isset($ptr->$part))
$ptr->$part = array();
$ptr =& $ptr->$part;
}
}
$ptr = $val;
return $var;
}
Using your example data:
$array = [];
$array = dict_set($array, 'resource1.unit1.2017-10', 'value1');
$array = dict_set($array, 'resource1.unit2.2017-11', 'value2');
$array = dict_set($array, 'resource2.unit1.2017-10', 'value3');
print_r($array);
Results in output like:
Array
(
[resource1] => Array
(
[unit1] => Array
(
[2017-10] => value1
)
[unit2] => Array
(
[2017-11] => value2
)
)
[resource2] => Array
(
[unit1] => Array
(
[2017-10] => value3
)
)
)
The second argument to dict_set() is a $path string in dot-notation. You can build this using dynamic keys with period delimiters between the parts. The function works with arrays and objects.
It can also append incremental members to deeply nested array by using [] as an element of the $path. For instance: parent.child.child.[]
Would it not be easier to do the following
$calcs = array(
$meter['Resource']['name'] => array(
$meter['UnitType']['name'] => 'Some Value',
$meter['UnitType']['name2'] => 'Some Value Again'
),
);
or you can use Objects
$calcs = new stdClass();
$calcs->{$meter['UnitType']['name']} = 'Some Value';
but I would advice you build your structure in arrays and then do!
$calcs = (object)$calcs_array;
or you can loop your first array into a new array!
$new = array();
$d = date('Y-m',$start);
foreach($meter as $key => $value)
{
$new[$key]['name'][$d] = array();
}
Give it ago and see how the array structure comes out.
Try to use a switch case.
<?php
$userinput = $calcs[$meter['UnitType']['name']] = $data;;
switch ($userinput) {
case "useriput1":
while () {
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
}
break;
case "userinput2":
while () {
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
}
break;
...
default:
while () {
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
}
}
?>
I agree with the comment on the OP by #Jake N that perhaps using objects is a better approach. Nonetheless, if you want to use arrays, you can check for the existence of keys in a conditional, like so:
if(
array_key_exists('Resource', $meter)
) {
$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
$calcs[$meter['UnitType']['name']] = $data;
}
On the other hand, if you want to use objects, you can create a MeterReading object type, and then add MeterReading instances as array elements to your $calcs array, like so:
// Object defintion
class MeterReading {
private $data;
private $resource;
private $startDate;
private $unitType;
public function __construct(Array $meter, $start, $data) {
$this->unitType = $meter['UnitType']['name'];
$this->resource = $meter['Resource']['name'];
$this->startDate = date('Y-m',$start);
}
public function data() {
return $this->data;
}
public function resource() {
return $this->resource;
}
public function startDate() {
return $this->startDate;
}
public function unitType() {
return $this->unitType;
}
}
// Example population
$calcs[] = new MeterReading($meter, $start, $data);
// Example usage
foreach($calcs as $calc) {
if($calc->resource()) {
echo 'Resource: ' . $calc->resource() . '<br>';
}
echo 'Unit Type: ' . $calc->unitType() . '<br>';
echo 'Start Date: ' . $calc->startDate() . '<br>';
echo 'Data: ' . $calc->data() . '<br>';
}
Obviously you can take this further, such as checking the existence of array keys in the object constructor, giving the object property resource a default value if not provided, and so on, but this is a start to an OO approach.
You can use this library to get or set value in multidimensional array using array of keys:
Arr::getNestedElement($calcs, [
$meter['Resource']['name'],
$meter['UnitType']['name'],
date('Y-m', $start)
]);
to get value or:
Arr::handleNestedElement($calcs, [
$meter['Resource']['name'],
$meter['UnitType']['name'],
date('Y-m', $start)
], $data);
to set $data as value.

How to pass an array into a function, and return the results with an array

So I'm trying to learn how to pass arrays through a function, so that I can get around PHP's inability to return multiple values. Haven't been able to get anything to work so far, but here is my best try. Can anybody point out where I'm going wrong?
function foo($array)
{
$array[3]=$array[0]+$array[1]+$array[2];
return $array;
}
$waffles[0]=1;
$waffles[1]=2;
$waffles[2]=3;
foo($waffles);
echo $waffles[3];
For clarification: I want to be able to pass multiple variables into a function, do something, then return multiple variables back out while keeping them seperate. This was just an example I was trying to get working as a work around for not being able to return multiple variables from an array
You seem to be looking for pass-by-reference, to do that make your function look this way (note the ampersand):
function foo(&$array)
{
$array[3]=$array[0]+$array[1]+$array[2];
}
Alternately, you can assign the return value of the function to a variable:
function foo($array)
{
$array[3]=$array[0]+$array[1]+$array[2];
return $array;
}
$waffles = foo($waffles)
You're passing the array into the function by copy. Only objects are passed by reference in PHP, and an array is not an object. Here's what you do (note the &)
function foo(&$arr) { # note the &
$arr[3] = $arr[0]+$arr[1]+$arr[2];
}
$waffles = array(1,2,3);
foo($waffles);
echo $waffles[3]; # prints 6
That aside, I'm not sure why you would do that particular operation like that. Why not just return the sum instead of assigning it to a new array element?
function foo(Array $array)
{
return $array;
}
Try
$waffles = foo($waffles);
Or pass the array by reference, like suggested in the other answers.
In addition, you can add new elements to an array without writing the index, e.g.
$waffles = array(1,2,3); // filling on initialization
or
$waffles = array();
$waffles[] = 1;
$waffles[] = 2;
$waffles[] = 3;
On a sidenote, if you want to sum all values in an array, use array_sum()
I always return multiple values by using a combination of list() and array()s:
function DecideStuffToReturn() {
$IsValid = true;
$AnswerToLife = 42;
// Build the return array.
return array($IsValid, $AnswerToLife);
}
// Part out the return array in to multiple variables.
list($IsValid, $AnswerToLife) = DecideStuffToReturn();
You can name them whatever you like. I chose to keep the function variables and the return variables the same for consistency but you can call them whatever you like.
See list() for more information.
i know a Class is a bit the overkill
class Foo
{
private $sum = NULL;
public function __construct($array)
{
$this->sum[] = $array;
return $this;
}
public function getSum()
{
$sum = $this->sum;
for($i=0;$i<count($sum);$i++)
{
// get the last array index
$res[$i] = $sum[$i] + $sum[count($sum)-$i];
}
return $res;
}
}
$fo = new Foo($myarray)->getSum();
Here is how I do it. This way I can actually get a function to simulate returning multiple values;
function foo($array)
{
foreach($array as $_key => $_value)
{
$str .= "{$_key}=".$_value.'&';
}
return $str = substr($str, 0, -1);
}
/* Set the variables to pass to function, in an Array */
$waffles['variable1'] = "value1";
$waffles['variable2'] = "value2";
$waffles['variable3'] = "value3";
/* Call Function */
parse_str( foo( $waffles ));
/* Function returns multiple variable/value pairs */
echo $variable1 ."<br>";
echo $variable2 ."<br>";
echo $variable3 ."<br>";
Especially usefull if you want, for example all fields in a database
to be returned as variables, named the same as the database table fields.
See 'db_fields( )' function below.
For example, if you have a query
select login, password, email from members_table where id = $id
Function returns multiple variables:
$login, $password and $email
Here is the function:
function db_fields($field, $filter, $filter_by, $table = 'members_table') {
/*
This function will return as variable names, all fields that you request,
and the field values assigned to the variables as variable values.
$filter_by = TABLE FIELD TO FILTER RESULTS BY
$filter = VALUE TO FILTER BY
$table = TABLE TO RUN QUERY AGAINST
Returns single string value or ARRAY, based on whether user requests single
field or multiple fields.
We return all fields as variable names. If multiple rows
are returned, check is_array($return_field); If > 0, it contains multiple rows.
In that case, simply run parse_str($return_value) for each Array Item.
*/
$field = ($field == "*") ? "*,*" : $field;
$fields = explode(",",$field);
$assoc_array = ( count($fields) > 0 ) ? 1 : 0;
if (!$assoc_array) {
$result = mysql_fetch_assoc(mysql_query("select $field from $table where $filter_by = '$filter'"));
return ${$field} = $result[$field];
}
else
{
$query = mysql_query("select $field from $table where $filter_by = '$filter'");
while ($row = mysql_fetch_assoc($query)) {
foreach($row as $_key => $_value) {
$str .= "{$_key}=".$_value.'&';
}
return $str = substr($str, 0, -1);
}
}
}
Below is a sample call to function. So, If we need to get User Data for say $user_id = 12345, from the members table with fields ID, LOGIN, PASSWORD, EMAIL:
$filter = $user_id;
$filter_by = "ID";
$table_name = "members_table"
parse_str(db_fields('LOGIN, PASSWORD, EMAIL', $filter, $filter_by, $table_name));
/* This will return the following variables: */
echo $LOGIN ."<br>";
echo $PASSWORD ."<br>";
echo $EMAIL ."<br>";
We could also call like this:
parse_str(db_fields('*', $filter, $filter_by, $table_name));
The above call would return all fields as variable names.
You are not able to return 'multiple values' in PHP. You can return a single value, which might be an array.
function foo($test1, $test2, $test3)
{
return array($test1, $test2, $test3);
}
$test1 = "1";
$test2 = "2";
$test3 = "3";
$arr = foo($test1, $test2, $test3);
$test1 = $arr[0];
$test2 = $arr[1];
$test3 = $arr[2];
Another way is:
$NAME = "John";
$EMAIL = "John#gmail.com";
$USERNAME = "John123";
$PASSWORD = "1234";
$array = Array ("$NAME","$EMAIL","$USERNAME","$PASSWORD");
function getAndReturn (Array $array){
return $array;
}
print_r(getAndReturn($array));

Categories