I created a model in Laravel. I always noticed the default would be use HasFactory. May I know what exactly does it work. In my understanding from reading documentation, it is for linking to database (I guess?) But I still don't understand how it works exactly.
HasFactory is not to link to the database.
It is a trait that links a Eloquent model to a model factory.
Factories are normally used in testing when wanted test-data for a specific model.
You can read more about factories in Laravel here: https://laravel.com/docs/9.x/database-testing#model-factories and here:
https://laravel.com/docs/9.x/eloquent-factories
The trait ensures that you can instantiate a factory like this:
User::factory()->create();
In older versions of Laravel the trait was not used, and instead a factory had to be instantiated by the global factory helper like this factory(User::class)->create(); but that caused a lot of problems with intellisense in IDE's.
Related
I have some issues regarding the zf2 to zf3 migration of my application. I've gone through the migration guides and started the migration process as describe there.
According to the migration guide, there is no serviceLocator available into controllers anymore. And I used to use it within each and every controller action to inject the config variable array (located in module.config.php), Doctrine MongoDB DocumentManager and the Doctrine EntityManager into the Models where they are needed. Now I'm getting so many deprecated warnings messages as below;
PHP Deprecated: Usage of
Zend\ServiceManager\ServiceManager::getServiceLocator is deprecated
since v3.0.0; please use the container passed to the factory instead
in
/var/www/html/LeapX/vendor/zendframework/zend-servicemanager/src/ServiceManager.php
on line 169
Since I need to access config variables and inject the Doctrine DocumentManager and Doctrine EntityManager into my Models, I had to call $this->getServiceLocator() within my controllers. Let me know how to fix this issue. Is there any possibility to directly inject these dependencies into my Model classes? Should I need to use factories for Models?
And the other question is when it comes to factories regarding the controllers, Should I need to create individual factory for each and every controller of my application? There are quite a lot of number of controllers spread within few Modules in the application. If I add dedicated factory for each and every controller there will be double the number. Let me know the best way to do this.
From what i have read myself, it is no longer possible to call getServiceLocator() from controllers, they removed it since it promotes antipattern.
Here's a blog post from Matthew himself on this issue:
https://mwop.net/blog/2016-04-26-on-locators.html
Another explanation from the guy himself here (shorter, might be easier to digest):
https://github.com/zendframework/zend-mvc/issues/89
I am currently also in the process of trying to migrate a ZF2 (2.4.10) project to ZF3 and face the same issue.
I personally agree with the recommendation to explicitly define dependencies of your classes and controllers instead of (over)using getServiceLocator() method, though depending on your code, refactoring lots of code for this purpose might seem to be a PITA.
Alternatively, this can probably help (though, i can't say for sure since i haven't tried this myself):
http://circlical.com/blog/2016/3/9/preparing-for-zend-f
The Laravel Lang class provides a convenient way of retrieving strings in various languages, allowing us to easily support multiple languages. e.g. Lang::get() can be used to retrieve localized message.
But according to API documentation (and sources), class Lang doesn't have get() method or other methods like setLocale() for example. Class Lang extends Facade but Facade doesn't have that methods too.
Instead class Illuminate\Translation\Translator contains all methods we used for localization like get()
Why then we don't use Translator::get() or Translator::setLocale() but Lang::get() ??? How these two classes are connected ?
How can we invoke non-existent methods for the class ?
Your answer is here:
http://laravel.com/docs/4.2/facades
The Laravel documentation is pretty comprehensive. If you really want to understand how things work in Laravel, please take some time and read it all.
I understand that by definition, a trait cannot extend a class, however I'm wondering if there's some kind of workaround.
My situation:
I created the package revisionable, which in its first incarnation was a class that you extended from your model which itself extended Laravels base Eloquent class, however over time there were plenty of requests to change this into a trait, so people could use revisionable, and be able to extend their own base class.
Currently, the only that I can think to allow for both an extendable class, and a trait, is to offer both as a whole files, which means I'm repeating the entire code in two files which could easily lead to trouble down the road.
I'm wondering if anybody knows of some solution where I can have one file that is god, and the other file relies on it.
Rules
The existing class cannot use a trait, as existing users of the package on php 5.3 will not have access to traits.
There's absolutely no way to accomplish what you want.
Since Laravel itself (in 4.2) has now abandoned PHP 5.3, it's time to move on too.
Tag a new release that drops the class, add a PHP 5.4 requirement to your composer.josn file, and add this information to your docs.
Anyone still stuck on 5.3 can always just composer require your previous version.
Php 5.3 is a problem.
Back in when it was popular, the programming style was all about include/require files into another files. If you can split your functionality into functions that may be included in trait and in class - it may be a solution. But it depends of the functionality.
Modern way would be decoupling and dependency injections, in other words think units and unittesting.
Problem of a trait as well as the problem of the child-class is that you cannot unittest the pure functionality of what you have done without touching the parent class functionality. You cannot mock parent class, you can only mock injected class, right?
Think modern. Create a class, inject Eloquent object there. And then use this class in traits and some parent class for laravel models.
And forgive Taylor for the fact that you cannot mock the Eloquent. He may be able to fix it in new versions of Laravel. But you'll have to move to PHP7 because it is a requirement for latest laravel releases.
In my models I use Ardent for self-validating but I have a model where I also need to use Sentry for authentication. So I need to extend Ardent and Sentry too, but I can't because there is no multiple inheritance in PHP. I tried to do it with traits, but traits can't extend. I hardly need both classes, is there a way I can use both of them?
I think the best way to do this would be to copy the entire User model directly from the Sentry folder:
e.g. src/Cartalyst/Sentry/Users/Eloquent/User.php
Copy that file to your models directory, then have it extend Ardent instead of Model since Ardent already extends Model.
This should work -- though there could be some complications or fixes needed to make it work, I'm doing something similar using Toddish/Verify instead of Sentry.
I've been told to use some ORM library to make storage easier.
I've read about Doctrine, RedBeans and some other ones. I'm giving RedBeans a try because it's quite simple and requires no configuration.
I already tried some basic code to store beans and so.
If I want to have a model class (a bean?), to add some basic behaviour and functions.
What class do I need to extend? What methods do I need to override and then how should I get an instance of them?
Example: a Blog class which contains a User and Posts
The answer to my question was a feature of RedBean called 'Fuse'.
It was as simple as extending RedBean_SimpleModel class and implementing delete and update methods.
The downside of RedBean is the lack of tutorials/documentations (their wiki is really poor)