Laravel Update or Create Relationships - php

I have an Item model, that has ItemTranslations, I'm receive a Request with the Item I'm updating and the translations for that Item.
Now some of those translations will already be in the database (they have their own id), and some of them will be new. Is there a clean way to go about this?
In pseudo: Update the Item with this request, for each Translations you find in this request, update the translation relation if it exists, else create it for this Item.
This is the layout of my Item.
class Item extends Model
{
protected $fillable = ['menu_id', 'parent_id', 'title', 'order', 'resource_link', 'html_class', 'is_blank'];
public function translations()
{
return $this->hasMany(MenuItemTranslation::class, 'menu_item_id');
}
}
This is the ItemTranslation
class ItemTranslation extends Model
{
protected $table = 'item_translations';
protected $fillable = ['menu_item_id', 'locale', 'name', 'order', 'description', 'link', 'is_online'];
}

You could use the updateOrCreate method on the translations() relationship. For example:
$item->translations()->updateOrCreate([
'name' => $translation['name'],
// Fields that should be used to find an existing record.
], [
'description' => "New description",
// Fields that should be updated.
]);
The first argument is the data that you want Eloquent to look up the translation by and second argument is the data that you want to be updated.
Both arguments will be used to create a new translation when an existing one couldn't be found.

Related

Remove specific field from model before creating after processing laravel

I am trying to make a trait for storing images for models. I am not able to remove the thumbnail from the model.
Is there any way to remove the thumbnail field from the model because there is no field like a thumbnail in the table?
trait ModelHelpers
{
protected static $thumbnail;
public static function boot()
{
parent::boot();
self::creating(function($model){
$collection = collect($model);
self::$thumbnail = $collection->only('thumbnail');
$collection->except(['thumbnail']);
$model->ignoreField('thumbnail');
// ... code here
});
}
}
OR
Is there any way to add the data in the model that don't process while mysql query but is available in the model for processing before or after creating?
Right now I am adding the thumbnail key in fillable to get into the model but it is processed while the insert query that i don't want to:
protected $fillable = ['user_id', 'title', 'meta_title', 'slug', 'summary', 'published','published_time', 'thumbnail'];
$fillbale is used to define the properties you want to use in inserting.
If you want to skip some properties to insert it, you must use $guarded

searchable method on BelongsTo filed dose not work in laravel nova, not returning any items

i have a model called Customer that has HasMany Relatinship toNotes model
public function notes()
{
return $this->hasMany(Note::class);
}
and Note has BelongsTo relationship to Customer
public function customer()
{
return $this->belongsTo(Customer::class);
}
then i defined the same relationship in Note nova resource
BelongsTo::make('Customer', 'customer', Customer::class)
until here every thing works perfectly now if want to call ->searchable() on BelongsTo field it doesn't return any thing from search
BelongsTo::make('Customer', 'customer', Customer::class)->searchable()
how can i solve this problem
Your BelongsTo field is in different table, so if you want to search something in Note Resource with Customer field your search won't work. In this case I use SearchesRelations package for searching. You could install this package and put this code in your Resource class
public static $searchRelations = [
'customer' => ['name', 'another_customer_field'],
];
Please check the documentation for more details SearchesRelations .
the field that you call srearchable() on must be in search array in your resource.
so if your field is BelogsTo you must put the title field of the resource that you are belonging to into sreach array
in my case the title field is
public static $title = 'name';
so i put it in
public static $search = [
'id',
'name',
];
and every thing works as expected

Laravel 5 Model: Do not include certain columns in Eloquent

I am trying to find an easier approach to this simple function I have. Basically what I am doing is dynamically loaded a form that's based on an Eloquent model. I do not want to include certain columns in the model like id's and the created_at and update_at columns. I am able to accomplish this with the following piece of code:
get Controller:
$cms_information = collect(CmsUserInformation::where('users_id', Auth::user()->id)->first()->toArray());
$cms_information->forget('id');
$cms_information->forget('users_id');
$cms_information->forget('created_at');
$cms_information->forget('updated_at');
$cms_information->all();
return view('cms::admin.profile', ['user' => Auth::user(), 'cms_information' => $cms_information]);
Then, I will loop through the fields in a form and post them like so:
Post Controller:
$profile = CmsUserInformation::where('users_id', Auth::user()->id)->first();
$cms_user_information = Input::except('_token', 'email', 'password');
foreach($cms_user_information as $field => $info ) {
$profile->$field = $info;
}
$profile->save();
My Eloquent table:
id
user_id
first_name
last_name
email
created_at
updated_at
This works exactly how I want but I feel like it's a quick and dirty way around using the Eloquent object to accomplish this. Does anyone have a way to accomplish this same thing but only use Eloquent object rather than converting to an array and using the collect() function?
You can use the $hidden property on your Eloquent model:
class CmsUserInformation extends Model
{
protected $hidden = [
'id',
'users_id',
'created_at',
'updated_at',
];
}
This will automatically exclude the given attributes when the models are ultimately serialized.
If you only want to hide it in a specific instance, use the setHidden method:
$info = CmsUserInformation::where('users_id', Auth::id())->first();
$info->setHidden([
'id',
'users_id',
'created_at',
'updated_at',
]);
Use hidden property in the model you are using like this:
class User extends Model{
protected $hidden=[
'id',
'created_at',
'updated_at'
];
...
}

shared pivot table for inherited table

I have 3 tables, people, instructors, and trainees. instructor and trainees inherit from people. both three table have relation to fee_instructor table. here is all the models.
// Person.php
class Person extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
'name'=>'required',
'institution_id'=>'required',
'pob'=>'required',
'dob'=>'required'
];
// Don't forget to fill this array
protected $fillable = [
'name',
'title',
'position',
'institution_id',
'pob',
'dob',
'photo',
'last_education',
'nip',
'role_id'
];
public function fee(){
return $this->belongsToMany('Fee', 'fee_instructor', 'person_id');
}
}
// Instructor.php
class Instructor extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
];
// Don't forget to fill this array
protected $fillable = [
'name',
'title',
'position',
'institution_id',
'pob',
'dob',
'photo',
'email',
'last_education',
'nip'
];
public function fee(){
return $this->belongsToMany('Fee', 'fee_instructor', 'person_id');
}
}
// Trainee.php
class Trainee extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
];
// Don't forget to fill this array
protected $fillable = [
'name',
'title',
'position',
'institution_id',
'pob',
'dob',
'photo',
'last_education',
'nip',
'reg_date',
'company_name',
'marital_status',
'email'
];
public function fee(){
return $this->belongsToMany('Fee', 'fee_instructor', 'person_id');
}
}
// Fee.php
class Fee extends \Eloquent {
// Add your validation rules here
public static $rules = [
// 'title' => 'required'
];
// Don't forget to fill this array
protected $fillable = ['name', 'tarif', 'unit_id'];
public function unit(){
return $this->belongsTo('Unit');
}
public function instructor(){
return $this->belongsToMany('Instructor', 'fee_instructor');
}
public function person(){
return $this->belongsToMany('Person', 'fee_instructor');
}
public function trainee(){
return $this->belongsToMany('Trainee', 'fee_instructor');
}
}
when i try to update an entry that is not belongs to instructor (in both person or trainee), laravel throw the following error.
SQLSTATE[23503]: Foreign key violation: 7 ERROR: insert or update on table "fee_instructor" violates foreign key constraint "fee_instructor_instructor_id_foreign" DETAIL: Key (person_id)=(5) is not present in table "instructors".
how is the correct way to use the pivot table for these scenario?
Ah so your using postgresql. That' why I thought it was weird that you were talking about table inheritance. Take note that based on the docs http://www.postgresql.org/docs/9.0/static/ddl-inherit.html
Inheritance does not automatically propagate data from INSERT or COPY commands to other tables in the inheritance hierarchy.
INSERT always inserts into exactly the table specified.
...
In some cases it is possible to redirect the insertion using a rule (see Chapter 37).
So if you're not in the bounds of the rule, you may be incorrectly assuming that a row that exists in instructor also exists in the super-table person and vice-versa. You're update/insert on fee_instructor is failing simply because a row with person_id = 5 does not exist in the instructor table. It may exist in the person table but that is irrelevant. If it does not exist in instructor it wont work.
If you scroll through the docs about inheritance, you will also come up with the caveats of using inheritance:
A serious limitation of the inheritance feature is that indexes (including unique constraints)
and foreign key constraints only apply to single tables, not to their inheritance children.
So if you really want FK relationships with fee_instructor for both instructor and trainee then separate FKs have to exist for each table which I'm assuming you already have in place.
Please also take not that eloquent's regular relationship does not work well with the idea of inheritance. However, you may be able to achieve an inheritance type of behavior using polymorphic relations: http://laravel.com/docs/4.2/eloquent#polymorphic-relations

Laravel Eloquent Save to DB Using Create - Unhelpful Error

I get a very unhelpful error when I try and insert a new record in to my db. Does anyone have any idea where to start to solve this error?
user_id
That's all it says. (This is the name of one of my required fields in the table I'm saving to but it's not very descriptive.)
For reference here's my code:
$data = array(
'user_id'=>1,
'post_type'=>'0',
'post_title'=>'blah',
'description'=>'blah');
//it fails on this line
$id = Post::create($data);
Here's what my model looks like:
class Post extends Eloquent{
public static $rules = array(
'user_id'=>'required',
'post_type'=>'required',
'post_title' => 'required|max:25',
'description'=>'required'
);
public static function validate($data){
return Validator::make($data, static::$rules);
}
public function user(){
return $this->hasOne('User', 'id', 'user_id');
}
}
Tried getting rid of all relationships and validation in the model. That didn't work.
This is called mass-assignment in Laravel, what you need to do to get it working on your model is to set a protected array called $guarded to be empty. Add this to your model.
protected $guarded = array();
What this array does, it can prevent attributes to be mass-assigned with an array, if you don't want an attribute to be filled with the Model::create() method, then you need to specify that attribute in the $guarded array.
If instead you want to specify only the fillable attributes, Laravel's Eloquent also provides an array called $fillable where you specify only the attributes that you want to fill via the mass-assigment way.
Further reading:
Mass Assignment:
http://laravel.com/docs/eloquent#mass-assignment
Create Method:
http://laravel.com/docs/eloquent#insert-update-delete

Categories