I have an API with Laravel, and I have decided to use relations between tables, I have related them using these functions in all migrations:
// Migration file: 2020_05_26_185555_create_customers_table.php on line 27
$table->foreign('user_id')->references('id')->on('users');
And then I've implemented functions like the following:
(which get the records it's related to):
// Model app\User.php on line 80
public function customers()
{
return $this->hasMany(Customer::class);
}
On Customers controller, How can I use the function to show above to list all the clients of that user** , that is, replace the following code:
// Controller Customer\CustomerController.php on line 17
public function index()
{
$user_id = Auth::id();
$customers = Customer::where('user_id', $user_id)->get();
return $this->showAll($customers, 200, $filters);
}
For something like the following (Just an example, it doesn't work, but it's the idea of what I mean):
// Controller Customer\CustomerController.php on line 17
public function index()
{
$customers = User::customers(); // Ejemplo
return $this->showAll($customers, 200, $filters);
}
My goal is to create relationship between relevant table, example, a user's clients** , without using a condition, like my current implementation of code.
Can someone help me with this?
You can use the dynamic property for the relationship to access it (and have it loaded):
public function index()
{
$user = Auth::user();
$customers = $user->customers;
...
}
Laravel 7.x Docs - Eloquent - Relationships - Relationship Methods vs Dynamic Properties
Related
To keep things simple, I'll give an example in code to what I'm trying to Achieve.
Let's assume that we have a model called User with the following code:
class User
{
public function posts()
{
return $this->hasOne(Post::class);
}
}
And the Post model look something like this.
class Post
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
And now what I want to be able to do is for example:
$user = Auth::user();
$comments = $user->post->comments; //here, I only want the "comment_id" and "comment_content" fields to be included, not all the Comment Model fields !
you can simply use hasManyThrough in user model to connect comments table.
read about hasManyThrough here: docs
and after having a relation between user and comments (hasManyThrough)
you can use load (Lazy eager loading) method
there is an piece of code you can use here
$user->load(["comments" => function($q){
$q->select("comment_id","comment_content");
}]);
read more about Lazy eager loading: docs
Database
I'm kind of new to databases and I made this small database, but I have problems fetching data from it.
Im trying to get all the racers from the logged in user, and it works properly, but if I enter $pigeons = $user->racer I only get back the racer table. I would like to know the attributes of the racers from the pigeons table aswell. I've made it work with query builder left joining the tables but I'm not sure why I set up this relationship if I can't use Laravel inner method.
In the User model I have these relationships:
public function pigeons(){
return $this->hasMany('App\Pigeon');
}
public function racers(){
return $this->hasManyThrough('App\Racer', 'App\Pigeon');
}
This is the Pigeon model:
public function user(){
return $this->belongsTo('App\User');
}
public function racer(){
return $this->hasMany('App\Racer');
}
}
And this is the Event model:
public function race(){
return $this->hasOne('App\Race');
}
public function racers(){
return $this->hasMany('App\Racer');
}
And this is what my EventsController looks like with the working alternative method and the commented not working.
public function upcoming(){
$id = auth()->user()->id;
$user = User::find($id);
$pigeons = DB::table('racers')->leftJoin('pigeons', 'racers.pigeon_id', '=', 'pigeons.id')->where('pigeons.user_id', '=', $id)->get();
//$pigeons = $user->racers;
return view('events.upcoming')->with('pigeons', $pigeons);
}
This is what I get with $user->racers or $user->racers()->get():
[{"id":1,"pigeon_id":14,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null},{"id":2,"pigeon_id":15,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null},{"id":3,"pigeon_id":16,"user_id":4,"event_id":1,"position":0,"created_at":null,"updated_at":null}]
And this is what I want to get, its not correct either since I should get id:1 but I want to pass to view these additional datas aswell like gender, color, ability (but they are in pigeons table not in racers).
[{"id":14,"pigeon_id":14,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"hen","color":"blue","ability":38},{"id":15,"pigeon_id":15,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"hen","color":"blue","ability":48},{"id":16,"pigeon_id":16,"user_id":4,"event_id":1,"position":0,"created_at":"2018-09-27 10:01:04","updated_at":"2018-09-27
10:01:04","gender":"cock","color":"blue","ability":11}]
To get the pigeons, what you would have to do is $pigeons = $user->racers()->get();. You can see an example of this in Laravel's official documentation https://laravel.com/docs/5.5/eloquent-relationships#introduction.
This is my Report Model
protected $fillable = [
'site_url',
'reciepients',
'monthly_email_date'
];
public function site()
{
return $this->belongsTo('App\Site');
}
This is my Site Model
public function report()
{
return $this->hasMany('App\Report');
}
This is my ReportController
public function showSpecificSite($site_name)
{
$records = DB::table('reports')
->select('email_date','url','recipient')
->whereHas('sites', function($query){
$query->where('site_name',$site_name);
})
->get();
return view('newsite')->with('records',$records)
->with('site_name',$site_name);
}
My Controller is not yet working as well.
The thing is I would like to copy all the three files from sites table to reports table.
Is it possible in insertInto ?
My code on ReportController shows you that I'm selecting data from reports table but I am the one who puts data to reports table to see the output but it is not yet working because of the it cant reach out the value of site_name even though I already put a relationship between the two tables.
You're not actually using Eloquent in your controller you're just using the Query Builder (DB). This will mean that you don't have access to anything from your Eloquent models.
Try:
$records = \App\Report::whereHas('site', function($query) use($site_name) {
$query->where('site_name', $site_name);
})->get(['id', 'email_date', 'url', 'recipient']);
I've added id to the list of columns as I'm pretty sure you'll need that to use whereHas.
NB to use a variable from the parent scope inside a closure you need to pass it in using use().
I am trying to make a one-to-many relationship, but I get the following error
Undefined property: stdClass::$client (View:
C:\wamp\www\intranet\resources\views\users\list.blade.php)
The problem is that I am working with an existing database that in the tables does not have id fields, and the foreign keys would also be the typical ones like client_id
My model Client.php
class Client extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmundfunc';
public function employee(){
return $this->hasMany('App\Employee');
}
}
My model Employee.php
class Employee extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmtrabajador';
public function client(){
return $this->belongsTo('App\Client', 'COD_UND');
}
}
In nmtrabajador COD_UND field would be the foreign key that relates to nmundfunc.
And I try to get the data out like this: {{$user->client->CEN_DESCRI}}.
but it does not throw me the error, how can I solve it?
My Controller where I send in sight
public function index(){
$users = DB::connection('dpnmwin')->table('nmtrabajador')->where('CONDICION', '=', 'A')->get();
return view('users.list',array(
'users' => $users
));
}
You have to call basis on relations.
This code will return you data.
If you have id then you can find by id like below
$employee=Employee::find(1);
Or if you want to fetch all data then you can call all method.
Employee::all();
And then you can just get it by relation as you define in models.
$client=$employee->client->CEN_DESCRI;
Retrieving data from the instance is based on the methods which we have use.
Here in this answer, you can get that
Property [title] does not exist on this collection instance
I hope it will work.
If table doesn't have 'id' as primary key you should specify what the primary key is inside your model:
protected $primaryKey = 'your_primary_key';
Relation looks good, after that you must make sure $user is a defined instance of Employee, because your error probably means that your instance wasn't even defined, so for example if you are using list.blade.php, you need to change the return of your controller and indicate that you want to pass data to your view, for example you could do it like this:
return view('users.list', compact('user'));
Where user is an instance of Employee saved on '$user'
Update
First you should check your user is retrieved properly, you can check it by placing a dd($user)
And when you return a view you can pass information to it, a cleaner way of doing what you are trying to do is what I wrote earlier so you would end up having something like this:
public function index()
{
$users = DB::table('nmtrabajador')
->where('CONDICION', '=', 'A')
->get();
// dd($user) for debugging you are retrieving the user properly
return view('users.list', compact($users));
}
I have 3 tables: orders, codes, events
I want to be able to pull all events that an order has, but there's an intermediary table that acts as a pivot table. I've been trying to use hasManyThrough and belongsToMany (along with withPivot) without any luck.
Examples:
public function events()
{
return $this->belongsToMany('events'); // tried this, fails
return $this->hasManyThrough('events', 'codes'); // tried this, fails
return $this->hasManyThrough('events', 'codes', 'event_id', 'id'); // tried this, fails
}
Any pointers would be great!
That's a belongsToMany setup. First, the first parameter is the name of the related class. Second, since your pivot table doesn't follow the Laravel naming conventions, you need to specify the name of the pivot table in your relationship definition:
public function events()
{
// first parameter is the name of the related class
// second parameter is pivot table name
return $this->belongsToMany(Event::class, 'codes');
}
With this setup, you can do:
// get an order
$order = Order::first();
// has all the events related to an order
$events = $order->events;
There are many ways to do this. I will show a one you can get it done.
In Order.php model
public function codes(){
return $this->has('App\Http\Code');
}
In Code.php model
public function orders(){
return $this->belongsTo('App\Http\Order');
}
public function events(){
return $this->hasMany('App\Http\Event');
}
In Event.php model
public function codes(){
return $this->belongsTo('App\Http\Code');
}
Then in you Controller, call them to get required data.
In your case you can do it like below:
$orders = Order::with(['codes' => function($q){
$q->with('events');
})->get();
May be you can get them with nested manner(not sure about this because i didn't tried before posting):
$orders = Order::with('codes.events')->get();
put return $orders; in your controller to see the query.
Enjoy!