Laravel cant flatten array after collection->forget - laravel

I have a loop inside loop on Laravel collection, and sometimes i need to delete some objects from second loop collection. Here is the code
public function remove_if_found($id)
{
$all_groups = Group::all();
$all_groups->load('templates');
foreach ($all_groups as $group)
{
foreach ($group->templates as $key => $template)
{
if($template->id = $id)
{
$group->templates->forget($key);
}
}
}
return $all_groups;
}
The problem is that collection of group->templates turns from simple(not assoc) array to object. Here is example how response looks
I am trying to flatten $group->templates->flatten() but in final response templates are still as object but not as array.
This test flatten works
...
foreach ($all_groups as $group)
{
foreach ($group->templates as $key => $template)
{
if($template->id = $id)
{
$group->templates->forget($key);
}
}
return $group->templates->flatten()//This code works i get fluttened array
}
But final variant still returns me object instead of array
$all_groups = Group::all();
$all_groups->load('templates');
foreach ($all_groups as $group)
{
foreach ($group->templates as $key => $template)
{
if($template->id = $id)
{
$group->templates->forget($key);
}
}
$group->templates->flatten()//Use flatten here
}
return $all_groups;//Templates are returned not as an array but still as an object (Same variant as on attached image)
}

Use values() to reset the keys and setRelation() to replace the relationship:
public function remove_if_found($id)
{
$all_groups = Group::all();
$all_groups->load('templates');
foreach ($all_groups as $group)
{
foreach ($group->templates as $key => $template)
{
if($template->id = $id)
{
$group->setRelation('templates', $group->templates->forget($key)->values());
}
}
}
return $all_groups;
}
You can also use except() instead of forget():
public function remove_if_found($id)
{
$all_groups = Group::all();
$all_groups->load('templates');
foreach ($all_groups as $group)
{
$group->setRelation('templates', $group->templates->except($id));
}
return $all_groups;
}

Related

How to get all routes within a route group?

I need to print a main menu and instead of having a database where the links/ routes are stored I thought it there would be a way to get all routes that are in a named group, but all I find is getting routes by action.
web.php
Route::group(['as' => 'main'], function () {
Route::get('/', function () {
return view('pages.start');
})->name('Home');
Route::get('/foobar', function () {
return view('pages.foobar');
})->name('Home');
Route::get('/business', function () {
return view('pages.business');
})->name('Business');
});
I was looking for something like:
$routes = getRoutesByGroup('main');
I cannot really believe that a function like that doesnt exist in current Laravel but I cant seem to find this. What am I missing?
Maybe this can solve partially in your case
function getRoutesByStarting($start = '')
{
$list = \Route::getRoutes()->getRoutesByName();
if (empty($start)) {
return $list;
}
$routes = [];
foreach ($list as $name => $route) {
if (\Illuminate\Support\Str::startsWith($name, $start)) {
$routes[$name] = $route;
}
}
return $routes;
}
usage
getRoutesByStarting('main')
More general solution
function getRoutesByGroup(array $group = [])
{
$list = \Route::getRoutes()->getRoutes();
if (empty($group)) {
return $list;
}
$routes = [];
foreach ($list as $route) {
$action = $route->getAction();
foreach ($group as $key => $value) {
if (empty($action[$key])) {
continue;
}
$actionValues = Arr::wrap($action[$key]);
$values = Arr::wrap($value);
foreach ($values as $single) {
foreach ($actionValues as $actionValue) {
if (Str::is($single, $actionValue)) {
$routes[] = $route;
} elseif($actionValue == $single) {
$routes[] = $route;
}
}
}
}
}
return $routes;
}
usage
getRoutesByGroup(['middleware' => 'api']);
getRoutesByGroup(['middleware' => ['api']]);
getRoutesByGroup(['as' => 'api']);
getRoutesByGroup(['as' => 'api*']);
getRoutesByGroup(['as' => ['api*', 'main']]);
$allRoutes = Route::getRoutes()->getRoutes(); // fetch all rotues as array
$name = 'main'; // specify your full route name
$grouped_routes = array_filter($allRoutes, function($route) use ($name) {
$action = $route->getAction(); // getting route action
if (isset($action['as'])) {
if (is_array($action['as'])) {
return in_array($name, $action['as']);
} else {
return $action['as'] == $name;
}
}
return false;
});
// output of route objects in the 'main' group
dd($grouped_routes);

how to return true to parent filter loop from child each loop on collection laravel

$products = $category - > products;
foreach($params as $key => $item) {
if ($key === 'attribute') {
$attributes = $item;
// dd($attributes);
foreach($attributes as $subkey => $value) {
// dd($subkey, $value);
$attr_ids = ProductAttribute::where('name', $subkey) - > pluck('id') - > toArray();
// print_r($attr_ids);
// dd($attr_ids);
foreach($attr_ids as $attr_id) {
$filtered_products = new Collection();
$filtered_products = $products - > filter(function($item) use($attr_id, $value)
{
// echo $attr_id;
$item - > characteristics - > each(function($charac) use($value)
{
// print_r($charac->value);
// dd($value);
return in_array($charac - > value, $value);
});
});
$products = $filtered_products;
}
}
}
}
I'm developing a filter.
after retrieving products by category
I'm looping through params url(which is http://127.0.0.1:8000/dariy?attribute[size][0]=xs&attribute[rang][0]=black&property[color][0]=green&property[color][1]=tomato)
in DB, I have got a table of products,productCharacteristics, and productAttributes.
I'm retrieving ids of attributes by name which are given in params(key).
productCharacteristics is being retrieved by relationship.
while I go through the product's characteristics, I check each characteristic's value against in value from params.
if right I should return true to filter. but here is where I'm stuck.
inside filter closure there's each that's why I can't return directly to filter.
How can I do that?
I'm
foreach ($params as $key => $item) {
if ($key === 'attribute' && !empty($item)) {
$filtered_products = new Collection();
$attributes = $item;
// dd($attributes);
foreach ($attributes as $subkey => $value) {
// dd($subkey, $value);
$attr_ids = ProductAttribute::where('name', $subkey)->pluck('id')->toArray();
// print_r($attr_ids);
// dd($attr_ids);
$attr_status = false; // assume there's no match
foreach ($attr_ids as $attr_id) {
$filtered_products = $products->filter(function ($item) use ($attr_id, $value, &$attr_status)
{
// assume product can't pass filter
$item->status = false;
$item->characteristics->each(function ($charac) use (&$item, $value, $attr_id)
{
// product characteristic's attribute_id and charac value match set to tru to return to filtered prducts
if($attr_id == $charac->attribute_id && in_array($charac->value, $value)){
$item->status = true; // now product can pass.
return true;
}
});
if ($item->status === true) {
$attr_status = true;
return true;
}else{
return false;
}
});
// setting there's a match for this filter.
if ($attr_status) {
continue 2; // skipping to next filter
}
}
}
$products = $filtered_products;
}
}
in first level of each closure I set a variable $attr_status = false so the each filter keeps going on.
2.in every product attribute checked the value and attribute id do match or not
if yes $product goes in the filter and I set $attr_status = true;
so the filter cycle can be skipped.

Laravel Session Forget using key

I've tried to use session forget of laravel but unfortunately I cant manage to run it also I'm trying to use UNSET() still not working, attached below is Controller for receiving a new product via saving is using array and validating whenever that product is already saved it will no be saved anymore.
$product_details = array('product_id' => $request->get('product_id'),
'product_qty' => $request->get('product_qty'));
$products = $request->session()->get('product');
if ($request->session()->has('product')) {
foreach ($products as $key => $value)
{
if($value['product_id']==$request->get('product_id'))
{
$request->session()->forget('product',$request->get('product_id'));
}
}
session()->push('product', $product_details);
}
else
{
session()->push('product', $product_details);
}
return true;
If I get your question, this code should work and a bit of optimizing. You don't need to forget old product and add a new product, that waste of time, just add a flag $product_exists to define is exists or not then add/not add.
$product_details = array('product_id' => $request->get('product_id'),
'product_qty' => $request->get('product_qty'));
$product_exists = false;
if ($request->session()->has('product'))
{
$products = $request->session()->get('product');
foreach ($products as $key => $value)
{
if($value['product_id']==$request->get('product_id'))
{
$product_exists = true;
}
}
if(!$product_exists){
session()->push('product', $product_details);
}
} else {
session()->push('product', $product_details);
}
return true;
Hope this help.
I did my own version by using .$key
$product_details = array('product_id' => $request->get('product_id'),
'product_qty' => $request->get('product_qty'));
$products = $request->session()->get('product');
if ($request->session()->has('product')) {
foreach ($products as $key => $value)
{
if($value['product_id']==$request->get('product_id'))
{
$request->session()->forget('product.'.$key);
}
}
session()->push('product', $product_details);
}
else
{
session()->push('product', $product_details);
}
return true;
}

How to parse data on the backend

I am using Angular2 for my frontend and laravel for my back end and I'm having trouble saving the data to the database
Each of the keys in the Order[] (ex prodName, prodDesc) are the same as the column names in the database so I was trying to loop the request and save the data but its not working
public function Order(Request $request) {
$input = $request->all();
$order = new Order;
foreach ($input as $key => $value) {
if (array_key_exists($key, $input) && !empty($value)) {
$order->$key = $value;
}
}
}
if($order->save()) {
return response()->json(['order' => $order], 201);
}
order.interface.ts
export interface Order {
prodName: string;
prodDesc: string;
}
Adding the item to the order
addToOrder.component.ts
orders = [] as Order[];
saveItem(): void {
this.orders.push({prodName: this.prodName, prodDesc: this.prodDesc});
this.dataService.save(this.orders).then(() => {
this.navCtrl.pop(Search);
});
}
How each item is stored in storage
order.storage.ts
save(data : Order[]): Promise<any> {
return this.getData().then((products: any[]) => {
if (products) {
products = products.concat(data);
return this.storage.set('products', products);
}
return this.storage.set('products', data);
});
}
How I retrieve the order from storage
order.component.ts
private order = [] as Order[];
constructor(public dataService: OrderStorage, public OrderService: OrderService) {
this.dataService.getData().then((products) => {
if (products) {
this.order = products;
}
});
}
onSubmit() {
this.OrderService.submit(this.order)
.subscribe();
}
Posting the data to the back end
order.service.ts
submit(order: Order[]): Observable<any> {
return this.http.post(localapi.app, order)
.map(
(response: Response) => {});
}
Structure of the order data being sent
Retrieving the data on the backend
public function Order(Request $request) {
$input = $request->all();
var_dump($input);
}
the var_dump output
It's actually foreach ($input as $key => $arr), then you can use your loop:
foreach ($input as $arr) {
foreach ($arr as $key => $value) {
if (array_key_exists($key, $arr) && !empty($value)) {
$order->$key = $value;
}
}
}
The first set of elements you will encounter in your loop are arrays, then you can loop the property off of your array.

How to split array name in laravel

I am working on a laravel webservice, my code is the following
public function getLanguageshow(){
$user_id=$_REQUEST['user_id'];
$profiles="SELECT * FROM `abserve_language_details` as `le` where `le`.`user_id`=".$user_id;
$details=\DB::SELECT($profiles);
$prof = \DB::table('abserve_proficiency')->select('*')->get();
$vals = explode(',', $details[0]->lan_proficiency);
foreach ($prof as $key => $value) {
if(in_array($value->id, $vals))
$lang_prof[] = $value->name;
}
$lang_prof = implode(',', $lang_prof);
foreach ($details as $key => $value) {
$value->lang_prof = $lang_prof;
}
$response['language_details'] = $details;
echo json_encode($response);exit;
}
and my result is
{
"language_details":[
{
"id":12,
"user_id":121,
"languages":"Tamil,English,Chinese,Bulgarian,Amharic,Fiji",
"lan_proficiency":"1,5,4,3,2,4",
"read":"1,1,1,1,1,1",
"write":"1,1,1,1,1,1",
"speak":"1,1,1,1,1,1",
"lang_prof":"elementary,limited_working,professional_working,full_professional,native_or_bilingual"
}
]
}
In this result lan_proficiency have 6 ids (1,5,4,3,2,4) but that id name ("lang_prof":"elementary,limited_working,professional_working,full_professional,native_or_bilingual") displays 5 names only 4 is repeated
I want result
{
"language_details":[
{
"id":12,
"user_id":121,
"languages":"Tamil,English,Chinese,Bulgarian,Amharic,Fiji",
"lan_proficiency":"1,5,4,3,2,4",
"read":"1,1,1,1,1,1",
"write":"1,1,1,1,1,1",
"speak":"1,1,1,1,1,1",
"lang_prof":"elementary,limited_working,professional_working,full_professional,native_or_bilingual,full_professional"
}
]
}

Resources