Laravel 7.x: Difference between fresh and refresh method? - laravel

While I was reading Laravel documentation, I faced a method named fresh and refresh on the Eloquent model. Please explain the major difference between them? I am having hard time understanding those.

This is the comment for the refresh method on Illuminate\Database\Eloquent\Model :
/**
* Reload the current model instance with fresh attributes from the database.
*
* #return $this
*/
public function refresh()
Here is the one for fresh:
/**
* Reload a fresh model instance from the database.
*
* #param array|string $with
* #return static|null
*/
public function fresh($with = [])
refresh will refresh the current model instance (including relationships). fresh will get a new instance of the model from the database and return it.

RefreshCommand
Reset and re-run all migrations
FreshCommand
Drop all tables and re-run all migrations

Related

How to perform action globally when record get updated in laravel

Is that possible to run this job UpdateRateZone globally wheneven Consignment Model gets updated anywhere in the system?
One method is to use Observer but observer doesn't work when update multiple reccord at once like
Consignment::where('status',1)->update(['address'=>'This']);
Is there anything else we can do?
As per laravel docs :
When issuing a mass update via Eloquent, the saving, saved, updating,
and updated model events will not be fired for the updated models.
This is because the models are never actually retrieved when issuing a
mass update.
Laravel does not fire updated event in case of mass update, so its not possible as per my knowledge. Other way is to do manually.
Other than observers there is methods such using closures for events and Registering events manually but all these methods would work if only laravel trigger an event on mass updation .
Yes you can create a Event Listener for your model. You can read up on more info here
In short first you need to create an Event for the needed model, so if its a Updated event create something like this.
php artisan make:event Consignment/Updated
In that file add
class Updated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* #var Consignment
*/
public $consignment;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Consignment $consignment)
{
$this->consignment= $consignment;
}
/**
* Get the event consignment property
*
* #return Consignment
*/
public function getConsignment()
{
return $this->consignment;
}
}
Now you must create a Listener for this event
php artisan make:listener Consignment/UpdatedEvent
And in the handle function add youre logic
/**
* Handle the event.
*
* #param Updated $event
* #return void
*/
public function handle(Updated $event)
{
//
}
And all that is left after that is to register the events for you Model and you do that in your Consignment.php class where you add
/**
* The event map for the category.
*
* #var array
*/
protected $dispatchesEvents = [
'updated' => Updated::class,
];
When you do this:
Model::where('status',1)->update([some stuff]);
Query Builder's update() method is executed instead of Eloquent's update() method.
If you want to trigger Eloquent events, you need to update rows one by one.
You can fire these events manually, but it's tricky and it's a bad idea.
You could just run the UpdateRateZone job manually for all the Consignments that were updated

Laravel run code when new user registrated with default registration code

Im running a laravel 6.9 application with default authentication/registration.
I want to maintain the default registration process but i want to run a curl command if a user has registered.
Is it possible to hook into the default registration process and extend it with extra code?
Observer is good point in code where you can, well, observe if user is just registered but good place to put additional code after user has been registered is event/listener group. There is already Registered event set in EventServiceProvider so you would need to put additional listener beside one already set there (for sending email to newly registered user if opted). To have all sorted next steps should be followed (disclaimer: I am taking that you use all default auth code so far):
First copy registered(Request $request, $user) method from Illuminate\Foundation\Auth\RegistersUsers.php trait to default App\Http\Controllers\Auth\RegisterController
/**
* The user has been registered.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function registered(Request $request, $user)
{
//
}
So you would override that piece of default code which is meant to stay intact (as should every code from vendor directory).
Then, you would need to create listener. In App\Providers\EventServiceProvider::listen array, add one more class into value array so it should looks like
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
\App\Listeners\FooBarBaz::class,
],
];
Don't bother for not having created class already, next artisan command will do that for you:
php artisan event:generate
Now, in \App\Listeners\FooBarBaz::class you can make your custom code related to new user:
namespace App\Listeners;
use Illuminate\Auth\Events\Registered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class FooBarBaz
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param Registered $event
* #return void
*/
public function handle(Registered $event)
{
// $event->user is accessible here
//
// this method should return void, it is just executed
}
}
Now, back to registered method of RegisterController. Here you would need to initiate event:
/**
* The user has been registered.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function registered(Request $request, $user)
{
event(new \Illuminate\Auth\Events\Registered($user));
}
And you are done.
I wanted to show you use of already lot of prebuilt code although Observer is also good place. But also for calling event; I wouldn't put more code than this event(new \Illuminate\Auth\Events\Registered($user)); line into UserObserver::created(User $user). Whole part with event/listener is very good and decoupled now. Of course, you can make even custom event not using default Illuminate's one, just set that new key => value into EventServiceProvider.
Events
Observers

How laravel facade can use DB and DB instance at the same time?

I use DB facade. I see it can use in DB::connection from Illuminate\Database\DatabaseManager and DB::select from Illuminate\Database\Connection.
I don't understand how one facade can apply two serivce?
Thank you for your asking!
One Facade can point to multiple classes for different methods. This is possible through the magic method __call.
Here's the __call method of the DatabaseManager class:
/**
* Dynamically pass methods to the default connection.
*
* #param string $method
* #param array $parameters
* #return mixed
*/
public function __call($method, $parameters)
{
return $this->connection()->$method(...$parameters);
}
The DB facade points to the DatabaseManager class and if the method is not found the DatabaseManager then forwards the call to the Connection class.

Custom laravel migration command "[Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable"

I'm trying to create a custom laravel (5.2) migration command that basically works the same as migrate:status except it just lists the pending migrations instead of all the migrations.
To do this i've very simply copied the migrate:status into another class within my app/console directory and adjusted the code to suit my needs. However whenever I try to run it I get an error:
[Illuminate\Contracts\Container\BindingResolutionException]
Target [Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable while building [App\Console\Commands\PendingMigrations, Illuminate\Database\Migrations\Migrator].
The contents of the class itself and the fire() method doesn't seem to matter as it doesn't get that far, it fails within the __construct() method.
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Migrations\Migrator;
class PendingMigrations extends Command
{
/**
* The console command name.
*
* #var string
*/
protected $name = 'migrate:pending';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Shows a list of pending migrations';
/**
* The migrator instance.
*
* #var \Illuminate\Database\Migrations\Migrator
*/
protected $migrator;
/**
* Create a new migration rollback command instance.
*
* #param \Illuminate\Database\Migrations\Migrator $migrator
* #return \Illuminate\Database\Console\Migrations\StatusCommand
*/
public function __construct(Migrator $migrator)
{
parent::__construct();
$this->migrator = $migrator;
}
/**
* Execute the console command.
*
* #return void
*/
public function fire()
{
}
}
The reason for it is likely to be something to do with the IoC container and the order with which things are loaded, but I don't know enough about the inner workings of Laravel to figure out any more than that.
It surely must be possible?
I am currently stuck on 5.2, so i'm not sure if this problem exists in more recent versions.
The only thing i've attempted so far is added the migration service provider to the top of the list in config/app.php however it didn't seem to have an affect and it was just a random guess anyway.
providers' => [
Illuminate\Database\MigrationServiceProvider::class,`
]
I got around this using:
$this->migrator = app('migrator');
but it is not necessarily the best way to do this
The Migrator instance is not bound to the class name in the IoC container, it is bound to the migrator alias.
From Illuminate\Database\MigrationServiceProvider:
/**
* Register the migrator service.
*
* #return void
*/
protected function registerMigrator()
{
// The migrator is responsible for actually running and rollback the migration
// files in the application. We'll pass in our database connection resolver
// so the migrator can resolve any of these connections when it needs to.
$this->app->singleton('migrator', function ($app) {
$repository = $app['migration.repository'];
return new Migrator($repository, $app['db'], $app['files']);
});
}
Since the class name is not bound in the IoC container, when Laravel resolves your command and attempts to resolve the Migrator dependency, it attempts to build a new one from scratch and fails because the Illuminate\Database\Migrations\MigrationRepositoryInterface is also not bound in the IoC container (hence the error you're receiving).
Since Laravel can't figure this out itself, you need to either register the binding for the Migrator class name, or you need to register the binding for your command. Laravel itself registers all the bindings for the commands in the Illuminate\Foundation\Providers\ArtisanServiceProvider. An example of the command.migrate binding:
/**
* Register the command.
*
* #return void
*/
protected function registerMigrateCommand()
{
$this->app->singleton('command.migrate', function ($app) {
return new MigrateCommand($app['migrator']);
});
}
So, in your AppServiceProvider, or another service provider you setup, you can add one of the following:
Register the command in the IoC:
$this->app->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
Or, register the Migrator class name in the IoC:
$this->app->singleton(\Illuminate\Database\Migrations\Migrator::class, function ($app) {
return $app['migrator'];
});
As I don't want to register the migrator everywhere in the app, but I still want to extend the MigrateCommand itself, I came up with this approach to maintain my app as it is:
public function __construct()
{
app()->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
parent::__construct(app('migrator'));
}

No relations updated in the DB after writing symfony/doctrine associations

So I am working on a project in symfony 3.0.1. I have generated entities (via doctrine:generate:entity with the following interactive setup questions) and then did the doctrine:schema:update --force to generate the tables in the DB from the Doctrine entities.
I then went in the entities and created associations.
After that I went ahead and did another doctrine:schema:update -- force and after checking in phpMyAdmin no relations were created by the schema update I forced.
Is there something else I am missing? See below my entities:
namespace MyAppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Logins
*
* #ORM\Table(name="logins")
* #ORM\Entity(repositoryClass="MyAppBundle\Repository\LoginsRepository")
*/
class Logins
{
/**
* #var int
*
* #ORM\Column(name="RoleID", type="integer")
* #ORM\ManyToOne(targetEntity="Roles", inversedBy="roleID")
* #ORM\JoinColumn(name="roleID", referencedColumnName="roleID")
*/
private $roleID;
'
'namespace MyAppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Roles
*
* #ORM\Table(name="roles")
* #ORM\Entity(repositoryClass="MyAppBundle\Repository\RolesRepository")
*/
class Roles
{
/**
* #var int
*
* #ORM\Column(name="roleID", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\OneToMany(targetEntity="Logins", mappedBy="roleID")
*/
private $roleID;
public function __construct() {
$this->roleID=new ArrayCollection();
Still not sure why there were conflicts, but I resolved my problem with Doctrine reverse engineering. I created the relations in PMA and then generated mapping from it. All worked out well.
EDIT: The guy in comments to my post was right. I cannot assign One-to-Many on an Identity property.
I have had frustrating problems with relations not updating on my production environment several times now. My code would execute as expected with no errors, but the table(s) simply wouldn't update.
I've discovered that if you are using APC and you have just added a new relationship, you need to restart the web server in order for old versions of the entity classes to be flushed out.

Resources