Doing a post request via url in Slim Framework - php

I'm trying to make a postrequest in slim, my intention is inserting data into a mysql database. It's the first time I try to do this, so sorry if I don't explain myself well.
Here's what I have:
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require 'vendor/autoload.php';
require "classes/Autoloader.php";
$app = new \Slim\App;
$app->post('/', function(Request $request, Response $response) use ($app) {
$postVars = $request->getParsedBody();
$id = $request->getAttribute('id');
$steps = $request->getAttribute('steps');
$date = $request->getAttribute('date');
echo $id . $steps . $date;
require_once "classes/Connection.php";
$userdata = new Insert($dbh, $id, $steps, $date);
$userdata->insert();
});
$app->run();
My intention is getting the values, and using them to insert the data, but I keep getting Slim's "Page Not Found" error. This is the url I'm trying with: http://localhost/wp-api/?id=1&steps=12&date=8787.
What am I doing wrong, or is this the correct way to do it?
Thanks in advance!
Edit: Following Justal's answer, I changed my code, on line 10; $app->post('/'... specifically. I now get Method not allowed. Must be one of: POST
Edit2: I changed line 12 (getQueryParams -> getParsedBody) , and used Postman, otherwise broswer does a getrequest (source of the previous error). It now inserts null values into the database, though.

page not found because you are requesting get on a post route.try below code.
All Data pass in the $request object.
$app->post('/', function(Request $request, Response $response) {
echo "<pre>";
print_r($request);
exit;
});

Related

does Slim framework have URL encoded annotation for POST method?

I'm developing a web RESTful API using slim framework of php.I want to know how do I add some annotation type thing on POST method so that it can behave as URL encoded method.Please help me in this regard.Advance thanks.
There is no pre-programmed way for this - there is no Slim or php method that will definitively check if your string is urlencoded. What you can do is implement Slim Middleware to your route.
<?php
$app = new \Slim\App();
$mw = function ($request, $response, $next) {
if ( urlencode(urldecode($data)) === $data){
$response = $next($request, $response);
} else {
$response = ... // throw error
}
return $response;
};
$app->get('/', function ($request, $response, $args) { // Your route
$response->getBody()->write(' Hello ');
return $response;
})->add($mw); // chained middleware
$app->run();
Discussion: Test if string is URL encoded in PHP
Middleware: https://www.slimframework.com/docs/v3/concepts/middleware.html
Since you're using Slim as the foundation to your API, the easiest way is to just build a GET route with the desired URL parameters defined:
$app->get('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
// Route actions here
});
In your documentation, make sure you inform the consumers of this API that it is a GET endpoint, so that a POST body should not be made; rather, the parameters that you outline in the URL should be used to pass the client's data over to the API.
If you are intent on using a POST route with just URL parameters, then you could also force a response back if the route detects an incoming POST body:
$app->post('/users/filter/{param1}/{param2}/{param3}', function (Request $request, Response $response) {
$postBody = $request->getParsedBody();
if (is_array($postBody)) {
$denyMsg = "This endpoint does not accept POST body as a means to transmit data; please refer to the API documentation for proper usage.";
$denyResponse = $response->withJson($denyMsg, $status = null, $encodingOptions = 0);
return $profileData;
}
});

laravel callback url with file_get_contents('php://input')

in vanilla php i would create a callbak url with just
try
{
//response content type application/json
header("Content-Type:application/json");
//read incoming request
$postData = file_get_contents('php://input');
.......
......
but in laravel i'm yet to get a clear explanation on how to achieve the same
ive tried using
$postData = Request::getContent();
but it returns blank
If you need data in request use (new \Illuminate\Http\Request())->all() or use DI
public function someAction(\Illuminate\Http\Request $request)
{
dd($request->all());
}

Guzzle: Access uploaded files in history middleware

I'm trying to access an uploaded file in the history middleware for Guzzle (v6).
My actual code receives a request (so is using the ServerRequestInterface), then uses Guzzle to send the request elsewhere.
I'm trying to test uploaded files going through this layer, but I can't seem to access them in the Request object returned by Guzzle's middleware.
Example code:
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\ServerRequest;
use GuzzleHttp\Psr7\UploadedFile;
class DoNotCommitTest extends \PHPUnit\Framework\TestCase
{
public function testUploads()
{
$request = new ServerRequest('GET', 'http://example.com/bla');
$file = new UploadedFile('test', 100, \UPLOAD_ERR_OK);
$request = $request->withUploadedFiles([$file]);
$this->assertCount(1, $request->getUploadedFiles());
// Mock Guzzle request, assert on the request it 'sent'
$mock = new MockHandler([
function (ServerRequest $request, array $options) {
// This fails...
$this->assertCount(1, $request->getUploadedFiles());
}
]);
$historyContainer = [];
$history = Middleware::history($historyContainer);
$handler = HandlerStack::create($mock);
$handler->push($history);
$client = new Client(['handler' => $handler]);
$client->send($request);
}
}
If you follow execution chain, $client->send($request) at some point calls private applyOptions function, which calls Psr7\modify_request function. If you look at Psr7\modify_request function:
...
if ($request instanceof ServerRequestInterface) {
return new ServerRequest(
isset($changes['method']) ? $changes['method'] : $request->getMethod(),
$uri,
$headers,
isset($changes['body']) ? $changes['body'] : $request->getBody(),
isset($changes['version'])
? $changes['version']
: $request->getProtocolVersion(),
$request->getServerParams()
);
}
...
It returns new ServerRequest object without preserving your uploaded files array (ServerRequest object doesn't have the uploadedFiles as an argument in the constructor). That's why you lost your uploadedFiles array.
UPDATE:
I created an issue and a pull request to fix it.

I can't receive POST data in php with slim framework

I try to make a RESTful api using slim framework.
I do not know details about the slim framework, because i'm beginner of this framework.
So, I followed all steps of how to get data in slimframework. But i can't get POST data.
Follow is my code to get POST data.
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
$app->post('/registration/user', function (Request $request, Response $response) use ($app) {
$data = $request->getParsedBody();
$name = $_POST['name'];
echo '1 : '.$data['name'];
echo '2 : '.$name;
});
That is result of when i send name data.
what i have to do for get post data??
Do you have any idea?
I use \Slim\Http\Request $request->getParsedBody() in my routes. The method contains all the $_POST data.
Example:
$postArr = $request->getParsedBody();
$name = $postArr["name"];
The following can be used:
$body= file_get_contents("php://input");
// $body = $request->getBody();
$data = json_decode($body, true);

How do I make an internal redirect in Silex / Symfony?

I have users getting auto-generated when they login via social media. I don't get their email so I want to make it that when they land on /whatever/page/after/login they see a screen that's like "Just enter email to continue on!"
I took a look at http://silex.sensiolabs.org/doc/cookbook/sub_requests.html and I'm either misreading or thinking I'd need to do it within a Silex\ControllerProviderInterface. I want this behavior to be for any request. Meanwhile if I make all my providers extend one, I'm not sure of the right way to cut out of a parent's connect without botching everything.
I also tried re-initializing everything similar to the answer here Unable to overwrite pathInfo in a Symfony 2 Request.
Here is the code I'm working with:
$app
->before(function (Request $request) use ($app) {
$token = $app['security']->getToken();
$app['user'] = null;
if ($token && !$app['security.trust_resolver']->isAnonymous($token)) {
$app['user'] = $token->getUser();
if (!$app['user']->isVerified()) {
$request->server->set('REQUEST_URI', '/signup');
$request->initialize($request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all(), $request->getContent());
}
}
});
I believe what you want to do is create a new Request object with the correct values and then tell that app to handle it.
If you don't care about preserving the request params from the original request then you can strip a lot of the extra stuff out.
$app
->before(function (Request $request) use ($app) {
$token = $app['security']->getToken();
$app['user'] = null;
if ($token && !$app['security.trust_resolver']->isAnonymous($token)) {
$app['user'] = $token->getUser();
if (!$app['user']->isVerified()) {
$subRequest = Request::create('/signup', 'GET', $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all(), $request->getContent());
$subRequest->request = $request->request;
$subRequest->query = $request->query;
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
}
});

Categories