Laravel Eloquent Foreign Key Relation - php

I have question about Laravel Eloquent. I created few tables and models, ~like this:
Trip
id
name
user
User
id
email
Message
id
content
trip
user
How can I get all message for single user with all foreign keys? You know, all data from this tables. Like this:
[
1 => [
'content',
'trip' => [
'name'
],
'user' => [
'email'
]
]
]
It's possible, to get in easy way all data?
My models:
// Message.php:
public function user()
{
return $this->belongsTo('App\User');
}
public function trip()
{
return $this->belongsTo('App\Trip');
}
// Trip.php:
public function user()
{
return $this->belongsTo('App\User');
}
// User.php:
public function trips()
{
return $this->hasMany('App\Trip');
}
public function messages()
{
return $this->hasMany('App\Message');
}
My Code
dd(
User::with([
'sent',
'recipient'
])->find(2)->toArray()
);
And what I want to get:
screen

I believe you are looking for the load method.
Lets say you have a user
$user->load('messages'); // var_dump($user);
If you vardump your user object you will see the related messages were loaded.

Use eager loading to achieve that.
Try this:
$users = User::with([
'messages.trip',
])->get();
dd($users);
Ref: https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

Related

Laravel: Seeding Database table with relationship When the table has two foreign key

I am using laravel factory method for populating my database table. I have three models and their relationship with each other are given below:
**User model**
class User extends Authenticatable
{
public function books() {
return $this->hasMany('App\Book', 'user_id', 'id');
}
public function ratings() {
return $this->hasMany('App\Rating', 'user_id', 'id');
}
}
**Book Model**
class Book extends Model
{
public function user() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function ratings() {
return $this->hasMany('App\Rating', 'book_id', 'id');
}
**Rating Model**
class Rating extends Model
{
public function book() {
return $this->belongsTo('App\Book', 'book_id', 'id');
}
public function user() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
}
And my factory definition for model Book and Rating look like this:
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->title,
'description' => $faker->sentence
];
});
$factory->define(Rating::class, function (Faker $faker) {
return [
'rating' => $faker->numberBetween(1,5)
];
});
Database table look like this:
User table:
id,name,email,password
Book table:
id,user_id,title,description
Rating table:
id,user_id,book_id,rating
The code for calling factory is given below:
public function run()
{
//create 10 users
$user = factory(App\User::class,10)->create();
// create 2 books for each user
$user->each(function ($user) {
$book = $user->books()->saveMany(factory(App\Book::class,2)->make());
});
});
So with this run method i am able to create 10 users and each user have two books. But i also want to have each book rated by 3 different users. So what extra code should i add in above method to achieve this.
I have a simple approaching method that you may consider
//create 10 users
$user = factory(App\User::class,10)->create();
$id_arr = Arr::pluck($user , 'id'); // get user id array
// create 2 books for each user
$user->each(function ($user) use($id_arr) {
$books = $user->books()->saveMany(factory(App\Book::class,2)->make());
$shuffle_id = Arr::shuffle($id_arr); // shuffle user_id each time create user successfully
// add 3 rates for each book with different user
$books->each(function ($book) use($shuffle_id) {
$book_id = $book['id'];
for ($i=0; $i<3; $i++){
$user_id = $shuffle_id[$i]; // get id in first 3 of shuffle_id array (this will make sure, user_id will never be duplicated
factory(App\Rate::class)->create(['book_id'=>$book_id, 'user_id' => $user_id]);
}
});
});
Hope it will help

laravel get user id in users table at the time of validation exists|users on call of api?

I have started using laravel and I am loving it.
I write APIs for mobile developers.
I use lot of tables with joins on id_user.
thus I always need id_user.
I have table users which has columns as follows:
1. id
2. token
3. full_name
I do validation as follows:
$result=$request->validate([
'token' => 'required|unique|exists:users'
]
]);
with above code I always get true or false in $result.
but I want the id of this token, which I use as unique in other tables.
thus
I fire the below query as follows:
$users=DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
$id_user=$users->id;
but my question is if in laravel validation, "unique|exists:users" checks for unique record existing in users table, and when it finds the record, it validates this constraint and (returns true), it must be storing this unique record somewhere.
Where can I get this record?
If laravel doesn't have this feature they must add it.
Why should I join user table (or fire another query again?) and make the process expensive?
you need to create models and set relationships (User and Order)
class User extends Authenticatable{
protected $fillable = [
'name', 'email','token', 'password',
];
public function order()
{
return $this->hasMany(Order::class);
}
}
class Order extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
set foreign key on orders table
$table->foreign('user_id')->references('id')->on('users');
then this should be the query
'token' => 'required|unique:users|exists:users'
$order = Order::find(1)->user()->where('token_in_orders_table', 'token_in_users_table')->first();
return $order;
Or create a Resource for the Order Model
class OrderController extends Controller
{
public function index(Request $request)
{
//validate token
'token' => 'required|unique:users|exists:users'
//then
return new OrderResource(Order::find(1));
}
}
Resource
class OrderResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'order_details' => $this->order_details,
'user' => $this->user()->where('token', $request->token)->first(),
];
}
}
enter image description here

Laravel Nova nested relation

Recently I've been trying to create Nova resource which depends on the other resource which provides the information for the main resource.
I have a table contest_entries which has the following fields:
id
contest_id
user_id
with the following relations
public function contest() : BelongsTo {
return $this->belongsTo(Contest::class, 'contest_id', 'id');
}
public function user() : BelongsTo {
return $this->belongsTo(User::class, 'user_id', 'id');
}
Also, i have a table contest_submissions with the following fields:
id
entry_id
task_id
comment
approved
declined
with the following relations:
public function entry() : BelongsTo {
return $this->belongsTo(ContestEntry::class, 'entry_id', 'id');
}
public function user() : BelongsTo {
return $this->entry->user();
}
public function contest() : BelongsTo {
return $this->entry->contest();
}
public function task() : BelongsTo {
return $this->belongsTo(Task::class, 'task_id', 'id');
}
I have no problem in fetching this data on the index and details view of Nova, everything 'just works', however, when I try to update the resource, I'm getting the error that user() or contest() is called on null.
I've tried the following,
return [
BelongsTo::make('Contest', 'contest', Contests::class)->exceptOnForms(),
BelongsTo::make('Task', 'task', ContestTasks::class)->exceptOnForms(),
BelongsTo::make('User', 'user', AccountUsers::class)->exceptOnForms(),
]
But for some reason, Nova is still trying to fetch these relationships ever when i explicitly tell it not to.
Any ideas are greatly appreciated, because it works everywhere, except on the update view (create view is explicitly disabled since the submissions are created by the user on the frontend)
You should also chain a hideWhenUpdating() constraint to it.
return [
BelongsTo::make('Contest', 'contest', Contests::class)
->hideWhenUpdating()
->exceptOnForms(),
BelongsTo::make('Task', 'task', ContestTasks::class)
->hideWhenUpdating()
->exceptOnForms(),
BelongsTo::make('User', 'user', AccountUsers::class)
->hideWhenUpdating()
->exceptOnForms(),
]

Display table data without user auth

I'm studying event message board. I can display table data by every Users own post. however I would like to display All post too. I wrote this as $tasksall but it didn't work. Could someone teach me what is wrong?
AController.php
public function index()
{
$tasks = Auth::user()
->tasks()
->orderBy('is_complete')
->orderByDesc('created_at')
->paginate(5);
$tasksall =
->tasks()
->orderBy('is_complete')
->orderByDesc('created_at')
->paginate(5);
return view('tasks', [
'tasks' => $tasks, 'tasksall' => $tasksall
]);
}
Task.php (model)
class Task extends Model
{
protected $casts = [
'is_complete' => 'boolean',
];
protected $fillable = [
'title',
'is_complete',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
AController.php I add this code
public function person()
{
return $this->belongsTo('App\Models\Task');
}
public function getData()
{
return $this->id . ':'/ $this->person->name.')';
}
index.blade.php I add this code
{{ $task2->getData() }}
You can just write a query to get all the task using eloquent to get all the tasks.
$tasksall = Task::all();
Have a look at this link.
Also for you case I think the problem is you are getting task from the User model so you $task will contain only task related to that particular user as you have a belongsTo relation of task with user.
For Your case to get name of User from task.
//Task model
class Task {
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
}
Then you can query like this in your controller.
$task = Task::find($id);
$name = $task->user->name;

How to load specific fields from a nested relationship with Eloquent?

I have an Order model which belongs to a User and has Revisions.
When I try to load orders including: the 'id' and 'name' field from its user and some fields including 'user_id' field from whole revisions, I do:
return Order::with(array('user' => function ($query) {
$query->select('id','name');
}), 'revisions' => function ($query) {
$query->select('id','created_at','user_id','operation','text');
})->get();
However, I'd like to get the name of the user, which naturally is at users table as 'name' field.
Relationships setup
Order
public function user() {
return $this->belongsTo('User');
}
public function revisions() {
return $this->hasMany('Revision');
}
Revision
public function order() {
return $this->belongsTo('Order');
}
User
public function orders() {
return $this->hasMany('Order');
}
public function revisions() {
return $this->hasMany('Revision');
}
Expected result
Just for fast typing reasons I represent it as a JS object ...
orders = [
{ id: 5,
user: {....},
revisions: [
{ id:100,
operation: 'Creation',
text: 'Please provide soon',
user: 'John Doe' // Here I got the name instead of a user_id
}
]
},
{...}
]
How can I complete this?
Note
I did the proper relationship setups at each model.
well, you get user_id in revisions because it is a property of revision itself, you should look for the username in the Order object returned
$x = Order::with(array('user' => function ($query) {
$query->select('id','name');
}), 'revisions' => function ($query) {
$query->select('id','created_at','user_id','operation','text');
})->get();
var_dump($x->user->name);
$x->user is the relation model, user->name is its property
So, to have it also in revision you have to do something like:
$x->each(function(&$order) {
$order->revisions->each(function(&$rev) use ($order) {
$rev->setUsername($order->user->name);
});
});
assuming you have a setUsername method in your relation Model. In any case, the username in relation model should be a private property, not a fillable field, because is not part of the table, and in this case you have to check if it is exported when you do a ->toJson()

Categories