I am trying to insert static data, with the help of the seeder and Eloquent as bellow.
use Illuminate\Database\Seeder;
use App\Role;
class RoleSeeder extends Seeder
{
public function run()
{
Role::insert(array(
array('name' => 'admin'),
array('name' => 'user')
));
}
}
Even after using Eloquent i am getting timestamp null in database.
The timestamp columns (created_at and updated_at) will be assigned automatically only if you are using the Eloquent
save() method and create method are Eloquent.
While insert method is not Eloquent, it's a query builder method. So use create method instead :
public function run()
{
Role::create(array(
array('name' => 'admin'),
array('name' => 'user')
));
}
When you are using query builder, you have to created_at and updated_at value by yourself :
Role::insert(array(
array('name' => 'admin'),
array('name' => 'user'),
array('created_at' => \Carbon\Carbon::now()),
array('updated_at' => \Carbon\Carbon::now()),
));
Try this instead
<?php
use Illuminate\Database\Seeder;
use App\Role;
class RoleSeeder extends Seeder
{
public function run()
{
Role::truncate();
Role::create(['name' => 'admin']);
Role::create(['name' => 'user']);
}
}
The error is generated because you are using insert instead of create.
Related
I want to use the Inline Create functionality of Backpack for Laravel but the button "Add +" doesn't shows up.
I have a 1 to n relationship
The primary model is Inscription and the secondary is InscriptionProduct
This is my code:
Models\Inscription
...
class Inscription extends Model
{
public function product() {
return $this->hasMany('App\Models\InscriptionProduct');
}
...
Models\InscriptionProduct
...
class InscriptionProduct extends Model
{
public function inscription()
{
return $this->belongsTo(Inscription::class);
}
...
Http\Controllers\Admin\InscriptionProductCrudController
...
class InscriptionProductCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
...
Http\Controllers\Admin\InscriptionCrudController
...
class InscriptionCrudController extends CrudController
{
protected function setupCreateOperation()
{
...
$this->crud->addField([
'type' => "relationship",
'name' => 'product',
'ajax' => true,
'inline_create' => true,
// 'data_source' => backpack_url('/admin/inscription-product/inline/create'),
// 'data_source' => backpack_url('inscription/fetch/inscription-product'),
// 'inline_create' => [ 'entity' => 'inscriptionproduct' ]
// These 3 commented lines are alternatives also tried with no results
]);
...
The Relationship is well constructed because I can see the Products I have created via the CRUD of InscriptionProduct
What am I missing?
I solve it to, in your main CrudController, you should call the InLineCreate just below CreateOperation.
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation { store as traitStore; }
Also in my secondary CrudController I had to create a fetch function, something I did
protected function fetchFeatures()
{
return $this->fetch([
'model' => \App\Models\Features::class, // required
'searchable_attributes' => ['name', 'slug'],
'query' => function($model) {
return $model;
} // to filter the results that are returned
]);
return $this->traitFetch();
}
I am having a hard to figuring out how to refractor a factory in Laravel 7 to Laravel 8. Below is the original factory in L7 and the L8 version below is the one I've tried refactoring. I know the $factory->define is wrong and this is where I am stuck.
Laravel 7 Version
<?php
/** #var \Illuminate\Database\Eloquent\Factory $factory */
use App\Login;
use Faker\Generator as Faker;
$factory->define(Login::class, function (Faker $faker) {
$randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');
return [
'user_id' => factory(App\User::class),
'tenant_id' => factory(App\Tenant::class),
'created_at' => $randomDateTime,
'updated_at' => $randomDateTime,
];
});
Laravel 8 Version
<?php
namespace Database\Factories;
use App\Models\Login;
use App\Models\Tenant;
use App\Models\User;
use Faker\Generator as Faker;
$factory->define(Login::class, function (Faker $faker) {
$randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');
return [
'user_id' => User::factory(),
'tenant_id' => Tenant::factory(),
'created_at' => $randomDateTime,
'updated_at' => $randomDateTime,
];
});
You have two options here:
Use old factories
If you don't have the time for properly refactoring your factories, you can still use your old Laravel 7 factories by pulling in the laravel/legacy-factories package:
composer require laravel/legacy-factories
Refactor your factories
Laravel 8 factories are now classes. Previously, you would call a define method on the $factory object, passing it the class and a closure that would return the factory definition like so:
<?php
use App\User;
use Faker\Generator as Faker;
use Illuminate\Support\Str;
$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
];
});
In Laravel 8, the same would be written as follows and be put in database/factories/UserFactory.php for auto-discovery:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
];
}
}
As you see, factories are now separate classes that extend from the Illuminate\Database\Eloquent\Factories\Factory class.
Additionally, you need to use the Illuminate\Database\Eloquent\Factories\HasFactory trait on the Model to allow the discovery of factories for the Model. Once you add this trait, Laravel expects a Factory class by the name of the Model, suffixed with Factory in the database/factories folder.
You can read up on all that in the Defining Model Factories chapter of the database testing documentation.
In your specific case
The code you posted would need to be refactored and put in database/factories/LoginFactory.php:
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class LoginFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
$randomDateTime = $faker->dateTimeBetween('-6 hours', 'now');
return [
'user_id' => User::factory(),
'tenant_id' => Tenant::factory(),
'created_at' => $randomDateTime,
'updated_at' => $randomDateTime,
];
}
}
Then you need to use Illuminate\Database\Eloquent\Factories\HasFactory; in your Login.php model class and of course you would have do the same for the User and Tenant models, creating UserFactory.php and TenantFactory.php.
I want to pass arguments ['site_id' => $site->id] to SiteMessage factory:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\SiteMessage;
use App\Models\Site;
class SitesMessagesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Site::chunk(200, function ($sites) {
foreach ($sites as $site) {
SiteMessage::factory()->count(rand(2, 6))->create(['site_id' => $site->id]);
}
});
}
}
How can I get those argument in my SiteMessage factory class?
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\SiteMessage;
use App\Models\Site;
use App\Models\Integration;
class SiteMessageFactory extends Factory
{
protected $model = SiteMessage::class;
public function definition()
{
return [
**// Soliution: remove line below, it will be overridden automaticaly. \\**
'site_id' => $arguments['site_id'], // Neet to use Id that I passed from seeder.
'integration_id'=> Integration::inRandomOrder()->first()->id,
'type' => rand(0,1) ? 'EMAIL' : 'SMS',
'title' => $this->faker->text($maxNbChars = 12),
'description' => $this->faker->sentence,
'message' => $this->faker->sentence,
'enabled' => 1,
'created_at' => now(),
'updated_at' => now(),
];
}
}
At older Laravel factory version I could pass them in callback like so:
$factory->define(SiteMessage::class, function (Faker $faker, array $arguments = []) {
//
});
but don't know how to achieve it with new Class factories. Any help would be very appreciated :)
As you can see in the laravel documentation about persisting models with factories, when you type:
SiteMessage::factory()->count(rand(2, 6))->create(['site_id' => $site->id]);
The site_id attribute from SiteMessage factory will be overrided by the $site->id you are specifying.
I tried creating a unit test for the relationships between my User and Shop models, however when I run vendor\\bin\\phpunit this error(s) are thrown, I have no idea about this since I'm a newbie in unit testing. I tried to run my code on my controller to see if the relationship actually works, and fortunately it is working as expected, but not when run in phpunit. What have I done wrong for this phpunit not to work with Models?
Fatal error: Uncaught Error: Call to a member function connection() on null in E:\projects\try\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:1013
Stack trace:
E:\projects\try\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php(979): Illuminate\Database\Eloquent\Model::resolveConnection(NULL)
This is my UserTest.php
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;
use App\Shop;
class UserTest extends TestCase
{
protected $user, $shop;
function __construct()
{
$this->setUp();
}
function setUp()
{
$user = new User([
'id' => 1,
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'JohnDoe#example.com',
'password' => 'secret',
'facebook_id' => null,
'type' => 'customer',
'confirmation_code' => null,
'newsletter_subscription' => 0,
'last_online' => null,
'telephone' => null,
'mobile' => null,
'social_security_id' => null,
'address_1' => null,
'address_2' => null,
'city' => null,
'zip_code' => null,
'signed_agreement' => 0,
'is_email_confirmed' => 0
]);
$user = User::find(1);
$shop = new Shop([
'id' => 1,
'user_id' => $user->id,
'name' => 'PureFoods Hotdog2',
'description' => 'Something that describes this shop',
'url' => null,
'currency' => 'USD'
]);
$user->shops()->save($shop);
$shop = new Shop([
'id' => 2,
'user_id' => $user->id,
'name' => 'PureFoods Hotdog',
'description' => 'Something that describes this shop',
'url' => null,
'currency' => 'USD'
]);
$user->shops()->save($shop);
$this->user = $user;
}
/** #test */
public function a_user_has_an_id(){
$user = User::find(1);
$this->assertEquals(1, $user->id);
}
/** #test */
public function a_user_has_a_first_name()
{
$this->assertEquals("John", $this->user->first_name);
}
/** #test */
public function a_user_can_own_multiple_shops()
{
$shops = User::find(1)->shops()->get();
var_dump($this->shops);
$this->assertCount(2, $shops);
}
}
It seems, this error is caused by this line of code:
$user->shops()->save($shop); - this code actually works when run in my sample routes or Controller but is throwing errors when run in phpunit
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $guarded = [ 'id' ];
protected $table = "users";
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* returns the Shops that this user owned
*/
public function shops()
{
return $this->hasMany('App\Shop');
}
}
Shop.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shop extends Model
{
protected $guarded = [ 'id' ];
protected $table = "shops";
/**
* returns the Owner of this Shop
*/
public function owner()
{
return $this->belongsTo('App\User');
}
}
Any help will be very much appreciated. Thanks!
First of all, setUp() is called before every test, so you shouldn't call it from within the constructor
Second of all, you should call the parent::setUp() in your setUp() to initialize the app instance.
One more reason
check if the test class is extending use Tests\TestCase; rather then use PHPUnit\Framework\TestCase;
Laravel ships with the later, but Tests\TestCase class take care of setting up the application, otherwise models wont be able to communicate with the database if they are extending PHPunit\Framework\TestCase.
Example:
<?php
class ExampleTest extends TestCase
{
private $user;
public function setUp()
{
parent::setUp();
$this->user = \App\User::first();
}
public function testExample()
{
$this->assertEquals('victor#castrocontreras.com', $this->user->email);
}
}
a solution
use PHPunit\Framework\TestCase
Put this
use Tests\TestCase
You are assigning the id '2' to both shops.
Assigning is should not be neccessary since I assume the shop table id field is an autoincrement field.
Also look into database factories in the Laravel docs, it will simplify things for you.
That can be happens when you try to read database from dataprovider function. Like me tried, yes. The work way:
protected static $tariffs_default;
protected function setUp(): void {
parent::setUp ();
if (!static::$tariffs_default){
static::$tariffs_default = DB::...;
}
}
// in dataprovider we use string parm, named as our static vars
public static function provider_prov2(){
return [
[".....", [ 'tariffs'=>'tariffs_default'] ],
];
}
// then, in test we can ask our data by code:
public function testSome(string $inn, string $ogrn, $resp_body){
if ( $ta_var = Arr::get( $resp_body, 'tariffs' ) ){
Arr::set($resp_body, 'tariffs', static::$$ta_var );
}
$this->assert...
}
Cause of the problem: you can't use Laravel Models functionality from code called in the constructor of Class UserTest - even though you put the code in the method "setUp", you unnecessarily called it from the constructor. SetUp is called by phpUnit without you needing to do it in the constructor.
When the UserTest constructor has run, the Laravel Bootstrap code has not yet been called.
When the UserTest->setUp() method is called, the Laravel Bootstrap code HAS been run, so you can use you Models etc.
class UserTest extends TestCase
{protected $user, $shop;
function __construct()
{
$this->setUp(); // **THIS IS THE PROBLEM LINE**
}
function setUp()
{
$user = new User([....
Try composer dump-autoload
~Regards
I don't want to use rows 'update_at' and 'create_at', but Laravel's seed file is trying to update it. How can I disable it?
Here is the code that I'm using:
use Illuminate\Database\Migrations\Migration;
class SeedUsersTable extends Seeder {
// $timestamps = false; <=== will return error
// public static $timestamps = false; <=== will return error
public function run()
{
DB::table('users')->delete();
User::create(array(
'id' => 1,
'name' => 'Админ',
'password' => Hash::make('admin'),
'login' => 'admin'
));
}
}
According to the Laravel docs,
... by default, Eloquent will maintain the created_at and updated_at columns on your database table automatically. Simply add these timestamp columns to your table and Eloquent will take care of the rest.
If you do not wish for Eloquent to maintain these columns, In your User model add the following:
class User extends Eloquent {
public $timestamps = false;
}
use Illuminate\Database\Migrations\Migration;
class SeedUsersTable extends Seeder {
public function run()
{
DB::table('users')->delete();
$user = new User(array(
'id' => 1,
'name' => 'Админ',
'password' => Hash::make('admin'),
'login' => 'admin'
));
$user->timestamps = false;
$user->save();
}
}