Pass array to the command bus - laravel

I'm trying to understand how to use the laravel 5.0 command bus, but I am struggling to get it right, so I'm looking for help with a few questions:
I'd like to dispatch an array of memberIds to run through a loop inside the handle function of the command.
$members:
array:2 [
0 => "147"
1 => "148"
]
This array is sent like this:
$this->dispatch(new SendMail($members));
How do I access the array in the handle method of SendMail command? I haven't found many examples, but nearly all of them pass $command into the handler.
public function handle($command)
{
//this doesn't work
foreach($command->members as $memberId){
$contractor = Contractor::find($memberId);
}
Do I need to return anything from the handler in order to continue running the other logic inside of my original function?

Since your trying to inject your $members array to your job's constructor method, you need to handle it there.
Then you'll be able to use your array in the hanle method.
// in your job class
protected $members;
public function __construct($members)
{
$this->members = $members
}
public function handle ()
{
foreach ($this->members as $member) {
//your logic
}
}
And if you want to inject an Eloquent model to your job (instead of an array) remember that you can typehint directtly in the constructor and , using the SerializesModels trait Laravel will retrieve it for you. This is described in the documentation.

Related

How to log every GET And POST data in Codeigniter 4?

my web application is doing a lot of AJAX calls (GET and POST) to our CodeIgniter 4 backend. My current approach to debug the AJAX call is setting manual logging messages within every method. Too time-consuming.
Do you know if there is a better way to do that? Overwriting a CI class?
I am happy about every help.
For logging the request you have to create the "after filters".
First You Define the Class which implements FilterInterface.
class Logger implements FilterInterface
{
use ResponseTrait;
public function before(RequestInterface $request)
{
...
}
public function after(RequestInterface $request, ResponseInterface $response)
{
...
}
}
In the after method, you will need to store the response and then save it using log_message.
public function after(RequestInterface $request, ResponseInterface $response)
{
$response_service = \Config\Services::response();
log_message('info', '{message}', ['message' => $response_service->getJSON()]
}
Here, I have stored used the response service explicitly and then simply called the getJSON to store the JSON body of the request. You will need to modify this for your problem. Also, do note you don't need to call the response service explicitly. There was another thread that showed how you can save the response implicitly, so you might want to refer to that.
Once the filter is done, you need to register the alias for the routes as below :
public $aliases = ['logger' => \App\Filters\Logger::class];
Once done you can either implement on individual routes or global routes.
Below is how you can implement it on global routes:
public $globals = [
'before' => [
...
],
'after' => [
'logger',
],
];
References : https://codeigniter4.github.io/userguide/incoming/filters.html?highlight=filter
https://codeigniter4.github.io/userguide/incoming/request.html?highlight=request
https://codeigniter4.github.io/userguide/general/logging.html?highlight=log_message
Just use
echo $this->request->getPost("usersemail"); die();
for usersemail input field

Returning same variable to every controller in laravel

I need to send the same result to almost every view page, so I need to bind the variables and return with every controller.
My sample code
public function index()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.index', compact('drcategory','locations'));
}
public function contact()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.contact', compact('drcategory','locations'));
}
But as you see, I need to write same code over and over again. How can I write it once and include it any function whenever I need?
I thought about using a constructor, but I cannot figure out how I can implement this.
You are able to achieve this by using the View::share() function within the AppServicerProvider:
App\Providers\AppServiceProvider.php:
public function __construct()
{
use View::Share('variableName', $variableValue );
}
Then, within your controller, you call your view as normal:
public function myTestAction()
{
return view('view.name.here');
}
Now you can call your variable within the view:
<p>{{ variableName }}</p>
You can read more in the docs.
There are a few ways to implement this.
You can go with a service, a provider or, like you said, within the constructor.
I am guessing you will share this between more parts of your code, not just this controller and for such, I would do a service with static calls if the code is that short and focused.
If you are absolutely sure it is only a special case for this controller then you can do:
class YourController
{
protected $drcategory;
public function __construct()
{
$this->drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
}
// Your other functions here
}
In the end, I would still put your query under a Service or Provider and pass that to the controller instead of having it directly there. Maybe something extra to explore? :)
For this, you can use View Composer Binding feature of laravel
add this is in boot function of AppServiceProvider
View::composer('*', function ($view) {
$view->with('drcategory', DoctorCategory::orderBy('speciality', 'asc')->get());
$view->with('locations', Location::get());
}); //please import class...
when you visit on every page you can access drcategory and location object every time
and no need to send drcategory and location form every controller to view.
Edit your controller method
public function index()
{
return view('visitor.index');
}
#Sunil mentioned way View Composer Binding is the best way to achieve this.

How do I convert an API resource class in Laravel 5.5 to an array BEFORE returning from controller?

Ordinarily, in Laravel 5.5, when using an api resource class, you simply return the resource class instance from your controller method, like so:
public function show(Request $request, MyModel $model)
{
return new MyModelResource($model);
}
This converts the model to an array (and ultimately to json) in the response to the client.
However... I am trying to figure out how to convert everything to an array BEFORE returning it from the controller method. I tried this:
public function show(Request $request, MyModel $model)
{
$array = (new MyModelResource($model))->toArray($request);
// ...
}
The problem here is that any relationships loaded on the resource aren't also converted to an array. They show up inside $array as an instance of a resource class. Obviously calling toArray() manually does not result in a recursive call, and methods such as ->whenLoaded('relationship_name') aren't really respected either.
So how do I get Laravel to do everything it does to convert the resource to an array recursively WITHOUT having to return it from my controller method?
I believe what you are looking for is the resolve method on the resource class. See definition.
From the looks of it, it should handle converting the relationships into an array as well. Just be sure you are setting up your resource relationships properly.
Neither the toArray() or resolve() methods convert the related models to arrays which is really annoying because you'd expect them to.
You're better off using toResponse(null) which will return a JsonRepsonse object. Which you can then use the getContent() method for a json encoded string or the getData() method for an object.
So if you wanted an array not wrapped in a data variable it would be:
$array = json_decode(
json_encode(
(new MyModelResource($model))
->toResponse(null)
->getData()
->data
),
true);
Ugly but it works unlike the accepted answer.

One associative array used across all controllers, one place to define it? - Laravel 5.3

I have an associative array which I use in approx all controllers and i was wondering if possible to define that array somewhere at one place and just use in in all controllers?
Kind of like we do in angular.
Like if i can define it in env file or something.
Please let me know if there is a way.
Creating an entry in the config/app.php
'myVar' => [
'key' => 'value'
],
and accesing it via config('app.myVar')
Put it in a helper file and access using that helper file
check out this answer https://stackoverflow.com/a/32772686/5808894
Using AppServiceProvider
In your app/providers/AppServiceProvider.php in the boot method add this, make sure to import App use App in AppServiceProvider
public function boot()
{
App::singleton('myVar', function(){
return [
'key' => 'value'
];
});
}
and access the variable in your controller using app('myVar');
Reference https://stackoverflow.com/a/25190686/5808894
Mentioning it here since no one else did:
public class SharedArrayContainer {
public static $data = [ 'key' => 'value' ];
}
and you can use it as:
SharedArrayContainer::$data
Not as good as adding it to the service container but this is what pre-framework me used to do.
I would recommend to create a provider class (service) for it and use laravel Service Container for injection. This way you can create helper methods like get, find, etc... and make use of laravels Dependency Injection (having single instance injected whenever & almost everywhere you want)
Laravel docs
class ExampelService
{
// associative array
private arr = []
public function get(item) { }
public function save(item) { }
public function has(item) { }
}

Accessing parameters in Request

I have a question about obtaining parameters from Request object.
What is the difference between
$name = $request->name;
OR
$name = $request->input("name");
They show the same behavior. I am asking that from the typing perspective, it is faster to utilize #1 method. But I don't know the difference. Is #1 prone to SQL injections?
Basically, the first case is just a syntactic sugar for the second. In Laravel, Request implements __get magic function to access its internal properties.
public function all()
{
return array_replace_recursive($this->input(), $this->allFiles());
}
public function __get($key)
{
$all = $this->all();
if (array_key_exists($key, $all)) {
return $all[$key];
} else {
return $this->route($key);
}
}
In the first case, if any files were uploaded, Laravel first looks for a property amongst them. And if there is no such param in files or in input, in your first snippet, Laravel also looks for a value amongst route parameters:
To protect your code against SQL injections, you have to use prepared statements/query builder/ORM. You should not escape/change input, so both these functions don't protect you against SQL injections.

Resources