In laravel 4, I could push a closure onto the queue with queue::push(function...), but this no longer works in laravel 5. Instead, it appears that I have to make a custom Job class for every function that I want to push onto the queue.
Since the functions I want to be pushing are only a couple of lines long, and are only ever used in exactly one place, it really seems like a waste of time and space to be writing up a full class for every case.
The best "solutions" I can currently think of, are to either have a helper function that uses PHP's reflection methods to dynamically generate a new class when called, or to have generic job that accepts a closure as parameter, i.e. dispatch(new ClosureJob(function(){...}));
These seem less than ideal to me. Is there another way to do this? Or am I going to have to implement one of these?
As of Laravel v5.7 you can queue an closure like this:
$podcast = App\Podcast::find(1);
dispatch(function () use ($podcast) {
$podcast->publish();
});
Docs:
https://laravel.com/docs/7.x/queues#queueing-closures
However it is strongly recommended to use a dedicated job class to improve your code quality and for the sake of a better maintenance of your application. Think of you want to check what tasks are left in queue, or want to control on which queue/connection the particular code should run at.
Therefore you need a dedicated job class:
https://laravel.com/docs/5.7/queues#creating-jobs
I'd say that writing a dedicated class is pretty much the Laravel standard and this is what you should align to.
I've accomplished this by relying on the OpisClosure library. Extend the class as so:
class QueueableClosure extends SerializableClosure
{
public function handle() {
call_user_func_array($this->closure, func_get_args());
}
}
Then use it like this:
Queue::push(new QueueableClosure(function(){
Log::debug("this is the QueueableClosure in action.");
}));
N.B. See the comment below from #Quezler about possible limitations!
https://laravel.com/docs/5.0/queues#queueing-closures says:
You may also push a Closure onto the queue. This is very convenient for quick, simple tasks that need to be queued:
Pushing A Closure Onto The Queue
Queue::push(function($job) use ($id)
{
Account::delete($id);
$job->delete();
});
However, my guess is that you're using Laravel 5.3+, because https://laravel.com/docs/5.3/upgrade#upgrade-5.3.0 says:
Queueing Closures is no longer supported. If you are queueing a Closure in your application, you should convert the Closure to a class and queue an instance of the class.
Related
I am creating an API. In this API I am accessing a (permissions) table from a database multiple times, in middleware as well as in controllers. I was thinking, instead of accessing the database multiple times, why don't I call it once and use it multiple times. After calling it once, I could store it in the cache within a service provider. But I am not sure if it is a good way to go because API routes don't load all the services like session.
There are other ways like storing data into the config. Or create a class and make a facade for it and then call it when ever it is needed. But I am curious if the cache would work in API routes and would it be a good idea?
Okay with the advice of #lagbox I created a dead simple class.
namespace App\Helpers;
use App\Permission;
class Provide
{
public $permissions = [];
function __construct() {
$this->permissions = Permission::whereNotNull('route_name')->get();
}
}
This may vary, it's just a class that will keep some collection data in it. I named it provide to keep it generic, just in case that I could need other data than permission in the future. Of course this class could be more detailed but just for storing and returning permissions it is enough.
Then I bound it as a singleton in my AppServiceProvider to run it only once.
public function register()
{
$this->app->singleton('App\Helpers\Provide', function ($app) {
return new \App\Helpers\Provide();
});
}
and when I need it I call it like
$provide->permissions->toArray()
All the features of the collection are available everywhere from the beginning to the end. Yes that may look like an overkill or an abuse of IoC but this über simple approach is in my case a superb solution.
This is something I have struggled with for a while to get my head around
I have a shell which at the moment grabs data from a 3rd party, processes it and saves processed data into my db. The processing can save to related tables as well.
I also want to have some way of submitting data via chrome extension to be processed in the same way. The data is going to be in the same format in both scenarios so I was hoping to move the logic I have in my shell into something that both a shell and controller can use.
Part of my processing involves loading any currently saved data in some situations too - and I found that I can't use loadModel unless I am in a controller?
So where should this logic go, and how do I make sure that solution has access to all the part of the framework I need still?
You can create an Utility folder under src containing php files.
Here you can define your namespace of class and can instantiate easily.
You can use statements also.
--src
|--Utility
|--Example.php
<?php
namespace App\Utility;
class Example
{
function __construct() {
//constructor
}
function demo() {
//function for specific task
}
}
I am a beginner starting out in laravel 5.2 and I think these concepts below should be explained more straight forward than just reading documentation.
Service Providers
Service Container
Contracts
Facades
I think a good explanation and examples that can really help beginners understand how these 4 concepts fit together in the framework.
Service provider :
The so called service providers are the heartbeat of your Laravel application. They are the central element of the initialization process where all the relevant and required code is loaded by PHP. This includes all the essentials from the framework itself, but also any own and custom code you need to load.
Inversion of Control, or IoC :
Can't be explained easly (i only have few ideas about this im not a pro)
Facades :
The Facade pattern is a software design pattern which is often used in object oriented programming. A facade is, in fact, a class wrapping a complex library to provide a simpler and more readable interface to it. The Facade pattern can also be used to provide a unified and well-designed API to a group of complex and poorly designed APIs.
A Laravel facade is a class which provides a static-like interface to services inside the container. These facades, according to the documentation, serve as a proxy for accessing the underlying implementation of the container’s services.
MORE
Contracts :
LARACASTS FREE VIDEO
I know this is not enough! what you are asking is complicated stuff a single answer can't be enough
Ok, so first I agree with the others that laracasts is an amazing resource, that will really go into greater detail and break things down very simply.
That being said, the brief overview is as follows:
Service Container (IoC container) is a laravel core process that allows you to load objects with their dependencies gracefully. For example, If I have a controller method like this:
public function update(Request $request, $id)
{
...
}
IoC container is smart enough to resolve the Request and load up all the dependencies associated with the Request class to make sure it gets instantiated properly.
It also allows you to instantiate classes without having to fully pass along all the dependencies as follows:
class ProductRepo(Product $product)
{
public function get($id)
{
...
}
}
I can reference this class without loading it with dependency injection as follows: (make sure to pass in full namespace)
app('App\ProductRepo')->get($id);
This allows me to not have to pass in a Product Object, Laravel is smart enough to resolve the Product object because the IoC container is doing the magic behind the scenes.
Service Providers are a place for you to lace in custom behavior when booting up or instantiating a class. For example, Laravel by default uses a class called the EventServiceProvider. This class's job is to configure the Event system in Laravel to make sure to include all the custom event listeners you create. So if I wanted to make sure that when the EventDispatcher is being loaded up, it brings in all the necessary dependencies.
Contracts are really simple. They are just an allusion to php object oriented concept of Interfaces. This concept states that there are classes that establish rules. For Example:
interface SearchableInterface
{
public function search($data);
}
class BinarySearch implements SearchableInterface
{
public function search($data)
{
...
}
}
This states that any class that implements the SearchableInterface, must have a function search that accepts one parameter. This creates a 'contract' that any classes that implement the SearchableInterface will have to have this function, or the application will throw an error.
This is great for using interchangeable pieces (siblings) and not having to worry that the class is missing a function you need.
Last but not least is the Facade. I love facades. In a nutshell all this is doing is creating a static representation of a class that was not defined statically. So lets say I have a class that will get a document from S3.
class S3
{
public function get($file)
{
...
}
}
Without a facade you would first have to instantiate and then call get on the class in order to get something from S3.
$s3 = new S3;
$s3->get('myAwesomeFile');
Laravel allows you to easily register Facades so that you can just use this statically for readability and convenience.
S3::get('MyAwesomeFile');
All of this has been an over-simplification of each concept, but goes into some detail about some of the basics of each concept. Hope this helps!
I need to run some code when one of my models is saved (created/updated) or deleted. What's the best way to do that?
There's three different ways that I'm aware of:
Override the save and delete methods on the model
Add creating/updating/deleting callbacks in the boot method
Bind an observer in the boot method
I haven't seen these compared and contrasted, so I don't know what the differences are. I'm worried that the events won't fire under certain conditions.
For example, in Django, deletes only fire if you delete the models one-by-one, but not in a mass delete.
To be clear, I'm looking for answers that compare and contrast these (or other) methods -- not simply suggest even more ways of doing the same thing.
It's just my opinion for several methods you mention previously.
Override the save and delete methods on the model ( If you override it then next update of Laravel change visibility of method your code does not work again. It would throw Exception or PHP error. You have to modify it to work again )
Add creating/updating/deleting callbacks in the boot method ( exist in Laravel 4 you should check it again in Laravel 5 maybe different implementation using Event and Listener )
Bind an observer in the boot method ( exist in Laravel 4 you should check it again in Laravel 5 maybe different implementation using Event and Listener )
I think you should using Event and Listener provided by Laravel. It maybe still work on next Laravel Update. I assume Event and Listener as minor change area in Laravel and changed maybe just different method implementation.
Laravel should have plan of development assign which part of Laravel will be developed as major change area ( big modification ) or minor change area ( little modification ). If you try to change or override major change area it would can't be used on next Laravel Update.
You can register Event and Listener for save and delete record. Laravel have fireModelEvent method on Model ( Illuminate\Database\Eloquent\Model ) which trigger specific Laravel Event. If you've registered Event, Dispatcher ( Illuminate\Events\Dispatcher ) will execute Listener of Event.
Documentation about Laravel Events:
https://laravel.com/docs/5.3/events
https://laravel.com/docs/5.2/events
I assume you have YourModel as Model then do the following action on the below.
Register Event and Listener. Open app\Providers\EventServiceProvider.php then Add Event and Listener to EventServiceProvider.listen properties for YourModel or follow Laravel Documentation to create event using other way.
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
...
'eloquent.saved: App\YourModel' => [
'App\YourModel#eventSaved',
],
];
}
Adding eventSaved method on App\YourModel as Listener for Event so you can do specific action after save or delete.
class YourModel extends Model
{
public function eventSaved(){
// You can add your code to catch save here
}
}
The three methods and 4th referred by #joko. There may be more as well but lets focus on the 4 methods.
Let me describe you them one by one:
1) Override the save and delete methods on the model
In this method you are using OOPD method overriding. You are overriding Laravel's interal save method and adding your additional code by defining your own save method on top of it. This should be avoided as Laravel keep evolving and it may happen that thing start to fail if major change is done like Suppose in future laravel replace save method with any other method to save the records. Then again you will have to create another method to override that new method. Also writing code here may grow your model class file. You model may keep handling things like he shouldn't handle(Example: Sending Email). This method should be avoided.
2) Add creating/updating/deleting callbacks in the boot method
Here you are defining code on the Boot method of the Model. This method should only be used if there is much little code/things that you need to handle on event. The drawback of this method is that it make code more complicated and cluttered as you may write all logic in one like like functional programming. Suppose if you have to do some stuff on before creating and after created. You boot method will grow.
3) Bind an observer in the boot method
This method is pretty good. You create one observer class which handles such stuff that what should happen on Laravel events. It makes code more cleaner and easy to maintain.
Example: Suppose you have to write code in creating, saving, saved, deleting in these methods. In this case, method 1) and method 2) won't be good practice because in
Method 1: We will have to create this 4 methods and override them as well and support them in future releases of Laravel. In this case, code in your Model will also grow because of overriding this methods
Method 2: In this case your boot method will grow as well so you Model file will become a junk of code.
In method 1 and 2 also remember that its not responsibility of your Model to do many of the stuff that you going to write. Like sending email when user is created. These codes you may end up writing in created method.
Suppose now you have scenario where you need to send email to user on created event as well as you need to make user's entry log user in customer CRM. then you will have to write code for both in same method. Probably, you may not following single responsibility principle there. What should we do in the case? See method 4.
4) Other method suggested by #joko
The scenario that i suggested in method 4's end. You may send email to user and log him in Customer CRM whenever it is created. Then your method will do 2 things(Sending email and logging in CRM). It may not following single responsibility principle. What if better we can decouple both of them. Then comes this method.
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
'eloquent.saved: App\User' => 'App\Listeners\SendWelcomeEmailToUser'
'eloquent.saved: App\User' => 'App\Listeners\LogUserInCRM'
];
}
Create two listener classes:
class SendWelcomeEmailToUser
{
public function handle(User $user){
// Write code to send email
}
}
class LogUserInCRM
{
public function handle(User $user){
// Write code to log
}
}
Through this you can separate out codes and make them more cleaner.
I generally prefer this method its mode clean. It also gives you much better idea that what actually happen when event happens. It becomes one single point for Event to Listener mapping.
You can create event handlers, for every create/update of model, for example to add to cache the model data which is just saved to database or going to save to database, easier to retrieve without select query call,
while delete call, use forget for given key on cache handler event to delete cache as well as to delete from database too.
I'm partial to doing things manually when you need to know exactly how they're done. I recently used this Laravel Boilerplate to start a project and I like the way they manually fire events in the repository when a model is updated:
https://github.com/rappasoft/laravel-5-boilerplate/blob/master/app/Repositories/Backend/Access/User/EloquentUserRepository.php
Since models should always be updated through the repository, you always get to manually decide how events are handled. You could fire your own event when multiple models are deleted, and act accordingly. All of your options will work though, you just need to find the option that suits your needs best.
You can create abstract Model class that extends Illuminate\Database\Eloquent\Model class and all your model will extend this class. With implementation like this you can have more control on the models. For example
<?php
namespace App\Base\Database;
use Illuminate\Database\Eloquent\Model as BaseModel;
abstract class Model extends BaseModel
{
public function save(array $options = [])
{
//your code here
return parent::save($options);
}
}
You can do this for all the methods of the Model class and also you can add additional methods that are relevant for all models in your application
I am developing a package for Laravel 5, and now I need to benefit from dependency injection to have a more scalable and relaible application, I don't know which approach is the best to take and why, this is a piece of my code and I need to injected the Lang class dependency
class MyController extends \App\Http\Controllers\Controller
{
public $text;
public $lang;
public function __construct()
{
// Some codes here
}
public function myFunction(){
$this->text = \Lang::get('package::all.text1');
}
}
In this link http://laravel.com/docs/4.2/ioc 2 approaches are suggested, Basic Usage and Automatic Resolution based on my understanding from the link
taking the first approach I need to add
App::bind('lang', function($app)
{
return new \Lang();
});
to the register part of application and then in the function I'll have something
like this :
public function myFunction()
{
$lang = \App::make('lang');
$this->text = $lang::get('package::all.text1');
}
The other way is to modify the constructor like
public function __construct(Lang $lang)
{
$this->lang = $lang;
}
And then instantiate object from Class like
$myController = App::make('MyController');
Which way is the better way to take for, considering that this class is a Controller and it will be called in the routes file, or please correct me if my understanding from the link is not right. please also inform me why you suggest any of those approaches.
It should be noted that using local IoC resolution ($app->make() stylee) is not much better than using the facades directly (Lang::get() stylee) - you're still very much relying on Laravel's specific classes without really making your code explicitly state that it needs these exact classes. So the general advice is to, as much as possible, code to an interface if you want your code to be as portable as possible.
Of course there are a couple of big downsides to this currently in PHP development:
These interfaces are not generally defined (except the PSR-3 LoggerInterface interface) so you still have to rely on a particular instance of the interface (in this case, Laravel's).
If you decide to make your own generic interface (or the FIG eventually creates some of these), the classes that Laravel provides for translation (for example) don't implement it anyway, so you then need to subclass the existing ones just to make it look like it implements your own interface. But hey, that's the current best practice, so I guess if you wanna be using the current best practices, code to an interface, and don't worry for the time being that the interface you're coding to is Laravel-specific.
But anyway, here are my thoughts on your specific question. First off I should say that I haven't actually used Laravel 5 yet (just the 4s), but I have generally followed its development.
If the class I am coding will use a given dependency quite a lot or as a core part of how the class works I will use constructor dependency injection. Examples here are the Request or some Repository class in a controller, or a business logic class in a console command class.
If what I need I only need for a specific purpose (maybe redirecting from a controller and needing to generate a URI) I will resolve a local version from the IoC container ($this->app->make()) and then use that. If I were using Laravel 5 and the method was called by Laravel directly (e.g. a controller's action method) I may use method injection for this, I'm not 100% sure.
As a final note, the general advice is that if your constructor method signatures get too big due to a lot of dependencies:
It's time to have a look at if your code relies too much on external dependencies. Maybe some of the functionality of your class can be extracted to its own class that splits the dependencies between the two.
You should consider using setter methods rather than constructor injection - so instead of accepting a Request object, you have a $class->setRequest() method. The downside of doing this is that you need to tell Laravel's IoC container how to instantiate your object (i.e. that these setters must be called). It's not that big a deal but something worth noting.
Relevant links:
Laravel 5's IoC article
Laravel 5's Controller injection advice