Convert only matching keys from an array into object properties that match - php

I am trying to convert only matching keys from an associative array into object properties that match them. The code I have below gives an error of Unidentified variable : key on this line if(array_key_exists($array[$key], $classprop)){.
<?php
class assoctoprop {
public $fname;
public $lname;
public $email;
public function assign(){
$array = array("fname"=>"firstname", "lname"=>"lastname", "email"=>"my#email.com" );
$classprop = get_object_vars($this);
if(array_key_exists($array[$key], $classprop)){
foreach($classprop as $key=>$value){
$this->{$key} = $array[$key];
}
}
}
}
$user = new assoctoprop;
$user->assign();
echo $user->fname."<br/>";
echo $user->lname."<br/>";
echo $user->email."<br/>";
?>
If I modify the method as such
public function assign(){
$array = array("fname"=>"firstname", "lname"=>"lastname", "email"=>"my#email.com" );
foreach(get_object_vars($this) as $key=>$value){
$this->{$key} = $array[$key];
}
}
it works, but when one key do not match property or vice versa, an undefined index is shown.

You need to move the if statement inside the foreach loop because outside of it, $key is undefined. You also need to check for this $key in your array:
foreach($classprop as $key=>$value){
if(array_key_exists($key, $array)){
You could of course also do it the other way around, loop over $array and check if the property exists in the object.

public function assign(){
$array = array("fname"=>"firstname", "lname"=>"lastname", "email"=>"my#email.com" );
foreach(get_object_vars($this) as $key=>$value){
if(isset($array[$key])){
$this->{$key} = $array[$key];
}
}
}
please add if(isset($array[$key]) check
or better of you still need to init unmutched vars in an object
public function assign(){
$array = array("fname"=>"firstname", "lname"=>"lastname", "email"=>"my#email.com" );
foreach(get_object_vars($this) as $key=>$value){
$this->{$key} = isset($array[$key])? $array[$key] : "";
}
}

Related

php output constructor array

I tried executing the code below to output each value from an array, end up result show:
Notice: Array to string conversion in C:\xampp\htdocs\test\tutor.php on line 22
_data : Array
PHP
<?php
class CateData
{
private $_data = array();
public function __construct($data){
$this->_data = $data;
}
}
$data = array(
'a'=>'Cate1',
'b'=>'Cate2',
'c'=>'Cate3',
'd'=>'Cate4'
);
$cate = new CateData($data);
foreach($cate as $key => $val){
echo $key." : ". $val;
}
?>
How can I solve this?
You're looping on the class object and not on the actual data.
In your class add:
public function getData(){
return $this->_data;
}
Then change:
foreach($cate as $key => $val){
echo $key." : ". $val;
}
To:
foreach($cate->getData() as $key => $val){
echo $key." : ". $val;
}
While the accepted answer is better, an alternative is to change the scope so you you dont need to add a getData() method. But can then access the class variables directly.
//change the variable to public, and loop $cate->_data
class CateData
{
public $_data = array();
public function __construct($data){
$this->_data = $data;
}
}
$data = array(
'a'=>'Cate1',
'b'=>'Cate2',
'c'=>'Cate3',
'd'=>'Cate4'
);
$cate = new CateData($data);
foreach($cate->_data as $key => $val){
echo $key." : ". $val;
}
First you should clear the differences between public protect and private.
In your code, you should change your _data to public because you want to visit outside your class.
Then change:
foreach($cate as $key => $val){
echo $key." : ". $val;
}
to:
foreach($cate->_data as $key => $val){
echo $key." : ". $val;
}

How looks good structure of construct for creating multidimensial array

I am trying to create constructor which creates an multidimensional array. My result should be like this:-
Checkout my array $result_array
For now I have error: Illegal offset type. Note that I have als use __toString() becose I work on xml data.
class Property {
public $xmlClass;
public $elemClass = '';
public $first_array = array();
public $result_array = array();
public $data = '';
public $data2 = '';
public function __construct($xml, $elem) {
$this->xmlClass = $xml;
$this->elemClass = $elem;
foreach ($xml->xpath('//*[#baza]') as $val) {
$this->first_array[] = $val;
foreach ($val->ksiazka as $value) {
$data = $value->$elem->__toString();
$this->result_array[$this->first_array][] = $data;
}
}
}
public function getResult() {
return $this->result_array;
}
}
$result_autor = new Property($xml, 'autor');
$autor = $result_autor->getResult();
You need to change your two foreach() like below:-
foreach($xml->xpath('//*[#baza]') as $val) {
//$this->first_array[] = $val; not needed
foreach($val->ksiazka as $key=> $value){ //check $key here
$data = $value->$elem->__toString();
$this->result_array[$key][] = $data; // add $key hear
}
}
If the above not worked then check this too:-
foreach($xml->xpath('//*[#baza]') as $key=> $val) { //check $key here
//$this->first_array[] = $val; not needed
foreach($val->ksiazka as $value){
$data = $value->$elem->__toString();
$this->result_array[$key][] = $data; // add $key hear
}
}

How to "skip" iteration when building a new array using recursion

I am stuck on something that might be very simple.
I am creating a new array by looping through an existing array using a recursion function yet I can not seem to get the values to stick to the new array. The function, in the end, will be a bit more complex, but for now I need some help.
I have tried soooo many ways to get this to work but I am at a loss right now.
Here is my php function
function recursive($array) {
$newArray = array();
foreach($array as $key => $value) {
if(is_array($value)){
recursive($value);
}else{
$newArray[] = $value;
}
}
return $newArray;
}
As is, the new array never gets filled...BUT, if I change this line...
recursive($value); // Why can't I just call the recursive function here?
...to...
$newArray[] = recursive($value); // Instead of having to set a new value to the new array?
everything works properly...except that my goal was to create a flat array with only the values.
So my question is, why is it necessary to set a new array value in order to call the recursive function again? Ideally, I want to skip setting a new array value if the value is an array and just continue the loop through the original array.
Use array_merge:
function recursive($array) {
$newArray = array();
foreach($array as $key => $value) {
if(is_array($value)){
$newArray = array_merge($newArray, recursive($value));
}else{
$newArray[] = $value;
}
}
return $newArray;
}
...or you could use special operator:
function recursive($array) {
$newArray = array();
foreach($array as $key => $value) {
if(is_array($value)){
$newArray += recursive($value);
}else{
$newArray[] = $value;
}
}
return $newArray;
}
...or pass a variable by reference like this:
function recursive($array, &$newArray = null) {
if (!$newArray) {
$newArray = array();
}
foreach($array as $key => $value) {
if(is_array($value)){
recursive($value, $newArray);
}else{
$newArray[] = $value;
}
}
return $newArray;
}
use array_merge() to merge the array returned from recursive($value); and $newArray
$newArray = array_merge($newArray,recursive($value));
You can guarantee that $newArray will be flat after this, as the previous value of $newArray was flat, and recursive always returns a flat array, so the combination of both should be a flat array.
You aren't doing anything with the return from your recursive function. Try this:
function recursive($array) {
$newArray = array();
foreach($array as $key => $value) {
if(is_array($value)){
// This is what was modified
$newArray = array_merge($newArray, recursive($value));
}else{
$newArray[] = $value;
}
}
return $newArray;
}

How to access object property of indeterminate depth

I have an object with data stored at multiple levels ( a JSON-decoded document ) like this:
$db = (object) array(
'simple_property' => 'value',
'complex_property' => (object) array(
'key' => 'value',
'nested' => (object) array(
'key' => 'value'
)
)
);
I want to be able to access and update data at any depth via reference. Example:
$db->{ $key } = $new_value
If $key is equal to 'simple_property', that works. But if $key is equal to 'complex_property->nested->key', it doesn't. Is there a way to accomplish what I want to, or am I looking at it incorrectly?
I don't think you can get it to work that way. You'll have to create a function (or class method) to do something like that. As an example:
function getRecursiveProperty($object, $path)
{
$array = explode('->', $path);
if (empty($array))
{
return NULL;
}
foreach ($array as $property)
{
if (!isset($object->$property))
{
return NULL;
}
if (!is_object($object->$property))
{
return $object->$property;
}
$object = $object->$property;
}
return $object->$property;
}
function setRecursiveProperty($object, $path, $value)
{
foreach (explode('->', $path) as $property)
{
if (!isset($object->$property))
{
return FALSE;
}
if (!is_object($object->$property))
{
$object->$property = $value;
return TRUE;
}
$object = $object->$property;
}
return FALSE;
}
$key = 'complex_property->nested->key';
echo getRecursiveProperty($db, $key); // value
setRecursiveProperty($db, $key, 'new_value');
echo getRecursiveProperty($db, $key); // new_value
Why you don't use $db = json_decode($json, true); instead of $db = json_decode($json);?
In this way you return an associative array instead of an object and you will not have these problems anymore.
json_decode ( string $json , bool $assoc)
json
The json string being decoded.
This function only works with UTF-8 encoded strings.
assoc
When TRUE, returned objects will be converted into
associative arrays.
More info: http://php.net/manual/en/function.json-decode.php

php read mongodb.findone() returned json values and create object

I have an employee class and i want to initialize the employee object from mongodb.findone() returned array.
foreach($res as $key => $value){
echo $value; // here values printed
}
but i need to do something like( if key = 'first_name' then employee_obj->set_first_name($value), if key = 'last_name' then employee_obj->set_last_name($value)... ) can you help me?
$employee = new Employee;
foreach($res as $key => $value){
if (property_exists($employee, $key)) {
$employee->$key = $value;
}
}
$employee->$key = $value is dynamically assigning $key property to the employee. Example:
$key = "name";
$employee->$key = "John Doe";
echo $employee->name; // John Doe
If you want to do this with private or protected properties you need to do the assignment within the class or instance:
class Employee {
// ...
private $name;
// lets you assign properties by passing in an array
public function __construct($arr = array()){
if count($arr) {
foreach($arr as $key => $value){
if (property_exists($this, $key)) {
$this->$key = $value;
}
}
}
}
}
$joe = new Employee(array('name' => 'Joe'));
echo $joe->name // Joe
$e = new Employee;
foreach($res as $k => $v){
if($k == 'first_name'){
$e->set_first_name($v);
}elseif($k == 'last_name'){
$e->set_last_name($v);
}else{
$e->$k = $v;
}
}
Does exactly that.

Categories