Laravel saving hasMany relationship - laravel

I'm using Laravel & Ardent and having issues saving through the hasMany relationship.
I have two classes.
Workorder:
protected $table = 'workorder';
protected $primaryKey = 'workorder_id';
public static $relationsData = [
'dates' => array(self::HAS_MANY, 'App\WorkOrderDate', 'foreignKey' => 'workorder_id'),
];
WorkOrderDate:
protected $table = 'workorder_date';
protected $primaryKey = 'date_id';
public static $relationsData = array(
'workorder' => array(self::BELONGS_TO, 'App\WorkOrder')
);
after saving my Workorder (which works fine), I'm trying to save a collection of Date models by executing:
$workorder->dates()->saveMany($myDateCollection->all());
But it's not running the date insert, and it's not giving me any errors. I turned on query logging and it looks like Laravel is trying to run an update instead of an insert. Do I have my relationship defined incorrectly here?

I was hydrating my date collection from user input, and when you hydrate a model, Laravel assumes the model exists already. Turns out this is not what I mean to do.
More detail here:
https://github.com/laravel/framework/issues/9360

Related

Laravel getAttribute() on eloquent?

so i just wondered, if something like this is possible, since my code does not work.
protected $appends = ['position_name'];
public function getPositionNameAttribute()
{
return $this->belongsTo('App\EmployeePosition', 'employee_position_id')->name;
}
Can I append the name of Eloquen relationship model?
edit: so far, i am using this:
foreach ($employees as $e) {
$e->position_name = $e->position->name;
}
So, I needed to use the relation defined before.
protected $appends = ['position_name'];
public function position()
{
return $this->belongsTo('App\EmployeePosition', 'employee_position_id');
}
public function getPositionNameAttribute()
{
return $this->position->name;
}
Based on your comments i'd suggest to use the laravel default solution for your problems API resrouces
eg
class EmployeeResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'position_name' => $this->position->name,
];
}
}
note: using the with as other people suggested to preload information can increase performance by reducing the amount of queries, if you are returning a collection of employees.
Creating an accessor that looks up a value in another model and appending this field by using $appends is bad practice and will lead to n+1 queries whenever you fetch your Employee model. You should avoid doing this and just use $employee->position->name.
You should also make sure to use Employee::with('position') when you need to show the position name, so that the position model is fetched in a single query.
If the position name is something that you need in all your Employee queries, then you can set the Employee to always eager load the position by defining the following inside your Employee model:
/**
* The relationships that should always be loaded.
*
* #var array
*/
protected $with = ['position'];
I think you can just create a model with position names and reference it to the position id in the other mode by using eloquent relationships.

Multiple Where Clause in Eloquent & Laravel

Trying to do a multiple select statement with eloquent.
used the Blog::where()
... function, and included an array in it.
$matchThese = ['title' => post('title'), 'slug' => post('slug')];
return Blog::where($matchThese)->get();
When tested it returns an empty value even for matching inputs, database table names correctly written
Model extends October CMS Model, so all eloquent methods in laravel are include. Blog Model Below
<?php namespace Andre\Blogroutes\Models;
use Model;
use ModelNotFoundException;
class Blog extends Model
{
use \October\Rain\Database\Traits\Validation;
public $table = 'blog';
}
Both of the following queries are exactly the same:
$matchThese = ['title' => post('title'), 'slug' => post('slug')];
return Blog::where($matchThese)->get();
and
return DB::table('blog')->where('title', '=',post('title'))->where('slug','=', post('slug'))->get();
if one worked and others didn't that means your Blog model is not actually targetting the right table blog. You should add the following line to you Blog model and see if the old query works:
protected $table = 'blog';
Also inside your controller, do not forget to add:
use App\Blog;
on top of it. Give the old query a roll and see if that works.
Was able to fix this:
DB::table('blog')->where('title', '=',post('title'))->where('slug','=', post('slug'))->get();
The $table variable must be protected not public
public $table = 'andre_blog';
to
protected $table = 'andre_blog';

Can eloquent ignore irrelevant data in Laravel 5.7

This is basically the same question as this here from 2013. Except the answer doesn't work for me.
I have a Model App\Post:
class Post extends Model
{
protected $fillable = ['title'];
// This Model doesn't contain an 'authorname' field
public function author()
{
return $this->belongsTo('App\Author');
}
}
and a Model App\Author:
class Author extends Model
{
protected $fillable = ['name'];
public function posts()
{
return $this->hasMany('App\Post');
}
}
And an array I want to save to that Model:
$posts = [
['title'=>'one post', 'authorname' => 'Mickey'],
['title'=>'another post', 'authorname' => 'Minny'],
];
foreach($posts as $post){
$authorModel=App\Author::firstOrCreate(['name'=>$post['authorname']]);
App\Post::create($post)->author()->associate($authorModel)->save();
}
According to this question, that should work, but I get an
SQL error 42522: Column not found: 1054 Unknown column 'authorname' in 'field list'
which suggests Laravel forwards the whole array to mySQL. Is there a way to make this work without unsetting the authorname key?
Obviously this is a simpified version of what I want to do and keeping track of what to unset seems unnecessary - as would be assigning all array keys to their respective database fields manually.
The only idea I have here is that you run this code in DatabaseSeeder (which automatically unguards models) or you somewhere manually call Eloquent::unguard() (or code similar to this). This would explain why any other fields are used when creating model no matter of $fillable property.

Why can't use create method when not all attributes are in $fillable array in Laravel

I am using laravel framework and I am trying to create a new record in the table "product"
and the table has 4 fields ('id','name','price','sec').
when I am writing this code a new row is added to the table successfully
class productModel extends Model
{
public $fillable = ['price','name'];
public $table = 'product';
public $timestamps = false;
public static function add(){
$model = new productModel();
$model->price = 6;
$model->name = 'pro2';
$model->sec = 33;
$model->save();
}
}
but when I write this code an error shows:
QLSTATE[HY000]: General error: 1364 Field 'sec' doesn't have a default value (SQL: insert into product (name, price) values (Flight 10, 44))
class productModel extends Model
{
public $fillable = ['price','name'];
public $table = 'product';
public $timestamps = false;
public static function add(){
productModel::create(['name' => 'Flight 10','price' => 44,'sec' =>
'content']);
}
}
but when I put the 'sec' field in the $fillable array it works well so what the problem?
The error you're getting is coming from your database, not Laravel.
When you assign the value explicitly (as in your first snippet), you aren't mass assigning it, so it doesn't matter what's in $fillable. You're giving it a value, so your database is happy.
When you don't have 'sec' in the fillable array, it's not getting assigned a value when you use create (which is mass-assigning the values). So, when Laravel goes to save your data, it's passing null to the database, which then responds with, "hey, this field isn't nullable and there's no default, so you have to tell me what to put into it."
So, your options are:
Update your database schema to make the field nullable, or add a default value at the database level.
Put "sec" into your $fillable array, so that it can be mass-assigned.
Set it explicitly somewhere in the create flow (either where you're setting the data or in some middleware layer, such as validation).
Which way you choose will depend on your needs.

Eloquent attribute type casting doesn't work in some models

Eloquent attribute casting is awesome, this is great feature that is useful to cast from DB type to native language types.
Boolean in my db is int(1), so I need to cast it to the bool type.
I have several models in my application, first model is User, and it works like a charm.
1 is converted into true, 0 into false, like I need.
class User extends Model {
protected $table = 'user';
protected $guarded = ['password','login','id','activationEmail'];
protected $hidden = [ 'password' ];
protected $casts = [
'activationEmail' => 'boolean',
'activationSMS' => 'boolean',
];
Everything is okay here, but I need to do the same trick in another model NewsArticle.
class NewsArticle extends Model
{
protected $table = 'news';
public $timestamps = false;
protected $casts = [
'Actual' => 'boolean',
];
}
But in this case cast doesn't work at all, I have tried to cast manually and it works, but casts array is ignored at all.
Is there any ideas where the problem can be ?
Thanks.
Sorry, I have made a mistake in file name of my class model, but the class name itself was correct and it successfully loaded because of some tricks with bootstrap file I have done in order to implement another task.
After file was renamed everything works like expected.

Resources