Laravel 4 - foreign key constraint fails - php

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.

Related

Create one to many table relationship with text input Laravel

I have two tables with a one to many relationship - gratitude_journal_entries and self_gratitudes. Multiple self gratitudes (which are submitted as text entries by the user) can apply to 1 gratitude_journal_entry. The data is passed to these two tables via a form.
I am trying to store the self gratitude text entries in an array and then pass these to the self_gratitude table along with the foreign key from the gratitude_journal_entries table.
The problem I'm having is I'm not sure how to take the input from the array and store this in the self_gratitude column.
Here are the columns for the gratitude_journal_entries table
Here are the columns for the self_gratitudes table
Here are the models and the store method in my controller
class SelfGratitudes extends Model
{
protected $table = 'self_gratitudes';
public $primarykey = 'id';
public function gratitudeJournalEntries() {
return $this->belongsTo(GratitudeJournalEntry::class);
}
}
class GratitudeJournalEntry extends Model
{
protected $table = 'gratitude_journal_entries';
public $primarykey = 'id';
public $timestamps = true;
public function user() {
return $this->belongsTo('App\User');
}
public function selfGratitudes()
{
return $this->hasMany(SelfGratitudes::class);
}
public function store(Request $request)
{
$this->validate($request, [
]);
$gj_entry = new GratitudeJournalEntry;
$gj_entry->user_id = auth()->user()->id;
$gj_entry['entry_date'] = date('Y-m-d H:i');
$self_gratitudes = $request->has('self_gratitudes') ? $request->get('self_gratitudes') : [];
$tj_entry->save();
$gj_entry->selfGratitudes()->sync($self_gratitudes);
return redirect('/dashboard')->with('success', 'You submitted a new journal entry');
}
If you want to keep array in database you can use casting on your columns:
laravel document
class SelfGratitudes extends Model
{
protected $casts = [
'self_graitude' => 'array',
];
protected $table = 'self_gratitudes';
public $primarykey = 'id';
public function gratitudeJournalEntries() {
return $this->belongsTo(GratitudeJournalEntry::class);
}
}

How to get only active element from many to many relationship with translation in laravel

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();

Array returning null value, many to many. laravel

I'm trying to retrieve data from many to many relationship.I have two tables :
companies: [cid,name,origin]
vehicle_types: [id, type]
their pivot table: companies_vehicle_types: companies_id,vehicle_types_id Relationship defined: In Companies:
class companies extends Model
{
//
protected $fillable = ['name','origin'];
protected $primaryKey = 'cid';
public function vehicles(){
return $this->hasOne('App\vehicles');
}
public function vehicle_types(){
return $this->belongsToMany('App\vehicle_types', 'companies_vehicle_types', 'companies_id', 'vehicle_types_id');
}
}
In vehicle_types
class vehicle_types extends Model
{
//
protected $fillable = ['type'];
public function vehicles(){
return $this->belongsTo('App\vehicles');
}
public function companies(){
return $this->belongsToMany('App\companies','companies_vehicle_types','vehicle_types_id','companies_id')->withTimestamps();
}
}
I want to retrieve companies where vehicle_types = specific type. How can i do that? I tried doing following in my controller:
$vehicle_types=vehicle_types::where('type','Bike')->get();
foreach ($vehicle_types as $vehicle_type) {
# code...
foreach ($vehicle_type->companies as $company) {
$brand[]=$company->pivot->name;
}
}
return $brand;
But it doesn't seem to be working. $vehicle_types is working fine and returning value. $brand is not returning any value.

Accessing nested relationship with Laravel 4

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');
}
}

Inserting data with one-to-many relationship

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.

Categories