MassAssignmentException in Laravel - php

I am a Laravel newbie. I want to seed my database. When I run the seed command I get an exception
[Illuminate\Database\Eloquent\MassAssignmentException]
username
db:seed [--class[="..."]] [--database[="..."]]
What am I doing wrong. The command I use is:
php artisan db:seed --class="UsersTableSeeder"
My seed class is as follows:
class UsersTableSeeder extends Seeder {
public function run()
{
User::truncate();
User::create([
'username' => 'PaulSheer',
'email' => 'psheer#rute.co.za',
'password' => '45678'
]);
User::create([
'username' => 'Stevo',
'email' => 'steve#rute.co.za',
'password' => '45678'
]);
}
}

Read this section of Laravel doc : http://laravel.com/docs/eloquent#mass-assignment
Laravel provides by default a protection against mass assignment security issues. That's why you have to manually define which fields could be "mass assigned" :
class User extends Model
{
protected $fillable = ['username', 'email', 'password'];
}
Warning : be careful when you allow the mass assignment of critical fields like password or role. It could lead to a security issue because users could be able to update this fields values when you don't want to.

I am using Laravel 4.2.
the error you are seeing
[Illuminate\Database\Eloquent\MassAssignmentException]
username
indeed is because the database is protected from filling en masse, which is what you are doing when you are executing a seeder. However, in my opinion, it's not necessary (and might be insecure) to declare which fields should be fillable in your model if you only need to execute a seeder.
In your seeding folder you have the DatabaseSeeder class:
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Eloquent::unguard();
//$this->call('UserTableSeeder');
}
}
This class acts as a facade, listing all the seeders that need to be executed. If you call the UsersTableSeeder seeder manually through artisan, like you did with the php artisan db:seed --class="UsersTableSeeder" command, you bypass this DatabaseSeeder class.
In this DatabaseSeeder class the command Eloquent::unguard(); allows temporary mass assignment on all tables, which is exactly what you need when you are seeding a database. This unguard method is only executed when you run the php aristan db:seed command, hence it being temporary as opposed to making the fields fillable in your model (as stated in the accepted and other answers).
All you need to do is add the $this->call('UsersTableSeeder'); to the run method in the DatabaseSeeder class and run php aristan db:seed in your CLI which by default will execute DatabaseSeeder.
Also note that you are using a plural classname Users, while Laraval uses the the singular form User. If you decide to change your class to the conventional singular form, you can simply uncomment the //$this->call('UserTableSeeder'); which has already been assigned but commented out by default in the DatabaseSeeder class.

To make all fields fillable, just declare on your class:
protected $guarded = array();
This will enable you to call fill method without declare each field.

Just add Eloquent::unguard(); in the top of the run method when you do a seed, no need to create an $fillable array in all the models you have to seed.
Normally this is already specified in the DatabaseSeeder class. However because you're calling the UsersTableSeeder directly:
php artisan db:seed --class="UsersTableSeeder"
Eloquent::unguard(); isn't being called and gives the error.

I used this and have no problem:
protected $guarded=[];

I was getting the MassAssignmentException when I have extends my model like this.
class Upload extends Eloquent {
}
I was trying to insert array like this
Upload::create($array);//$array was data to insert.
Issue has been resolve when I created Upload Model as
class Upload extends Eloquent {
protected $guarded = array(); // Important
}
Reference https://github.com/aidkit/aidkit/issues/2#issuecomment-21055670

User proper model in your controller file.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;

if you have table and fields on database you can simply use this command :
php artisan db:seed --class=UsersTableSeeder --database=YOURDATABSE

This is not a good way when you want to seeding database.
Use faker instead of hard coding, and before all this maybe it's better to truncate tables.
Consider this example :
// Truncate table.
DB::table('users')->truncate();
// Create an instance of faker.
$faker = Faker::create();
// define an array for fake data.
$users = [];
// Make an array of 500 users with faker.
foreach (range(1, 500) as $index)
{
$users[] = [
'group_id' => rand(1, 3),
'name' => $faker->name,
'company' => $faker->company,
'email' => $faker->email,
'phone' => $faker->phoneNumber,
'address' => "{$faker->streetName} {$faker->postCode} {$faker->city}",
'about' => $faker->sentence($nbWords = 20, $variableNbWords = true),
'created_at' => new DateTime,
'updated_at' => new DateTime,
];
}
// Insert into database.
DB::table('users')->insert($users);

Use the fillable to tell laravel which fields can be filled using an array.
By default, Laravel does not allow database fields to be updated via an array
Protected $fillable=array('Fields you want to fill using array');
The opposite of fillable is guardable.

If you use the OOP method of inserting, you don't need to worry about mass-action/fillable properties:
$user = new User;
$user->username = 'Stevo';
$user->email = 'steve#rute.co.za';
$user->password = '45678';
$user->save();

Related

Laravel 8 - Test suite isn't firing Traits and causes "Integrity constraint violation" errors

I have a Trait that I use on multiple models in my app for setting a UUID on the model:
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait UsesUuid
{
protected static function bootUsesUuid()
{
static::creating(function ($model) {
if (!$model->uuid) {
$model->uuid = (string) Str::orderedUuid();
}
});
}
}
It works fine when using the app normally, but when I try to write tests for creating the model via a post route and dump the response I get an Integrity constraint violation: 19 NOT NULL constraint failed: venues.uuid 500 error.
An example of the test I'm doing is:
public function testOwnerCanSuccessfullyCreateVenue()
{
$amenity = Amenity::inRandomOrder()->pluck('id')->first();
$response = $this->actingAs($this->createdUser('owner'))->post(route('venues.store'), [
"name" => "create-name",
"address_line_1" => "create-address_line_1",
"address_line_2" => "create-address_line_2",
"county" => "create-county",
"postcode" => "create-postcode",
"phone_number" => "create-phone_number",
"notes" => "create-notes",
"amenities" => [$amenity]
]);
dd($response);
}
And the column in my migration is $table->uuid('uuid')->unique();
Everything else is working brilliantly, but I'm new to writing tests and not sure how to get around this problem.
The reason I was using a Trait was to get around outlining all the column values when persisting to the database, as I'm using $request->validated() to fill the model:
$venue = Venue::create($request->validated());
And obviously because the UUID isn't being set here, it's being done by a Trait, its failing the test. I can get the test to pass and have the app still work if I remove the Trait and do:
$venue = Venue::create(
$request->validated() + ['uuid' => Str::orderedUuid()]
);
Which is fine, I can live with that, but I would like to understand more about why the Trait isn't firing and how to get around it.
Edit:
Just to add more based on the answer below, the fillable fields are defined correctly:
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'uuid',
'name',
'address_line_1',
'address_line_2',
'county',
'postcode',
'phone_number',
'notes',
];
I think it's problem in model. Venue model should use a protected $fillable = ['uuid'];.
Laravel protect mass assignment by default. In case you provide array on create model, Laravel doesn't allow it. You need to provide a protected fillable array, So laravel can unlock only for those fields.
it's a bit late answer but did you figure out what was the problem and if you did, can you please provide an answer?
In older versions of Laravel problem was that the composer could not find the trait because of the way tests are autoloaded, and autoloading was defined in composer as "tests/TestCase.php"
I had a similar problem with Traits but one that was created in the test/Billing folder.
So in composer, it should be:
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
and, don't forget like me, trait needs to be namespaced.
After all of that setup, I had to run composer dump-autoload

what is the procedure to add field in laravel 5.2 migration while keeping the testing data?

i'm learning and trying to use laravel 5.2, i'm confusing how to add field in a table.
I create a migration file called 2016_01_29_093417_create_thread_table.php, everytime i want to add a field, i add a code inside the file e.g
$table->string('content');
and then run the command
php artisan migrate:refresh
the new field will appear in the table but the testing data (e.g a user in user table will be truncated)
The questions are:
1) what is the right way (best practice) to add new field to a table?
2) how to keep the testing data all the tables, e.g user in users table?
Anyone know how to do?
There are two ways to do this.
Your application is already live with people using it and you don't want to lose their data: you simply make a new migration and supply up() and down() with corresponding operations. For example:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UsersNewField extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('users', function ($table) {
$table->string('email');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('users', function ($table) {
$table->dropColumn('email');
});
}
}
After you run php artisan migrate it will simply run the latest migration.
Your application is still in development and nobody is using it yet: you use seeds to populate your database with testing data and edit your initial migration as necessary. For example:
<?php
use Illuminate\Database\Seeder;
class UsersSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
DB::table('users')->insert([
'name' => 'First User',
'email' => 'user1#example.com',
'password' => bcrypt('somepass9019'),
]);
DB::table('users')->insert([
'name' => 'Second User',
'email' => 'user2#example.com',
'password' => bcrypt('somepass2039'),
]);
DB::table('users')->insert([
'name' => 'Third User',
'email' => 'user3#example.com',
'password' => bcrypt('somepass0534'),
]);
}
}
After you run php artisan migrate:refresh --seed it will reset the database and seed it with initial/testing data.
well you need to create a new migration for each column changes
you need to use migrate
migration:refresh will reset and seed the database again
I would suggest make use of seeders and model factories if you wish to preserve your testing data and save time entering data again
https://laravel.com/docs/5.1/seeding#using-model-factories

Laravel 5 roles and permissions (Bican/Roles)

I'm trying to get roles and permissions to work properly, but I can't seem to get this right. I get an error while seeding the database:
[BadMethodCallException]
Call to undefined method Illuminate\Database\Query\Builder::attachRole()
I assume I'm doing something wrong, but I can't see what it would be.
use Bican\Roles;
use Bican\Roles\Models\Role;
use Illuminate\Database\Seeder;
use Illuminate\Foundation\Auth\User;
class UserTableSeeder extends Seeder
{
public function run()
{
// Create admin
$adminRole = Role::where('name', '=', 'Admin')->first();
$user = User::create([
'name' => 'Admin',
'email' => 'email#domain.com',
'password' => bcrypt('Password99')
]);
$user -> attachRole($adminRole);
}
}
What I try to use is this: https://github.com/romanbican/roles
I followed the installation instructions and all went well until I was going to test it. The roles table seeder runs fine, and I can see the roles in the database. But I cant assing roles to users.
What am I doing wrong?
Just found out... I'm using use Illuminate\Foundation\Auth\User; when I need to use use App\User; Working now.

Laravel 5 Seeding

I am following the tutorial in "Laravel 5 Essentials." When I try to seed my database with the command
php artisan db:seed
I receive the error
[ReflectionException]
Class BreedsTableSeeder does not exist
The code for BreedsTableSeeder is defined below:
<?
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class BreedsTableSeeder extends Seeder {
public function run()
{
DB:table('breeds')->insert([
['id' => 1, 'name' => "Domestic"],
['id' => 2, 'name' => "Persian"],
['id' => 3, 'name' => "Siamese"],
['id' => 4, 'name' => "Abyssinian"],
]);
}
}
The DatabaseSeeder is defined as such:
<?php
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Model::unguard();
// $this->call(UserTableSeeder::class);
$this->call('BreedsTableSeeder');
}
}
1
I noticed that "DB" has a different color when I load sample code in Sublime, which makes me suspect that this has something to do with the DB namespace. Because I am new to Laravel, I am not sure where DB should be defined.
I also tried executing
composer dump-autoload
but that did not work. Does anyone know how to fix this problem? Thanks!
Try:
php artisan make:seeder BreedsTableSeeder
Details can be found - Laravel seeding
A couple things :
It sounds like your seeder class didn't get added to the classmap for some reason. The place to check is the /vendor/composer/autoload_classmap.php file. If you see your class in there, it should work. If you don't, then a name change or something else went wrong at some point and you may need to add it manually.
You will need to add the namespace for the DB class. It should be :
use Illuminate\Support\Facades\DB;
You just need to add use Illuminate\Support\Facades\DB; to the top of your BreedsTableSeeder file.

Laravel Seeder, call to undefined method ::create

I have a Seeder for different models and one of them is giving me the following error when I try to artisan db:seed
PHP Fatal error: Call to undefined method Illuminate\Events\Dispatcher::create() in C:\www\site\bootstrap\compiled.php on line 3155
Here's Event.php, the model that seems to cause the problem:
<?php
class Event extends Eloquent {
protected $fillable = array('name', 'played_on');
protected $table = 'events';
// RELATIONSHIPS ----------------------------
// Event has many Decks
public function decks() {
return $this->belongsToMany('Deck', 'decks_events', 'event_id', 'deck_id');
}
}
Note: I added the protected $table = 'events' to try and see if this was causing the problem, I don't think it's required. Here is part of the Seeder. The Deck part works fine (in fact, I do see the 'Added some cards to some decks' message because it crashes)
// Decks
$deck_1 = Deck::create(array(
'meta' => 'U/W Control',
'player' => 'Cookie Monster'
));
$deck_2 = Deck::create(array(
'meta' => 'RDW',
'player' => 'Suzy Waterbottle'
));
// All 3 cards in Deck 1
$card_1->decks()->attach($deck_1->id);
$card_2->decks()->attach($deck_1->id);
$card_3->decks()->attach($deck_1->id);
// 2 cards in Deck 2
$card_1->decks()->attach($deck_2->id);
$card_2->decks()->attach($deck_2->id);
$this->command->info('Added some cards to some decks');
// Events
$event_1 = Event::create(array(
'name' => 'Super Duper Tourney',
'played_on' => '07/05/2014'
));
$deck_1->events()->attach($event_1->id);
$deck_2->events()->attach($event_1->id);
$this->command->info('Added decks to the event');
This leads me to believe that something wrong happens on the $event_1 = Event::create line but I can't figure out what as it looks exactly like the code used for $deck_1... and $deck_2...
Event is a "reserved" word in Laravel. You may have to change it or namespace your class.
So, instead of your Event model class, it is using Laravel Event, which is Illuminate\Events\Dispatcher.
It is actually an Alias we have on app/config/app.php.
Namespacing it:
<?php namespace App;
use Eloquent;
class Event extends Eloquent {
...
}
Using it namespaced:
<?php
use App\Event;
class Whatever {
$event_1 = Event::create(array(
'name' => 'Super Duper Tourney',
'played_on' => '07/05/2014'
));
}
You may need to
composer dumpautoload
To refresh your autoloaded namespaces and classes.

Categories