I have three tables: Products, Company, Type. Company and Types has one-to-many relationship with Products.
[type model]
class Type extends BaseModel {
public static $table = "type";
public static $timestamps = true;
public function products() {
return $this->has_many('Products');
}
}
[company model]
class Company extends BaseModel {
public static $table = "company";
public static $timestamps = true;
public function products() {
return $this->has_many('Products');
}
}
[products model]
class Products extends BaseModel {
public static $table = 'products';
public static $timestamps = true;
public function company() {
return $this->belongs_to('Company');
}
public function type() {
return $this->belongs_to('Type');
}
}
In add_product route i have
$product = new Products($new_product);
$company_id = $all_posts['company_id'];
$company = Company::find($company_id);
$company->products()->save($product);
$type_id = $all_posts['type'];
$type = Type::find($type_id);
$type->products()->save($product);
but when I try to insert data to db i get:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '11' for key 'PRIMARY'
How do I update both type_id and company_id in Products table?
If I am not wrong, your products table should have product_id and type_id columns ? Just specify these values:
$new_product['company_id'] = $all_posts['company_id'];
$new_product['type_id'] = $all_posts['type'];
$product = new Products($new_product);
$product->save();
You don't need to use Company and Type model to make relationship between them and a product. You can simply fill the ids.
Related
I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
I get the results by this:
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
but I want to get only the active accessories something like where accessori.active = 1 but I really don't know where to put it. I've tried in different way but I'm stuck on it by 2 days.
IIRC you don't need a model for the intermediate table on your many to many relationships.
If you want to return Products where Accessori is active you can use whereHas on the Product model.
$prod = Product::whereHas('accessori', function($query) {
$query->where('active', 1);
})->get();
Where the $query param will be running on the Accessori model.
You can do the inverse as well with Accessori to Product.
$acessoris = Accessori::where('active', 1)->whereHas('accessoriProduct')->with(['accessoriLang', 'accessoriProducts.productsLang'])->get();
What am I trying?
Get a particular category and it's associated Sub Categories
Category Model
class Category_Model extends Model
{
protected $table = "tblcategory";
protected $primaryKey = "CategoryID";
public $timestamps = false;
public function Subcategories()
{
return $this->hasMany('\App\Models\Skill\SubCategory_Model');
}
}
Sub Category Model
class SubCategory_Model extends Model
{
protected $table = "tblsubcategory";
protected $primaryKey = "SubCategoryID";
public $timestamps = false;
}
Action Method
public function SubCategories($category)
{
$Categories = \App\Models\Skill\Category_Model
::where("Category", "=", $category)
->Subcategories;
dd($Categories);
}
When I run the code. I get below error
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'tblsubcategory.category__model_id' in 'where clause' (SQL: select *
from tblsubcategory where tblsubcategory.category__model_id = 1
and tblsubcategory.category__model_id is not null)
From the comments, it is most likely that your subcategory table doesn't have a category_model_id but likely a category_id. By default, Laravel tries to extrapolate the name of the foreign column from the model name (in this case Category_Model, which explains the category_model_id. Changing the class to:
class Category_Model extends Model
{
protected $table = "tblcategory";
protected $primaryKey = "CategoryID";
public $timestamps = false;
public function Subcategories()
{
return $this->hasMany('\App\Models\Skill\SubCategory_Model', 'category_id')->get(); // Or whatever the column is actually called
}
}
should solve the issue.
To return both the category object and its subcategories, change the action code to:
public function SubCategories($category)
{
$Categories = \App\Models\Skill\Category_Model
::where("Category", "=", $category)
->with("Subcategories")
->first();
dd($Categories);
}
The $Categories should also now contain a Subcategories object, accessed via $Categories->Subcategories, which should return a collection of Subcategory objects. If you wanted to see each one, you would loop through with a foreach
foreach($Categories->Subcategories AS $Subcategory){
echo $Subcategory->name;
// etc etc.
}
I have the following relations:
Discount:
<?php
class Discount extends Eloquent {
protected $table = 'discount';
public $timestamps = true;
public function title()
{
return $this->hasOne('Translation', 'labelId', 'titleLabelId')->where('languageId', T::getLang())->first()['phrase'];
}
public function titles()
{
return $this->hasMany('Translation', 'labelId', 'titleLabelId');
}
}
?>
Translation:
<?php
class Translation extends Eloquent {
protected $table = 'translations';
public $timestamps = false;
protected $fillable = array('phrase', 'languageId', 'labelId');
public function language()
{
return $this->belongsTo('Language', 'languageId');
}
public function label()
{
return $this->belongsTo('Label', 'labelId');
}
}
?>
Label:
<?php
class Label extends Eloquent {
protected $table = 'label';
public $timestamps = false;
protected $fillable = array('key');
public function translations()
{
return $this->hasMany('Translation', 'labelId', 'id');
}
}
?>
There are three database tables with the following columns:
Discount:
id | titleLabelId
Translation:
id | languageId | labelId
Label:
id
The problem: I'd like to create a title (translation) and associate it with the discount. Here's what I've tried:
$discount = new Discount;
/*create a new label*/
$labelKey = Label::max('key') + 1;
$label = new Label(array('key' => $labelKey));
$label->save();
/*create a new title (and associate it with the label)*/
$title = new Translation(
array(
'phrase' => $input['title'],
'languageId' => 3,
'labelId' => $label->id
));
$title->save();
$discount->save();
$discount->titles()->save($title);
Apparently, the $discount->titles()->save($title); part doesn't work. The title is only attached to the discount if I do it manually: $discount->titleLabelId = $label->id. Is there a way to do it using the ORM?
In your Discount Model, do you have your relationship set up to use the proper table and foreign key?
class Discount extends Eloquent
{
public function titles()
{
return $this->belongsTo('Translation', 'translations', 'titleLabelId');
}
}
When trying to associate one model with another through a defined relationship in Eloquent, you should use the associate() method rather than the save() method.
$discount->titles()->associate($title);
Before this happens though, you should be sure to call the save() method on anything that has been altered or is new.
I'm having trouble figuring out how to access a nested relationship within Laravel. The specific example I have is a Movie that has many entires in my Cast table which has one entry in my People table. These are my models:
MOVIE
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
MOVIECAST
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public function person()
{
return $this->hasOne('Person', 'person_id');
}
public function netflix()
{
return $this->belongsTo('Movie', 'movie_id');
}
}
PERSON
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
In my controller I can access the cast (containing person_id and role_id) like so:
public function movie($id)
{
$movie = Movie::find($id);
$cast = $movie->cast();
return View::make('movie')->with(array(
'movie' => $movie,
'cast' => $cast
));
}
...but I don't know how to access the corresponding name field in my People table.
EDIT 1:
Using the classes exactly as defined below in #msturdy's answer, with the controller method above I try to render the person names like so inside my view:
#foreach($cast->person as $cast_member)
{{$cast_member->person->name}}
#endforeach
Doing this i get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$person
I don't know if it makes a difference or not but I have no id field on my People table. person_id is the primary key.
It should be simple, once you have accessed the cast...
Route::get('movies', function()
{
$movie = Movie::find(1);
$cast = $movie->cast;
return View::make('movies')->with(array(
'movie' => $movie,
'cast' => $cast));
});
Note: at this point, $cast is an instance of the Collection class, not a single object of the MovieCast class, as the
relationship is defined with hasMany()
you can iterate over it in the View (in my case /app/views/movies.blade.php
#foreach($cast as $cast_member)
<p>{{ $cast_member->person->name }}</p>
#endforeach
Class definitions used for testing:
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
public $timestamps = false;
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public $timestamps = false;
public function person()
{
return $this->hasOne('Person', 'person_id');
}
}
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public $timestamps = false;
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
I have a laravel model
class Project extends Eloquent {
public static $timestamps = true;
public $includes = array('members','members.memberdata');
public function tasks() {
return $this->has_many('Usertask','project_id');
}
public function members() {
return $this->has_many('Projectmember','project_id');
}
}
and a related models
class Projectmember extends Eloquent {
public static $table = "project_members";
public static $timestamps = true;
public function project() {
return $this->belongs_to('Project');
}
public function memberdata() {
return $this->has_one('Usermetadata','user_id');
}
}
class Usermetadata extends Eloquent {
public static $table = "users_metadata";
public function user() {
return $this->belongs_to('User');
}
public function member() {
return $this->belongs_to('Projectmember','user_id');
}
}
When i attempt to retrieve a single project model like so
$project = Project::find($id);
return Response::eloquent($project);
my json output looks like this
{"id":1,"user_id":1,"name":"UberWork","description":"Web based project management \/ task management app","target_date":"2013-11-15 00:00:00","budget":null,"status":0,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","members":[{"id":1,"project_id":1,"user_id":1,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","memberdata":{"user_id":1,"first_name":"Tamarakuro","last_name":"Foh","photo":"","company_name":null,"phone":null,"package":"free","subscription_start":"0000-00-00 00:00:00","subscription_end":"0000-00-00 00:00:00","api_key":"12b14a7d3ca48c53bb5b1a88fa3eca3b"}},{"id":3,"project_id":1,"user_id":3,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","memberdata":{"user_id":3,"first_name":"Ebere","last_name":"Uche","photo":"","company_name":"Chronotech Labs","phone":null,"package":"free","subscription_start":"0000-00-00 00:00:00","subscription_end":"0000-00-00 00:00:00","api_key":"ab446bd9ffbb898e818a892c7401e0f6"}},{"id":4,"project_id":1,"user_id":2,"created_at":"2013-04-17 08:13:00","updated_at":"2013-04-17 08:13:00","memberdata":null}]}
My database look like this;
Users
id
email
password
ip_address
active
...
users_metadata
id
user_id
first_name
last_name
profile_photo
...
Projects
id
user_id
name
description
status
...
project_members
id
project_id
user_id
My question is why is the last member of the project having its memberdata as "null", while the others are not null. Am i doing something wrong?
Relationships in Eloquent always link a primary key (pk) with a foreign key (fk). However, you're trying to base a relationship on two foreign keys, skipping out a relationship. The only Eloquent solution is to include the extra relationship step. Here are some models (I've ommited the relationships we don't need for this example)...
class Project extends Eloquent {
public static $timestamps = true;
public $includes = array('members','members.user', 'members.user.metadata');
public function members()
{
return $this->has_many('Projectmember','project_id');
}
}
class Projectmember extends Eloquent {
public static $table = "project_members";
public static $timestamps = true;
public function user()
{
return $this->belongs_to('User');
}
}
class User extends Eloquent {
public static $timestamps = true;
public $hidden = array('password', 'ip_address');
public function metadata()
{
return $this->has_one('Usermetadata');
}
}
class Usermetadata extends Eloquent {
public static $table = "users_metadata";
public function user() {
return $this->belongs_to('User');
}
}
I can see why you'd want to skip the relationship, but sadly it's not possible with relationships.