In PHP-MySQL I can create this query...
$sql = "SELECT * FROM product";
$result = $conn->query($,con, $sql);
while($row =mysql_fetch_array($result)){
$sqlquantity = "SELECT * FROM quantity where branchid='4' and productid='$row['productid']'";
$resultquantity = $conn->query($,con, $sqlquantity);
if (mysqli_num_rows($resultquantity) == 0) {
echo $row['productname']. "not available in branch"
}
else {
echo $row['productname']. "available in branch"
}
}
But how can I do this using Laravel?
I have 3 tables
+-----------------+ +-----------------+ +----------------+
| product table | | quantity table | | branch table |
+-----------------+ +-----------------+ +----------------+
| id | | productid | | id |
| productname | | branchid | | branchname |
+-----------------+ | quantity | +----------------+
+-----------------+
My problem is that I am trying to create a model, view and controller where I can display all the products that is not available yet on each branch base on the quantity table. Can anyone help?
Product model
public function quantity()
{
return $this->hasMany('App\Quantity', 'productid', 'id');
}
Quantity model
public function product()
{
return $this->belongsTo('App\Product', 'productid', 'id');
}
Branch Model
public function products()
{
return $this->hasMany('App\Quantity', 'branchid', 'id');
}
What I am trying to create is that if I view the branch I can add those product quantity table if the product does not exist.
You could also try this one...
Please check many-to-many relationship at the Official Docs for better explanation. .
You don't need to create a Quantity model because it serves as a pivot or joining table (not an entity) between Product and Branch model. Since you have custom pivot table name, which is quantity you need to pass it to the 2nd argument or else Eloquent will automatically create a table name for you which is branch_product (alphabetical). 3rd and 4th arguments are foreign keys of current model and the joining model respectively.
Product model
public function branches()
{
return $this->belongsToMany('App\Branch', 'quantity', 'productid', 'branchid')
->withPivot('quantity'); //additional pivot column
}
Branch model
public function products()
{
return $this->belongsToMany('App\Product', 'quantity', 'branchid', 'productid')
->withPivot('quantity');
}
Product Controller
$products = Product::all();
if($products){
$x = 0;
foreach ($products as $prod) {
$products[$x] = $prod->branches()
// ->wherePivot('productid', '=', $prod->id)
->wherePivot('branchid', '=', 4)
->wherePivot('quantity', '=', 0)
->get();
$x++;
}
}
return response(['products' => $products],200);
//get all the products in branch 4 with quantity = 0
Then you could do the conditional if to determine if it is available or not.
You could use whereHas() method like :
Product::whereHas( 'Quantity', function($sQuery){
$sQuery->where('branchid', 4);
})->get();
Related
I have Three Models name Invoices, Invoiceitems and Products.
Each Invoices HasMany Relationship with Invoiceitems Model.
Each Invoiceitems HasOne Relationship with Products Model.
I need to sum of Invoiceitem product amount where the Product has category 4.
Table Structure
Invoice
id | date | total_amt
Invoiceitem
id | invoiceid | product_id | product_amt | quantity | total_amt
Product
id | product_name | category_id
Relationship
Invoice Model
public function invoiceitems()
{
return $this->hasMany('App\Invoiceitems', 'invoiceid', 'id');
}
Invoiceitem Model
public function products()
{
return $this->hasOne('App\Products', 'id', 'product_id');
}
Expected Report
Invoice No | Date | Veg Category Product Amt | NonVeg Category Product Amt | Total Amt
KL0001 | 15-05-2021 | 0.00 | 190.366 | 190.366
KL0002 | 16-05-2021 | 20.00 | 350.000 | 370.000
Currently we use following Helper Function to get Particular category Products Total Amount
function getInvdiscsumamt($inv_id, $prdtype)
{
$totaldisamt = Invoiceitems::Where('invoice_id', $inv_id)->whereHas('products', function ($query) use ($prdtype) {
$query->where('category_id', $prdtype);
})->sum('total_amt');
return $totalpdtamt;
}
How to display particular category products total amount using Elequoent method
You can try one of the aggregate functions that already exist in Eloquent, see https://laravel.com/docs/8.x/eloquent-relationships#other-aggregate-functions, for instance withSum:
$invoiceItem = InvoiceItem::query()
->where('invoice_id', $invId)
->withSum(['products', function($query) use ($productType) {
$query->where('category_id', $productType);
}, 'frequency'])
->first();
Your property will then be available using the property {relation}_{function}_{column}, so in this case products_sum_frequency.
Note that the withSum does not share anything with the with (or whereHas) function, that means that if you use a subselection in your query like ->with(['products', function($query){...}]) that will be a separate selection from the withSum query.
I also recommend to use proper camelcasing in your functions and also your models. I'd also use singular names for all your model class names. So Invoiceitems would become InvoiceItem (models/InvoiceItem.php). This is the default way to define it in laravel as far as I'm aware.
I want to delete the product_id in the inventories table after deleting a specific group.
Table Structure:
product_groups
id | grp_name
products
id | prod_name | price | group_id
inventories
id | product_id | in_stock
Code:
public function ProductGroups_destroy($id)
{
$product_group = ProductGroup::find($id);
$product_group->delete();
$product_group->product()->delete();
$product_group->product->inventory()->delete();
Session::flash('success', 'Product group deleted');
return redirect()->back();
}
Models
Product Model, ProductGroup Model
Inventory Model
1) You can use this in your Inventory Migration :
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
Source : https://laravel.com/docs/5.5/migrations#foreign-key-constraints
2) You can overwrite the delete method :
class Product extends Model {
protected $table = 'products';
public function inventory(){
return $this->hasMany('App\Inventory', 'product_id');
}
public function delete()
{
DB::transaction(function()
{
$this->inventory()->delete();
parent::delete();
});
}
}
I have 4 tables in my database:
Table 1: Category
---|------
id | name
---|------
1 | Cars
In 'Category' model class I have defined the following relationship:
class Category {
public function fields() {
return $this->belongsToMany('App\Field');
}
}
Table 2: Field
id | name
---|-------
1 | Make
In 'Field' model class I have defined the following relationship:
class Field {
public function categories() {
return $this->belongsToMany('App\Category');
}
}
Table 3: Field_Options
field_id | value
---------|-------
1 | Audi
1 | BMW
In 'FieldOption' model class I have defined the following relationship:
class FieldOption extends Model
{
public function field() {
return $this->belongsTo('App\Field');
}
}
Table 4: Category_Field
category_id | field_id
------------|-------
1 | 1
Now I need to fetch all the fields and field_options for category_id=1. How can I achieve this using Laravel?
Thanks!
First define relationship between Field and FieldOptions
public function options() {
return $this->hasMany('App\FieldOption');
}
Then you can eager load all relationships like this
$category = Category::with('fields.options')->find(1);
//Get category 1, with all fields and their respectif fieldOptions
I read the laravel documentation but I couldn't understand very well.
I have this structure on my database.
PriceTable - which contains info about the period of promotional prices and the default price.
Product - which contains info about products.
and PriceTable_Product - which contains the foreign keys of Product and PriceTable and the respective price.
Example:
PriceTable | PriceTable_Product | Product
id | description | PriceTable_id | Product_id | price | product_id| name
1 | default | 1 | 1 | 5.00 | 1 | test
2 | promotional | 2 | 1 | 3.50 |
And at the Order table I can have multiples products, so I want to know if it is possible to relation Order table, with the pivot table PriceTable_Product, because I need the information of which table belongs the price when the product was sold.
First of all you may define the relations between Product and PriceTable.
Product model (App\Product.php)
<?php
namespace App;
class Product extends Model {
protected $table = 'products';
//if the default primary key isn't 'id' you may use $primaryKey
protected $primaryKey = 'product_id';
public function pricetables() {
return $this->belongsToMany('App\PriceTable');
}
}
PriceTable model (App\PriceTable.php)
<?php
namespace App;
class PriceTable extends Model {
protected $table = 'pricetable';
public function products() {
return $this->belongsToMany('App\Product');
}
}
If you created the relations then you can use:
$product = App\Product::find(1);
foreach ($product->pricetables as $pricetable) {
echo $pricetable->pivot->description;
}
I have three tables:
products: id|name|description|slug|category_id|...
reviews: id|product_id|review_text|name|email|...
review_rows id|review_id|criteria|rating
the review table stores the review text, writer of the review and has a foreign product_id key. The review_rows table stores the ratings for different criteria like:
----------------------------------------
| id | criteria | rating | review_id |
----------------------------------------
| 1 | price | 9 | 12 |
----------------------------------------
| 2 | service | 8 | 12 |
----------------------------------------
| 3 | price | 6 | 54 |
----------------------------------------
| 4 | service | 10 | 54 |
----------------------------------------
review rows are linked to the review table with the review_id foreign key. I've set up my model relationships like this:
Product -> hasMany -> Review
Review -> belongsTo -> Product
Review -> hasMany -> ReviewRow
ReviewRow -> belongsTo -> Review
Now I would like to display the average rating for a product on my category and product pages. How can I achieve this?
I need to sum and average all the reviewRows per review and then sum and average all of those for each review to end up with the overall rating for that product. Is this possible via Eloquent or do I need a different solution or a different database design/structure?
Thanks in advance!
You need something like this http://softonsofa.com/tweaking-eloquent-relations-how-to-get-hasmany-relation-count-efficiently/ only slightly adjusted to match your needs:
public function reviewRows()
{
return $this->hasManyThrough('ReviewRow', 'Review');
}
public function avgRating()
{
return $this->reviewRows()
->selectRaw('avg(rating) as aggregate, product_id')
->groupBy('product_id');
}
public function getAvgRatingAttribute()
{
if ( ! array_key_exists('avgRating', $this->relations)) {
$this->load('avgRating');
}
$relation = $this->getRelation('avgRating')->first();
return ($relation) ? $relation->aggregate : null;
}
Then as simple as this:
// eager loading
$products = Product::with('avgRating')->get();
$products->first()->avgRating; // '82.200' | null
// lazy loading via dynamic property
$product = Product::first()
$product->avgRating; // '82.200' | null
Maybe you can try with Eloquent relationships and a little help from php function array_reduce
//model/Reviews.php
public function sum() {
return array_reduce($this->hasMany('ReviewRows')->lists('rating'), "sumItems");
}
public function sumItems ($carry, $item) {
$carry += $item;
return $carry;
}
Or with Eloquent RAW querys like:
//model/Reviews.php
public function avg() {
$result = $this->hasMany('ReviewRows')
->select(DB::raw('avg(rating) average'))
->first();
return $result->average;
}
Simple and easy solution. Add this into product model
protected $appends = ["avg_rating"];
public function reviewRows()
{
return $this->hasManyThrough('App\ReviewRow','App\Review','product_id','review_id');
}
public function getAvgRatingAttribute()
{
return round($this->reviewRows->average('rating'),2);
}
see https://github.com/faustbrian/laravel-commentable
public function comments(): MorphMany
{
return $this->morphMany($this->commentableModel(), 'commentable');
}
public function avgRating()
{
return $this->comments()->avg("rating");
}
$products = \App\Models\Products::with(
[
"comments" => function ($q) {
$q->with(["children" => function ($qch) {
$qch->take(2);
}
])->withCount("children")->where("parent_id", '=', null);
},]
)->take(5)->get();
foreach ($products as &$product) {
$product["avgRating"] = $product->avgRating();
}
dd($products);
use withAvg() as mentioned in laravel official documentation here