I have some script for long random xml and I need to find value when I know key.
I tried to use array_walk_recursive - but when I used it - I took value only when I used echo. When I used return I took only true or false...
I need to take back a variables for next processing.
Can you help me please?
class ClassName{
private $array;
private $key ;
public $value;
public $val;
function getKey($key) {
$this->key = $key;
return $key;
}
function getFind($value, $key)
{
static $i = 0;
if ($key === ($this->key)) {
$value = $value[$i];
$i++;
return $value;
}
}
}
$xml_simple = simplexml_load_file('./logs/xml_in1.xml');
$json = json_encode($xml_simple);
$array = json_decode($json, TRUE);
$obj = new ClassName();
$obj_key = 'pracovnik';
$obj->getKey($obj_key);
print_r(array_walk_recursive($array,[$obj,"getFind"]));
print_r( $obj->value);
The return value of array_walk_recursive is:
Returns true on success or false on failure.
What you might so as an idea is to use an array where you can add values to when this if clause is true:
if ($key === $this->key) {
Then you could create another method to get the result:
For example
class ClassName
{
private $key;
private $result = [];
function setKey($key) {
$this->key = $key;
}
function find($value, $key) {
if ($key === $this->key) {
$this->result[$key][] = $value;
}
}
function getResult(){
return $this->result;
}
}
$xml_simple = simplexml_load_file('./logs/xml_in1.xml');
$json = json_encode($xml_simple);
$array = json_decode($json, TRUE);
$obj = new ClassName();
$obj->setKey('pracovnik');
array_walk_recursive($array, [$obj, "find"]);
print_r($obj->getResult());
A few notes about the code that you tried:
You have a line after the return statement return $value; that will never be executed
You have declared but not using public $val; and private $array;
I think function getKey is better named setKey as you are only setting the key
I have array of arrays - tree structure of main menu.
I try to find in this tree one node with needed slug and return this node with all it's childs.
I write little recurcive function
<?php
$tree = '[{"id":1,"structure":1,"parent":0,"slug":"medicinskaya-ge","child":{"2":{"id":2,"structure":1.1,"parent":1,"slug":"dnk-diagnostika","child":{"3":{"id":3,"structure":"1.1.1","parent":2,"slug":"dnk-diagnostika","datafile":"ssz","template":"ssz"},"4":{"id":4,"structure":"1.1.2","parent":2,"slug":"dnk-diagnostika","child":{"5":{"id":5,"structure":"1.1.2.1","parent":4,"slug":"dnk-diagnostika"},"6":{"id":6,"structure":"1.1.2.2","parent":4,"slug":"testirovanie-ge"},"7":{"id":7,"structure":"1.1.2.3","parent":4,"slug":"dnk-diagnostika"}}},"8":{"id":8,"structure":"1.1.3","parent":2,"slug":"dnk-diagnostika"},"9":{"id":9,"structure":"1.1.4","parent":2,"slug":"texnologiya-kol"}}}}}]';
$tree = json_decode($tree, true);
function getSlugData(string $slug, array $data)
{
foreach ($data as $row) {
if ($row['slug'] == $slug) {
return $row;
}
if (isset($row['child'])) {
//return $this->getSlugData($slug, $row['child']);
}
}
return [];
}
$result = getSlugData('testirovanie-ge', $tree);
print_r($result);
But as a result I have an empty array. If I print_r($row) when $row['slug'] == $slug - It appears on screen.
if ($row['slug'] == $slug) {
exit(print_r($row));
return $row;
}
What's my mistake?
In programming, recursion is a useful and powerful mechanism that allows a function to call itself directly or indirectly, that is, a function is said to be recursive if it contains at least one explicit or implicit call to itself.
I modified your code a bit and got the solution below.
$tree = '[{"id":1,"structure":1,"parent":0,"slug":"medicinskaya-ge","child":{"2":{"id":2,"structure":1.1,"parent":1,"slug":"dnk-diagnostika","child":{"3":{"id":3,"structure":"1.1.1","parent":2,"slug":"dnk-diagnostika","datafile":"ssz","template":"ssz"},"4":{"id":4,"structure":"1.1.2","parent":2,"slug":"dnk-diagnostika","child":{"5":{"id":5,"structure":"1.1.2.1","parent":4,"slug":"dnk-diagnostika"},"6":{"id":6,"structure":"1.1.2.2","parent":4,"slug":"testirovanie-ge"},"7":{"id":7,"structure":"1.1.2.3","parent":4,"slug":"dnk-diagnostika"}}},"8":{"id":8,"structure":"1.1.3","parent":2,"slug":"dnk-diagnostika"},"9":{"id":9,"structure":"1.1.4","parent":2,"slug":"texnologiya-kol"}}}}}]';
$tree = json_decode($tree, true);
//print_r($tree);
//die();
function getSlugData(string $slug, array $data, string $key = 'slug')
{
$result = [];
foreach ($data as $row) {
// Checks if the key exists and is the desired value for that key in the array
if (isset($row[$key]) && $row[$key] === $slug) {
return $row;
}
// If it is an array, apply recursion by calling getSlugData again
if (is_array($row)) {
$result = getSlugData($slug, $row, $key);
if ($result !== []) {
return $result;
}
}
}
return $result;
}
print_r(getSlugData('testirovanie-ge', $tree));
print_r(getSlugData('texnologiya-kol', $tree));
print_r(getSlugData('nothing-here', $tree));
die();
In the recursive function, you must not break the loop early unless you find your slug match. If a non-slug-match has a child element, you must iterate it and potentially pass up a match in subsequent recursive calls.
Code: (Demo)
function getSlugData(string $slug, array $data): array
{
foreach ($data as $row) {
if ($row['slug'] === $slug) {
return $row;
}
if (isset($row['child'])) {
$deeper = getSlugData($slug, $row['child']);
if ($deeper) {
return $deeper;
}
}
}
return [];
}
P.s. you aren't calling a class method, so $this-> is inappropriate.
I'm trying to pass a list of objects in php to a json but the output is not being as expected.
Controller:
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
require_once "../dao/SubstanciaDAO.php";
require_once "../utils/php/Serialize.php"; // importing util to serialize list of objects
if(array_key_exists("fetchAll",$_GET))
{
$subs = SubstanciaDAO::read(array("all"));//fetching list of objects
if($subs) {
$list = jsonSerializeList($subs);//this function is written bellow in another file
if(isset($list))
echo json_encode($list, JSON_UNESCAPED_UNICODE);//writting output
else
echo "Erro";
}
}
}
Util to serialize list of objects:
First try:
function jsonSerializeList( array $arr ) {
$res = array();
foreach ($arr as $a) {
$aux = get_class_vars(get_class($a));
array_push($res, $aux);
}
return $res;
}
Output:
[[],[],[]]
Second try:
function jsonSerializeList( array $arr ) {
$res = array();
foreach ($arr as $a) {
$aux = get_object_vars($a);
array_push($res, $aux);
}
return $res;
}
Output:
[[],[],[]]
Conclusion
My guess is that there is a problem with the class's private attributes.
In the "$ subs" object list, each position is an object of the "Sustancia.php" class:
class Substancia {
private $id;
private $principioAtivo;
private $nomeComercial;
private $apelidos;
public function __construct() {
$this->apelidos = array();
}
...
Would it be possible to correct the "jsonSerializeList" function so that it works correctly? I really need a function that does this object serialization to use whenever necessary.
How to pass the array into another page?
Example is I have the controller code below
$values = array(
'RECEIVER_PHYSICAL',
'RECEIVER_VIRTUAL',
'EMAIL_TEMPLATE'
);
foreach ($values as $id) {
$data['email'] = $this->mod_rewards->getEmail($id);
}
And this is the model that I want to pass the array
public function getEmail($id) {
$info = $this->core_db->select('*')
->from($this->schema.'.'.$this->v_system_config)
->where("key",$id)
->get();
return $return;
}
You can just add a new argument to the method getEmail.
$values = array(
'RECEIVER_PHYSICAL',
'RECEIVER_VIRTUAL',
'EMAIL_TEMPLATE'
);
foreach ($values as $id) {
$data['email'] = $this->mod_rewards->getEmail($id, $values);
}
add the argument like this:
public function getEmail($id, $values) {
though i think there must be something wrong with the design here.
Just rewrite your model function as:
public function getEmail($id,$array) {
//use array here
$info = $this->core_db->select('*')
->from($this->schema.'.'.$this->v_system_config)
->where("key",$id)
->get();
return $return;
}
While calling this model in controller you need to pass this array.
I have an object named Property, how can I convert that to array
/**
* #Route("/property/{id}/pictures/download_all", name="property_zip_files_and_download", methods={"GET"})
*/
public function zipFilesAndDownloadAction(Property $property)
{
$pictures = $property->pictures;
$compressPath = $this->get('some_service.property.picture_compress')->compress($pictures);
//some code for download...
....
}
How can I convert the pictures to array and pass it to my service? Can anyone please help me out here
What is pictures?
In simple cases you can use (array) $pictures.
Also, you can use Serializer Normalizers
if variable is Iterator (ArrayCollection or PersistentCollection for example) and service method has array as typehinting, you can convert it to simple array with iterator_to_array function.
Try:
$compressPath = $this->get('some_service.property.picture_compress')->compress(iterator_to_array($pictures));
This is how I turned my model MyObject object into a data array.
class MyObject{
public function getContentArr($objInstance, $filter=true){
$arr = array();
if($objInstance){
$response = new Response(GeneralFunctions::getKernel()->getContainer()->get('serializer')->serialize($objInstance, 'json'));
$arr = json_decode($response->getContent(), true);
//remove all items that are null, or empty string
//if($filter){
//$arr = $this->filterContentArr($arr); // optional
//}
}
return $arr;
}
/**
* Returns filtered array removing empty/null
*
* #param array $data
* #return array
*/
public function filterContentArr($data){
foreach($data as $key => $val){
if(is_array($val)){
$data[$key] = $this->filterContentArr($val);
if(empty($data[$key])){
unset($data[$key]); //remove empty array
}
}else{
if($val == "" || $val == null){
unset($data[$key]);
}
}
}
return $data;
}
}
$myObject = new MyObject();
print_r($myObject->getContentArr($myObject));