Let's say I have 2 functions that can call each other
public static function goToAction($action,$sender_id)
{
$actions = array();
$logic = file_get_contents('../../logic/logic.json');
$logic_array = json_decode($logic, true);
unset($logic);
if (!isset($logic_array[$action])) {
return false;
} else {
foreach ($logic_array[$action] as $action) {
$actions[] = self::parseActionType($action,$sender_id);
}
}
return $actions;
}
public static function parseActionType($actions,$sender_id)
{
$data = array();
foreach ($actions as $key => $action) {
switch ($key) {
case 'goto': {
$goto_actions = self::goToAction($action,$sender_id);
foreach ($goto_actions as $goto_action){
$data[] = $goto_action;
} break;
...
}
}
return $data;
}
and here is my json file:
"no_return": [
{ "text": "Должно быть: 1, 2, 3"},
{ "text": "1" },
{ "goto": "2nr", "no_return": true},
{ "text": "5" }
],
"2nr": [
{ "text": "2" },
{ "goto": "3", "no_return": true},
{ "text": "4"}
],
"3nr": [
{ "text": "3" }
],
it returns 12345 , and its right, but how can I make it return 123 if no_return is setted to true? Maybe function must return something?
foreach ($logic_array[$action] as $action) {
$actions[] = self::parseActionType($action,$sender_id);
if (!empty($action['no_return'])) { break; }
}
Using break inside of a loop stops it even if there are more element left, there is also continue this will end the current run and proceed with the next element.
Related
I have flat array like:
[
{
"id": "1",
"parentId": "0",
"cost": 1000
},
{
"id": "2",
"parentId": "1",
"cost": 2000
},
{
"id": "3",
"parentId": "2",
"cost": 4000
},
...
]
Requirement:
convert flat array to tree array --> (DONE)
sum of each id is the total price of it and its child
now the problem appears:
should summation be done before or after converting from flat array to tree array
This is my code is try convert flat to tree:
public function buildTree(array $flat)
{
$grouped = [];
$fnBuilder = function ($companies) use (&$fnBuilder, $grouped) {
foreach ($companies as $k => $company) {
$id = $company['id'];
if (isset($grouped[$id])) {
$company['children'] = $fnBuilder($grouped[$id]);
}
$companies[$k] = $company;
}
return $companies;
};
return $fnBuilder($grouped[0]);
}
My expect result is like:
[
{
"id": "1",
"sum": 7000,
"children": [
{
"id": "2",
"sum": 6000,
"children": [
{
"id": "3",
"sum": 4000,
},
I wonder if it's possible to handle the summing inside the buildTree?
My idea is to have a tree and then handle the sum of sublevels, but i can't handle assigning the sum to the parent element
I created a class and incorporated your ideas.
class TreeBuilder {
private $flatArr;
private $idToNode;
public function __construct($flatArr) {
// Keep the flat arr in case we need it.
$this->flatArr = $flatArr;
// Create an array to lookup a node to determine if it exists.
$this->idToNode = array_combine(array_column($flatArr, 'id'), $flatArr);
}
public function buildTree() {
// create an empty array to hold root nodes
$roots = [];
// iterate through each node and add it to its parent's children list
foreach ($this->flatArr as &$node) {
$id = $node['id'];
$parentId = $node['parentId'];
if (isset($this->idToNode[$parentId])) {
$this->out("add child to $parentId " . print_r($node, true));
$parentNode = &$this->idToNode[$parentId];
if ( isset($parentNode['children']) ) {
$parentNode['children'] = [&$this->idToNode[$id]];
} else {
$parentNode['children'][] = &$this->idToNode[$id];
}
// $children[] = &$node;
} else {
$this->out("add to root " . print_r($node, true));
$roots[] = &$this->idToNode[$id];
}
}
// calculate the sum of each node and its children recursively
foreach ($roots as &$root) {
$this->calculateSum($root);
}
return $roots;
}
private function calculateSum(&$node) {
// calculate the sum of the current node
$node['sum'] = $node['cost'];
// recursively calculate the sum of the children nodes
$children = &$node['children'];
if (isset($children)) {
foreach ($children as &$child) {
$node['sum'] += $this->calculateSum($child);
}
}
return $node['sum'];
}
private function out($s) {
echo "$s\n";
}
}
You could build the tree without recursion, and then use recursion to update the sum, in post-order depth first order:
function buildTree(array $flat) {
foreach ($flat as ["id" => $id, "cost" => $sum]) {
$keyed[$id] = ["id" => $id, "sum" => $sum];
}
foreach ($flat as ["id" => $id, "parentId" => $parentId]) {
if (isset($keyed[$parentId])) {
$keyed[$parentId]["children"][] = &$keyed[$id];
} else {
$root = &$keyed[$id];
}
}
function updateSum(&$node) {
foreach ($node["children"] ?? [] as &$child) {
$node["sum"] += updateSum($child);
}
return $node["sum"];
}
updateSum($root);
return $root;
}
Example run:
$flat = json_decode('[
{
"id": "1",
"parentId": "0",
"cost": 1000
},
{
"id": "2",
"parentId": "1",
"cost": 2000
},
{
"id": "3",
"parentId": "2",
"cost": 4000
}
]', true);
$root = buildTree($flat);
print_r($root);
Controller: for get data from session
public function SessionDestroy(Request $request)
{
if ($request->session()->has('data')) {
return $request->session()->get('data');
} else {
return "No Data";
}
}
this is session data i have and i want remove a single array:
[
{
"app_date": "2022-03-16",
"department": "2",
"doctor": "4",
"fee": "150"
},
{
"app_date": "2022-03-17",
"department": "2",
"doctor": "4",
"fee": "150"
},
{
"app_date": "2022-03-16",
"department": "2",
"doctor": "4",
"fee": "150"
}
]
So, How can i remove a single Array or Item
you don't have a unique id in your session to remove by this unique id ..
this may help you !
public function SessionDestroy(Request $request)
{
if (session()->has('data')) {
session()->forget('data');
if(!empty(request('app_date')) && is_array(request('app_date')))
$new_data = [];
$x = 0;
foreach(request('app_date') as $app_date){
$new_data[]['app_date'] = $app_date;
$new_data[]['department'] = request('department')[$x]??'';
$new_data[]['doctor'] = request('doctor')[$x]??'';
$new_data[]['fee'] = request('fee')[$x]??'';
}
session()->put('data', $new_data);
return session('data');
} else {
return "No Data";
}
}
I want to make a folder tree array in php. I coded something, it is almost done but there is some issue.
So, all files and folders should be in same json as they are in folders. Here my codes:
function getDirContents($dir, &$results = array(), $counter = 0 ) {
$files = scandir($dir);
foreach ($files as $key => $value) {
$path = realpath($dir . DIRECTORY_SEPARATOR . $value);
if (!is_dir($path)) {
$results[] = array('name'=>$path,'type'=>'file');
} else if ($value != "." && $value != "..") {
$results[] = array('name'=>$path,'type'=>'folder','subfolders'=>array());
getDirContents($path, $results[count($results)]['subfolders']);
}
}
return $results;
}
print_r(json_encode(getDirContents('./')));
The result is like below. But it has subfolders label at different place. For example; subfolder test4 should be in test2 subfolder buut it is district from test2 folder.
[
{
"name":"C:\\xampp\\htdocs\\test\\test.php",
"type":"file"
},
{
"name":"C:\\xampp\\htdocs\\test\\test.txt",
"type":"file"
},
{
"name":"C:\\xampp\\htdocs\\test\\test1",
"type":"folder",
"subfolders":[
]
},
{
"subfolders":[
{
"name":"C:\\xampp\\htdocs\\test\\test1\\test2",
"type":"folder",
"subfolders":[
]
},
{
"subfolders":[
{
"name":"C:\\xampp\\htdocs\\test\\test1\\test2\\test4",
"type":"folder",
"subfolders":[
]
},
{
"subfolders":null
}
]
},
{
"name":"C:\\xampp\\htdocs\\test\\test1\\test3.txt",
"type":"file"
}
]
},
{
"name":"C:\\xampp\\htdocs\\test\\test_1.php",
"type":"file"
}
]
Result should be like that:
[
{
"folder1": {
"name": "test1.txt",
"type": "file",
"subfolders": {
"subfolder1": {
"name": "test1",
"type": "folder"
},
"subfolder2": {
"name": "test2",
"type": "folder",
"subfolders": {
"subfolder3": {
"name": "test3",
"type": "folder"
},
"subfile":{
"name":"test3.txt"
"type":"file"
}
}
}
}
}
}
]
I hope I could explain my situation. At the result, datas is not in one back datas.
The problem is here when you call getDirContents($path, $results[count($results)]['subfolders']); recursivelly, you provide second parameter with wrong index of array. When you store the first folder to $results it has index in array = 0. But then you use count() function to get number of records from $results array it returns 1 not 0. Also I think you have disabled notice error reporting and you just havent seen it.
Replace count($results) with array_key_last or count($results) - 1
This question already has an answer here:
How to extract and access data from JSON with PHP?
(1 answer)
Closed 3 years ago.
i have a json file of users with all descriptions and its hard to find them with data[2]. imagine in data[0]->users->data i have 3 user and i want to find name = "Stafin" to get description->data->instagram and get value. i'll give you a simple json data
{"data":[
{
"id":1,
"category_name":"Writers",
"users":{
"data":[{
"name":"Steve",
"id":"1",
"description":{
"data":[
{
"instagram":"steveid"
}
]
}
},{
"name":"Stafin",
"id":"2",
"description":{
"data":[
{
"instagram":"stafinid"
}
]
}
},{
"name":"Sara",
"id":"3",
"description":{
"data":[
{
"instagram":"saraid"
}
]
}
}]
}
}
]}
Code:
<?php
$str = file_get_contents('http://localhost/json/test.json');
$json = json_decode($str, true);
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['id'] === $id) {
return $key;
}
}
return null;
}
$id = searchForId('2', $json);
echo $id;
?>
note that: answer it in php language
sorry for my bad English language. if you didn't get that, just tell me to describe more
Your function searches for id, but you said you wanted to search for name. You can make the key another parameter of the function. Then you can use it to find the id in the data array, and the name in the users['data'] array.
function searchArray($searchkey, $searchval, $array) {
foreach ($array as $key => $val) {
if ($val[$searchkey] === $searchval) {
return $val;
}
}
return null;
}
foreach ($json['data'] as $data) {
$user = searchArray('name', 'Stafin', $data['users']['data']);
if ($user) {
echo "Found Stafin";
foreach ($user['description']['data'] as $desc) {
if (isset($desc['instagram'])) {
echo ", Instagram is {$desc['instagram']}";
break;
}
}
break;
}
}
I am trying to create a dynamic endpoint for a API I am creating in order to include some data but only if it is required so I can use it in multiple places.
The idea is to have api.domain.com/vehicle to bring back basic vehicle information but if I did api.domain.com/vehicle?with=owners,history then the idea is to have a function which maps the owners and history to a class which will return data but only if it is required.
This is what I currently have.
public static function vehicle()
{
$with = isset($_GET['with']) ? $_GET['with'] : null;
$properties = explode(',', $with);
$result = ['vehicle' => Vehicle::data($id)];
foreach ($properties as $property) {
array_push($result, static::getPropertyResponse($property));
}
echo json_encode($result);
}
Which will then call this function.
protected static function getPropertyResponse($property)
{
$propertyMap = [
'owners' => Vehicle::owner($id),
'history' => Vehicle::history($id)
];
if (array_key_exists($property, $propertyMap)) {
return $propertyMap[$property];
}
return null;
}
However, the response I'm getting is being nested within a index, which I don't want it to be. The format I want is...
{
"vehicle": {
"make": "vehicle make"
},
"owners": {
"name": "owner name"
},
"history": {
"year": "26/01/2018"
}
}
But the format I am getting is this...
{
"vehicle": {
"make": "vehicle make"
},
"0": {
"owners": {
"name": "owner name"
}
},
"1": {
"history": {
"year": "26/01/2018"
}
}
}
How would I do this so it doesn't return with the index?
Vehicle::history($id) seems to return ['history'=>['year' => '26/01/2018']], ...etc.
foreach ($properties as $property) {
$out = static::getPropertyResponse($property) ;
$result[$property] = $out[$property] ;
}
Or your methods should returns something like ['year' => '26/01/2018'] and use :
foreach ($properties as $property) {
$result[$property] = static::getPropertyResponse($property) ;
}