I have two tables: users, orders. I try to get all orders for current user.
Users Orders
_____ ______
id | name id | user_id
User model:
public function orders(){
return $this->hasMany("App\Order");
}
Order model:
public function user(){
return $this->hasOne("App\User", 'user_id', 'id');
}
Query in controller:
public function index()
{
$orders = Order::where('user_id', Auth::guard('api')->id())->get();
return response()->json(
$orders->user
);
}
I get NULL result, I do something wrong, because there are related rows in both tables.
If you want to retrieve all the Orders belonging to the current user, try using the following function.
public function index()
{
$orders = Auth::user()->with('Orders')->get()->toArray();//To get the output in array
/* ^ ^
This will get the user | This will get all the Orders related to the user*/
return response()->json($orders);
}
As pointed out by #Martin Heralecký, you would also need to change the hasOne() to belongsTo() in Order Model. See following (copied from #Martin Heralecký answer)
public function user(){
return $this->belongsTo("App\User");// second and third arguments are unnecessary.
}
Why belongsTo():
has_one and belongs_to generally are the same in the sense that they point to the other related model. belongs_to make sure that this model has the foreign_key defined. has_one makes sure that the other model has_foreign key defined.
Your $orders array will look something like this:
User => [
id => 'user id',
name => 'user name'
orders => [
0 => [
//order data
]
1 => [
//order data
]
.
.
.
.
]
]
In Order model you need to use the belongsTo relationship:
public function user()
{
return $this->belongsTo("App\User"); // second and third arguments are unnecessary.
}
In User model you can use hasMany relationship, for example in:
App/User.php
Add
public function orders()
{
return $this->hasMany("App\Order", "user_id", "id");
}
Now you can use this:
return User::find(1)->orders;
Related
I am struggling with an eloquent request. Let me explain what I want to do:
I have two models: User and Item
One User can have many Item and one Item belongs to One user.
I wrote the two method for this relation in my models as followed:
class Item extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
}
class User extends Model {
public function items() {
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
}
}
I try to access to the items from my controller its user's relation with:
public function index()
{
$items = Item::with('user')->get();
dd($items);
FYI: I seeded my items table with 10 items and my user table with 4 users:
items table:
users table:
My problem is that in the when I check my query with dd() here is what I get: Only the 4 first items get the relation, the others 6 return a null value
Relation working:
Relation returning null:
Thank you for helping me!
According to Laravel doc, hasMany relationship parameters are the following:
return $this->hasMany(Myclass::class, 'foreign_key', 'local_key');
So try to change your relationship in your User class like that
// change this
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
// to this
return $this->hasMany(Item::class, 'user_people_id', 'id');
The easiest solution would be to rename your foreign key to user_id. That is what Laravel expects, so you won't need to deal with extra arguments in your hasMany() functions.
If you can't do that I think this'll work: return $this->hasMany(Item::class, 'user_people_id');.
Please try to add all in your query to see if it will work:
Update
public function index()
{
$items = Item::all();
dd($items);
}
Hey from my website I'm sending multiple notifications to users, I'm assigning users to a team and then I assign this team to the notifications table.
However when I do SiteNotification::find(1)->notifications() then I get the name of the team, however, I was looking to get the user model and all the details related to that. Is there an easy way to obtain this using Laravel Eloquent relationships?
My DB model and Eloquent model are below;
DB tables;
User
id | username | email
Teams
id | name |
Team Members
team_id | user_id
Site Notifications
site_notification_id | team_id
Model Here:
class SiteNotification extends Model {
public function notifications()
{
return $this->belongsToMany(Team::class, 'site_check_notifications', 'site_check_id', 'team_id');
}
}
Update:
I've tried updating the Team Model as follows;
class Team extends Model
{
public function users()
{
return $this->hasManyThrough(
User::class,
TeamMember::class,
'team_id',
'id'
);
}
}
However this throws an error as follows when running this;
$site = Site::find(1);
foreach( $site->notifications as $notification) {
dd($notification->users);
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'team_members.id' in 'on clause' (SQL: select `users`.*, `team_members`.`team_id` from `users` inner join `team_members` on `team_members`.`id` = `users`.`id` where `team_members`.`team_id` = 4)
Any ideas what I'm doing wrong??
I've found a solution which has meant that I do not need to amend my existing database structure and I've found the correct relationship to use.
public function users()
{
return $this->belongsToMany(
User::class,
'team_members',
'team_id',
'user_id'
);
}
Now I can do Site::find(1)->users->pluck('email')
You have to change the model structure... This is how I would have reached your goal... Take it as a "working solution", maybe not the best!
First of all, database. You should have these tables, there is no need to
users => users table
teams => teams table
team_user => pivot table n:n
team_site_notification => pivot table n:n
site_notifications => notifications table
user_site_notification => pivot table n:n
Then you create the related models relations
public class User {
// [...]
public function teams() {
return $this->belongsToMany(Team::class)
}
public function notifications() {
return $this->belongsToMany(SiteNotification::class)
}
}
public class Team {
// [...]
public function users() {
return $this->belongsToMany(User::class)
}
public function notifications() {
return $this->belongsToMany(SiteNotification::class)
}
}
public class SiteNotification {
// [...]
public function teams() {
return $this->belongsToMany(Team::class)
}
public function users() {
return $this->belongsToMany(User::class)
}
}
In your controller, when you create the SiteNotification model, you'll have to associate also the users. For example
public function store(Request $request) {
// Do your stuff
$team = Team::findOrFail($request->your_team_id);
$notification = Notification::create($data);
$notification->teams()->associate($request->your_team_id);
// Retrieve the users from the team... Maybe not everyone should receive a notification
$team->users()->whereIn('id', $user_ids)->get()->pluck('id')
$notification->users()->associate($ids);
}
When you want to get your users list you simple retrive the associated users in this way:
dd($notification->users);
// [ User:{id: 1, '...'}, User:{id: 2}, User:{id: 7} ]
Hope this is what you're looking for!
I have 2 models:
class Order extends Model
{
protected $fillable = ['user_id','name','surname','fathers_name','phone_number','city','post_office','comment'];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Product', 'order_product');
}
}
class Product extends Model
{
public function order()
{
return $this->belongsToMany('App\Order', 'order_product');
}
public function category()
{
return $this->belongsTo('App\Category');
}
}
3 tables:
product:
id
name
...
order_product:
id
order_id
prod_id
qty
...
order
id
city
phone
...
and 2 arrays of data:
$data = $request->except('_token','submit'); - information about client
$order_content - array with info about products in cart
So, the question is how to insert all this data in DB? I tried to read about many to many insertion: sync, attach, etc.. but understood nothing :c
Imagine you have a product with id 1. And an order with id 1. The product is part of the order, so you have to attach them. You do
$product = Product::find(1);
$order = Order::find(1);
$order->products()->attach($order->id);
However, in your case, your pivot table has more data, like 'qty'. Then you do,
$order->product()->attach($order->id, ['qty' => 2]);
So far, we were only attaching a single product to an order. If you want to attach many products simultaneously, you do:
$order->products()->sync([
$product->id => ['qty' => 1],
$product2->id => ['qty' => 3]
]);
I hope this helps understand better. I recommend you read the doc again and again until it makes sense.
after 2 days of looking on laravel docs and stackoverflow with no success I have to ask the question
I have 4 models so far and I am trying to get all related info in one go.
user model has relationship:
public function transactions() {
return $this->hasMany( 'App\Transaction' );
}
store model has relationship: :
public function transactions() {
return $this->hasMany( 'App\Transaction' );
}
product model has relationship: :
public function transactions() {
return $this->hasMany( 'App\Transaction' );
}
and finally transaction model has relationships:
public function user() {
return $this->belongsToMany( 'App\User' );
}
public function product() {
return $this->belongsToMany( 'App\Product' );
}
public function store() {
return $this->belongsToMany( 'App\Store' );
}
transaction table (looks like a pivot table):
transactions:
id - integer
user_id : integer
product_id : integer
store_id : integer
....... some additional columns containing transaction specific data.
I would like to get all transactions with referenced details for auth user
aka "$user->transactions" however with this i am getting only ids no data from related tables. I did try by joining but it looks messy and I think there is better way of getting this data well structured in laravel
the join looks like:
$transactions = DB::table( 'transactions as t' )->where( 'user_id', Auth::id() )
->join( 'products', 'products.id', '=', 't.product_id' )
->join( 'stores', 'stores.id', '=', 't.store_id' )
->get( array( 't.id', 't.product_id', 'products.name as product_name', 't.store_id', 'stores.name as store_name' ) );
my objective is to get user object with all information about user including transactions and other details as one JSON response using as little queries as possible.
You just have to append the needed values from your relationships on the transaction. First add them as attributes on the Transaction model as follows:
public function getProductNameAttribute()
{
return $this->product?$this->product->name:"";
}
public function getStoreNameAttribute()
{
return $this->store?$this->store->name:"";
}
Now, you can append them to your transaction in the Transaction model like this:
protected $appends = ['product_name','store_name'];
And retrieve the transactions as usual like this:
Auth::user()->transactions;
Or append them to the transactions (after the first step) at run time like this:
Auth::user()->transactions()->setAppends(['product_name','store_name'])->toArray();
If your objective is to get an user object then you should query the user, not the transactions.
Since you have defined all the relationships you can leverage the query to Eloquent, no need to do it by hand.
User::whereId(Auth::user()->id)->with('transactions','transactions.product','transactions.store')->get();
I want to perform the following (with some rather crude pseudo code):
SELECT a users orderLines WHERE the orderheader's status ='paid' AND the orderLine's productId>5
In other words, a user can place many orders. Each order has one or many order lines. I want to find all of the order lines that the user has placed (order lines, not orders) but only if the order header has a certain status, and only if the order line has another parameter checked. This could be the date the line was added, or the productId being x, and so on.
Simple enough to do with a standard MySql query.
I have the nescessary models:
User
OrderHeader (Intermediate relationship)
OrderLine (Distant relationship - this is what I want to fetch, via the intermediate)
Here are how the relationships are defined in each model:
User
public function orders()
{
return $this->hasMany('App\OrderHeader', 'user_id', 'id');
}
public function lines()
{
return $this->hasManyThrough('\App\OrderLine', 'App\OrderHeader', 'user_id', 'order_header_id');
}
OrderHeader
public function lines()
{
return $this->hasMany('App\OrderLine', 'order_header_id', 'id');
}
public function user(){
return $this->belongsTo('User', 'id', 'user_id');
}
OrderLine (Fetch these for the User, using hasManyThrough)
public function header()
{
return $this->belongsTo('App\OrderHeader', 'order_header_id');
}
public function products()
{
return $this->belongsToMany('App\Product');
}
So, I load the User, using:
$person = User::findOrFail($id)
Then I can use:
$user->lines()->where('product_id','>=',10)->paginate(20);
So, that works brilliantly to get ALL of the lines that the user has placed, which match the condition on the line records. However, I can't figure out how to add a second condition on the intermediate, so that not only do I check the product_id, but also interrogate the OrderHeader entity via the orders() relationship.
I've tried:
return $user->orders()->where('status','=','Paid')->lines()->where('product_id','>=',20))->paginate(20);
but that returns the error: Call to undefined method Illuminate\Database\Query\Builder::lines()
hasManyThrough is a special case in Eloquent, where table is joined (intermediate table), so it's pretty simple - just query that table. Nothing to do with the other relation.
This is what you want:
$throughTable = $user->lines()->getParent()->getTable();
$user->lines()
->where('product_id', '>=', 10)
->where('orderheaders.status', 'paid')
// or
// where("{$throughTable}.status', 'paid')
->paginate(20);
Btw this relation is wrong:
// OrderHeader model
public function user(){
return $this->belongsTo('User', 'id', 'user_id'); // wrong keys order
}
// should be
public function user(){
return $this->belongsTo('User', 'user_id', 'id');
}