Laravel Factory State- Unable to locate factory - php

I have a problem when executing the factory, i have used the factory state for factories but it will give me an error when i execute the factory
https://laravel.com/docs/5.6/database-testing#factory-states
I have this UserFactory.php which contains the code below.
<?php
use Faker\Generator as Faker;
$factory->state(App\User::class,'suggestor', function (Faker $faker) {
return [
'FirstName'=>$faker->firstName,
'LastName'=>$faker->lastName,
'Username'=>$faker->userName,
'password'=>bcrypt('123asd!##'),
'Email'=>$faker->email,
'AccountType'=>0,
];
});
i am using tinker to execute the factory commands and tried different syntax but it really does not solve the problem.
>>> factory(User::class, 1)->states('suggestor')->make();
[!] Aliasing 'User' to 'App\User' for this Tinker session.
InvalidArgumentException with message 'Unable to locate factory with name [default] [User].'
>>> factory(App\User::class, 1)->states('suggestor')->make();
InvalidArgumentException with message 'Unable to locate factory with name [default] [App/User].'
>>> factory(\App\User::class, 1)->states('suggestor')->make();
InvalidArgumentException with message 'Unable to locate factory with name [default] [App/User].'
>>> factory('App\User')->states('suggestor')->make();
InvalidArgumentException with message 'Unable to locate factory with name [default] [App/User].'
>>> factory('App\User',1)->states('suggestor')->make();
InvalidArgumentException with message 'Unable to locate factory with name [default] [App/User].'
>>>
i hope there's anyone out there can help me.
Update:
I have tried running it on database seed but i think it's still the same error.
but when i tried on the other model it seems fine. i think the problem is on the User model which comes out of the box by laravel and note that i haven't change anything on the user model except the model attributes.
error produce by seeder

As the error states, you need a default factory. Please compare the following two:
$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'email' => $faker->safeEmail,
'password' => bcrypt(str_random(10)),
'remember_token' => $faker->randomNumber(),
];
});
$factory->state(App\User::class, 'test_state', function (Faker\Generator $faker) {
return [
'name' => 'Namoshek',
'email' => 'namoshek#example.com',
];
});
The first definition is the default factory for users, when not giving a state. You can call them with factory(App\User::class, 10)->create() where 10 is optional to give the number of models to create.
You can also chain ->states('test_state') after the call to factory():
factory(App\User::class)->states('test_state')->create(), which will first run the default factory and then apply the changes defined by the given state on the model. But you always need a default factory, otherwise the system doesn't know where and what to apply the state to.
By the way, there is a difference between ->create() and ->make(). The latter does only create the models without persisting them in the database, whereas the first one persists them. So ->create() is equivalent to ->make()->save().

sometimes it also happens that factory works fine in web routes and tests but in tinker it behaves as it is mentioned above. In that case you can try to clear laravel application cache. here are the commmands.
php artisan cache:clear
php artisan config:clear
php artisan route:clear
this will clear all the caches. then i could create model instances using factory.
>>> factory(User::class)->create() // or
>>> factory(Book::class)->create()

Related

Laravel passport can't find ApproveAuthorizationController

I'm trying to setup a laravel application with oauth autorization by using the laravel passport functionality. I'm using the official tutorial (https://laravel.com/docs/master/passport). But now if I make a post request to '/oauth/authorize' the following error message occurs:
Class App\Http\Controllers\Laravel\Passport\Http\Controllers\ApproveAuthorizationController does not exist
I don't know what I've been doing wrong. I use the routes getting from 'Passport:routes' and no self defined routes.
I've already made a composer update, install and clear cache but nothing worked.
The problem get caused here:
/**
* Register the routes needed for authorization.
*
* #return void
*/
public function forAuthorization()
{
$this->router->group(['middleware' => ['web', 'auth']], function ($router) {
$router->get('/authorize', [
'uses' => 'AuthorizationController#authorize',
]);
$router->post('/authorize', [
'uses' => 'ApproveAuthorizationController#approve',
]);
$router->delete('/authorize', [
'uses' => 'DenyAuthorizationController#deny',
]);
});
}
I've already tried it by importing the missing class with a use statement but it still wont work.
Can somebody help me?
It looks like you're missing a use statement at the top of a controller or service proivder. Somewhere you have a class being used with out properly importing it first. That's why you're seeing the concatenated string like:
App\Http\Controllers\Laravel\Passport\Http\Controllers\ApproveAuthorizationController.
I assume what you need is this:
use Passport\Http\Controllers\ApproveAuthorizationController;
or Passport in Passport::routes is not being imported, one of the two. In AppServiceProvider:
use Laravel\Passport\Passport;

Laravel model factories using same seed for testing purposes

I am trying to set up a default seed for Faker in Laravel which is normally achieved in this way (not in Laravel):
<?php
$faker = Faker\Factory::create();
$faker->seed(1234);
according to Faker's GitHub page.
I am trying to do this so that can I get the same data generated each time so that I can write some unit tests but I have no idea how to do that in Laravel. I've checked Laravel's documentation and tried googling the issue but I found nothing.
Here's how to do apply the seed to Faker in Laravel 5.
Inside your app/database/factories directory, create a new file. I called mine SeedFactory.php.
<?php
$factory->faker->seed('1');
That's it!
Now you have consistent random data for your unit testing!
NB: If you only have one or two factories, you could append that line to an existing factory file.
Here's why it works.
When Laravel processes all the files in the app/database/factories directory, it executes them straightaway. The $factory object passed around is an instance of Illuminate\Database\Eloquent\Factory.php, which keeps with it it's own internal Faker\Generator instance.
Also, you won't need to worry about the naming of the file or execution order, because this will get fired before any of the factory callbacks (assuming you did it as instructed in the Laravel docs).
it is easy. Just define a factory. Let's have a look at the default factory shipped
with laravel 5.5
File: database/factories/ModelFacotry.php
<?php
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
/** #var \Illuminate\Database\Eloquent\Factory $factory */
$factory->define(App\User::class, function (Faker\Generator $faker) {
static $password;
// Add this line to original factory shipped with laravel.
$faker->seed(123);
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
Then use tinker to test it:
yudu#YududeMacBook-Pro ~/demo> php artisan tinker
Psy Shell v0.8.1 (PHP 7.1.8 — cli) by Justin Hileman
>>> $user = factory(App\User::class)->make()
=> App\User {#880
name: "Jessy Doyle",
email: "jalen86#example.net",
}
>>> $user = factory(App\User::class)->make()
=> App\User {#882
name: "Jessy Doyle",
email: "lbode#example.org",
}
Laravel Docs:
how to define and use factory
Seeding

Laravel : BadMethodCallException Method [show] does not exist

(1/1) BadMethodCallException
Method [show] does not exist. in Controller.php (line 82)
I am new to Laravel and PHP and have been stuck on this error for a very long time with other questions not providing a solution. I was following an example (where the example worked) and made very little changes beside name changes.
Here is the code:
web.php file
Route::get('/', 'PagesController#home');
Route::get('faq', 'PagesController#faq');
Route::resource('support', 'UserInfoController');
UserInfoController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\UserInfo;
class UserInfoController extends Controller
{
//
public function create(){
$userInfo = new UserInfo;
return view('contact', ['userInfo' => $userInfo]);
}
public function store(Request $request){
$this->validate($request, [
'name' => 'required',
'email' => 'required',
'subject' => 'required',
'description' => 'required',
]);
UserInfo::create($request->all());
return redirect()->route('contact')->with('success','Enquiry has been
submitted successfully');
}
}
UserInfo.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserInfo extends Model {
protected $fillable = [
'name','email','subject','description',
];
}
The Route::resource is the one giving me the problem as I am trying to access the page support/contact. Would be very grateful if someone knew how to solve this.
That is because you are doing resource routes in your routes.php file that generates all the routes for the CRUD functions when you have to generate a route for the show method you find that it does not exist.
To solve it only creates the methods that you ask or, also you can define only the routes that you need.
The controller is trying to invoke the 'show' method - which you should have defined if you're going to load /support/{id} via GET in your browser. You can see the expected methods for a resource here:
https://laravel.com/docs/5.4/controllers#resource-controllers
You can also make your life somewhat easier by starting with a valid controller by using the built in generator:
php artisan make:controller UserInfoController --resource
If you don't want to supply ALL the methods, you have to specify, for example:
Route::resource('support', 'UserInfoController', ['only' => [
'create', 'store'
]]);
Have you added method Show to your Controller ? Route::Resource has 7 basic routes:
Verb Path Action Route Name
GET /support index support.index
GET /support/create create support.create
POST /support store support.store
GET /support/{support} show support.show
GET /support/{support}/edit edit support.edit
PUT /support/{support} update support.update
DELETE /support/{support} destroy support.destroy
As you see there is a route called show which will be default when you route to support so you must connect this route to it's method in the controller which is in resource case CONTROLLER/show, however in your case you're trying to get a static page from a prefix called support which is different from resources because show in resource handling dynamic results.
Use this syntax to get a page called contact from prefix called support
Route::prefix('support')->group(function () {
Route::get('contact', function () {
// Matches The "/UserInfoController/contact" URL
});
});

Change Faker Locale in Laravel 5.2

Is there a way to specify the Faker locale in the database/factories/ModelFactory.php file ? Here is my non functioning attempt at doing so >,<
$factory->define(App\Flyer::class, function (Faker\Generator $faker) {
// What is the correct way of doing this?
$faker->locale('en_GB');
return [
'zip' => $faker->postcode,
'state' => $faker->state,
];
});
Thanks for reading!
Faker locale can be configured in the config/app.php configuration file. Just add the key faker_locale.
e.g.: 'faker_locale' => 'fr_FR',
See also my PR to document that previously undocumented feature: https://github.com/laravel/laravel/pull/4161
THIS ANSWER IS ONLY VALID FOR LARAVEL <=5.1 OR WHEN YOU WANT TO USE MANY DIFFERENT LOCALES see this answer for a solution in Laravel >=5.2.
To use a locale with Faker, the generator needs creating with the locale.
$faker = Faker\Factory::create('fr_FR'); // create a French faker
From the faker documentation:
If no localized provider is found, the factory fallbacks to the default locale (en_EN).
Laravel by default, binds the creation of a faker instance in the EloquentServiceProvider. The exact code used to bind is:
// FakerFactory is aliased to Faker\Factory
$this->app->singleton(FakerGenerator::class, function () {
return FakerFactory::create();
});
It would appear that Laravel has no way to modify the locale of the faker instance it passes into the factory closures as it does not pass in any arguments to Faker.
As such you would be better served by using your own instance of Faker in the factory method.
$localisedFaker = Faker\Factory::create("fr_FR");
$factory->define(App\Flyer::class, function (Faker\Generator $faker) {
// Now use the localisedFaker instead of the Faker\Generator
// passed in to the closure.
return [
'zip' => $localisedFaker->postcode,
'state' => $localisedFaker->state,
];
});
I prefer to use it:
$fakerBR = Faker\Factory::create('pt_BR');
$factory->define(App\Flyer::class, function (Faker\Generator $faker) use (fakerBR) {
return [
'name' => $fakerBR->name,
'cpf' => $fakerBR->cpf,
'zip' => $faker->postcode,
'state' => $faker->state,
];
});
Late in the party, but after some research I've found this in faker documentation:
[...] since Faker starts with the last provider, you can easily override existing formatters: just add a provider containing methods named after the formatters you want to override.
That means that you can easily add your own providers to a Faker\Generator instance.
So you can do something like this
$faker->addProvider(new Faker\Provider\pt_BR\Person($faker));
Just before return [] and then use specific providers, like (in this case) $faker->cpf;
Tested on Laravel 5.3
More info on Faker documentation
#IvanAugustoDB, there is a another form of doing that. When Laravel initalize faker, it can be constructed on another locale, just create a Service Provider and put the following snippet inside it.
use Faker\Generator as FakerGenerator;
use Faker\Factory as FakerFactory;
$this->app->singleton(FakerGenerator::class, function () {
return FakerFactory::create('pt_BR');
});
$factory->define(App\User::class, function (Faker\Generator $faker) {
$faker->addProvider(new Faker\Provider\ng_NG\Person($faker));
$faker->addProvider(new Faker\Provider\ng_NG\PhoneNumber($faker));
...
in the above code, "ng_NG" is for Nigeria and can be replaced with any other locale.
To my knowledge, you would have to specify Person, PhoneNumber and others depending on what you have in your vendor\fzaninotto\faker\src\Faker\Provider folder. However if the provider you intend using isn't available, then it will resolve back to using "en".
This works like charm for me, and it should work for you too.
This answer is valid just for Laravel 5.4 and greater:
Since this pull, you can just use 'faker_locale' as a variable in your app config file. It just works really good.
this is the link for all providers that used in faker
for arabic lang example
use Faker\Factory as Faker; ### in the head off class
$faker = Faker::create();
$faker_ar = Faker::create('ar_SA');
for ($i = 0; $i < 10; $i++) {
DB::table('categories')->insert([
'name' => $faker->name,
'name_ar' => $faker_ar->name,
'created_at' => now(),
'updated_at' => now(),
]);
}
If you are using multiple languages for the same table and can't use local
you can use: shuffleString
'name'=>$faker->shuffleString('abddefhig')
'name_ar'=>$faker->shuffleString('البتثجحخدزسش')

Missing argument 1 for Illuminate\Auth\AuthManager::createDriver() lumen and JWT

I am trying to implement JWT token in my API using Lumen + JWT. I am using this JWT Library, I have set up it, but when I want to validate passed using JWTAuth::attempt($credentials) I get next error
ErrorException in AuthManager.php line 16:
Missing argument 1 for Illuminate\Auth\AuthManager::createDriver(), called in /home/admin/web/mkopilka.ru/public_html/api/referral/vendor/illuminate/support/Manager.php on line 87 and defined
I know where is the problem, but cannot figure out how to solve it because I don't know internals of framework well.
I have question about how does JWT authenticate the user (checks credentials in database, as I can gues it uses model class provided in jwt.php with the following line 'user' => 'App\Models\User'
By default 'user' => 'App\User'
So even if I changed user model in this file I got the next error
vendor/illuminate/auth/EloquentUserProvider.php line 126:
Class '\App\User' not found
I thought and decided to add config/auth.php file with succeeding content
return [
'model' => 'App\Models\User'
];
And now I get the the first exception.
What is wrong I can quess that I have overridden all parameters in auth config file.
Aslo I wonder where can I find (except source code, it will take a lot of time to understand it) explanation how JWTAuth::attempt works ?
Thanks.
Just had same issue myself and stumbled upon this question.
Solution is to add 'driver' => 'eloquent' into your created auth.php file.
I had the same problem on my upgrade from Laravel 4.1 to 4.2 (I think mainly because I updated all the files and tried to make a composer update afterwards).
For me the following worked (like reverting the relevant update steps):
1. Modify auth.php
Add driver, model and table to config/auth.php main array (additionally to the already existing one in the providers sub array):
<?php
return [
'driver' => 'eloquent',
'model' => App\User::class,
'table' => 'users',
// ...
2. Add ArtisanServiceProvider
To prevent the error Artisan: Command clear-compiled is not defined readd Illuminate\Foundation\Providers\ArtisanServiceProvider to the service providers
<?php
return [
// ...
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
// ...
3. Update and revert changes
Perform update (composer update) and revert the two previous steps by removing the added lines.

Categories