I have the database like this
+------------------+
| Invoices |
+------------------+
| id |
| customer_id (Fk) |
| description |
+------------------+
+------------------+
| InvoiceItems |
+------------------+
| id |
| Item_name |
| price |
| discount |
| description |
+------------------+
+------------------+
| Customers |
+------------------+
| id |
| firstname |
| lastname |
| description |
+------------------+
According to the database I made relations in the models as follows.
In Invoices model,the relation is like this
public function relations()
{
return array(
'invoiceitem' => array(self::HAS_MANY,'InvoiceItems','invoice_id'),
'customers' => array(self::BELONGS_TO,'Customer','customer_id'),
);
}
In InvoiceItems model relation is like this
public function relations()
{
return array(
'invoice' => array(self::BELONGS_TO,'Invoices','invoice_id'),
);
}
In Customers model the relations is like this
public function relations()
{
return array(
'invoice' => array(self::HAS_MANY, 'Invoices','customer_id')
);
}
Now I want to know if the relations between these models are right or not?
Your Invoice item does not have a field called invoice_id in the table description. The relations need a reference to the primary key to work. The db-field you declare in the relation should contain the primary key of the model you are working with. So if you are working with a invoice, the HAS_MANY relation should be able to find the id of the invoice in the invoice_id field on the item.
You could also use a separate table for the relation data and declare it like:
array(self::HAS_MANY,'InvoiceItems',reltable('invoice_id', 'item_id))
You can read more about the relations here
Related
I'd like to export data from my database but have problems with multiplying and sum using laravel eloquent with relation
So i have 2 tables there (budgets, items)
Budget's:
// Table
+----+---------------+-----------------+------+-----+--------------------+
| id | delivery_plan | item_code | curr | qty | price |
+----+---------------+-----------------+------+-----+--------------------+
| 1 | 2022-08 | 201.0001 | IDR | 1 | 2000.0000000000 |
| 2 | 2022-08 | 201.0001 | IDR | 3 | 2000.0000000000 |
| 3 | 2022-07 | 201.9999 | IDR | 2 | 2000.0000000000 |
+----+---------------+-----------------+------+-----+--------------------+
// Relation
public function item()
{
return $this->belongsTo(Item::class, 'item_code', 'item_code');
}
Items :
// Table
+----+----------------+-----------+
| id | subgroup | item_code |
+----+----------------+-----------+
| 1 | KOMPONEN MESIN | 201.0001 |
| 2 | EQUIPMENT LAIN | 201.9999 |
+----+----------------+-----------+
// Relation
public function budgets()
{
return $this->hasMany(Budget::class, 'item_code', 'item_code');
}
So, the scenario is :
Multiply the "qty" * "price" columns and name them as "total" like so
Group them by "subgroup" column, which came from item() relationship
Group them by "delivery_plan"
I prefer using eloquent because to minimize the complexity because i need that "whereHas" method
This is what i've tried so far and isn't working :
$budgets = Budget::with('item', 'rate')->whereHas('period.term', function (Builder $builder) {
$builder->where('name', '=', Session::get('term-budget'));
})->where('section', Session::get('section-budget'))->getQuery();
$result = $budgets->sum('price * qty')->get();
How can i achieve this ?
This can be solved by a join with SUM(), something like below (untested):
Budget::leftJoin('items', 'budgets.item_code', '=', 'items.item_code')
->addSelect('subgroup')
->addSelect('delivery_plan')
->addselect(\DB::raw('SUM(qty * price) as total'))
->groupBy('subgroup', 'delivery_plan')
->get();
please help..
I have 2 tables
Current user_id = 3
Users Table:
| user_id | email | name |
-------------------------------------------
| 1 | one#gmail.com | ridwan |
| 2 | two#gmail.com | budi |
| 3 | six#gmail.com | stevan |
| 4 | ten#gmail.com | agung |
Relations Table [ user_id and follower_id are related to Users Table ]
| relation_id | user_id | follower_id |
-----------------------------------------
| 1 | 1 | 3 |
| 2 | 2 | 3 |
i want to get the list of the user, but if i already have relation with a user, it will give me a status 'following', just like instagram, maybe look like this
{
user_id : 1,
name : ridwan,
status : following
},
{
user_id : 2,
name : budi,
status : following
},
{
user_id : 4,
name : agung,
status : not following
}
how can i do that in laravel?
thank you..
In your Relations model
public function user()
{
return $this->belongsTo(User::class);
}
Then, in your controller (where you want to get this list), you just need to use Eloquent or Query Builder to get what you want (with eager loading, it's always better) :
//get all users related to your_current_user
$relations = Relation::where('follower_id', your_current_user_id)->with('user')->get();
Finally, you just have to make manipulate your data like you want, for example :
foreach($relations as $relation){
$relation->user->name; //get the name of the related user
}
Take a look at Relationships !
Thank you guys.. finally I use sql case, i was only confusing about how to get the data with 'following' status
here is the code:
DB::table('users')->leftjoin('relationships', 'users.user_id', '=', 'relationships.user_id')->select('users.user_id','users.status as user_type','users.email','users.display_name','users.profile_image',DB::raw('(CASE WHEN relationships.follower_id = ' . $user_id . ' THEN "Following" ELSE "Not Following" END) AS status'))->orderBy('user_id','asc')->where('users.user_id','!=',$user_id)->get();
Items Table
| id | item_id | item_title |
|-------|---------|------------|
| 1 | 1002 | A |
| 2 | 1003 | B |
| 3 | 1004 | C |
Sells Table
| id | item_id |
|----|-----------|
| 1 | 1002 1003 |
| 2 | 1003 1004 |
| 3 | 1004 1002 |
I want result : Sells Table 1. item title is A B
I want to combine the sells table with the item table and then match the item_id of the sells table to the item_title of the item table.
The table definitions look incorrect, you should have a pivot table linking items with sells, so a sell_item table:
item_id | sell_id
-----------------
1 | 1
1 | 3
2 | 1
2 | 2
3 | 2
3 | 3
Then using eloquent, you'd create models to represent your tables and define the relationships using BelongsToMany:
class Item extends Model {
public function sells() {
return $this->belongsToMany(Sell::class);
}
}
class Sell extends Model {
public function items() {
return $this->belongsToMany(Item::class);
}
}
Each instance of either model will then have access to it's related models via $item->sells and $sell->items.
The query builder can perform a join if not going the Eloquent route:
DB::table('sells')->join('items', 'sells.item_id', '=', 'items.item_id')
->select('sells.*', 'items.title')
->get();
The table definitions look incorrect, If you corrected already then your model replationship should be like
class Item extends Model {
public function sells() {
return $this->belongsToMany(Sell::class);
}
}
class Sell extends Model {
public function items() {
return $this->belongsToMany(Item::class);
}
}
Each instance of either model will then have access to it's related models via $item->sells and $sell->items.
The query builder can perform a join if not going the Eloquent route:
DB::table('sells')->join('items', 'sells.item_id', '=', 'items.item_id')
->select('sells.*', 'items.title')
->get();
Or if your model name is Sell then
$response=Sell::with('items')->get();
I'm designing an application where a retailer can add a product with an initial price (store in a products table shown as example), then customers can claim the price of the product purchased from the retailer (this information stores in the prices table shown as example). The retailer then can update / reclaim the price inside the prices table too. and customers can reclaim the price of the product over and over again.
So, I have 2 roles of users called retailer and customer. I'm using Entrust Role package with the default relationship between role and user in the model. Before I explain next, here is my simple database design with all working example (feel free to ask for anything to include):
=============== MY Database Design with sample ===============
table users
__________________________
| id | email | password |
|-------------------------|
| 1 | a#g.com | 123 |
| 2 | b#g.com | 123 |
| 3 c#g.com | 123 |
| 4 d#g.com | 123 |
--------------------------
table roles
______________
|id | slug |
|--------------|
|1 | customer |
|2 | retailer |
----------------
table role_user
__________________
|id_user | id_role|
|------------------|
| 1 | 1 | -> a#gmail.com is a customer
| 2 | 2 | -> b#gmail.com is a retailer
| 3 | 1 | -> c#gmail.com is a customer
| 4 | 1 | -> d#gmail.com is a customer
------------------
table price:
(customer or retailer can claim 1 or more prices):
_____________________________________
|id| user_id | product_id | price |
|----------------------------|
|1 | 1 | 1 |10.00 | -> price claimed by a customer a#gmail.com on product 1
|2 | 2 | 1 |5.00 | -> price claimed by a retailer b#gmail.com on product 1
|3 | 1 | 1 |6.00 | -> price claimed by a previous customer a#gmail.com on product 1
|4 | 3 | 1 |5.00 | -> price claimed by a customer c#gmail.com on product 1
|5 | 2 | 1 |7.00 | -> price claimed by a previous retailer b#gmail.com on product 1
|6 | 3 | 1 |8.00 | -> price claimed by a customer c#gmail.com on product 1
Table products
_____________________________________
|id | user_id| name | Price
|-------------------------------------
| 1 | 1 | Milk | 10.00
| 2 | 2 | Phone | 12.33
| 3 | 1 | computer | 33.44
| 4 | 1 | Banana | 33.22
--------------------------------------
=============== MY Model Relationship ===============
Price model relationship
class Price extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
Product model relationship
class Product extends Model
{
public function prices()
{
return $this->hasMany('App\Price');
}
}
User model relationship //a user can claim 1 or more prices
class User extends Model
{
public function prices ()
{
return $this->hasMany('App\Price');
}
}
=============== MY Product Controller ===============
This is the tricky part here on how to get the price of all customers except retailer:
class ProductController extends Controller
{
public function show($id)
{
$product = Product::findOrFail($id);
// This query should return all price claimed by customers except retailer. But the problem is, it only return 1 row, the first row which the output is 10.00.
$query_customer =$product->prices()->whereHas('user', function ($q) {
$q->whereHas('roles', function ($q) {
$q->where('slug', 'customer');
});
});
$latest_price_by_customer= $query_customer->value('price');
dd($latest_price_by_customer);
//it just return 1 row: price 10.00
/* It should return the collection that I can do foreach statement. The output should be like this:
10.00
6.00
5.00
7.00
8.00
*/
}
}
The query in the controller above return all prices claimed by customers except retailer. But the problem is, it only return 1 row, the first row which the output is 10.00.
It should output all prices claimed by customers from the prices table like below:
10.00
6.00
5.00
7.00
8.00
Any idea?
Update:
So far I changed my controller codes from this:
$product = Product::findOrFail($id);
$query_customer =$product->prices()->whereHas('user', function ($q) {
$q->whereHas('roles', function ($q) {
$q->where('slug', 'customer');
});
});
$latest_price_by_customer= $query_customer->value('price');
dd($latest_price_by_customer);
to this:
$product = Product::with('prices')->findOrFail($id);
$product_query= $product->prices()->where('product_id', $id) ->whereHas('user', function ($q) {
$q->whereHas('roles', function ($q) {
$q->where('slug', 'customer');
});
})->select('price')->get();
dd($product_query); //display collection and return the correct values
}
I have one small problem here: When loop through the collection
foreach($product_query->prices as $pr)
{
// dd($pr);
// echo $pr->price . ' ___ ' ;
}
I got an error of ErrorException in ProductController.php line 72:
Undefined property: Illuminate\Database\Eloquent\Collection::$prices
but the relationship is exist as shown.
If anyone looking for the answer this is the correct query that returns collection instead of 1 row:
$product = Product::with('prices')->findOrFail($id);
$product_query= $product->prices()->where('product_id', $id) ->whereHas('user', function ($q) {
$q->whereHas('roles', function ($q) {
$q->where('slug', 'customer');
});
})->select('price')->get();
foreach($product_query as $price)
{
echo $price->price;
}
table1(users)
|ID|name |type |
|1 |demo |admin |
|2 |demoX |client|
table2(visits)
|ID|admin_id|visitor_id|visit_date|...
|1 |1 |2 |2013-01-01|...
admin(fk)->users(id)
user(fk)->users(id)
simple scheduler project, it contain 2 tables.
1st (users) contain all users, 2nd table contain all bookings(visits).
to get all bookings of an admin i run Select * from visits where admin_id=$id;, and join
visitor info from users table.
........
so basically,
every admin can have many visit
visit must contain (ONE)admin and (ONE)visitor.
how can i setup this kind of relation in datamapper orm ?
This should do it:
class Users extends Datamapper
{
public $has_many = array(
'admin' => array(
'class' => 'users',
'other_field' => 'admin', // FK = admin_id
),
'visitor' => array(
'class' => 'users',
'other_field' => 'visitor', // FK = visitor_id
),
);
}
class Visits extends Datamapper
{
public $has_one = array(
'admin' => array(
'class' => 'users',
'join_self_as' => 'admin', // FK = admin_id
),
'visitor' => array(
'class' => 'users',
'join_self_as' => 'visitor', // FK = visitor_id
),
);
}
// then in your controller you can do:
$visit = new Visitor(1);
echo $visit->admin->name; // echo's 'demo';
echo $visit->visitor->name; // echo's 'demoX';
First of all I think, instead of having a table with admin_id and user_id (isn't helpful), you should have a separate table with users and privileges, then the table structure would be.
Users privileges
| id | user | privilege_id | | id | privilege |
| 1 | user1 | 1 | | 1 | user |
| 2 | admin1 | 2 | | 2 | admin |
Then when you are calling the user level within the application just:
SELECT privilege FROM privileges WHERE id = <privilege_id from users table which should already be set within your code> (MySQL)
you should ALWAYS try and set id's in your tables for this purpose, this will be the basis of your relationship data when your gathering data from another table, so in this example it will be the <id> field of the privileges table and the <privilege_id> of the users table.
From here you should be able to transfer this method across to Datamapper or codeigniter or whatever your misleading tags mean =]
if you need to SELECT a booking from a database, select the booking(make an additional table and append as below) and look for the times of the bookings where ((privilage_id == 1) && (privilage_id == 2)) this will look for the dates where there is both a admin and a user, instead of just looking at one user type you are looking at them all and also saving yourself some hassle by making the call to one column rather than several. also this way you can easily manage your tables as their names relate to there function.
Users privileges booking
| id | user | privilege_id | | id | privilege | | id | date | privilege_id |
| 1 | user1 | 1 | | 1 | user | | 1 |5/2/13| 1 |
| 2 | admin1 | 2 | | 2 | admin | | 2 |5/2/13| 2 |
so the MySQL would be SELECT date FROM booking WHERE ((privilege_id == 1) && (privilege_id == 2)) this will give you the results you would expect, if you need to sanitise your data to go into the tables then you would require two rows to be made in one database which would be done by a procedure like this (this example will use an imaginary filled booking form(and is done in PHP)):
if((isset($user) && (isset($usertype)) && (isset($usertypetwo)) && (isset($date)))
{
if(($usertype != $usertypetwo))
{
"Insert BLAH BLAH"
}
}
also remember using this method you will need to get the user type from the user table to get the privilege_id