Marking properties as fillable when using Laravel relationship functions - laravel

I have a Team model which can have many Site models attached, and has a createSite function to add sites:
public function createSite($domain) {
$site = new Site(['domain' => $domain]);
return $this->sites()->save($site);
}
Running this fails, as domain is not fillable. While easily fixed, I've read the docs on Mass Assignment and am trying to minimise which fields are fillable.
What's best practice here? Should I use $fillable or explicitly assign these properties (ie $site->domain = $domain)?

you can also protected $guarded = [] it is same as fillable but its functionality is opposite to the fillable you can read about it on the official web.

Related

What is $model in Yii2?

I'm new to MVC and Yii Framework. The $model variable seems very confusing to me.
Where is it declared in the fist place? Where does it come from?
When I work with GridView I see that some functions take $model as a parameter. Neither model nor model search of this GridView declares $model variable anywhere. Yet it is widely used in all sorts of data management. It just doesn't make sense to me.
So I need a simple, straight forward, "for dummies" explanation of $model variable in Yii Framework v2. Help in clarifying these questions is much appreciated:
1. What is the origin of $model variable?
2. How to identify what model of the app is the $model variable representing when it's used in view files?
3. There are sometimes multiple $model variables in a single view file. Do all of them represent one model class? How to distinguish them when used for multiple classes?
Thanks.
If you are unsure where $model, $searchModel and other variables come from, you are most likely searching for them on the view file where they are used.
They are created on the controller that renders said view, just like any other object/variable.
From the controller, you can render a view and pass objects/variables the following way:
// MyController.php
...
public function actionMyAction($id) {
// Create and manipulate $model and $searchModel
...
/*
* First param is the name of the view to be rendered
* Second param is an Associative Array with params
* that will be made available to the view.
*/
return $this->render('my-view-name', [
'model' => $model,
'searchModel' => $searchModel,
]);
}
The $model is a var as the others ...normally in the yii2 samples contain an instance of a model class (as tiplically an active record=)
assuming you have a class
class Category extends \yii\db\ActiveRecord
{
........
a tipical code could be
$model = Category::findOne($id);
where Category::findOne($id) find an instance form database using $id as primary key and assign the result to $model ..
then you can access to the instance attribute (eg:attribute1) using
$model->attribute1
you can take a look at this guide
http://www.yiiframework.com/doc-2.0/guide-index.html
http://www.yiiframework.com/doc-2.0/guide-structure-models.html
http://www.yiiframework.com/doc-2.0/guide-db-active-record.html

Model returns relation´s dynamic attributes but null relation

I have set 2 models (Post and Category) with it´s proper relationships configured
class Post extends Model
{
protected $fillable = [
'title',
'excerpt',
'body',
'featured',
'published',
'category_id',
];
public function category()
{
return $this->belongsTo('App\Category');
}
}
class Category extends Model
{
protected $fillable = [
'name',
];
public function posts()
{
return $this->hasMany('App\Post');
}
}
And my Post´s storing method is
public function store(Request $request)
{
$post = Post::create($request->all());
return redirect('admin/posts');
}
The thing is, it´s actually working ok, it sets the category_id on the table and I can fetch all the dynamic data by using $post->category->name, but when I var_dump($post->relation) I get a null return.
I if create a new Post model, set all the attributes, save it and then associate the Category model (as documented on the official channel), it will return everything as expected.
For now, all I need is to fetch it´s dynamic attributes, and it´s working fine now, but I know I must be doing something wrong to get the null response. My concern is that it may be working fine now, but when the project gets larger I´ll probably face a bigger problem and I´ll have a lot of work to fix this issue.
The relation isn't there because you haven't loaded it. All it knows is the foreign key. It would be wildly inefficient if it grabbed all that information for you because it wouldn't always need all that. Think of instances where a single model could have many relationships, that would be many database calls for no reason.
If you need the relation, you can use $post->category. Since the relation is not yet loaded, it will get it for you when you do this.
Or you can eager load it by using the following $post->load('category') although this doesn't really benefit you because you are working with a single Post at this point. If you had a collection of Post objects, then you'd start seeing the benefits of using $posts->load('category') otherwise you end up with the n + 1 problem.
Consequently, if you use $post->load('category') and then var_dump($post), you should see that the relation is no longer null.

Can you create a new Model instance without saving it to the database

I want to create a whole bunch of instances of a model object in Laravel, then pick the optimal instance and save it to the database. I know that I can create an instance with Model::create([]), but that saves to the database. If possible I'd like to create a bunch of models, then only "create" the one that is best.
Is this possible?
I am using Laravel 5.0
You create a new model simply by instantiating it:
$model = new Model;
You can then save it to the database at a later stage:
$model->save();
You can create instances with Model::make(). It works the same way as create but it doesn't save it.
Whether or not this is best practice is another matter entirely.
Yes, it is possible different ways: you can use the mass assignment without saving.
Please remember to set first the $fillable property in your model.
WAY #1: using the method fill
$model = new YourModel;
$model->fill([
'field' => 'value',
'another_field' => 'another_value'
]);
$model->save();
WAY #2: using the constructor
$model = new YourModel([
'field' => 'value',
'another_field' => 'another_value'
]);
$model->save();
In YourModel set the $fillable property with the fileds allowed for mass assignment:
class YourModel extends Model
{
protected $fillable = ['field', 'another_field'];
// ...
}
Laravel documentation: https://laravel.com/docs/9.x/eloquent#mass-assignment
there is also a method you can call it statically to get new instance:
$modelInstance = $modelName::newModelInstance();
it takes array $attributes = [] as a parameter

Laravel 4 : Can't add new element in a database

I am new in Laravel 4 framework, I am working on library management project. I get all the data from my DB but I can't add a new book to my database.
I've created a form to add new books to my database. I get the Input::get('element') value from my store() method but the create Methode doesn't work . here's my code to save a new book :
Livre::create(array('titre' => Input::get('titre'),
'resume'=> Input::get('resume') ));
and here's my Model :
class Livre extends Eloquent {
protected $table = 'livre';
}
You need to create a new Model instance by calling:
$livre = new Livre;
Then add your 'fields':
$livre->titre = Input::get('titre');
$livre->resume = Input::get('resume');
Then save your new book by calling the save() or push() method:
$livre->save();
Or if you'd like to save a model with its relationships, use the push() method:
$livre->push();
Seems that when you say that create method doesn't work you mean that the record in your DB is created, but it has empty values. This happens when you dont't specify the fields enabled for massive assignment.
By default , the Eloquent model has the guarded attribute set to a wildcard blocking of mass assignment. To use the code that you showed us, modify your model :
class Livre extends Eloquent {
protected $table = 'livre';
protected $fillable = array(
'titre',
'resume'
);
}
You can read more here : Mass Assignment

How to: mass assign an update in Laravel 4?

This is an for internal app, mass assignment security is not an issue in this case.
I'm dealing with very large (numerous) form fields, so mass assigning the user edits would be great. Mass assignment seems to work fine with 'create()' but not with doing a find & save.
This is what I have:
$post_data = Input::all();
$formobj = HugeForm::find($id);
$formobj->save($post_data);
How do I go about it? I'd rather not specify many dozens of form inputs.
You should be able to use fill(array $attributes)...
$post_data = Input::all();
$formobj = HugeForm::find($id);
$formobj->fill($post_data);
$formobj->save();
In case of mass update it could be written even shorter.
$post_data = Input::all();
HugeForm::find($id)->update($post_data);
To allow mass assignment within Laravel you need to add:
protected $guarded = array();
Into your model. Basically this tells laravel not to protect any fields, you could also use:
protected $fillable = array();
And then set the fields you want to be fillable.
Hope this helps
This worked for me just 1 line (Laravel 8):
#ModelName::find($id)->update($request->all());

Resources