Nested Eloquent Relation - HasOneThrough Issue - eloquent

I have below setup for tables:
Product_variant Table
Product_variant -> id, name, code, image
Warehouse table
Warehouse -> id, name, address
Product Variant Stock table
Product_Variant_stock -> stock_id, warehouse_id, variant_id, stock_qty
Now, what i need to get information is about in which Warehouse, variant has been stored, when i try to access product variant information.
What i have tried in ProductVariation model:
public function warehouseName()
{
return $this->hasOneThrough(Warehouse::class, ProductVariantStock::class, 'warehouse_id', 'id');
}
Above is not working as expected. Any help is appreciated.

laravel hasOneThrough works like this
class ModelA extends Model
{
...
public function cModel()
{
return $this->hasOneThrough(
ModelC::class,
ModelB::class,
'model_a_id', // Key on B that relates to A
'model_c_id', // Key on C that relates to B
'a_id', // Key on A that relates to B
'b_id', // Key on B that relates to C
);
}
}
so your code will be
public function warehouseName()
{
return $this->hasOneThrough(Warehouse::class, ProductVariantStock::class, 'variant_id', 'id', 'id', 'warehouse_id');
}

Related

Laravel eloquant belongsToMany get records belongs to relationship

I'm using many to many relationship with products and product_categories tables using product_product_category pivot table.
Product model
class Product extends Model
{
public function product_categories() {
return $this->belongsToMany(ProductCategory::class, 'product_product_category');
}
}
ProductCategory model
class ProductCategory extends Model {
public function products() {
return $this->belongsToMany(Product::class, 'product_product_category');
}
}
What I need to do is when I supply an array of categories need to get products only with these categories. This is my code
$selectedCategotries = array(1, 2);
$products = Product::with(['product_categories' => function($q) use ($selectedCategotries){
$q->whereIn('product_categories.id', $selectedCategotries);
}])->get();
But I get all the products instead. It will be a great help if you can supply a solution for me.
Finally, I found an answer with whereHas. Adding the answer for anyone who come up with the same issue.
$products = Product::whereHas('product_categories', function ($q) use ($selectedCategotries) {
$q->whereIn('product_categories.id', $selectedCategotries);
})->get();

Eloquent Relation with foreign key

I have issues by connecting to tables
I have 2 Model
First Model called PodioBorgerNotat with columns in the table called podio_borger_notats
id
user_id
item_id
app_item_id
borger_item_id (foreign key) 🔐
medarbejder_item_id
status
The second Model called PodioBorgerStamark with columns in the table podio_borger_stamarks
id
item_id (local key) 🔑
app_item_id
status
initials
name
I want to make a connection between PodioBorgerNotat and PodioBorgerStamark
so this is what I do in PodioBorgerNotat Model
public function borger()
{
return $this->belongsTo(PodioBorgerStamark::class, 'borger_item_id', 'item_id');
}
Now I want to output the result by executing this output
$borgernotater = PodioBorgerNotat::orderBy('created_at', 'acs')->orderBy('id', 'desc')->with('PodioBorgerStamark')->paginate(10);
This wont work and i get this error messsage
Call to undefined relationship [PodioBorgerStamark] on model [App\PodioBorgerNotat].
Your relation name is borger:
public function borger(){
...
}
You should call borger in with():
$borgernotater = PodioBorgerNotat
::orderBy('created_at', 'acs')
->orderBy('id', 'desc')
->with('borger')
->paginate(10);

eloquent refer to a column of a related a model

I have three tables:
categories
id, title
products
id, name
categories_products
id, category_id, product_id
I have also setup the according models and relationships (both have belongsToMany of the other)
Now I want to get all products belonging to a category
Category::where('title','Electronics')->first()->products()->limit(10)->get(['products.name']);
which works fine, but I also want to include the category title for each product as well:
Category::where('title','Electronics')->first()->products()->limit(10)->get(['products.name','category.title']);
However it returns: Column not found category.title
I thought that the relation would take care of it.
EDIT: Models -->
Category:
class Category extends Model
{
protected $fillable = array('title');
public function products()
{
return $this->belongsToMany('Product', 'categories_products', 'category_id', 'product_id');
}
}
class Product extends Model
{
protected $fillable = array('name');
public function categories()
{
return $this->belongsToMany('Category', 'categories_products', 'product_id', 'category_id');
}
}
The reason you're getting the error is because get() works just like select() and because you're running the category query and then running the product query after there is no categories table to reference for the select.
Look into Eager Loading. It will help with a lot of these kinds of issues. Your query can be written as:
Product::select('id', 'name')
->with(['categories' => function($query) {
return $query->select('id', 'title');
}])
->whereHas('categories', function($query) {
return $query->where('title', 'Electronics');
})
->limit(10)
->get();
Because we are lazy loading you NEED the id column on each model so Laravel knows where to attach the relationships after the queries are run.
The with() method above will eager load the categories relationship and the whereHas() method puts a relationship constraint on the current query.
UPDATE
Similar query from Category model:
$category = Category::where('title','Electronics')
->with(['products' => function($query) {
return $query->select('id', 'name')->limit(10);
}])
->first(['id', 'title']);
Then access the products with:
$category->products

Nested wherehas with different relation in Eloquent

Here is some relation between Eloquent classes in a Laravel 5 application:
B belongs to A
B has one C
Table are built with the correct foreign keys.
Here is a scope method of A:
public function scopeMyScope(Builder $query)
{
return $query->whereHas('B.C', function($q) {
$q->whereRaw("1=1");
});
}
If we call A::myScope()->get(), it results in an SQL error, because laravel built this query:
select * from "a" where (select count(*) from "b" where "a"."a.b_id" = "b"."id" and (select count(*) from "c" where "c"."b_id" = "b"."id" and 1=1) >=1 ) >= 1
The error is:
Illuminate\Database\QueryException with message 'SQLSTATE[42703]: Undefined column: 7 ERROR: column c.b_id does not exist
So, the query built is wrong because there is no c.b_id column (because B hasOne C, so the join column is in C). Am I doing something wrong or is it a bug in laravel's query builder?
From what I can understand, you need to do a nested whereHas, so:
public function scopeMyScope(Builder $query)
{
// b is the name of the relationship...
return $query->whereHas('b', function($q)
{
// c is the name of the relationship...
$q->whereHas('c', function()
{
$q->where(1, 1);
});
}
}
Does this solve your problem?

Updating Foreign Key Table in EF4.1 MVC3. Object is null on POST

When i use foreign keys in the entity framework the foreign key object is null when i do a POST. I am using MVC3 and EF 4.1. I have two tables, Product and Product Details. I am exposing them using the HTML helpers in a Razor view. When the GET happens, the product details are shown. But when i do a form Submit and post to the server, the Product Details collection is null. I lose all my changes.
Any ideas what i am doing wrong?
Thanks for your help!
The Code (i shortened it because it is fairly lengthy):
Database:
Table Product
{
int Id
varchar Name
}
Table ProductDetails
{
int id,
int ProductId, <- foreign key SQL 2008 to Product Table
varchar Details
}
View:
#model WebSite.Models.Product
#{
ViewBag.Title = "MyLifeSaverStoreInfo";
}
#Html.TextBoxFor(m => m.Product.Name)
#Html.TextBoxFor(m => m.Product.ProductDetails.FirstOrDefault().Description)
Controller:
public ActionResult EditProduct(int productId)
{
var Product = _productRepository.GetProduct(productId);
return View(product);
}
[HttpPost]
public ActionResult EditProduct(Product model)
{
string name = model.Name; <- this update comes through
string description = model.ProductDetails.FirstorDefault().Description;
}
Thanks
Got it!
Instead of creating the "Product" entity on the POST EditProduct method, i use a Form Collection and then set each product detail according to that form collection and then save. I don't understand why it doesn't work the first way. I am manually updating the foreign reference. Maybe i am missing something?
[HttpPost]
public ActionResult EditProduct(int id, FormCollection formCollection)
{
var model = new MyLSstoreInfoViewModel{
StoreCurrent = _profileRepository.GetProduct(Id)
};
var productDetails = model.Product.ProductDetails.Where(p => p.productId == id).Single();
productDetaisl.Details = formCollection["details"];
if (TryUpdateModel(model.StoreCurrent))
{
_profileRepository.Save();
}
}
It's a bit late, but maybe useful for someone in the future:
If you pass the primary key of the referenced child as a hidden input in the view, it will correctly resolve the child model in the action.