Laravel getting results from model belongsToMany relationship back to controller - php

I'm using Laravel 5 and Eloquent, I have 3 tables setup:
photos
+----+---------------+------------------+
| id | photo_name | photo_location |
+----+---------------+------------------+
| 1 | kittens.jpg | C:\kittens.jpg |
| 2 | puppies.jpg | C:\puppies.jpg |
| 3 | airplanes.jpg | C:\airplanes.jpg |
| 4 | trains.jpg | C:\trains.jpg |
+----+---------------+------------------+
photo_set (pivot table)
+------------+----------+
| set_id | photo_id |
+------------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
+------------+----------+
sets
+----+----------------+
| id | description |
+----+----------------+
| 1 | cute animals |
| 2 | transportation |
+----+----------------+
I created a belongsToMany relationship in my photos and sets models to link these two together.
class Photo extends Model {
public function sets()
{
return $this->belongsToMany('App\Set');
}
}
and
class Set extends Model {
public function photos()
{
return $this->belongsToMany('App\Photo');
}
}
However I'm trying to reference the $Sets->photos() model function in my controller, so that given a set of id=1, I can return the photo_location value for each row [C:\kittens.jpg,C:\puppies.jpg], but I don't know how to access it..
Also, I can "sort of" access this information in the view with:
#foreach($sets as $set)
{{$set->images}}
#endforeach
but it looks like it only iterates through once and returns a json (?) of the necessary information, though I'm not sure how to parse that to regular HTML either.
So in short, I'm having trouble accessing this data (photo_location) from both the controller and the view

Use Collection::lists()
$locations = Set::find(1)->photos->lists('photo_location');
It will return an array ['C:\kittens.jpg', 'C:\puppies.jpg']
http://laravel.com/api/4.2/Illuminate/Database/Eloquent/Collection.html#method_lists

In your controller try this :
$result = PhotoSet::where('set_id', $set_id)
->with('sets')
->with('photos')
->get();
$photo_location = $result->photos->photo_location;
here PhotoSet is the model for photo_set table, because it is a pivot table we will be able to access both sets and photos table from it.

Related

How to filter post by category in laravel?

I am currently trying to make a relation between 3 tables.
post
id
name
category
id
name
post_category
id
post_id
category_id
Database
post
| 1 | post1 |
| 2 | post2 |
| 3 | post3 |
category
| 1 | cat1 |
| 2 | cat2 |
| 3 | cat3 |
post_category
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 2 |
| 3 | 2 | 2 |
| 3 | 1 | 3 |
Model Post.php
public function getCategory()
{
return $this->belongsToMany(Category::class, 'post_category');
}
PostController.php
$data = Post::with('getCategory')->get();
It returns correct post list.
Now i want to filter the post by category. I try, but it not working
$categoryId = [1,2];
$data = Post::with('getCategory')->whereHas('category', function ($query) use ($categoryId) {
$query->whereIn('id', $categoryId);
})->orderBy('id','DESC')->get();
please help me
use Laravel 5.4
apparently everything is fine!
One suggestion is to add two more parameters to the belongsToMany method, like:
public function getCategory()
{
return $this->belongsToMany(Category::class, 'post_category', 'post_id', 'category_id');
}
https://laravel.com/api/7.x/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_belongsToMany
You should rename your getCategory() function to simply category(). That makes the relation names much more straightforward and probably fixes your issue.
THEN, you should be able to call whereHas('category', ...).
If it still does not work, simply chain a ->toSql() to any of your queries and debug the actual query that way.

How can I write a relation for pivot table in Laravel?

Here is my table structure:
// tickets
+----+------------+----------------------+--------+---------+-------------------+
| id | subject | content | closed | user_id | unique_product_id |
+----+------------+----------------------+--------+---------+-------------------+
| 1 | subject1 | question1 | 0 | 123 | 2 |
+----+------------+----------------------+--------+---------+-------------------+
// unique_product
+----+---------------+------------+
| id | serial_number | product_id |
+----+---------------+------------+
| 1 | 2342rd34fc | 3 |
| 2 | fg34gt4r5t | 1 |
| 3 | 34ffvv4et6 | 3 |
+----+---------------+------------+
// products
+----+--------------+
| id | name |
+----+--------------+
| 1 | Router-rb51 |
| 2 | Switch-sfx2 |
| 3 | Router-rb300 |
+----+--------------+
Now I have a collection of tickets like this:
$tickets = tickets::where(user_id, "$user_id")->get();
foreach( $tickets as $ticket ){
$ticket->{I need to get the name of product here}
}
I can write a relation in the tickets model like this:
public function unique_product()
{
return $this->hasOne(unique_product::class, 'id', 'unique_product_id');
}
And I need one more relation to the products table for getting the name of product (i.e. Switch-sfx2). How should I write that relation?
$tickets = tickets::where(user_id, "$user_id")->with('unique_product.product')->get();
You can take advantage eager loading using with().
but for using with('unique_product.product') You have to define the relation ships between unique_products and products.
In your UniqueProduct model create a new relationship
public function product()
{
return $this->BelongsTo(Product::class, 'id', 'product_id');
}
After that you can access the column of a name like
foreach( $tickets as $ticket ){
$ticket->unique_product->product->name
}

laravel 5 - Eloquent Relationships (permissions table)

I think am struggling to get the relationships correctly in the scenario I have.
I have three tables
Table: users
| id | username |
----------------------
| 1 | pluto |
|------|-------------|
Table: permissions
| id | user_id | level_id | app_id |
--------------------------------------------------
| 1 | 1 | 2 | 9 |
|------|-------------|--------------|------------|
Table: levels
| id | level |
----------------------
| 1 | admin |
|------|-------------|
| 2 | manager |
|------|-------------|
| 3 | editor |
|------|-------------|
The result I am looking to get is
manager //through User:: model or Auth::
I would like to get a value from levels table in level column either through User model. This is the last version on what I have in my classes...
class User extends Authenticatable
{
public function permissions()
{
return $this->hasOne('App\Permissions');
}
}
class Permissions extends Model
{
public function user()
{
return $this->hasMany('App\User');
}
public function levels()
{
return $this->hasMany('App\Levels');
}
}
class Levels extends Model
{
public function permissions()
{
return $this->belongsTo('Modules\Ecosystem\Entities\permissions');
}
}
Using this in the controller I am able to retrieve values from permissions table. However I am unable to get values from levels table...
$user = User::with('permissions')->find(Auth::user()->id);
However I am unable to get values from levels table when I try this...
$user = User::with('permissions.levels')->find(Auth::user()->id);
That produces an error:
Column not found: 1054 Unknown column 'levels.permissions_id' in 'where clause' (SQL: select * from `levels` where `levels`.`permissions_id` in (1))
I understand that I am not understanding exactly how relationships would work in this instance but I don't want to just guess a solution. I'd like to understand it.
The thing is ,, Levels table serves only as a list of permission levels (roles). I recognize that I can define permission levels in some other way but for the moment this is how everything is set up.
If you are making a usual user permission system, where 'roles' is replaced by 'levels', then you need to reorganized your tables and relationships.
Table: users
| id | username | level_id |
---------------------------------------
| 1 | pluto | 2 |
|------|-------------|----------------|
Table: levels
| id | level |
----------------------
| 1 | admin |
|------|-------------|
| 2 | manager |
|------|-------------|
| 3 | editor |
|------|-------------|
Table: permissions
| id | level_id | app_id |
-----------------------------------
| 1 | 2 | 9 |
|------|-------------|------------|
So now User
hasOne('App\Levels', 'level_id');
Levels
hasMany('Modules\Ecosystem\Entities\permissions', 'level_id');
Permissions
belongsTo('App\Levels', 'level_id');
That is probably what you were trying to do, and it will works.
However, if many roles may have similar permissions, e.g: admin, manager & editor can all have access to a 'Page' or 'Content' or whatever that they all have access to, then you will need a 4th table to have many-to-many relationship between permissions and levels.
Table: permissions
| id | app_id |
---------------------
| 1 | 9 |
|------|------------|
Table: levels_permissions
| level_id | permission_id |
-----------------------------------
| 2 | 1 |
|-------------|-------------------|
With this, in Levels
belongsToMany('Modules\Ecosystem\Entities\permissions', 'levels_permissions', 'level_id', 'permission_id');
Inverse the relation in Permissions
belongsToMany('App\Levels', 'levels_permissions', 'permission_id', 'level_id');
In both approaches, you can now do
$user = User::with('levels.permissions')->find(Auth::user()->id);

Laravel Eloquent how to return one to many to many collection

Is it possible to get an eloquent relation based on a One->Many->Many relationship? In the below example, I would want to get all of the gallery_votes for a given user.
users
+----+---------------+
| id | user_name |
+----+---------------+
| 1 | bob |
| 2 | sam |
+----+---------------+
galleries
+----+---------------+-----------+
| id | gallery_name | user_id |
+----+---------------+-----------+
| 1 | Alaska Pics | 1 |
| 2 | Texas Pics | 1 |
| 3 | California | 2 |
| 4 | Cars | 2 |
+----+---------------+-----------+
gallery_votes
+----+---------------+--------+
| id | gallery_id | vote |
+----+---------------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 4 | 2 | 1 |
+----+---------------+--------+
The relationships are setup as follows.
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {{
...
public function galleries()
{
return $this->hasMany('App\Gallery');
}
}
and
class Gallery extends Model {
....
public function votes()
{
return $this->hasMany('App\GalleryVote');
}
}
$user->galleries returns a collection of associated galleries, so that works correctly. and $gallery->votes returns a collection of associate votes, so that also works correctly. But $user->galleries->votes gives
Undefined property: Illuminate\Database\Eloquent\Collection::$votes on line 1
Is what I'm trying to do even possible with straight Laravel? Or do I need to write the SQL directly?
The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation.
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {{
...
public function galleries()
{
return $this->hasMany('App\Gallery');
}
public function votes()
{
return $this->hasManyThrough('App\GalleryVote', 'App\Gallery');
}
}
Now $user->votes will return all votes for that user. Remember you need to create the GalleryVote eloquent model as well.
You can read more about that type of relation, as well as some example usage in the documentation.

Laravel Eloquent many to many using with() returning empty array

I'm using Laravel 5 and Eloquent and have a many to many relationship setup as follows
images
+----+---------------+------------------+
| id | image_name | image_location |
+----+---------------+------------------+
| 1 | kittens.jpg | C:\kittens.jpg |
| 2 | puppies.jpg | C:\puppies.jpg |
| 3 | airplanes.jpg | C:\airplanes.jpg |
| 4 | trains.jpg | C:\trains.jpg |
+----+---------------+------------------+
image_set (pivot table)
+------------+----------+
| set_id | image_id |
+------------+----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
+------------+----------+
sets
+----+----------------+
| id | description |
+----+----------------+
| 1 | cute animals |
| 2 | transportation |
| 3 | food |
+----+----------------+
I created a belongsToMany relationship in my photos and sets models to link these two together.
class Image extends Model {
public function sets()
{
return $this->belongsToMany('App\Set');
}
}
and
class Set extends Model {
public function images()
{
return $this->belongsToMany('App\Image');
}
}
What I'm trying to accomplish is perform a query that only gives me the sets that have images associated with them. Essentially join the sets and image_set table to only return sets of 1,2
I currently have a rather long query that works...
$availSets = Set::join('image_set','image_set.set_id','=','sets.id')
->groupBy('sets.id')
->get();
But I've seen plenty of examples that this should also work.
$availSets = Set::with('images')->get();
However it's returning all 3 sets, including those that have no associated images.
#relations: array:1 [▼
"images" => Collection {#179 ▼
#items: []
}
]
Am I using this incorrectly? Is with() supposed to work this way?
You're looking for the has() method, not the with() method:
$availSets = Set::has('images')->get();
This will return all the sets that have at least one image. The documentation for this can be found here.
The with() method is used to eager load the given relationship. It does not put any restraints on retrieving the parent records. You can read more on eager loading here.

Categories