search php object for empty value - php

Looking for best way to accomplish below. I want to return TRUE if ANYTHING is empty in my user object, I don't care which one is empty. I think I've done this before with searching for empty values in an array but can't think of the best way to do this with objects.
I know I can loop thru the object and break once I find an empty value in the object, but checking first to see if there is a better way of doing this, thanks!
function is_it_empty($user)
{
$is_it_empty = FALSE;
if( isset($user->first_name) )
$is_it_empty = TRUE;
if( isset($user->last_name) )
$is_it_empty = TRUE;
return $is_it_empty;
}
also:
function name($user)
{
foreach($user as $u):
if( isset ($user->value) ): // or should it be isset?
return true;
break;
endif;
endforeach;
return true;
}

$user = new stdClass();
$user->firstName = 'Mark';
$user->lastName = 'Baker';
$user->sanity = NULL;
function is_it_empty($user) {
foreach($user as $property) {
if (empty($property)) {
return true;
}
}
return false;
}
var_dump(is_it_empty($user));

u can use foreach. it's better than ur code.
function is_it_empty($user)
{
foreach($user as $key=>$value)
{
if( empty($value) ){
return = TRUE;
}
}
}

In case any one ever happens to care about encapsulation, this code might come in handly. The first function inspect public attributes only.
function is_prop_empty( $object ) {
$reflect = new ReflectionClass($object);
$props = $reflect->getProperties();
foreach ($props as $prop) {
try {
$result = $prop->getvalue( $object );
if( $result === null ) {
return true;
}
} catch( Exception $e ) {
}
}
return false;
}
var_dump( is_prop_empty($user) );
And with this second one, you can look into private and protected properties:
function is_prop_empty( $object ) {
$reflect = new ReflectionClass($object);
$props = $reflect->getProperties();
foreach ($props as $prop) {
$prop->setAccessible(true);
$result = $prop->getvalue( $object );
if( $result === null ) {
return true;
}
}
return false;
}
EDIT
By empty, i assumed you meant null but you can modify the function(s) above to meet your requirements of "empty".

I think having this generic function to check if a value exists would do the job
function is_empty($data) {
if(empty($data) || !isset($data) || $data == false) {
return true;
}
return false;
}

Related

Failing to recursively filter multidimensional array of objects

I have a variable which may be an object or an array. If it is an array, it will be of objects. Each object may have a parameter which is another object or an array of objects. All arrays may be n levels deep.
All objects have a parameter 'isAccessible'. The value of this parameter may be true or false.
If it is false, that object must be removed from the structure.
I have tried array_filter and because I was not able to recursively filter as described, I have written a home rolled recursion function.
However I have not been able to get it to work. Here is my code:
public static function jsonGateway($json) {
$object = json_decode($json);
$newJSON = '';
// $object may be a stdClass Object or it may be an array of stdClass Objects
// An objects parameters may be a string, integer, or an array of stdClass Objects.
// This function must recurse arbitrarily deep
// Any object where isAccessible = 0 must be purged (numeric string or int?)
if (is_object($object)) {
if ($object->isAccessible == 1 || $object->isAccessible == '1' || $object->isAccessible == true) {
$newJSON = $json;
}
} else if (is_array($object)) {
$newJSON = json_encode(self::filterRecursive($object));
}
echo $newJSON;
}
public static function filterRecursive(Array $source) {
$result = array();
foreach ($source as $key => $value) {
if (is_object($value)) {
$object = $value; // Just a comprehension aid
if ($object->isAccessible == 1 || $object->isAccessible == '1' || $object->isAccessible == true) {
// Keep this object
// This objec though, may have a parameter which is an array
// If so, we need to recurse
$objectVars = get_object_vars($object);
if (count($objectVars) > 0) {
foreach ($objectVars as $objectParameter => $objectValue) {
if (is_object($objectValue)) {
if ($object->isAccessible == 1 || $object->isAccessible == '1' || $object->isAccessible == true) {
$object[$objectParameter] = $objectValue;
}
} else if (is_array($objectValue)) {
$object[$objectParameter] = self::filterRecursive($objectValue); // Line 177
}
}
}
$result[$key] = $object;
} else {
// don't need this block
error_log("deleting: " . print_r($object,true));
}
}
if (is_array($value)) {
$array = $value; // Just a comprehension aid
$result[$key] = self::FilterRecursive($array);
continue;
}
}
return $result;
}
Not only am I not succeeding at filtering anything, I am getting the following error:
PHP Fatal error: Cannot use object of type stdClass as array in /home1/lowens/public_html/dev/classes/Lifestyle/RBAC.php on line 177
Can you help?
Solution:
/**
* #param array $array
* #return array
*/
public static function filterArray(Array $array) {
$result = array();
foreach ($array as $key => $value) {
if (is_object($value)) {
$newObject = self::filterObject($value);
if (count(get_object_vars($newObject)) > 0) {
$result[$key] = $newObject;
}
} else if (is_array($value)) {
$newArray = self::filterArray($value);
if (count($newArray) > 0) {
$result[$key] = $newArray;
}
} else {
$result[$key] = $value;
}
}
return $result;
}
/**
* #param \stdClass $object
* #return \stdClass
*/
public static function filterObject(\stdClass $object) {
$newObject = new \stdClass();
if ($object->isAccessible == 1) {
$objectVars = get_object_vars($object);
foreach ($objectVars as $objectParameter => $objectValue) {
if (is_object($objectValue)) {
$newObject->$objectParameter = self::filterObject($objectValue);
} else if (is_array($objectValue)) {
$newObject->$objectParameter = self::filterArray($objectValue);
} else {
$newObject->$objectParameter = $objectValue;
}
}
}
return $newObject;
}

In CodeIgniter how can i pass an array type argument to a controller from url

//let my controller be C and method be:
function X($array){}
//And my url to call it is:
localhost/mysite/C/X/array
Well i tried it but it returns 400-Bad Request response.
Does anyone know how to do it? Quick response will help me a lot//Thanx
localhost/mysite/C/X/?array=1&&?array=2....
$array = $this->input->get('array');
or
localhost/mysite/C/X/1,2,3,4,5
$array = explode(',' $this->uri->segment(n));
// in app/config/config.php
$config['permitted_uri_chars'] = 'a-z 0-9~%.:,_-';
My variant for array in url (/tours/novogodniye-turi/visa=yes;duration=small;transport=4,7,6,2/)
if ( ! function_exists('filter_parse_segment'))
{
function filter_parse_segment($segment, $merge_to_get = FALSE)
{
if(empty($segment))
{
return FALSE;
}
$parameters = explode(";", (string)$segment);
if(empty($parameters))
{
return FALSE;
}
$parameters_array = array();
foreach($parameters as $parameter)
{
if(empty($parameter))
{
continue;
}
$parameter = explode("=", $parameter);
if( ! isset($parameter[0], $parameter[1]) or empty($parameter[0]))
{
continue;
}
if(strpos($parameter[1], ','))
{
$parameter[1] = explode(",", $parameter[1]);
}
$parameters_array[$parameter[0]] = $parameter[1];
}
if($merge_to_get === TRUE)
{
$_GET = array_merge($_GET, $parameters_array);
}
return $parameters_array;
}
}
// --------------------------------------------------------------------
if ( ! function_exists('filter_collect_segment'))
{
function filter_collect_segment($array, $suffix = '', $remove = array())
{
if(empty($array) || ! is_array($array))
{
return '';
}
$segment_str = '';
foreach ($array as $key => $value)
{
if(empty($key) || in_array($key, (array)$remove))
{
continue;
}
if( ! $segment_str == '')
{
$segment_str = $segment_str.';';
}
if( ! is_array($value))
{
$segment_str = $segment_str.$key.'='.$value;
continue;
}
if(empty($value))
{
continue;
}
$parsed_value = '';
foreach ($value as $item)
{
if( ! $parsed_value == '')
{
$parsed_value = $parsed_value.',';
}
if(is_array($item) || empty($item))
{
continue;
}
$parsed_value = $parsed_value.$item;
}
$segment_str = $segment_str.$key.'='.$parsed_value;
}
if($segment_str != '')
{
$segment_str = $segment_str.$suffix;
}
return $segment_str;
}
}
// --------------------------------------------------------------------
if ( ! function_exists('filter_key'))
{
function filter_key($filter_array, $key, $value = NULL)
{
if( ! isset($filter_array[$key]))
{
return;
}
if($value == NULL)
{
return $filter_array[$key];
}
if( ! is_array($filter_array[$key]) && $filter_array[$key] == (string)$value)
{
return $value;
}
if(is_array($filter_array[$key]) && in_array($value, $filter_array[$key]))
{
return $value;
}
return FALSE;
}
}
If you want the solution in the pretty nice URL then you have to loop the array first and then concatenate the elements with some - dash or + plus signs like this;
$array = array(1,2,3,4);
$string = "";
foreach($array as $value){
$string .= $value."-";
}
$string = rtrim($string, "-");
redirect(base_url()."get_products?param=".$string);
And on the next page just get the param and use explode() function with - dash sign to create the array again.
try your url like this
if value you have to pass is
[1,2,3,2]
then
localhost/mysite/index.php/C/X/1,2,3,2
In a simple way you can make the array a string with some special character in between the values of the array.
Then in the landing page you can split the string with the special character and get the array again.
If the values are [1,2,3,4], then make it using a loop "1,2,3,4".
Then pass the string.
In teh landing page split the string with "," and you will again get the array.
Hope it helps you.
Thanks
Why don't you use uri segments for array? You can count uri segments and could use them. Even u could check how many arrays already there.
url.com/1/2/3
http://ellislab.com/codeigniter/user-guide/libraries/uri.html
Note: uri segment doesnt work on main controller index function, you have to define another function than index for example: I don't know what it happens but i think because of htaccess file I'm using do remove index.php.
url.com/uri_segment_controller/go/1/2/3

Returning array inside function that returns another value

Why does the following script does not work?
$arr = array();
function collect( $array , $val) {
$array[] = $val;
return $array;
}
function checkFoo( $s ) {
$valid = true;
if ( strlen( $s ) === 0 ) {
$isValid = false;
collectFoo( $arr , $s );
}
return $valid;
}
function checkBar( $t ) {
$valid = true;
if ( strlen( $s ) != 10 ) {
$isValid = false;
collectFoo( $arr , $t );
}
return $valid;
}
if ( checkFoo( $that ) && checkBar( $this ) ) {
echo "success";
} else {
print_r( $error );
}
I always get
Notice: Undefined variable: error in /my.php on line 12
where line 12 resembles the second occurrence of collect(...);
I know that a function can only return one value, but what if a function returns something in a function that returns something? Because collect returns $array inside checkBar that returns $valid.
you are using a global variable ($arr), so you need do declare it as such. example:
function checkFoo( $s ) {
global $arr; // declare $arr to be usable inside this function scope
$valid = true;
if ( strlen( $s ) === 0 ) {
$isValid = false;
collectFoo( $arr , $s );
}
return $valid;
}
You aren't declaring your $arr variable as global inside the functions that use it. You can find some info about that here.
Also, it doesn't look like you are actually using the return value of collect, so I'd say that your problem is that either checkBar or checkFoo are returning false, which makes you fall through to the print_r function, with a $error variable that you have not initialized.
Finally, it seems to me like your collect function is not actually doing anything to the $arr variable, because you are not passing it to collect by reference. you can read up on passing variables by reference here. There is also a S.O. question about this here.
Edited
You need more practice, because totally your code is incorrect !
you must changes this parts of your codes :
$arr = array();
function collectFoo( $arr , $val) {
global $arr;
$arr[] = $val;
}
function checkFoo( $s ) {
global $arr;
$valid = false;
if ( strlen( $s ) === 0 ) {
$valid = false;
collectFoo( $arr , $s );
}
return $valid;
}
function checkBar( $t ) {
global $arr;
$valid = true;
if ( strlen( $t ) != 10 ) {
$valid = false;
collectFoo( $arr , $t );
}
return $valid;
}
$a = checkFoo( $that );
$b = checkBar( $this );
if ( $a && $b ) {
echo 'Success !';
} else {
print_r( $err );
}

PHP testing array_walk result

I'm sure this is an easy solution - I wrote found this endswith function and thought I'd try the array_walk function instead of testing each string separately. I'd assumed that the result of the array_walk function would be false but it returns 1...How do I get it to test all the strings and return false if it didn't find a match? Thanks
class {
function endsWith($value,$key,$haystack)
{
$length = strlen($value);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $value);
}
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
echo array_walk($arr,array($this,"endsWith"),$email);
}
}
The return value of array_walk is not determined by whatever the callback does; it only informs you if walking the entire array was completed successfully.
You may want to look into a few alternatives.
This will return the number of matching elements and will also serve as a boolean test, but it will evaluate every element no matter what:
echo count(array_filter($arr,array($this,"endsWith")));
This will stop evaluating elements with endsWith as soon as a match is detected and will return true if there is a match, false otherwise:
$self = $this;
// cast to int because false is printed as the empty string
echo (int)array_reduce($arr,
function($result, $v) use ($email, $self) {
return $result || $self->endsWith($v, null, $email);
},
false);
Try this
class {
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
foreach ($arr as $domain) {
$length = strlen($value);
if ($length != 0) {
if (substr($email, -$length) === $domain) { echo $domain; break; }
}
}
}
}
array_walk() just iterates over the elements of an array and returns true, if it was able to do it. (echo casts boolea true to a string '1') Have a look at array_recude()
$that = $this; // Cannot access $this directly before PHP 5.4
var_dump(
array_reduce (
$arr,
function($result, item) use ($email, $that) { return $result || $that->endsWith($item, null /* not used anyway */, $email);},
false
)
);
Additional $key is not used and useless in endsWith().
If you want to apply a function to all values and return a single result you should use array_reduce.
As of PHP 5.3, you can use anonymous functions:
class {
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
$match = '';
$found = false;
array_walk($arr,function($value) use (&$match, &$found, $email) {
$length = strlen($value);
if ($length == 0) {
$found = true;
return;
}
if (substr($email, -$length) === $value) {
$match = $value;
$found = true;
}
});
if ($found) {
echo 'Found match: ' . $match;
} else {
echo 'No match found :(';
}
}
}

Getting a value into multidimensional array from a list of indexes (array too)

I'm looking for a nice way of doing the magicFunction():
$indexes = array(1, 3, 0);
$multiDimensionalArray = array(
'0',
array('1-0','1-1','1-2',array('2-0','2-1','2-2')),
array('1-4','1-5','1-6')
);
$result = magicFunction($indexes, $multiDimensionalArray);
// $result == '2-0', like if we did $result = $multiDimensionalArray[1][3][0];
Thanks.
You can solve this recursively.
$indexes = array(1, 3, 0);
$multiDimensionalArray = array(
'0',
array('1-0','1-1','1-2',array('2-0','2-1','2-2')),
array('1-4','1-5','1-6')
);
$result = magicFunction($indexes, $multiDimensionalArray);
function magicFunction($indices, $array) {
// Only a single index is left
if(count($indices) == 1) {
return $array[$indices[0]];
} else if(is_array($indices)) {
$index = array_shift($indices);
return magicFunction($indices, $array[$index]);
} else {
return false; // error
}
}
print $result;
This function will go down the $multiDimensionalArray as long as there are indices available and then return the last value accesses by the index. You will need to add some error handling though, e.g. what happens if you call the function with $indexes = array(1,2,3,4);?
This is a recursive version. Will return null if it cannot find a value with the given index route.
function magicFunction($indexes, $array) {
if (count($indexes) == 1) {
return isset($array[$indexes[0]]) ? $array[$indexes[0]] : null;
} else {
$index=array_shift($indexes);
return isset($array[$index]) ? magicFunction($indexes, $array[$index]) : null;
}
}
You can just step trough based on your keys (no need to do any recursion, just a simple foreach):
$result = &$multiDimensionalArray;
foreach($indexes as $index)
{
if (!isset($result[$index]))
break; # Undefined index error
$result = &$result[$index];
}
If you put it inside a function, then it won't keep the reference if you don't want to. Demo.
I think something like this should do the trick for you.
function magicFuntion($indexes, $marray)
{
if(!is_array($indexes) || count($indexes) == 0 || !is_array($marray))
return FALSE;
$val = '';
$tmp_arr = $marray;
foreach($i in $indexes) {
if(!is_int($i) || !is_array($tmp_arr))
return FALSE;
$val = $tmp_arr[$i];
$tmp_arr = $tmp_arr[$i];
}
return $val;
}
Try this :P
function magicFunction ($indexes,$mdArr){
if(is_array($mdArr[$indexes[0]] && $indexes)){
magicFunction (array_slice($indexes,1),$mdArr[$indexes[0]]);
}
else {
return $mdArr[$indexes[0]];
}
}
My own attempt ; found it simpler by not doing it recursively, finally.
function magicFunction($arrayIndexes, $arrayData)
{
if (!is_array($arrayData))
throw new Exception("Parameter 'arrayData' should be an array");
if (!is_array($arrayIndexes))
throw new Exception("Parameter 'arrayIndexes' should be an array");
foreach($arrayIndexes as $index)
{
if (!isset($arrayData[$index]))
throw new Exception("Could not find value in multidimensional array with indexes '".implode(', ', $arrayIndexes)."'");
$arrayData = $arrayData[$index];
}
return $arrayData;
}
Exceptions may be somewhat "violent" here, but at least you can know exactly what's going on when necessary.
Maybe, for sensitive hearts, a third $defaultValue optional parameter could allow to provide a fallback value if one of the indexes isn't found.

Categories