Is it possible to separate data by keys in Laravel? - php

From the database I get the data in the following style:
Array
(
[0] => stdClass Object
(
[id] => 2
[name] => edit_sites
)
[1] => stdClass Object
(
[id] => 1
[name] => view_sites
)
)
Does Laravel have any built-in methods for obtaining data by the keys like this:
Array
(
[id] => Array
(
[0] => 1
[1] => 2
)
[name] => Array
(
[0] => view_sites
[1] => edit_sites
)
)
or i need to do it by myself ?

Unfortunately, there is none, you have to do it by yourself albeit an easy one really.
$processedData = array();
foreach($dbData as $row) {
foreach($row as $dbKey => $value) {
$processedData[$dbKey][] = $value;
}
}

If you're getting the data back as a raw array (which you seem to be), then array_pluck will do most of what you want:
For example:
// you could use this wherever you needed the specific lists
$ids = array_pluck($results, 'id'); // [ 1, 2 ]
// or if you wanted the array exactly as asked for in the question:
$sortedArray = array(
'id' => array_pluck($results, 'id'),
'name' => array_pluck($results, 'name')
);
// [
// 'id' => [1,2],
// 'name' => [ 'view_sites', 'edit_sites' ]
// ]
If you are getting the results as some kind of Illuminate\Support\Collection class (say, from an Eloquent query), then you can use the lists method on the Collection as an alias to array_pluck
$results->lists('id'); // [ 1, 2 ]

Related

Adding variable to upcomming array

I have a multi dimensional array with some values coming from a foreach, i need to insert this values into the array, but at this moment my result is this, not sure why:
Array
(
[0] => Array
(
[title] => MySecure
)
[1] => Array
(
[productTitle] => My New Product
)
[2] => Array
(
[title] => My Second Company
)
[3] => Array
(
[productTitle] => Another Product
)
[4] => Array
(
[productTitle] => Away Product
)
)
This is wrong, what i need is:
Array
(
[0] => Array
(
[title] => MySecure
[productTitle] => My New Product
)
[2] => Array
(
[title] => My Second Company
[productTitle] => Another Product
[productTitle] => Away Product
)
)
So this is what i have done:
$companies[] = [
'title' => $getCompanie->getTitle()
];
Then inside products :
$companies[] = [
'productTitle' => $getProduct->getTitle(),
];
so i assume im using the wrong array call, not sure about array_push?
You need to add both keys in the same inner array, rather than pushing them separately.
Use nested loops to get all the products associated with a company in the same loop.
$companies = [];
foreach ($all_companies as $companie) {
$products = [];
foreach ($companie->getProducts() as $getProduct) {
$products[] = $getProduct->getTitle());
}
$companies[] = [
'title' => $companie->getTitle(),
'productTitle' => $products
]
}
I've had to make up names for some of the things I assumed are in your code. You should be able to extrapolate from this to your actual design.
$newArray= [
'title' => array_map($yourArray,fn($ar)=>$ar['title']),
'productTitle' => array_map($yourArray,fn($ar)=>$ar['productTitle'])
];

In a SQL loop how to I amend to a sub-array?

I am trying to add data in from SQL loop into a specific section of an array, however it does't seem to keep the array format when I do a json encode.
I create the array:
$array['type'] = 'update';
$array['tags']['data'] = array(array('name' => "Tag", 'tags' => array()));
Then in my sql loop in the while:
$array['tags']['data']['tags'][] = array('a' => "$row[a]", 'b' => "$row[b]");
after this loop, json encode:
json_encode($array);
In the output, the "tags" has the rows added under data, and the one I setup for the array is now under tags:data:0:tags , and it has not populated this.
Also data has gone from [ ] to { }, and I need it to be [{ }]. If I take out the loop, the data section is with [ { } ] as expected.
Hope that makes sense! if not can expand more.
Many thanks
You have an extra array between data and tags
$array['tags']['data'] = array(array('name' => "Tag", 'tags' => array()));
print_r($array);
Output
Array
(
[tags] => Array
(
[data] => Array
(
[0] => Array
(
[name] => Tag
[tags] => Array
(
)
)
)
)
)
Then you try to access (for assignment)
$array['tags']['data']['tags'][] = array('a' => "$row[a]", 'b' => "$row[b]");
Which based on your $array should actually be
$array['tags']['data'][0]['tags'][]
Or something like that...
Without more to actually go on that's the best I can do, this really doesn't rate a answer, but there was no way to illustrate an array with that much nesting within a comment.
What you'll wind up with is something like this:
Array
(
[tags] => Array
(
[data] => Array
(
[0] => Array
(
[name] => Tag
[tags] => Array
(
)
),
[tags] => Array
(
[0] => Array
(
a => "$row[a]",
b => "$row[b]"
)
[1] => Array(...)
)
)
)
)
Which because of the mixed keys ['data' => [0 => ['name'=>'Tag',...], 'tags' => [...]] Will give you a JSON object at that location {data : {0:{name:"Tag",...},tags:[]}}
P.S this really annoys me "$row[a]" - I don't know why but it does ... lol

How to move array in multidimensional array using key value?

How to move array in multidimensional aray with key value?
I'm using array_push to add values to a multidimensional array. i have an array
$myArray = Array(Array('code' => '1','room' => Array('name' => 'Room-A')),Array('code' =>'1','room' => Array('name' => 'Room-B'
)), Array('code' => '2','room' => Array('name' => 'Vip-1')),Array('code' => '2','room' => Array('name' => 'Vip-2')));
i tried using code like this:
for ($i=0; $i <count($myArray) ; $i++) {
if ($myArray[$i]['code']=='1') {
array_push($myArray[$i]['room'], $myArray[$i]['room']);
}
else{
array_push($myArray[$i]['room'], $myArray[$i]['room']);
}
}
i want the result like this :
Array
(
[0] => Array
(
[code] => 1
[room] => Array
(
[0] => Array
(
[name] => Room-A
)
[1] => Array
(
[name] => Room-B
)
)
)
[1] => Array
(
[code] => 2
[room] => Array
(
[0] => Array
(
[name] => Vip-1
)
[1] => Array
(
[name] => Vip-2
)
)
)
)
Any idea how to join this array?
You can use array_reduce to summarize the array into an associative array using the code as the key. Use array_values to convert the associative array into a simple array.
$myArray = ....
$result = array_values(array_reduce($myArray, function($c, $v){
if ( !isset( $c[ $v['code'] ] ) ) $c[ $v['code'] ] = array( 'code' => $v['code'], 'room' => array() );
$c[ $v['code'] ]['room'][] = $v['room'];
return $c;
},array()));
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[0] => Array
(
[code] => 1
[room] => Array
(
[0] => Array
(
[name] => Room-A
)
[1] => Array
(
[name] => Room-B
)
)
)
[1] => Array
(
[code] => 2
[room] => Array
(
[0] => Array
(
[name] => Vip-1
)
[1] => Array
(
[name] => Vip-2
)
)
)
)
This is the foreach() equivalent of Eddie's answer (I find it easier to read/maintain).
Code: (Demo)
$myArray = [
['code' => '1', 'room' => ['name' => 'Room-A']],
['code' => '1', 'room' => ['name' => 'Room-B']],
['code' => '2', 'room' => ['name' => 'Vip-1']],
['code' => '2', 'room' => ['name' => 'Vip-2']]
];
foreach ($myArray as $row) {
if (!isset($result[$row['code']])) {
$result[$row['code']] = ['code' => $row['code'], 'room' => [$row['room']]];
// ^------------^-- pushed deeper
} else {
$result[$row['code']]['room'][] = $row['room'];
// ^^-- pushed deeper
}
}
var_export(array_values($result));
This question is very similar to many pre-existing questions that want to group by a particular column. I was not able to find an exact duplicate to close with because the requirement of this question is to created a deeper structure to contain the room sub arrays.
Typically I would write:
if (!isset($result[$row['code']])) {
$result[$row['code']] = $row;
to cut down on syntax, but the new output structure must be applied to both the if and the else.
To avoid key duplication/collision, the room subarrays need to be pushed/indexed to a lower level.
In the end, the technique has been demonstrated here many, many times on StackOverflow. You target an element value to group by and use that value as the temporary key as you iterate the input array. Checking if the temporary keys exist or not is the fastest way to determine if a group is new or previously encountered. When you are done, call array_values() to remove the temporary keys (re-index the array).

How to attach data from one array to another in php

I am building a [post, comments] project where post details are stored in posts table and comment details are stored in comments table. The project is generated in Laravel(Php). Here is the piece of code.
//get data from Post table
$posts = $this->postsRepo->getAllPosts();
//get data from comments table
$comments = $this->commentRepo->getAllComments();
print_r($posts);
print_r($comments);
The result of post table
Array
(
[0] => stdClass Object
(
[id] => 1
[post_text] => This is a test post
)
)
[1] => stdClass Object
(
[id] => 2
[post_text] => This is another test
)
)
The result of comments table
Array
(
[0] => stdClass Object
(
[id] => 1
[post_id] => 1
[comments_text] => This is a test comment 1
)
[1] => stdClass Object
(
[id] => 2
[post_id] => 1
[comments_text] => This is a test comment 2
)
)
Now I want result like
Array
(
[0] => stdClass Object
(
[id] => 1
[post_title] => This is a test post
[comments] => Array
(
[0] => stdClass Object
(
[id] => 1
[post_id] => 1
[comment_text] => This is a test comment 1
)
[1] => stdClass Object
(
[id] => 2
[post_id] => 1
[comment_text] => This is a test comment 2
)
)
)
)
[1] => stdClass Object
(
[id] => 2
[post_title] => This is another test
[comments] => Array()
)
)
I've used following technique, and it is working
foreach ($posts as $postIndex => $post) {
foreach ($comments as $commentIndex => $comment) {
if($post->id == $comment->post_id) {
$posts[$postIndex]->comments[] = $comment;
}
}
}
There's another way like running comments inside post for loop. I'll send the post_id to comments table. But this technique will be slow, as data increases
Could anybody please suggest a better technology to solve this issue?
Also, I used Repository design pattern for getting posts & comments
There are a couple of ways of doing this, depending on the version of PHP your using (although 1 will always work). The main principle is to index one of the arrays by the ID so that instead of looping over both arrays, you can use an index to set the values. As each post can have multiple comments, it seemed easier to index the posts by the ID and loop over the comments adding them into the correct post...
$posts = [
(object)[
"id" => 1,
"post_text" => "This is a test post"
],
(object)[
"id" => 2,
"post_text" => "This is another test"
]
];
$comments = [(object)
[
"id" => 1,
"post_id" => 1,
"comments_text" => "This is a test comment 1"
],
(object)
[
"id" => 2,
"post_id" => 1,
"comments_text" => "This is a test comment 2"
]
];
$postIndex = array_column($posts, null, "id");
//$postIndex = array_reduce($posts, function ($result, $post) { // PHP pre 7
// $result[$post->id] = $post;
// return $result;
//}, array());
foreach ( $comments as $comment ) {
$postIndex[ $comment->post_id ]->comments[] = $comment;
}
echo "<pre>";
print_r($postIndex);
Outputs...
Array
(
[1] => stdClass Object
(
[id] => 1
[post_text] => This is a test post
[comments] => Array
(
[0] => stdClass Object
(
[id] => 1
[post_id] => 1
[comments_text] => This is a test comment 1
)
[1] => stdClass Object
(
[id] => 2
[post_id] => 1
[comments_text] => This is a test comment 2
)
)
)
[2] => stdClass Object
(
[id] => 2
[post_text] => This is another test
)
)
The only difference is that from PHP 7.0, you can use array_column() with an array of objects. Prior to that you had to manually do the conversion.
You better use eloquent relationships...
but to answer your question for current case, if you need to accomplish this in php way.
// for all the post of the posts array
foreach ($posts as $key => $value) {
// get comments which only belongs to the post
$post_comments = [];
foreach ($comments as $comment) {
if ($comment['post_id'] == $value['id']) {
array_push($post_comments, $comment);
}
}
// add a new attribute (comments) to each post
// set created comments array of the post
$post[$key]['comments'] = $post_comments;
}
If you loop posts then you can use array_intersect and array_intersect_key.
This means you only loop one array once but use array functions to get the correct comments.
This means the arrays have to be arrays and not objects.
Foreach($posts as $key => $post){
$matches = array_intersect(array_column($comments, "post_id"), [$post["id"]]);
$new[$key][] = $post;
$new[$key]["comments"][] = array_intersect_key($comments, $matches);
}
Var_dump($new);
https://3v4l.org/eq20D

Joining arrays to go in to a multidimensional array

I need to dynamically produce child elements of an array, these are arrays them selves. So the end result should be (this is a simplified version of the code below to make it easier to understand):
Array
(
[id] => 5000038642
[name] => TrackVia Legacy Section of Array
[description] =>
[table_id] => 5000005024
[records] => Array
(
[0] => Array
(
[id] => 1
[table_id] => 1
[fields] => Array
(
[Name] => First Item
)
)
[1] => Array
(
[id] => 1
[table_id] => 1
[fields] => Array
(
[Name] => Second Item
)
)
)
)
The nested arrays within Results are produced dynamically from a MySQL table, so >
$allItems = array();
$item = array();
// Get each result and build the arrya
while($row = $resultAvailableBoxes->fetch_assoc()) {
$item = array (
"id"=> $row['id'],
"table_id"=> $row['id'],
"fields"=> array (
"Name"=> $row['box_title'],
)
);
// Append the arrays on to each other
$allItems[] = array_merge($allItems, $item);
}
// Place the arrays within the "parent" array
$completeArray = array(
"id"=> 1000,
"name"=> "Sample",
"description"=> "",
"table_id"=> 1000,
"records"=>
$allItems
);
As you can see I am then also trying to append each new array on to the last, before placing those arrays in to the "parent" array. This is where the problems happen.
Using the method
$allItems[] = array_merge($allItems, $item);
I get every array appended on to the last, but then again and again. Like this:
Array
(
[id] => 5000038642
[name] => TrackVia Legacy Section of Array
[description] =>
[table_id] => 5000005024
[records] => Array
(
[0] => Array
(
[id] => 1
[table_id] => 1
[fields] => Array
(
[Name] => Texan BBQ 1
)
)
[1] => Array
(
[0] => Array
(
[id] => 1
[table_id] => 1
[fields] => Array
(
[Name] => Texan BBQ 1
)
)
[id] => 9
[table_id] => 9
[fields] => Array
(
[Name] => Goan Sorpotel with Pea & Mint Pilau and Tomato Chutney
)
)
)
)
When I have 20 items, you can see this would become massive list and just doesn't work. Using the method
$allItems = array_merge($allItems, $item);
Returns only the last array being appended (i.e. it always overwrites whats already in the "allItems" array.
I have also used a simple method that I didn't expect to work, and sure enough it didnt:
$allItems .= $item;
I've come to the conclusion after reading these stackover flow questions which seem like the same thing but aren't or give weird results that I must be approaching this all wrong. Is this the wrong method full stop, or is it that I have missed something out to stop the child elements being continually added?
Appending Arrays (Stack Overflow)
Can't concatenate 2 arrays in PHP
I've lost count of the other questions I've look at on this, including the PHP manual but I can't find anything more relevant the arrays_merge
why don't you just do this?
$items = array();
while($row = $resultAvailableBoxes->fetch_assoc()) {
$items[] = array (
"id"=> $row['id'],
"table_id"=> $row['id'],
"fields"=> array (
"Name"=> $row['box_title'],
)
);
}
// Place the arrays within the "parent" array
$completeArray = array(
"id"=> 1000,
"name"=> "Sample",
"description"=> "",
"table_id"=> 1000,
"records"=> $items
);
this should create an array with all the items and then add it to the $completeArray
Try to use $allItems[] = $item; instead of $allItems[] = array_merge($allItems, $item);

Categories