Laravel find record in another table associated with $data - laravel

I am looking over some laravel code and I have a few questions regarding the code. In the view, I see a piece of code "$data->profile->age". Does this code automatically find the profile record in the profile table associated with the $data? How does it find the associated profile?
Controller:
return view('new-design.pages.influencer.info')
->withData($data)
View:
$data->profile->age

Yes. It finds the associated profile using the relations you definied in your Profile model
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
Here's a simple example from the documentation to help you understand:
Let's say you have a posts table and a comments table:
We need to define a relationship between this two tables.
A one-to-many relationship is used to define relationships where a single model owns any amount of other models. For example, a blog post may have an infinite number of comments.
Note: you must have a foreign key in your comments table referencing the posts table, like post_id, in this case, if you use a different name you should inform that in your relation:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
In your Post model you could do:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
And in your Comment model you should define the inverse relationship
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
Now, if you want to access all comments from a post you just need to get the relation:
$post = Post::find($id); // find a post
$post->comments; // This will return all comments that belong to the given post
So, you basically access them as if they were a property from the model, as said in the documentation
In your view you could do something like this:
#foreach($post->comments as $comment)
{
{{$comment->text}}
}
#endforeach
This example will print every comment text from the Post we get in the controller.

I reckon in your model for $data there is a function called profile. From that it is getting the equivalent profile.
Example: Imagine you have a model called phone and you want to find the user who owns it. You can write the following function in your model.
public function user()
{
return $this->belongsTo('App\User');
}
And in the view you may write something like
$phone->user->name
Now, behind the scene laravel will go to the phone and get the value from user_id for that phone. (If the foreign key is located in different column you can specify that too). Then laravel will find the users table with that user_id and retrieve the row. Then show the name on view.
Now if there is a complex query you can also write a function for that in the model.

Related

How get users from section table ? laravel

The idea is that I have relation between two table's section and user
the section_id exist in users table it relation with id section
SO for ex : section_id = 2 > want to bring all users belongs to id section
My code here use id from url and I don't want to do this I want without id bring all users :
public function getAllUsers($id)
{
$data = User::where('section_id',$id)->get();
}
If I'm understanding you correctly, you want to get all the users for a particular Section that have the relationship to that section.
Assuming you have the relationship set up correctly on the Section model:
public function users() {
return $this->hasMany('App\User');
}
I suggest you go about this 'backward' and just pull the users from the Section model itself (eager loading allows one query):
$section = Section::with('users')->first();
$usersForThisSection = $section->users;
If you setup a One to Many relationship you can say things like: $user->section to return the section a user belongs to...and $section->users to get a collection of all the users in a section -- the getAllUsers() is redundant in this case.
Make sure your User and Section models contain these methods. Sounds like your migration was setup properly if you have a section_id column on your users table.
More info on one-to-many here: https://laravel.com/docs/5.8/eloquent-relationships#one-to-many
// app/User.php
class User extends Model
{
public function section() {
return $this->belongsTo('App\Section');
}
}
// app/Section.php
class Section extends Model
{
public function users() {
return $this->hasMany('App\User');
}
}
Test out your relationships in php artisan tinker like so...
$user = User::find(1);
$user->section
$section = Section::find(1);
$section->users
you need a unique identifier to receive section_id's users. receive it from url(get) or ajax(post) . if you worry about users access then use "auth"

Laravel - How to query a relationship on a pivot table

My Setup
I have a many-to-many relationship setup and working with my database. This is using a pivot table that has an extra column named "linked_by". The idea of this is that I can track the user that created the link between the other 2 tables.
Below is an attempted visual representation:
permissions -> permissions_roles -> roles
permissions_roles -> persons
The Issue
The permissions_roles table has an addition column names "linked_by" and I can use the ->pivot method to get the value of this column. The issue is that it only returns the exact column value. I have defined a foreign key constraint for this linked to persons.id but I can't manage to work out a way to query this from a laravel Eloquent model.
The Question
How do I query the name of the person linked to the "linked_by" column form the Eloquent query?
Ideally, I would like the query to be something like:
permissions::find(1)->roles->first()->pivot->linked_by->name;
BUT, as I haven't defined an eloquent relationship for this pivot table column I can't do this but I can't work out how I would do this if it is even possible?
Is the only way to do this to do:
$linkee = permissions::find(1)->roles->first()->pivot->linked_by;
$person = person::find($linkee);
$person->name;
->using();
I have discovered that Laravel has a way to do what I wanted out of the box by creating a model for the pivot table.
This works by adding ->using() to the return $this->belongsToMany() model function.
By putting the name of the newly created pivot model inside the ->using() method, we can then call any of the functions inside this pivot model just like any other eloquent call.
So assuming that my permissions belongs to many roles and the pivot table has a 3rd column named "linked_by" (which is a foreign key of a user in the Users table):
My permissions model would have:
public function roles()
{
return $this->belongsToMany('App\roles','permissions_roles','permissions_id','roles_id')
->using('App\link')
->withPivot('linked_by');
}
and the new link model would contain:
Notice the extends pivot and NOT model
use Illuminate\Database\Eloquent\Relations\Pivot;
class link extends Pivot
{
//
protected $table = 'permissions_roles';
public function linkedBy()
{
return $this->belongsTo('App\users', 'linked_by');
}
}
Obviously you would need to define the opposite side of the belongsToMany relationship in the roles model, but once this is done I can use the following to pull the name of the person that is linked to the first role in the linked_by column:
permissions::find(1)->roles->first()->pivot->linked_by->name;
You should be able to achieve that in toArray method in Permission model.
/**
* Convert the model instance to an array.
*
* #return array
*/
public function toArray(): array
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
// Detect if there is a pivot value and return that as the default value
if (isset($attributes['pivot']['linked_by']) && is_int($attributes['pivot']['linked_by'])) {
$linkeeId = $attributes['pivot']['linked_by'];
$attributes['pivot']['linkee'] = Person::find($linkeeId)->toArray();
//unset($attributes['pivot']['linked_by']);
}
return $attributes;
}

Many-to-many withouth relations (Laravel)

I have two application, in two different server.
In the first Laravel application I have my User model, and in the secound application I have my Blog model.
There is a many-to-many relationship between them, a user can have multiple blogs, and one blog can belongs to many user.
They have two different database, but everything is built like its only one app in one server.
They have a REST API, and its communicating between them. The problem is, I cant set up real relations between them (like belongsToMany in the Eloquent Model), and I can't list User's blogs.
Is there a way to copy the "User::blogs()" relation function, with some query work on Blog:: class? For e.g. select all blogs where user_id is equal to 1 in the pivot table?
<?php
class User extends Model{
protected $connection = 'Your Connection';
public function blogs(){
return $this->belongsToMany(Blog::class);
}
}
Blog.php
class Blog extends Model{
protected $connection = 'Your other connection';
public function users(){
return $this->belongsToMany(User::class);
}
}
You can set the multiple connections in your database.php and assign each model a different connection.
I am assuming that you have a user_blogs table. some where
hope this helps.
I found it, like this:
Blog::join('blog_user', 'blogs.id','=','blog_user.blog_id')->where('blog_user.user_id', '=', $this->userId)->get();

How does eloquent recognize tables?

I am curious about how eloquent knows in which table it should save the records we give it by running $ php artisan tinker . I do not actually remember setting so an option.
In Laravel when using Eloquent you should assign a table name using the property $table for example:
protected $table = 'some_thing';
Otherwise it assumes that the table name is the plural form of the model name and in this case for User model the table name should be users. Follwing paragraph is taken from Laravel website:
Table Names
Note that we did not tell Eloquent which table to use for our Flight
model. The "snake case", plural name of the class will be used as the
table name unless another name is explicitly specified. So, in this
case, Eloquent will assume the Flight model stores records in the
flights table.
// You may use this instead:
class Flight extends Model
{
// Explicit table name example
protected $table = 'my_flights';
}
So, if you don't follw this convention when creating/naming your database tables that Laravel expects then you have to tell Laravel the name of the table for a model using a protected $table property in your model.
Read the documentation here.
Actually if you not set the $table property, Eloquent will automatically look the snake case and plural name of the class name. For example if class name is User, it will users.
Here the code taken from Illuminate/Database/Eloquent/Model.php
public function getTable()
{
if (isset($this->table)) {
return $this->table;
}
return str_replace('\\', '', Str::snake(Str::plural(class_basename($this))));
}
Model name is mapped to the plural of table name, like User model maps to users table and so.
When you do
User::all() laravel knows that you want the records from users table.
To specify the table name explicitly you use protected $table ='name' field on model.
Actually, Eloquent in its default way, is an Active Record System just like Ruby On Rails has. Here Eloquent is extended by a model. Those model name can be anything starts with capital letter. Like for example User or Stock
but the funny thing is this active record system will imagine that if no other name of custom table is specified within the class model then the table name should be the small cased plural form of the Model name. In these cases users and stocks.
But by keeping aside theses names you can extensively can provide your own table name within the model. As in Laravel protected $table= 'customTableName'
Or, in a more descriptive way,
class Stock extends Eloquent{
// Custom Table Name
protected $table = 'custom_tables';
}
I hope this will solve your curious mind.

Eloquent hasOne vs belongsTo degenerate to same function if both keys are specified?

For the case of a one-to-one relationship, if I fully specify the keys in the method calls, is there a difference between hasOne and belongsTo relationships? Or, asked differently, if I used hasOne on both sides of the relation, would it be the same result?
Yes it works for some cases to specify the keys and make the relation work. And with some cases I mean mainly retrieving results. Here's an example:
DB
users profiles
----- --------
id id
etc... user_id
etc...
Models
Using "wrong" relations with hasOne twice
class User extends Eloquent {
public function profile(){
return $this->hasOne('Profile');
}
}
class Profile extends Eloquent {
public function user(){
return $this->hasOne('User', 'id', 'user_id');
}
}
Queries
Let's say we wanted to get the user from a certain profile
$profile = Profile::find(1);
$user = $profile->user;
This is working. But it's not working how it's supposed to be. It will treat the primary key of users like a foreign key that references user_id in profiles.
And while this may work you will get in trouble when using more complicated relationship methods.
For example associate:
$user = User::find(1);
$profile = Profile::find(2);
$profile->user()->associate($user);
$profile->save();
The call will throw an exception because HasOne doesn't have the method associate. (BelongsTo has it)
Conclusion
Whereas belongsTo and hasOne may behave similar in some situations. They are clearly not. More complex interactions with the relationship won't work and it's nonsense from a semantic point of view.

Resources