I have one model and one controller and multiple configurations.
If I'm on config #1 my models $guarded property should be
$guarded = ['foo', 'bar'];
If I'm on config #2 my models $guarded property should be only
$guarded = ['foo'];
The config loaded is dependant on a domain/subdomain.
In my controller I have an import function which takes an array of data. 4 or so of the fields need to go to one table which is common across all configs and the remaining values(which are variable depending on the config loaded) need to go into a separate pivot table. So one config might have 8 fields but another may have 9 or more / less.
I've tried to remove the variable fields from the insert into the first table with guarded with something similar to the code here. After which I take the variable fields and insert into the other table.
protected $guarded = ['some', 'common', 'guarded', 'fields'];
function __construct()
{
$this->guarded = array_merge($this->guarded, config('custom_fields_for_domain'));
}
While I can dd($this->guarded) directly after and see the variable fields correctly in the model, I receive errors when trying to import into the first table as it's still trying to import all the variable fields rather than just the 4 or so fields I want.
If I manually add in all the variable fields, it works fine, so it seems that modifying $guarded even as early on as in the constructor doesn't work. It this correct? Is there a better way to modify the $guarded values based on different configurations?
I've not tried yet, but would I be better off using $fillable for just the fields I know are constant?
Related
I have run into an issue with Laravel that hopefully someone could help explain. The fill command is not setting the properties of the model, and instead can only be used to save them to the database with the ->save() function. Is there a way to do fill where it actually sets the properties of the model from an array.
Example of problem below.
$comment = new comment();
$comment->fill(['name' => 'Bob']);
echo($comment->name); // Gives null/error.
$comment = new comment();
$comment->name = 'Bob';
echo($comment->name); // Gives Bob.
The reason is name filed is not fillable in comment model .To Solve this issue you have to add fillable for that field in comment model
protected $fillable = [
'name',
];
If you try to access non fillable field then it will return null.
If don't want to add it in fillable then you can use forceFill.
forceFill: Fill the model with an array of attributes with force mass assignment.
$comment = new comment();
$comment->forceFill(['name' => 'Bob']);
echo($comment->name);
Yes, you need to use fillable property of the model and need to add name inside fillable array. That's the recommended way to do it.
As suggested by John Lobo's answer, You can forcibly override that mechanism using forceFill or forceCreate.
Both ignores fillable property in the model. It may possible that you may have a column like is_admin and you do not want to update it but force will do it.
Notes :
The main problem with forceCreate or forceFill, is that we have to manage the foreign key assignment manually.
forceFill will do fill (properties) only. You need save method call to save the actual record while forceCreate will do fill (properties) and Save both together.
in my controller i have $data['column1'] = 1; It updates database with $x->update($data);
Why if add $data['column2'] = 2; it ignores second parameter? I checked with dd($data); and it shows both parameters.
I removed default value, which being inserted by mysql, but that did not help.
Make sure that column2 is listed in the $fillable property of your model. Only attributes that are listed there can get a value assigned with your model's create/update methods.
I am using laravel 5.3 and in my custom model, I have some guarded fields like following.
protected $guarded = ['id', 'tnant_id', 'org_id', 'fac_id', 'slug', 'created_at', 'updated_at', 'deleted_at'];
Now When I try to add record using following.
CUSTOM::create(['tnant_id'=>123]);
It returns me following error.
Field 'tnant_id' doesn't have a default value.
Setting field default value in table will not work because each time I am passing value and it is giving error for all guarded fields.
So how I can add guarded fields value in database? In update query, It is allowing to update but on create it gives error.
You simply can't. Model::create(array $attributes = []) is using method fill(array $attributes = []), which, we may say, filter out all guarded attributes, so they will not be assigned. So in point of creation tnant_id will be null.
I come up with two ways of doing this:
A
create a new model instance
set your attribute
save (persist) it to dabase;
So:
$model = new Model;
$model->tnant_id = 123;
$model->save();
B
This is more likely update than create, but, might be useful for you.
Change your DB schema to allow null values for your attribute or put default value.
create model using Model::create()
set attribute & update.
So:
Assuming you are using migrations, in your migration file use:
Schema::create(..
$table->integer('trant_id')->nullable();
//OR
$table->integer('trant_id')->default(0);
...);
Note: It's hard to say which one is more suitable for you use-case, but I see your attribute is called trant_id, which is some form of relation I guess, so I suggest you to take look at Eloquent's relationship, which might be a better answer.
I'm trying to get the dot notation working in Jenssegers MongoDB package for Laravel. According this issue it's already been implemented:
link
But it doesn't seem to work in the latest version.
protected $fillable = ['title', 'some.data'];
Doesn't work. But if I open it all up it works fine.
protected $guarded = [];
So that works, not sure if this feature is still there or I need to pre filter my fields manually for now?
Nested fields are not currently supported in $fillable.
Unfortunately this means you have to do it manually. There are two ways to go:
If you have an embedded Some model, you can set $fillable on that, create/fill it with new data, then attach it to the parent model.
If you don't have/want a whole separate model for your subdocument, you would have to define e.g. $someFillable = ['data']; and use that to filter your new $some data prior to manually setting it on the model. You can basically just copy how Eloquent does it in its fill method.
The documentation doesn't go into much detail about saving data to mongodb.
I've installed a fresh install of laravel and set the up the mongo connections as in the docs, installed mongodb itself.
Created a model
use Jenssegers\Mongodb\Model as Eloquent;
class Notifications extends Eloquent {
protected $connection = 'mongodb';
protected $collection = 'notifications';
public static function foo()
{
return 'test returning from model';
}
}
And create a simple route to test
Route::get('notifiction' , function(){
$notifiction = new Notifications();
$arr = array('name' => 'John Doe');
$notifiction->save($arr);
});
But when I run localhost/mongo/public/notifiction I get Whoops, looks like something went wrong. I'm not sure what else needs doing to save information to mongodb through laravel?
This error is most likely to do with mass assignment. That is laravel treats every thing as unsafe before saving it to database. Thus we have to whitelist the fields we are trying to save.
The way we do this is in model. Lets say you are trying to save data in Users table using USER model. First open app/models/user.php and add following line:
class User extends Eloquent {
protected $fillable = ['name'];
}
Above, in fillable we are listing name as we want to save name from controller (if you have any additional data fill in the array). Now we can save data from controller.
Eg: User::create(array('name' => 'John')); will save name in Users collection. Please note the name of collection will be the name of the model unless specified otherwise.
[If this does not solve your problem, enable debug by going to app/config/app.php and setting debug =true. Find the error and try searching.]
You need not to do like model for SQL.
You try model like this
class User extends Moloquent {
protected $connection = 'mongodb';
protected $collection = 'collection1';
protected $fillable = ['_id','userName','passwd'];
}
You can try this to insert
DB::connection('mongodb')->collection('collection1')
->insert(array(
'_id' => 'H12345',
'userName' => 'Nithil',
'passwd' => 'qwoeuig'));
Using Moloquent is more convenient in using multiple DBS. For using Moloquent, you may register an alias for the MongoDB model by adding the following to the alias array in app/config/app.php:
'Moloquent' => 'Jenssegers\Mongodb\Model',
This will allow you to use the registered alias like:
class MyModel extends Moloquent {}
As OP has mentioned the error was due to
Did not installed the MongoDB PHP Library
Apart from that, to do mass assignment in Laravel, the fields should either be "white listed" or "black listed"
To whitelist the field(s) add
// name, age, username and email could be mass assigned
protected $fillable = ['name', 'age', 'username', 'email'];
To blacklist the field(s) add
// except _id everything could be mass assigned
protected $guarded = ['_id'];
to your model file