laravel middleware setting $request attribute, does it affect performance - laravel

In one of my middleware I have used something like this
$user = [
'name' => 'noob',
'phone' => '87548154'
]; /* which actually comes from redis cache */
$request->attributes->set('user', $user);
and in the controller i use it like
$request->get('user')['name']
OR
$request->get('user')['phone']
As this seems very flexible, I would like to attach more data into the $user array.
In the laravel docs its written above the get() method of Request class is
* Gets a "parameter" value from any bag.
* This method is mainly useful for libraries that want to provide some flexibility. If you don't need the
* flexibility in controllers, it is better to explicitly get request parameters from the appropriate
* public property instead (attributes, query, request).
* Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY
My question is, is it going to be a good idea? because the most frequently used data is already attached in the middleware. So that I dont have to write extra codes in the controller methods again and again. Will it affect on performance for a high traffic server?

I personnally never work this way. You can access the current user from anywhere using the Auth facade as following :
\Auth::user()
It enable you to never send it when unnecessary and still use it from anywhere (controllers, models, blades or everything else).
Then to access your properties :
\Auth::user()->phone
and so on...

Related

Using a single policy method to cover every action on a resource

I have a resource named Post. Every Post is related to a single User, and a User may have several (or zero) Posts.
I'm using Route::resource to map routes for every possible action on the Post resource to a single resource controller, PostController.
Now, I wish to implement a policy for the Post resource. Aiming to keep everything as simple and fool-proof as possible, I'd like to make the policy as follows:
Every user is authorized to make any action that doesn't require an existing Post (e.g. create).
A User is only authorized to access its own Posts for every action that accesses a Post (e.g. edit, update, delete).
What I'm trying to do right now is to create a single policy method called access, which would check that the Post is owned by the User. Then, in my PostController, every method that has a Post object in its parameters (such as edit(Post $post)) would begin with
$this->authorize('access', $post);
However, I don't like that I need to put those lines manually. If I ever forget one of those, I'll have a security hole right there.
On the other hand, I have the authorizeResource method, which makes authorization automatic but requires the policy to have several methods so they are mapped to the each of the controller's methods. Also, I tried to use the Authorize/can middleware, but it didn't work (maybe because I used it on a Route::resource mapping).
The question is: What would be the cleanest and more secure way to achieve the result I described (i.e. authorizing every possible action that accesses a resource with the exact same rule)?
You can use authorizeResource() and override the resourceAbilityMap() method in your controller. The latter method returns a mapping from controller methods to the policy methods that will be called.
https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/Access/AuthorizesRequests.php#L105
E.g.
class MyController extends Controller
{
// ...
/**
* Get the map of resource methods to ability names.
*
* #return array
*/
protected function resourceAbilityMap()
{
return [
'edit' => 'access',
'update' => 'access',
'destroy' => 'access',
];
}
// ...
}

Passing Data between middlewares

I have created a couple middlewares, one per specific function, and I want the succeeding middlewares to make use of the data created from the previous middleware, instead of generating it from scratch. Is there a way to do that? I'm not sure if I should mess with $request or $next.
You can use Session::put('key',$value) method to store data in session and then get it from next middleware by using Session::get('key'), or you can pass that data in $request object, for example $request->addCustomField = 'custom field value' and then you can get it from next middleware by using $request->addCustomField.
Hope it will help
Use the merge function to add to the input:
return $next($request->merge(['my_data' => $data]));
It's then accessible as $request->input('my_data'), for example.
offsetUnset can be used to remove the data in the next middleware if need be.

Is it better to post json data or just key-value pairs in Laravel Apis?

i have developed the Api in Laravel now one of my team member saying that i will post the data in Json format during api call. now what should i do?
is it better to post data in Json format or just use key-value pairs?
please help
I would recommend using laravel resources
From docs:
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
If you want to return one object
Route::get('/user', function () {
return new UserResource(User::find(1));
});
If you want to return a collection
Route::get('/user', function () {
return UserResource::collection(User::all());
});
This way you can control what is being returned by the route and it will default to json
https://laravel.com/docs/5.6/eloquent-resources
"Better" is very subjective. Nothing fits EVERY use case (especially if dealing with legacy code), but generally data in an API is transferred using either JSON (in most REST API's) or XML (used in SOAP). Here are some things to consider though:
1) REST is agnostic in that it cares none about what format you use for your data, so there are apps that transmit data as csv, JSON, XML, or anything else you can imagine.
2) I believe the most common thing to see from a true headless API is JSON.
3) As someone mentioned before, JSON plays well with other languages that are often used to consume API's. Most of the time if I am consuming an API it is in Javascript, Java, or Python and all three are very "JSON friendly". This would be my preferred format for this reason.
4) Consider what will be consuming your API now, and in the future and build it to work best and "future proof" as much as possible.
5) Someone else will have to read your code later. Using a well defined, well documented format will be a lot easier than deciphering some method you have to parse data from strings or deal with arrays in some custom manner.Sticking with things like JSON that have become somewhat of a standard for REST will help with that.
6) Laravel response()->json() is available from your controller already. That plus JS's native JSON methods just seem like they were meant to go together.
That is just my view though.
Json is very easy to manipulate and is both accessible to php and JavaScript. Parsing your site's data to json opens a wide door of possibilities that will be otherwise dificult. if you are using laravel, you can use the json_encode and json_decode() functions to parse data to and fro or the JSON helper class

Adding attribute to a user when register in Laravel 5.1

When a user Register, I want to add location data for the user.
I get those with GeoIP.
So, each time a user is created, I would like somewhere to add Country, City, etc.
I was thinking about setting Hidden fields in view, but I think it a hugly way to do it, and I'm sure there is a better way to do...
Any Idea???
Any time I create a record that needs extra data, involves inserting additional records into additional tables, etc, I create a service class. Something like "UserCreator" then I pass it the input, do any additional operations, wrap multiple database calls in a transaction and so on.
That said there are so many ways to do what you want. You could Input::merge(...) then save, you could separate the process of creating a user from your controller / route function, etc.
If you are just getting started with Laravel and/or your project is rather simple, then you probably want to look at Input::merge
I solved it using Request Contructor as said here in laracast
In the Form Request's constructor I inject \Illuminate\Http\Request. I can then add my value to the request instance as such:
public function __construct(\Illuminate\Http\Request $request)
{
$request->request->add(['date_of_birth' => implode('-', $request->only('year', 'month', 'day'))]);
}

Magento - Separate contact forms

I'm working on a website where the client needs to have multiple separate contact forms (one for contact, one for "request a quote", another couple for stuff like that).
I've already managed to create another contact form with additional fields, but it was the contact one, so the fields were only name, email, subject and message.
Now I've got the "skeleton" of the others, but my question is: is there a way to take advantage of the "Contact" backend to send emails? Or do I need to have another controller to manage them?
If so, can you show me some links or piece of code to start off with?
Thanks in advance.
To do what you want, a custom controller is necessary to pass the POST data.
If you examine \app\code\core\Mage\Contacts\controllers\IndexController.php on line ~62 you'll find postAction() which is called by indexAction() - the default action of the controller.
This is the method that is collecting the passed POST parameters and using the core/email_template model to send off the e-mail. I'd use this code as a reference for your controller.
Be sure you put it all in your own module as always with functionality additions.
To know what you can and cannot pass to the core/email_template model, take a look at \app\code\core\Mage\Core\Model\Email\Template.php. It's got loads of documentation in there for you.
Heck, it's even got example code!
// Loading of template
$emailTemplate = Mage::getModel('core/email_template')
->load(Mage::getStoreConfig('path_to_email_template_id_config'));
$variables = array(
'someObject' => Mage::getSingleton('some_model')
'someString' => 'Some string value'
);
$emailTemplate->send('some#domain.com', 'Name Of User', $variables);
In particular take a look at line ~371, where it passes the variables you set to the layout-specified e-mail template.
/**
* Send mail to recipient
*
* #param array|string $email E-mail(s)
* #param array|string|null $name receiver name(s)
* #param array $variables template variables
* #return boolean
**/
public function send($email, $name = null, array $variables = array())
Magento is doing the same thing that you'd do with any contact form on a plain old PHP form processor. It just delegates everything out to models like the one above so you don't have to do so much work re-inventing the wheel, as it were. Just a new controller to accept the parameters in the POST data.
Feel free to follow up and I'll update the answer to help you where I can!
Here's a concise list of things you'll need to make this happen:
A custom controller to accept the form(s) POST data and pass it to the core/email_template model.
A custom form in the front-end pointing to your controller URL (already done!)
A custom e-mail template for the core/email_template to use to display the data in the e-mail the recipient sees.

Resources