Why is php artisan make:factory not Generating with a Model - php

So long story short, I have a model in my Larvel 8 (Jetstream) application called Board. I am trying to generate a factory for this Board model.
When I use either of the commands below:
php artisan make:factory BoardFactory
or
php artisan make:factory BoardFactory --model=Board
I get a factory class generated with seemingly no errors or issues. However, when I open the class it contains nothing to do with the model.
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class BoardFactory extends Factory{
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
//
];
}
}
I have tried this with all the Model's within my application and this persists. Once again no error to say the model is not found. The command seemingly runs successfully but obviously hasn't generated the factory for the Model.
I know I can easily write this manually if needs be, but I would like to understand why this isn't working and how I can fix it. The faster I can get through my testing... the better :)
Thanks in advance for any help.

Try publishing your laravel stubs and confirm that the stub file contents are defined as expected.
Publish the stubs.
php artisan stub:publish
This should create a /stubs folder in the root project directory.
Inside that folder, you will see all stubs.
Most specifically, open the stub file called factory.stub
It's file contents should look something similar to this:
<?php
namespace {{ factoryNamespace }};
use Illuminate\Database\Eloquent\Factories\Factory;
use {{ namespacedModel }};
class {{ factory }}Factory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = {{ model }}::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
//
];
}
}
Notes:
From the looks of it, it appears as if your current factory stub is missing the section(s) below:
// ...
use {{ namespacedModel }};
// ...
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = {{ model }}::class;
// ...
Ideally speaking, in normal (default) cases, running a command that generates a factory with a linked model should look like this:
Command:
php artisan make:factory BoardFactory --model=Board
Expected Output File (database/factories/BoardFactory.php):
<?php
namespace Database\Factories;
use App\Models\Board;
use Illuminate\Database\Eloquent\Factories\Factory;
class BoardFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Board::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
//
];
}
}
Addendum:
As pointed out in a comment by #miken32, in Laravel versions published later than Oct 22, 2021, declaring a model attribute in your Factory class will no longer be necessary:
Laravel Pull Request
At this time, database factories have this hidden feature where
database models can be "guessed".
So, this pull request proposes that remove protected $model from the
Factory stub, as probably the current "guess" logic works for
99.99% of the people. In addition, I've also pull requested to the
skeleton that we remove protected $model = User::class from the
UserFactory.php:
laravel/laravel#5713.

Related

Why is this method available in this trait?

I am looking to extend a trait by using it in another trait. However the trait is using a method that looks like it isn't extending. The trait works, so I am wondering how.
Why does this trait have access to the markEntityForCleanup method?
The code is in this repo for Drupal Test Traits
<?php
namespace weitzman\DrupalTestTraits\Entity;
use Drupal\Tests\node\Traits\NodeCreationTrait as CoreNodeCreationTrait;
/**
* Wraps the node creation trait to track entities for deletion.
*/
trait NodeCreationTrait
{
use CoreNodeCreationTrait {
createNode as coreCreateNode;
}
/**
* Creates a node and marks it for automatic cleanup.
*
* #param array $settings
* #return \Drupal\node\NodeInterface
*/
protected function createNode(array $settings = [])
{
$entity = $this->coreCreateNode($settings);
$this->markEntityForCleanup($entity);
return $entity;
}
}
I found the issue.
When using the Drupal Test Traits package you are expected to use your own custom php-unit bootstrap.php and manually load the required packages.
Adding this line to the bottom of the bootstrap script will gain access to the namespace in php.
// <?php is needed for SO to do the syntax highlighting.
<?php
// Register more namespaces, as needed.
$class_loader->addPsr4('weitzman\DrupalTestTraits\Entity\\', "$root/vendor/weitzman\drupal-test-triats\src\Entity");

Binding to Laravel IoC instead of instantiating again and again

In my app I have a service called "LogService" to log events and other items. I basically need to use this on every controller to log events by users. Instead of having to instantiate this service in each controller, I had two thoughts for accomplishing this.
Option 1: Bind the service into the IoC and then resolve it that way
Option 2: Make a master class with the service in it and then extend it for other classes so they come with the service already bound
I have questions for each of these methods:
Option 1: Is this even possible? If so, would it just be with "App::make()" that it would be called? That way doesn't seem to play too well with IDE's
Option 2: I have done this kind of thing in the past but PHPStorm does not seem to recognize the service from the parent object because it is instantiated by "App::make()" and not through the regular dependency injection.
What would be the best course of action?
Thanks!
You can have it both ways, I think the neatest way would be:
1) Have an interface that describes your class, let's call it LogServiceInterface
2) Create a Service Provider that instantiates your class, like so:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class LoggerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
$this->app->bind(LogServiceInterface::class, function($app)
{
return new LogService();
});
}
}
3) Register this service provider in config/app.ph file:
'providers' => [
// Other Service Providers
App\Providers\LoggerServiceProvider::class,
],
4) Now, in controller you can request the instance of something that implements LoggerServiceInterface straight in the constructor:
(Some controller):
<?php namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Repositories\OrderRepository;
class OrdersController extends Controller {
/**
* The logger service.
* #var LoggerServiceInterface $loggerService
*/
protected $loggerService;
/**
* Create a controller instance.
*
* #param OrderRepository $orders
* #return void
*/
public function __construct(LoggerServiceInterface $loggerService)
{
$this->loggerService = $loggerService;
}
/**
* Show all of the orders.
*
* #return Response
*/
public function index()
{
// $this->loggerService will be an instance of your LoggerService class that
// is instantiated in your service provider
}
}
This way, you have got an easy way to quickly change the implementation of your service, moreover, Phpstorm can handle this very easily.
You will still be able to use app()->make() to obtain an instance of your service.
This, however, will not be automatically picked up by Phpstorm. But you can help it to understand that, all you need to do is to use #var annotation, see:
/**
* #var LoggerServiceInterface $logger
*/
$logger = app()->make(LoggerServiceInterface::class);
That way, Phpstorm will know what to expect from that $logger object.

Doctrine2: persisting parent entity given child class

I've got a User Entity defined (mapping in yml)
namespace My\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class User
{
...
And I created a child class that inherits from that entity, so that I can add some custom validation methods and a few fields that I need but do not need to be persisted (e.g. ConfirmPassword, ConfirmEmail fields)
namespace My\SecondBundle\EditModels;
use My\CoreBundle\Entity\User;
class UserModel extends User
{
When the user submit a registration form, I map the request to a UserModel entity, and if it is valid I try to persist the user.
The following code throws an exception
$entityManager->persist($userModel);
//=>The class 'My\SecondBundle\EditModels\UserModel' was not found in the chain configured namespaces My\CoreBundle\Entity
Question: How can I persist $userModel (instance of UserModel) as a User entity class? Possible options:
Do not use an inherited class and add custom fields and validation method to the User entity itself
Copy the fields from the UserModel to the User entity and persist the user entity
I don't think I should use Doctrine inheritance mechanism as I do not want to save the extra fields.
Thank you
I think your problem here, is that you've just configured My\CoreBundle\Entity namespace in Doctrine2, but the entity you actually want to persist is located in My\SecondBundle\EditModels.
Usually when inheriting classes marked as #ORM\Entity() the class you are extending from must have the class annotation #ORM\MappedSuperclass(). But normally you use this for single table inhertiance e.g., not for your usecase.
In my opinion the approach to split database related attributes from the others, is not affordable. I would keep validation related stuff in the model itself - you need it in your create/update action.
I'm not familiar with XML configuration, but when using annotations you need to mark each property to be mapped with database (using #ORM\Column()). So Doctrine will ignore all the other attributes and methods entirely.
So here I share my recently developed AbstractModel for you, to see how I've implemented validation (with respect/validation):
<?php
namespace Vendor\Package\Model;
use Doctrine\ORM\Mapping as ORM;
/**
* Abstract Model
*
* #ORM\MappedSuperclass()
*/
abstract class AbstractModel
{
/**
* #var \Respect\Validation\Validator
*/
protected $validator;
/**
* AbstractModel constructor
*/
public function __construct()
{
$this->validator = static::validation();
}
/**
* Defines validation for this model
*
* #return \Respect\Validation\Validator
*/
public static function validation() : \Respect\Validation\Validator
{
return \Respect\Validation\Validator::create();
}
/**
* Executes validations, defined in validation method.
*
* #return bool
*/
public function isValid() : bool
{
if (is_null($this->validator)) {
$this->validator = new \Respect\Validation\Validator();
$this->validation();
}
return $this->validator->validate($this);
}
}
A model which extends from the AbstractModel needs to implement a static validate method, to define class validation:
<?php
namespace Vendor\Package\Model;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="my_model")
*/
class MyModel extends AbstractModel
{
/**
* #var string
* #ORM\Column(type="string")
*/
private $name;
/**
* Defines validation for this model
*
* #return \Respect\Validation\Validator
*/
public static function validation() : \Respect\Validation\Validator
{
return \Respect\Validation\Validator::create()
->attribute('name', \Respect\Validation\Validator::notEmpty()->stringType()->length(null, 32))
;
}
// getter, setter, ...
}
Each entity, persisted to database, will have the $validator property and all these methods, but because I left annotations here (and pretty sure this also works with xml/yaml) Doctrine ignores it.
And this way you also keep validation related stuff out of the model class itself, which is good for readability. The validation itself should be defined in the model itself, imho. But this respect/validation framework is neat way to achive this. Hope this helps :)

Create an artisan command for generating custom classes or files

What's the best way ( or maybe the way it's actually done ) of creating an artisan command for generating custom classes or files? Like php artisan make:console itself that creates a php class for our new artisan command.
From what I can think of, we have two options:
Add the template for that new file using php heredoc(or any string inside the new command's class file for that matter), which is really messy.
Put a template file somewhere, read it, replace what's necessary, and then create the new file. But I don't know where would be best to put the template file.
So is there a best-practice for handling this situation in Laravel? I googled it, but there was only articles and documentation for simple artisan command creation.
Update 04/2020: Laravel 7 comes with a way to edit the default stubs to make changes to them and have Laravel pick up those changes. If you want to make a completely different stub to publish a totally different file the process below is appropriate otherwise look at the docs at the link below.
https://laravel.com/docs/7.x/artisan#stub-customization
I know this question is a bit old but this is pretty easy if you just want to create a similar file that Laravel already does. (I wanted to create a job with some custom traits attached on creation)
So first look at the stubs Laravel comes with here on github.
Next, pick the stub of the type of class you want (I copied the job-queued stub) and paste it somewhere you can access in your app. I put mine inside App\Console\Stubs since that makes sense that commands will use the stubs.
After that, create your artisan command with php artisan make:command commandName.
Inside the command created use this file Illuminate\Console\GeneratorCommand. Now make your command extend this class instead of Command; This class is the class Laravel uses to create classes and it extends Command itself.
Inside your command create a few properties and methods as follows:
protected $name = 'make:custom-file'; The name of your command. This replaces $signature
protected $description = 'Command description.';
protected $type = 'Job'; Type of class to make
//location of your custom stub
protected function getStub()
{
return app_path().'/Console/Stubs/custom-job.stub';
}
//The root location the file should be written to
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Jobs';
}
//option flags if any see this for how it works
protected function getOptions()
{
return [];
}
A full example of how the class should look is like this:
<?php
namespace App\Console\Commands;
use Illuminate\Console\GeneratorCommand;
class CustomJob extends GeneratorCommand
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $name = 'make:custom';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Create a custom job.';
/**
* The type of class being generated.
*
* #var string
*/
protected $type = 'Job';
/**
* Get the stub file for the generator.
*
* #return string
*/
protected function getStub()
{
return app_path().'/Console/Stubs/custom-job.stub';
}
/**
* Get the default namespace for the class.
*
* #param string $rootNamespace
* #return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Jobs';
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return [];
}
}
Once you run your custom artisan command it will write your custom stub to where you specify.
Laravel uses .stub files as templates, and replaces the tokens inside the template.
Since you mentioned the make:console command, for reference you can take a look at the following files:
vendor/laravel/framework/src/Illuminate/Foundation/Console/stubs/console.stub
(on github)
This the template for making new console commands.
vendor/laravel/framework/src/Illuminate/Foundation/Console/ConsoleMakeCommand.php
(on github)
This is the code that is executed when you run the php artisan make:console command.
If you want to take a look at packages that have done this, as well, a good example is the generators package by Jeffrey Way at Laracasts.

Add Class to Laravel 4 Package

I am using this Laravel 4 package for interacting with the Xero accounting application: https://github.com/Daursu/xero
In the GitHub README, it says that you can extend the package easily by using the following code:
namespace Daursu\Xero;
class CreditNote extends BaseModel {
/**
* The name of the primary column.
*
* #var string
*/
protected $primary_column = 'CreditNoteID';
}
I tried adding this as a new Model, but Laravel gives me a Class not found error.
I'm assuming this is a namespacing issue a but can't seem to get it right. I have tried using \Darsu\Xero and also \Darsu\Xero\BaseModel, and other various combinations with and without the initial \.
Any tips on how to do this right?
Easiest way to achieve your intentions:
1) Create a file CreditNote.php in app\models
2) Put the following code in the above file:
use Daursu\Xero\BaseModel;
class CreditNote extends BaseModel {
/**
* The name of the primary column.
*
* #var string
*/
protected $primary_column = 'CreditNoteID';
}
3) Whenever you need to use the CreditNote model, use $creditNote = new CreditNote();

Categories