Laravel Seeding Output - php

Usually when seed my database it tells me which table I'm seeding on the command line but because I am passing an argument to my seeder the message has disappeared (makes debugging really hard because I don't know which seeder it's on when it breaks).
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class SeedTestLargeData extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Model::unguard();
// Default
$this->call(UsersSeeder::class, 'large_test_data');
Model::reguard();
}
public function call($class, $data_filename = null) {
$this->resolve($class)->run($data_filename);
}
}
Any idea of how to get it back?

Change your call() method like this:
public function call($class, $data_filename = null)
{
$this->resolve($class)->run($data_filename);
if (isset($this->command)) {
$this->command->getOutput()->writeln("<info>Seeded:</info>".$class);
}
}

In the original Seeder class call method has an additional statement, try to add it:
public function call($class) {
//...
if (isset($this->command)) {
$this->command->getOutput()->writeln("<info>Seeded:</info> $class");
}
}

Related

Passing a quantity or other arguments to a Laravel seeder

I would like to pass an argument as to define how many records I want to create during database seeding, without having to edit the factory manually.
I have tried different variations on php artisan db:seed --class=UsersTableSeeder [using different args here]
I can't seem to find any documentation, so I don't know if that functionally exists. Does something like that exist?
class UsersTableSeeder extends Seeder
{
public $limit = null;
public function __construct($limit = 1) {
$this->limit = $limit;
}
public function run()
{
echo $this->limit;
}
}
There is no way to directly specify an argument.
If you want to specify a parameter via the command line, you could use an environment variable.
class UsersTableSeeder extends Seeder
{
public function run()
{
$limit = env('SEEDER_LIMIT', 1);
echo $this->limit;
}
}
Call like this:
SEEDER_LIMIT=10 php artisan db:seed --class=UsersTableSeeder
You can set it up this way:
public function run($count = 1)
And then you can pass the argument this way:
$this->call(ClientSeeder::class, false, ['count' => 500]);
From what I know there's no such thing as parameters for seeders, but you could implement it yourself. You could create a new command which accepts parameters and calls a seeder programmatically with those additional parameters.
Something like this should do the trick:
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
public function run(int $limit)
{
echo $limit;
// Seed some stuff
}
}
namespace App\Console\Commands;
use Illuminate\Console\Command;
use UsersTableSeeder;
class SeedCommand extends Command
{
protected $signature = 'app:seed {limit}';
public function handle(UsersTableSeeder $seeder)
{
$limit = $this->argument('limit');
$seeder->run($limit);
}
}
you can ask for that limit before call any other seeders using
// DatabaseSeeder.php
$limit = $this->command->ask('Please enter the limit for creating something !!');
and then you can pass that limit to any additional seeders from 'DatabaseSeeder' like this
//DatabaseSeeder.php
$this->call(AnyAdditionalSeeder::class, false, compact('limit'));
then in 'AnyAdditionalSeeder' you can add parameter and name it $limit to the run() method like this
public function run($limit)
{
// you can access limit variable here
}
then when you run the command php artisan db:seed it will ask you for the limit :)
my solution:
// MemberSeeder.php (example for Members Table)
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Member as ModelsMember;
class MemberSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
static function run(int $nRec=1) {
ModelsMember::factory()->times($nRec)->create();
}
}
Call from a .php file
// Members.php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Member;
use Database\Seeders\MemberSeeder;
class Members extends Component
{
public $members, $name, $email, $phone_number, $status, $member_id;
public $bldModal = '';
...
...
public function generaRecords() {
MemberSeeder::run(2);
}
}
Schema for to create table
Schema::create('members', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('phone_number');
$table->char('status',1);
$table->timestamps();
});
Shortly: to change
public function run() {
To
static function run(int $nRec=1) {
As of Laravel 8 you can use callWith to pass parameters to the run method of your seeders. Something like this:
class UsersTableSeeder extends Seeder
{
public function run($count = 1)
{
User::factory()->count($count)->create();
}
}
And then your could use those seeders in other seeders like this:
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->callWith(UsersTableSeeder::class, ['count' => 10]);
}
}
Note that the parameter array you give to callWith is associative, and its keys should match the run method's parameters, because the call will ordinarily be resolved through the Laravel's application container.
you can pass a parameter as quantity to a seeder like this:
First, create a custom command
php artisan make:command generateFakeCompanyData
generateFakeCompanyData.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Database\Seeders\CreateFakeCompanySeeder;
class generateFakeCompanyData extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'create:fake-comapnies {count}';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle(CreateFakeCompanySeeder $seeder)
{
$limit = $this->argument('count');
$seeder->run($limit);
}
}
create seeder file:
php artisan make:seeder CreateFakeCompanySeeder
CreateFakeCompanySeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class CreateFakeCompanySeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run(int $limit)
{
\App\Models\Company\Company::factory($limit)->create();
}
}
create factory file
php artisan make:factory Company\CompanyFactory --model=Company
CompanyFactory.php
<?php
namespace Database\Factories\Company;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\Blog;
/**
* #extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Company\Company>
*/
class CompanyFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition()
{
return [
'name' => $this->faker->company,
'email' => $this->faker->unique()->email,
'logo' => $this->faker->imageUrl(640,480),
'website' => Str::slug($this->faker->name).'.com',
// 'website' => $this->faker->text(),
];
}
}
in route: web.php
Route::controller(CompanyController::class)->group(function() {
Route::prefix('company')->group(function () {
Route::post('/store', 'companyInsert')->name('company.add');
});
});
in controller: CompanyController.php
class CompanyController extends Controller{
public function companyInsert(Request $request){
$limit = $request->no_of_company;
\Artisan::call('create:fake-comapnies '.$limit);
return redirect()->back()->with('crudMsg','Total of '.$limit.' Company
Successfully Added');
}
}

Silex call controller within controller

When I receive an API request it routes trough the Application.php to the UserController.
The UserController does his thing with the information and I need to call the EmailController, because that is the controller that manages all the emails.
In the EmailController I have a function (its simplified):
class EmailController {
public function getEmail() {
return 1337 ;
}
}
In the UserController I have a function:
class UserController {
public function getUserMail(Request $request, Application $app) {
$number = ???;
return $number;
}
}
What do I have to call within the UserController to get the getEmail function of the EmailController?
If this is not a correct way of doing it, I would love to hear what term I am acutally searching for :)
Edit1:
As #lawrence-cherone pointed out, it should have been in a model.
It was stuck in my head that I had to use the controller for this task.
You could use the dependency injection to share the class that return number.
So your controllers will look like:
class EmailController
{
/**
* #var NumberCalculatorInterface
*/
private $numberCalculator;
/**
* #param NumberCalculatorInterface $numberCalculator
*/
public function __construct(NumberCalculatorInterface $numberCalculator)
{
$this->numberCalculator = $numberCalculator;
}
public function getEmail()
{
return $this->numberCalculator->getNumber();
}
}
and
class UserController
{
/**
* #var NumberCalculatorInterface
*/
private $numberCalculator;
/**
* #param NumberCalculatorInterface $numberCalculator
*/
public function __construct(NumberCalculatorInterface $numberCalculator)
{
$this->numberCalculator = $numberCalculator;
}
public function getUserMail(Request $request, Application $app)
{
$number = $this->numberCalculator->getNumber();
return $number;
}
}
Your class that calculate number or other more complex logic will be
interface NumberCalculatorInterface
{
public function getNumber();
}
class DefaultNumberCalculator implements NumberCalculatorInterface
{
public function getNumber()
{
return 1337;
}
}
Since the number calculation is not a logic proper to your EmailController cause you use the logic in several classes, it make sense to be an external class. You will be able to unit test it properly and to inject in all the classes that need this calculation to be done.
You will be able to declare it as service:
class NumberCalculatorProvider implements ServiceProviderInterface {
public function register(Container $pimple)
{
$pimple['number_calculator'] = function () {
return new DefaultNumberCalculator();
};
}
}
And inject it inside your controller easily (in the following example is use the ServiceControllerServiceProvider to declare controller as services):
class ControllerProvider implements ServiceProviderInterface {
public function register(Container $pimple)
{
$pimple['controller.user'] = function ($pimple) {
return new UserController($pimple['number_calculator']);
};
$pimple['controller.email'] = function ($pimple) {
return new EmailController($pimple['number_calculator']);
};
}
}
note: In my example i use silex 2., since its not specified in your question, you may need to adapt it if you use an older version but the logic remain the same.*
I think you need to make UserController inherit the function getEmail() from EmailController
class UserController extends EmailController {
public function getUserMail(Request $request, Application $app) {
$number = ???;
return $number;
}
}

How to seed database migrations for laravel tests?

Laravel's documentation recommends using the DatabaseMigrations trait for migrating and rolling back the database between tests.
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
/**
* A basic functional test example.
*
* #return void
*/
public function testBasicExample()
{
$response = $this->get('/');
// ...
}
}
However, I've got some seed data that I would like to use with my tests. If I run:
php artisan migrate --seed
then it works for the first test, but it fails subsequent tests. This is because the trait rolls back the migration, and when it runs the migration again, it doesn't seed the database. How can I run the database seeds with the migration?
All you need to do is make an artisan call db:seed in the setUp function
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
// seed the database
$this->artisan('db:seed');
// alternatively you can call
// $this->seed();
}
/**
* A basic functional test example.
*
* #return void
*/
public function testBasicExample()
{
$response = $this->get('/');
// ...
}
}
ref: https://laravel.com/docs/5.6/testing#creating-and-running-tests
With Laravel 8, if you're using the RefreshDatabase trait you can invoke seeding from your test case using below:
use Illuminate\Foundation\Testing\RefreshDatabase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
/**
* A basic functional test example.
*
* #return void
*/
public function testBasicExample()
{
// Run the DatabaseSeeder...
$this->seed();
// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);
$response = $this->get('/');
// ...
}
}
see docs for more information/examples:
https://laravel.com/docs/8.x/database-testing#running-seeders
It took me some digging to figure this out, so I thought I'd share.
If you look at the source code for the DatabaseMigrations trait, then you'll see it has one function runDatabaseMigrations that's invoked by setUp which runs before every test and registers a callback to be run on teardown.
You can sort of "extend" the trait by aliasing that function, re-declare a new function with your logic in it (artisan db:seed) under the original name, and call the alias inside it.
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations {
runDatabaseMigrations as baseRunDatabaseMigrations;
}
/**
* Define hooks to migrate the database before and after each test.
*
* #return void
*/
public function runDatabaseMigrations()
{
$this->baseRunDatabaseMigrations();
$this->artisan('db:seed');
}
/**
* A basic functional test example.
*
* #return void
*/
public function testBasicExample()
{
$response = $this->get('/');
// ...
}
}
I know this question has already been answered several times, but I didn't see this particular answer so I thought I'd throw it in.
For a while in laravel (at least since v5.5), there's been a method in the TestCase class specifically used for calling a database seeder:
https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed
with this method, you just need to call $this->seed('MySeederName'); to fire the seeder.
So if you want this seeder to fire before every test, you can add the following setUp function to your test class:
public function setUp()
{
parent::setUp();
$this->seed('MySeederName');
}
The end result is the same as:
$this->artisan('db:seed',['--class' => 'MySeederName'])
or
Artisan::call('db:seed', ['--class' => 'MySeederName'])
But the syntax is a bit cleaner (in my opinion).
With Laravel 8, the RefreshDatabase is now looking for a boolean property called "seed".
/**
* Illuminate\Foundation\Testing\RefreshDatabase
* Determine if the seed task should be run when refreshing the database.
*
* #return bool
*/
protected function shouldSeed()
{
return property_exists($this, 'seed') ? $this->seed : false;
}
Simply give your test class the protected property $seed and set it to true if you wish to seed.
class ProjectControllerTest extends TestCase
{
protected $seed = true;
public function testCreateProject()
{
$project = Project::InRandomOrder()->first();
$this->assertInstanceOf($project,Project::class);
}
The nice part about this method is that individual tests won't seed everytime they are ran. Only seed necessary test will build the database.
If you're using the RefreshDatabase testing trait:
abstract class TestCase extends BaseTestCase
{
use CreatesApplication, RefreshDatabase {
refreshDatabase as baseRefreshDatabase;
}
public function refreshDatabase()
{
$this->baseRefreshDatabase();
// Seed the database on every database refresh.
$this->artisan('db:seed');
}
}
Here is an alternate solution, in case you prefer to bypass Artisan's native DatabaseMigrations and seeder/migration methods. You can create your own trait to seed your database:
namespace App\Traits;
use App\Models\User;
use App\Models\UserType;
trait DatabaseSetup
{
public function seedDatabase()
{
$user = $this->createUser();
}
public function createUser()
{
return factory(User::class)->create([
'user_type_id' => function () {
return factory(UserType::class)->create()->id;
}
]);
}
public function getVar() {
return 'My Data';
}
}
Then call it in your test like this:
use App\Traits\DatabaseSetup;
class MyAwesomeTest extends TestCase
{
use DatabaseSetup;
use DatabaseTransactions;
protected $reusableVar;
public function setUp()
{
parent::setUp();
$this->seedDatabase();
$this->reusableVar = $this->getVar();
}
/**
* #test
*/
public function test_if_it_is_working()
{
$anotherUser = $this->createUser();
$response = $this->get('/');
$this->seeStatusCode(200);
}
}

Laravel 5.0 model test Mockery unable to mock method/static method does not exist?

I am using Laravel 5.0 to create phpunit test alongside the actual model.
I get errors in phpunit tests but no errors when controller calls the model and it returned the desired data.
sample.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class sample extends Model {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'sample';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','username','details','image'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
public static function test()
{
return "Returned Text.";
}
public static function gettest()
{
return self::test();
}
public static function getItem()
{
return self::orderBy('username','asc')->get();
}
public static function findItem($id)
{
return self::find($id);
}
}
SampleTest.php
<?php namespace App;
use Mockery as m;
class SampleTest extends \PHPUnit_Framework_TestCase {
protected function setUp()
{
$this->mock = m::mock('App\sample')->makePartial();
}
protected function tearDown()
{
m::close();
}
/** #test */
public function should_return_string()
{
$response = $this->mock->test();
var_dump("test() returns :".$response);
}
/** #test */
public function should_return_string_from_test_function()
{
$response = $this->mock->gettest();
var_dump("gettest() returns :".$response);
}
/** #test */
public function should_return_mocked_data()
{
$this->mock->shouldReceive('test')->andReturn('Return Mocked Data');
$response = $this->mock->gettest();
var_dump("gettest() returns :".$response);
}
/** #test */
public function should_return_some_data_using_this_mock()
{
$this->mock->shouldReceive('get')->andReturn('hello');
$response = $this->mock->getItem();
}
}
Problem
When I use controller to call the model, it returned the desired data.
When I run phpunit on command prompt:-
test function is not mocked properly as it still returns the original string
getItem and findItem functions return an error saying
1) App\SampleTest::should_return_some_data_using_this_mock
BadMethodCallException: Static method Mockery_0_App_sample::getItem()
does not exist on this mock object
Question
How can I mock the function properly? Why it is saying the error code as shown above? Where was I doing it wrong?
Any help will be much appreciated.
Note: Test assertions is removed and replaced with var_dump to see the output on the command prompt.

Laravel after composer update model method call undefined

I am working on a project with Laravel 4.2 and I created some models and controllers and called model function from controller, the problem is after composer update command it displays this error: Call to undefined method Department::getAllParent() but before composer update it works fine. You think what is the problem with this issue? thanks in advance
Model code:
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
$table = DB::table('department');
$object = $table->get();
return $object;
}
public static function getAllParent()
{
$table = DB::table('department');
$table->where('parent',0);
$object = $table->get();
return $object;
}
}
And Controller code:
class DepartmentController extends BaseController
{
/*
Getting all records from department
#param: none
#Accessiblity: public
#return: Object
*/
public function getAllDepartment()
{
//get data from model
$deps = Department::getAllParent();
$depAll = Department::getAll();
//load view for users list
return View::make("department.dep_list")->with('deps',$deps)->with('all',$depAll);
}
}
Don't think this is related to your issues but this might be a better way to handle these queries. you are using Eloquent and setting the table parameter. why not use Eloquent's build in power?
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
return Department::get();
}
public static function getAllParent()
{
return Department::where('parent', 0)->get();
}
}
I think you might also be able to use $this->get(); but I can't test right now.

Categories