PHP how can I find out right properties within Object - php

class a {
public $a = "3";
public $b = "0";
public $b = "3";
public $c = "0";
public $d = "0";
public $e = "0";
public $g = "0";
}
How can I find out which properties are greater than zero?

You can use the get_class_vars function outside the object itself like that:
$a = new a();
$class_vars = get_class_vars(get_class($a));
foreach ($class_vars as $name => $value) {
if ($value > 0) {
echo "$name : $value\n";
}
}

put this method inside your class and it will return all vars in array:
public function test() {
$vars = get_object_vars($this);
$r = array();
foreach($vars as $k => $v) {
if($v > 0){ $r[$k] = $v; }
}
return $r;
}

Related

PHP recursive multidimensional loop

$printArr = recursive($newArray); //calls recursive function
$data = [];
var_dump($data);
var_dump($printArr);
function recursive($array, $level = 0)
{
$searchingValue = 'tableName';
foreach($array as $key => $value)
{
//If $value is an array.
if(is_array($value))
{
recursive($value, $level + 1);
}
else
{
//It is not an array, so print it out.
if($key == $searchingValue)
{
echo "[".$key . "] => " . $value, '<br>';
$data[] = $value;
}
}
}
}
So I have this function and I am trying to save $value value into $data[] array. But it always returns it empty and I don't know why I can't get $value saved outside the function.
If i echo $value I get what i need but like I've mentioned the variables doesn't get saved in this case - table names.
You need to pass the $data to your recursive function. Also you need to return the $data.
Try this code :
function recursive($array, $level = 0, $data =[])
{
$searchingValue = 'tableName';
foreach($array as $key => $value)
{
//If $value is an array.
if(is_array($value))
{
recursive($value, $level + 1 , $data);
}
else
{
//It is not an array, so print it out.
if($key == $searchingValue)
{
echo "[".$key . "] => " . $value, '<br>';
$data[] = $value;
}
}
}
return $data;
}
You can't access variable $data, which is outside the function, from the function. You need to pass it by reference or return it. Small example
<?php
$a = 1;
// Your case
function b() {
$a = 4;
return true;
}
// Passing by reference
function c(&$d) {
$d = 5;
return true;
}
// Using return
function d($d) {
$d = 6;
return $d;
}
b();
var_dump($a);
c($a);
var_dump($a);
$a = d($a);
var_dump($a);
https://3v4l.org/UXFdR

Combining two reference variables

Is it somehow possible to "glue" two reference variables?
For example
$more = &$first.':'.&$second;
Using this, i receive a syntax error, an unexpected &.
Full code
$numOf = isset($_GET['numof']) ? $_GET['numof'] : 'x';
if($numOf == 1) {
$more = &$first;
} else if($numOf == 2) {
$more = &$first.':'.&$second;
} else {
$more = '';
}
$results = array(); // array with results from database
foreach($results as $res) {
$first = $res[0];
$second = $res[1];
echo $more.$res[3];
}
You should use a Closure to achieve what you want. Indeed, you need PHP 7(Maybe 5.6, can't tell as I can't test) in order to achieve desired result. Here's an example:
<?php
$first = "a";
$second = "b";
$more = function(){ global $first,$second; return $first.$second; };
echo $more()."<br>"; // This will output ab
$first = "b";
echo $more(); // This will output bb
One thing you can do is the following :
$ar = array(&$first, &$second);
$more = implode(":", $ar);
not directly, at least not that i know of.
what you could do is create a class with a method that automatically combines the values. if you only want string output, you can use the magic method __tostring, so you can use the class directly:
class combiner
{
private $a;
private $b;
public function __construct(&$a, &$b)
{
$this->a = &$a;
$this->b = &$b;
}
public function __tostring() {
return $this->a.":".$this->b;
}
}
$ta = "A";
$tb = "B";
$combined = new combiner($ta, $tb);
echo $combined; //A:B
$ta = "C";
echo $combined; //C:B
You can get your required result by:
<?php
function more($first, $second){
if(!empty($_GET['numof'])){
if($_GET['numof']==1)
return $first;
elseif($_GET['numof']==2)
return $first.':'.$second
}
return '';
}
$results = array(); // array with results from database
foreach($results as $res) {
$first = $res[0];
$second = $res[1];
echo more($first, $second).$res[3];
}

How to convert dot notation to object in php?

I need a function that give an instance and a dot notation string and return its equivalent object. Something like this
public function convert($instance , $str) {
//If $str = 'instance' return $instance
//If $str = 'instance.name' return $instance->name
//If $str = 'instance.member.id' return $instance->member->id
//...
}
How can I do this
class sth
{
public function convert($instance , $str)
{
$params = explode('.', $str);
if($params == 1) {
return $instance;
} else {
$obj = $instance;
foreach($params as $key => $param) {
if(!$key) {
continue;
}
$obj = $obj->{$param};
}
}
return $obj;
}
}
$obj = new stdClass();
$obj->test = new stdClass();
$obj->test->test2 = new stdClass();
$sth = new sth();
var_dump($sth->convert($obj, 'sth.test.test2'));

php function and change two loops to one loop?

I have a simple function:
function test(){
//some code
$X_has_val = $Y_has_val= array();
foreach ($A as $id => $row){
if(is_take($id)){
$X_has_val[$id] = $row;
}
}
foreach ($B as $id => $row){
if(is_take($id)){
$Y_has_val[$id] = $row;
}
}
//some code
}
I did this for get the equivalence
function test(){
//some code
$X_has_val = $Y_has_val= array();
foreach(array($A, $B) as $key=>$value){
foreach ($value as $id => $row){
if(is_take($id)){
$X_has_val[$id] = $row;
continue;
$Y_has_val[$id] = $row;
}
}
}
//some code
}
Looks like all you need is array_filter()
$X_has_cc = array_filter($A, 'isTake');
$Y_has_cc = array_filter($B, 'isTake');
like e.g. in
<?php
test();
function test() {
$A = array(1,2,3,4,5,6,7,8,9,10);
$B = array(99,100,101,102,103,104);
$X_has_cc = array_filter($A, 'isTake');
$Y_has_cc = array_filter($B, 'isTake');
var_dump($X_has_cc, $Y_has_cc);
}
// select "even elements"
function isTake($x) {
return 0==$x%2;
}
(and sorry, no, your approach doesn't make much sense ;-))

compare object properties and show diff in PHP

I'm searching for a way to show me the different properties/values from given objects...
$obj1 = new StdClass; $obj1->prop = 1;
$obj2 = new StdClass; $obj2->prop = 2;
var_dump(array_diff((array)$obj1, (array)$obj2));
//output array(1) { ["prop"]=> int(1) }
This works very well as long the property is not a object or array.
$obj1 = new StdClass; $obj1->prop = array(1,2);
$obj2 = new StdClass; $obj2->prop = array(1,3);
var_dump(array_diff((array)$obj1, (array)$obj2))
// Output array(0) { }
// Expected output - array { ["prop"]=> array { [1]=> int(2) } }
Is there a way to get rid of this, even when the property is another object ?!
Something like the following, which iterates through and does a recursive diff is the item in the array is itself an array could work:
Des similar work to array_diff, but it does a check to see if it is an array first (is_array) and if so, sets the diff for that key to be the diff for that array. Repeats recursively.
function recursive_array_diff($a1, $a2) {
$r = array();
foreach ($a1 as $k => $v) {
if (array_key_exists($k, $a2)) {
if (is_array($v)) {
$rad = recursive_array_diff($v, $a2[$k]);
if (count($rad)) { $r[$k] = $rad; }
} else {
if ($v != $a2[$k]) {
$r[$k] = $v;
}
}
} else {
$r[$k] = $v;
}
}
return $r;
}
It then works like this:
$obj1 = new StdClass; $obj1->prop = array(1,2);
$obj2 = new StdClass; $obj2->prop = array(1,3);
print_r(recursive_array_diff((array)$obj1, (array)$obj2));
/* Output:
Array
(
[prop] => Array
(
[1] => 2
)
)
*/
My solution will recursively diff a stdClass and all it nested arrays and stdClass objects.
It is meant to be used for comparison of rest api responses.
function objDiff($obj1, $obj2):array {
$a1 = (array)$obj1;
$a2 = (array)$obj2;
return arrDiff($a1, $a2);
}
function arrDiff(array $a1, array $a2):array {
$r = array();
foreach ($a1 as $k => $v) {
if (array_key_exists($k, $a2)) {
if ($v instanceof stdClass) {
$rad = objDiff($v, $a2[$k]);
if (count($rad)) { $r[$k] = $rad; }
}else if (is_array($v)){
$rad = arrDiff($v, $a2[$k]);
if (count($rad)) { $r[$k] = $rad; }
// required to avoid rounding errors due to the
// conversion from string representation to double
} else if (is_double($v)){
if (abs($v - $a2[$k]) > 0.000000000001) {
$r[$k] = array($v, $a2[$k]);
}
} else {
if ($v != $a2[$k]) {
$r[$k] = array($v, $a2[$k]);
}
}
} else {
$r[$k] = array($v, null);
}
}
return $r;
}
Here is a comparison function that I built using the pattern:
function objEq(stdClass $obj1, stdClass $obj2):bool {
$a1 = (array)$obj1;
$a2 = (array)$obj2;
return arrEq($a1, $a2);
}
function arrEq(array $a1, array $a2):bool {
foreach ($a1 as $k => $v) {
if (array_key_exists($k, $a2)) {
if ($v instanceof stdClass) {
$r = objEq($v, $a2[$k]);
if ($r === false) return false;
}else if (is_array($v)){
$r = arrEq($v, $a2[$k]);
if ($r === false) return false;
} else if (is_double($v)){
// required to avoid rounding errors due to the
// conversion from string representation to double
if (abs($v - $a2[$k]) > 0.000000000001) {
return false;
}
} else {
if ($v != $a2[$k]) {
return false;
}
}
} else {
return false;
}
}
return true;
}
Usage:
$apiResponse = apiCall(GET, $objId);
$responseObj = json_decode($apiResponse);
// do stuff ...
if(!objEq($myObj, $responseObj) apiCall(PUT, $myObj, $objId);
Note that the apiCall function is just a mock to illustrate the concept.
Also this solution is incomplete because it does not take into account any key->value pairs that are unique to obj2. In my use case this is not required and could be neglected.
NB: I borrowed heavily from Peter Hamiltons contribution. If you like what I did then please upvote his solution. Thanks!

Categories