Slim PHP - Right way to use request and response objects - php

I'm new to Slim and PHP, but I'm trying to do a simple rest API with Slim. It's working, but I don't know if I'm doing it the right way and I cannot find another way to do it.
For example, I've a route like that:
$app->get('/contacts', '\Namespace\Class:method');
The method:
public function searchContacts($request, $response) {
return Contact::searchContacts($resquest, $response);
}
So, the unique way I found to access request and response from other classes is by passing the objects as params. Is it correct or is there a better (right) way to do it?

I think your way is not good.
Controller should process request and return response.
Your model(Contact) should'nt process requests. It should take needed params and return data.
Simple example:
public function searchContacts($request, $response)
{
// to example, you pass only name of contact
$results = Contact::searchContacts($request->get('contactName'));
$response->getBody()->write(json_encode($results));
return $response;
}
You don't need access to Request and Response objects from another classes. If it required, possible your architecture is wrong.
Good example from official site: http://www.slimframework.com/docs/tutorial/first-app.html#create-routes

the simplest way is to get the values from params and recieved the response in method.
$app->get('/contacts', function (Request $request, Response $response) {
$Contactname = $request->getAttribute('contact');
//You can put your search code here.
$response->getBody()->write("Contact name is, $name");
return $response;
});

Related

Laravel - How to set HTTP response status code from Controller

I'm new to laravel and am successfully directing users tothe appropriate views from a controller, but in some instances I want to set an http status code, but it is always returning a response code of 200 no matter what I send.
Here is the code for my test controller function:
public function index()
{
$data=array();
return response()->view('layouts.default', $data, 201);
}
If I use the same code within a route, it will return the correct http status code as I see when I call the page with curl -I from the command line.
curl -I http://localhost/
Is there a reason why it doesn't work within a controller, but does within a route call?
I'm sure there is something I'm just misunderstanding as a newbie, but even the following code works in a route but not a controller:
public function index()
{
abort(404);
}
What am I doing wrong?
Solution
You could use what is mentioned here. You will need to return a response like this one:
public function index()
{
$data = ['your', 'data'];
return response()->view('layouts.default', $data)->setStatusCode(404);
} // ^^^^^^^^^^^^^^^^^^^
Notice the setStatusCode($integer) method.
Alternative
You could set an additional header when returning the view to specify additional data, as the documentation states:
Attaching Headers To Responses
Keep in mind that most response methods
are chainable, allowing for the fluent construction of response
instances. For example, you may use the header method to add a series
of headers to the response before sending it back to the user:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');

Laravel - check request method

I'm an iOS lead on an app and trying to fix some API bugs whilst our dev is 'unavailable'. I'm almost completely new to Laravel and trying to check what the request method is. I have followed some guidance from another question but have been unable to get it working:
public function defaults(Request $request, User $user){
$follow_ids = explode(',', env('FOLLOW_DEFAULTS'));
if ($request->isMethod('post')) {
return ['user' => $user];
}
$user->follows()->syncWithoutDetaching($follow_ids);
return ['user.follows' => $user->follows->toArray()];
}
Do you know where I might be going wrong here? Thanks in advance.
When the request is returned it always just seems to skip over and return ['user.follows' => $user->follows->toArray()]
$request should be an instance of Illuminate\Http\Request. This class extends Symfony's request (Symfony\Component\HttpFoundation\Request), which is actually where the isMethod() method is defined.
Basically, given the function definition as posted, it reads "if this is a POST request, just return the user data. if this is not a POST request (e.g. GET), update and return the relationship data."
So, if you send a POST request, you'll get the ['user' => $user] response. If you send any other request method (e.g. GET), you'll modify the follows relationship and get the ['user.follows' => $user->follows->toArray()] response.
To me, this seems backwards. I would think you'd want the POST request to update the data, and any other request (e.g. GET) to just return data.
If this is correct, you need to negate your isMethod check:
if (! $request->isMethod('post')) {
return ['user' => $user];
}
More appropriately you should define separate controller actions to handle POST vs GET requests, but that is outside the scope of this question, and probably more than you want to get into as a temporary maintainer.
It seems that the request is not a POST so the if check is never true. You could echo the method name like this:
$method = $request->method();
echo $method;
// or var_dump($method);

Getting values sent using post method in controller in magento 2 api

I can not get values sent from post method, using http request.
I am getting values using get method, but I need to get it using post method.
I am not using any view, I want to call http url, and send some data in my controller using post method.
This is how my controller looks like,
namespace Spaarg\eMenuApi\Controller\Index;
class Products extends \Magento\Framework\App\Action\Action
{
public function __construct(\Magento\Framework\App\Action\Context $context)
{
return parent::__construct($context);
}
public function execute()
{
//$token = $this->getRequest()->getPostValue();
$token = $this->getRequest()->getPost();
}
}
I am new to magento 2, and I don't understand what is the problem.
It will be great if someone can help.
It probably has to do with the Content-type of the http request, where Magento only understands Json and Xml (this is explained here). If you're using a different Content-type in the request or your data doesn't match the type declared in the header, then getPost() will not work.
As a fallback, you can always get all the POST data by using the following way:
public function execute()
{
$postData = file_get_contents("php://input");
}
Keep in mind that this will get the raw string, so you will likely need to process it accordingly before using it (for example with json_decode() or something like that).
For more information about this, check this SO question.

how to use same route url for multiple action in slim framework

I am creating the API using slim framework. I faced the following problem.
I use one of the routes for given input.That is, json input: { "tagname": "tname"}. Route is
$app->post('/tag',function () use($app, $db){
//code
});
Now, I want to use the same route for another input.json: [{"tid": "1"},{"tid": "2"}]. Route is
$app->post('/tag',function () use($app, $db){
//code
});
How do solve it?
Slim's router can't call different functions for same path based on received content.
In your particular case the simplest way to deal with two different types of input data on one route would be something like this (I assume you are getting data as POST body with application/json which is not processed by Slim2)
$app->post('/tag',function () use($app, $db){
$payload = json_decode(file_get_contents('php://input'));
if(is_array($payload)) {
// code to deal with [{"tid": "1"},{"tid": "2"}]
} else {
// code to deal with { "tagname": "tname"}
}
});
But even easier and logically would be make /tag route for single and /tags for multiple. Or just require to send all tags as array - even single one.
you can pass extra parameter to perform another action in same route and separate your code with if condition

Capture all informations passed to a view in Laravel

I want to capture every information passed to view using the afterFilter. So I need to know:
all variables
session flash
the action executed (last action)
the view called
This is because I need to check if the request is json or not for change the response.
Currently I use afterFilter like this:
public function __construct()
{
// Here's something that happens after the request
$this->afterFilter(function() {
});
}
What I want is: use the afterFilter method in BaseController to capture all events/actions and then decide if the request is json or not.
If you need more information, comment please.
And sorry for my english
Do you need to know if JSON or if AJAX? If AJAX then just use:
if (Request::ajax())
{
//
}
You may use Request::wantsJson() to determine if the request is asking for json in return using:
// In app/filters.php
App::after(function($request, $response)
{
if($request->wantsJson()) {
//...
}
});
In this case, Laravel (through Base/Symfony class) checks if the Accept header is set and if that is application/json.

Categories