Laravel sync users to all of categoires which they can be unlimited - php

In our web application each user can create multiple nested category by selecting the parent which that specified with category_id column.
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_id')->index()->nullable();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->string('category_name');
...
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();
});
now you supposed one of our user created this category structure:
multiple nested categories children are unlimited, that means every category can be have child and we can't use any static or fixed number for example in for statement to sync the category to specify users.
my question is how can i set specify users to all of categories from parent?
this query only can set users for single child of parent. you can suppose 1,3,4,5,6,7 in above screen shot and not working for 2 and all of their children
children of parent category can be unlimited and how can we set users from the parent to all of nested and children categories?
$category = Category::whereId($request->category_id)->whereNull('category_id')->with('childrenCategories')->first();
$category->users()->sync($request->users);
foreach ($category->childrenCategories as $category) {
$category->users()->sync($request->users);
}
simplified output of query:
App\Entities\Category {#2114 ▼
...
#attributes: array:11 [▶]
#original: array:11 [▶]
...
#relations: array:1 [▼
"childrenCategories" => Illuminate\Database\Eloquent\Collection {#2118 ▼
#items: array:4 [▼
0 => App\Entities\Category {#2133 ▶}
1 => App\Entities\Category {#2134 ▶}
2 => App\Entities\Category {#2135 ▼
...
#attributes: array:11 [▶]
#original: array:11 [▶]
...
#relations: array:1 [▼
"categories" => Illuminate\Database\Eloquent\Collection {#2138 ▼
#items: array:1 [▼
0 => App\Entities\Category {#2157 ▼
...
#attributes: array:11 [▶]
#original: array:11 [▶]
...
#relations: []
...
}
]
}
]
...
}
3 => App\Entities\Category {#2136 ▶}
]
}
]
...
}

You have to use a recursive function like below:
private function syncCategories($category,$request){
if($category->childrenCategories->first()){
foreach ($category->childrenCategories as $childCategory) {
$childCategory->users()->sync($request->users);
$this->syncCategories($childCategory);
}
}
}

Related

How to display pagination links in a blade on Laravel 8?

I need to add pagination, but it seems complicated in my case, because I get data from database with paginate, but then I modify this data and when I call links() method on the blade, I get the following exception
Method Illuminate\Support\Collection::links does not exist.
My code in the Controller method:
$transactionsByLastMonth = Transaction::where('created_at', '>=', Carbon::now()->subDays(30)->toDateTimeString())
->where('user_id', Auth::user()->id)
->with(['user', 'propertyFrom', 'propertyTo', 'paddockFrom', 'paddockTo', 'cattleTypeFrom', 'cattleTypeTo'])
->paginate(10);
$transactionsByDays = collect(TransactionResource::collection($transactionsByLastMonth))
->sortByDesc('created_at')
->groupBy(function($date) {
return Carbon::parse($date['created_at'])->format('d');
});
return view('user.reports.index', compact('transactionsByDays'));
Yes, a pagination limits my data to 10 rows, but due to I'm grouping data by days, my collection modifies itself and I can't use $transactionsByDays->links() method to show pagination.
If see dd($transactionsByDays) , it looks like:
Illuminate\Support\Collection {#1381 ▼
#items: array:3 [▼
"01" => Illuminate\Support\Collection {#1019 ▼
#items: array:7 [▼
0 => array:16 [▶]
1 => array:16 [▶]
2 => array:16 [▶]
3 => array:16 [▶]
4 => array:16 [▶]
5 => array:16 [▶]
6 => array:16 [▶]
]
}
31 => Illuminate\Support\Collection {#1386 ▼
#items: array:2 [▼
0 => array:16 [▶]
1 => array:16 [▶]
]
}
30 => Illuminate\Support\Collection {#1384 ▼
#items: array:1 [▼
0 => array:16 [▶]
]
}
]
}
Therefore I need to paginate all arrays together which inside "01", 31, 30...
How can I do it?
Maybe rewrite code above in the controller somehow?
The main aim is that I need to group data to every day according to my json-resource class.
Any ideas?
I've found a solution gyus. I had to pass also a variable transactionsByLastMonth and use links() method over this.
In the meantime I use foreach on the my blade file over transactionsByDays variable. It's correctly works together cause it uses the same data from database, just in the first case its not filtered and not grouped and in the second one it is.
return view('user.reports.index', compact('transactionsByLastMonth', 'transactionsByDays'));

Laravel get only users which they have specific Role using RelationShip

In my Laravel implemented web application i have Users and Roles tables with models which they are ManyToMany.
i want to get all users which they have specific role, for example:
$users = User::with(['roles' => function ($query) {
$query->whereLabel('is-portal-manager');
}])->get();
unfortunately this code return all users and compare role label and return that in relation ship array
Illuminate\Database\Eloquent\Collection {#2069 ▼
#items: array:3 [▼
0 => App\User {#2076 ▼
...
#relations: array:4 [▼
"properties" => null
"child" => Illuminate\Database\Eloquent\Collection {#2073 ▶}
"parent" => null
"roles" => Illuminate\Database\Eloquent\Collection {#2087 ▼
#items: array:1 [▼
0 => App\Entities\Role {#2074 ▼
...
#attributes: array:5 [▼
"id" => 1
...
"label" => "is-portal-manager"
...
]
...
}
]
}
]
...
}
1 => App\User {#2077 ▼
...
#relations: array:4 [▼
"roles" => Illuminate\Database\Eloquent\Collection {#2093 ▼
#items: []
}
]
...
}
]
}
as you can see in above output second user doesn't have any role and #items: [] is empty. i don't need to have this output structure and i want to have only which users have specific role, not all users with empty roles. second item of this collection shouldn't this output
Make your relationship conditional by using Laravel's whereHas:
$users = User::whereHas('roles', function ($query) {
$query->whereLabel('is-portal-manager');
})->with('roles')->get();
Official documentations for further reading on Eloquent Relationship Existence methods whereHas, has, doesntHave and whereDoesntHave

Laravel 5.6 Many to Many relationship throwing errors during display

**** UPDATE *******************************************************
I'm not sure why, but moving everything into the controllers index() method rather than having it in the show() method solved the problem. Don't know why it works, but it does.
Original Question:
Cant figure out what is wrong here, i have followed the docs, tried variations, etc... still no luck making this work correctly.
Model A: (Slide)
public function carousels() {
return $this->belongsToMany(Carousel::class)->withTimestamp()
}
Model B: (Carousel)
public function slides() {
return $this->belongsToMany(Slide::class)->withTimestamp()
}
Pivot Table
--------------------------------------------------
|carousel_id | slide_id | created_at | updated_at|
--------------------------------------------------
From Controller:
public function show(Carosuel $carousels) {
$carousels = $carousel->with('slides)->get();
return view('myView', compact(['carousels']));
}
In the following dump, the "slides" are not in the attributes object of the collection; however, they are in the relations object. Im not sure if this is normal behavior or if the slides array should be in the attributes object. If the latter is the case, then how does one go about making that happen?
$caousels dump:
Collection {#1320 ▼
#items: array:20 [▼
0 => Carousel {#798 ▼
#fillable: array:4 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [▼
"id" => 1
"name" => "Prof. Andre Gerlach"
"category" => "Dr."
"active" => 0
"deleted_at" => null
"created_at" => "2018-04-07 21:10:52"
"updated_at" => "2018-04-07 21:10:52"
]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"slides" => Collection {#1300 ▼
#items: array:5 [▼
0 => Slide {#1023 ▶}
1 => Slide {#1024 ▶}
2 => Slide {#1025 ▶}
3 => Slide {#1026 ▶}
4 => Slide {#1027 ▶}
]
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
1 => Carousel {#799 ▶}
2 => Carousel {#800 ▶}
In the View:
foreach($carousels as $carousel){
echo $carousel->name;
foreach($carousel->slides as $slide){
echo $slide->tag;
}
}
This throws the E_ERROR Invalid argument supplied for foreach() in view
If, however, I cast this to an array, it works. Problem is that i also need to paginate the results. Once i do, the slides array is again inaccessible.
public function show(Carosuel $carousels) {
// This works - slides are available to me in the view
$carousels = $carousel->with('slides)->get()->toarray();
// This DOESN'T work - slides are not available to me in the view
$carousels = $carousel->with('slides)->paginate(6)->toarray();
return view('myView', compact(['carousels']));
}
dump as array:
array:12 [▼
"current_page" => 1
"data" => array:6 [▼
0 => array:8 [▼
"id" => 1
"name" => "Prof. Andre Gerlach"
"category" => "Dr."
"active" => 0
"deleted_at" => null
"created_at" => "Apr 07 2018"
"updated_at" => "2018-04-07 21:10:52"
"slides" => array:5 [▼
0 => array:11 [▶]
1 => array:11 [▶]
2 => array:11 [▶]
3 => array:11 [▶]
4 => array:11 [▶]
]
]
1 => array:8 [▶]
2 => array:8 [▶]
3 => array:8 [▶]
4 => array:8 [▶]
5 => array:8 [▶]
]
"first_page_url" => "//localhost:3000/admin/carousel/show?page=1"
"from" => 1
"last_page" => 4
"last_page_url" => "//localhost:3000/admin/carousel/show?page=4"
"next_page_url" => "//localhost:3000/admin/carousel/show?page=2"
"path" => "//localhost:3000/admin/carousel/show"
"per_page" => 6
"prev_page_url" => null
"to" => 6
"total" => 20
The problem here is that, in the view, the slides key is no longer accessible. Throws following error (only if I use ->paginate()).
E_ERROR Trying to get property 'slides' of non-object
Everything I have read in the docs and from other sources show this to be a pretty basic operation. For the live of me, i cant figure out why its causing such an issue. I should be able to access this in the view by simply nesting a foreach.
Any help with this would be greatly appreciated.
In the following dump, the "slides" are not in the attributes object of the collection; however, they are in the relations object.
Yes this is normal.
This is where you have a problem:
public function show(Carosuel $carousels) {
// ...
return view('myView', compact(['carousels']));
}
Typehinting a model in a function is reserved for model binding. Which is not what you're doing here since you don't have an {id} or some other parameter in your route.
Remove the typehinting and call the model instead:
public function show() {
$carousels = Carousel::with('slides')->get();
return view('myView', compact(['carousels']));
}
If you'd like to remove the dependency from the method, you should do it in the constructor instead.
Edit:
While I don't see any other problem and the above solution should work, if it's true that ->toArray() works for you (but you still need pagination), you could just convert the underlying collection:
public function show() {
$carousels = Carousel::with('slides')->paginate();
$carousels->setCollection(collect($carousels->getCollection()->toArray()));
return view('myView', compact(['carousels']));
}
Can you try this?
Model B: (Carousel)
public function slides() {
return $this->hasMany(Slide::class)->withTimestamp();
}

Laravel 5 Query Builder not returning any data

I have some nested query in my application such as example follow.
$arrData = DB::table('service as tsv')
->select($afields)
->join('shops as ts', 'ts.id', '=', 'tsv.shop_id')
->where('ts.name','like','%'.$searchstring.'%');
if(!empty($type) && $type == 'individual')
$arrData->where('ts.type','=', '1');
$arrData->groupBy('tsv.id')->get();
This query not returning the exact output it display the content like
Builder {#351 ▼
#connection: MySqlConnection {#336 ▶}
#grammar: MySqlGrammar {#347 ▶}
#processor: MySqlProcessor {#348}
#bindings: array:5 [▶]
+aggregate: null
+columns: array:7 [▶]
+distinct: false
+from: "service as tsv"
+joins: array:3 [▶]
+wheres: array:3 [▶]
+groups: array:1 [▶]
+havings: null
+orders: array:1 [▶]
+limit: 4
+offset: 0
+unions: null
+unionLimit: null
+unionOffset: null
+unionOrders: null
+lock: null
#backups: []
#operators: array:26 [▶]
#useWritePdo: false
}
I want to display the data how should I access the data from this situation.

How can I get object with query builder in laravel

I'm new to laravel.
In RouteServiceProvider when I'm fetching the article using following code
$router->bind('articles',function($id) {
return \App\Article::active()->findOrFail($id);
});
I get an object:
Article {#323 ▼
#fillable: array:18 [▶]
#dates: array:1 [▶]
...
}
But when I build a custom query using QueryBuilder
public static function getArticleById($id) {
return DB::table('articles')
->leftJoin('news','articles.news_id','=','news.id')
->select('articles.*','reports.name as selected_report_id')
->where('articles.id',$id)
->get();
}
I get array:
array:1 [▼
0 => {#342 ▼
+"id": 40
...
}
]

Categories