Slim 3 direct access to a file - php

I want to make a route to directly access to a document.
For example, I want to access to domain/file/document.pdf but by domain/doc.
I tried this:
$app->get('/docs/v1', function ($request, $response){
$this->view->render( $response, '/docs/document.pdf');
});
But it doesn't work. I also saw this on the official doc:
$app = new \Slim\App();
$app->get('/hello', function ($req, $res) {
$this['view']->display('profile.html', [
'name' => 'Josh',
'url' => 'https://joshlockhart.com'
]);
});
But the display function does not exist.
Fatal error: Call to undefined method Slim\Views\PhpRenderer::display()
Maybe I missed something, I don't know, I didn't find anything else in the doc.
Thanks!

A few points here:
1) In Slim v3, "$this['view']" typically points to your Twig renderer. So you're trying to call a Twig renderer, which is probably not what you want to do in this case.
2) The correct syntax to invoke a Twig renderer and return it's output is
return $this->view->render ($response, 'yourTemplate.twig', [ ... array of parameters goes here ...]);
3) As for directly accessing a document (I've never done this before, so my answer might be wrong), you probably want to redirect to the document itself like this:
return $response->withRedirect ((string)($request->getUri()->withPath('path/to/document')));
and just let the browser deal with how to handle that document type.
Hope this helps.

Related

Laravel Exception handler logs also the request

I'm working on a Laravel 5.8 project, and I want to log inside the daily log file the request that has caused the exception, if some exception occurs.
I've tried this in the public function report(Exception $exception)
parent::render(request());
but it doesn't work at all. I've also tried this
\Log::error(json_encode(request()));
But it logs this
local.ERROR: {"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}
How should i do it? I need it in order to understand which request has caused that exception, and if it's possible, i need to log also other values, but i think that solved this, i can reuse the code to logs also the others
You can't just json_encode() the entire request as many properties are private/protected and require the use of getters for access. You will need to determine which values are important to you and build an appropriate response.
$response = [
'method' => request()->method(),
'url' => request()->url(),
'full_url' => request()->fullUrl(),
'data' => request()->all(),
];
Then you can pass your response array as a second parameter to the log handler, without needing to use json_encode().
\Log::error('Request details: ', $response);

How can multiple method calls be chained on slim's response object?

I want to chain multiple method calls on slims's $response object, but if i do i get an error ( status 500) and nothing happens.
This might aswell be a lack of basic PHP knowledge, i am not very experienced in PHP and it is my first time working with slim, or any serverside / API framework for that matter.
I have tried flipping arround the order of the calls, and doing them in different lines but to no awail. The long term goel of this, to build an API for an update application. So i will have to handle get requests with multiple parameters, evaluate them and depending on the results, do and return deffirent responses.
// this one fails, i set the status to 900 on purpose just to see what happens
$app->get('/', function (Request $request, Response $response, array $args) {
$response->getBody()->write("Slim main page")->withStatus(900);
return $response;
});
The first example does give me an 500 error on the network tab. This would suggest some type of syntax error i guess? If i alter this route a little bit to look like this :
# this one works fine, except the status code setting gets ignored, but why?
$app->get('/', function (Request $request, Response $response, array $args) {
$response->write("Slim main page")->withStatus(900);
return $response;
});
things alsmost work out, but the status code is not set for some reason.
I would expect the first one, to return the string "slim main page" with the status code 900. Even if i use a non made up status code, this setting gets ignored.
The second code block ist just an alteration for testing purposes.
I am pretty sure this a newby thing but i am really lost here, so any advice, or some fool proof articles / docs besides the slim docs are appreciated.
The write method returns the number of bytes written to the stream (and not the new response object). Try this:
$app->get('/', function (Request $request, Response $response, array $args = []) {
$response->getBody()->write('Slim main page');
$response = $response->withStatus(200);
return $response;
});
Notice 1: Enable the error details on dev: 'displayErrorDetails' => true
Notice 2: The HTTP code 900 is an invalid status code for Slim and will throw the following execption.
Type: InvalidArgumentException
Message: Invalid HTTP status code
File: vendor/slim/slim/Slim/Http/Response.php
Line: 228

Symfony 3 Ajax call routing issue

I'm setting up a simple Ajax call in one of my forms. When a user enters characters in a field, the following Ajax call is activated:
self.modify = function (input_field) {
if ($(input_field).val().length > 5) {
$.post("{{path('get_bio_control_sample')}}", {sample_number: $(input_field).val()},
function (response) {
if (response.code == 100 && response.success) {
alert(response.sample_number);
}
}, "json");
}
};
Which is meant to access the following controller action:
class BioControlController extends Controller {
/**
* #Route("/bio_control/sample", name="get_bio_control_sample")
*/
public function getBioControlSampleAction(Request $request){
$sample_number = $request->query->get('sample_number');
$response = array("code" => 100, "success" => true, "sample_number" => $sample_number, "sample_data" => "test");
return new JsonResponse($response);
}
}
However, when the call is activated JS returns the error:
http://127.0.0.1:8000/omics_experiment/%7B%7Bpath('get_bio_control_sample')%7D%7D 404 (Not Found)
I'm accessing the Ajax call from omics_experiment/new (which is in the OmicsExperimentController) and using the route /bio_control/sample (as shown by the annotation), but it's not working. Can someone explain what I'm doing wrong?
I used this question as a template, the fact I'm using Symfony 3 might mean there are syntactic errors.
I just had to do this recently. I'm no expert on Symfony either, but since I just did this I may be able to help. Using Symfony is not really much different than doing it with a static URL. The main thing is to make sure that your controller and route are set up properly and working without AJAX, then you just need to use the path set in your route for the .post call.
And what makes it worse, is that it's really hard to test this type of interaction. Even your twig includes can cause it to fail if they are set up wrong.
Looking at your code again I think this may be the problem. Change this
$.post("{{path('get_bio_control_sample')}}", {sample_number:
to this
$.post("/bio_control/sample", {sample_number:
Because I think the way you have it is only good for twig templates, so if Symfony is not looking at your JQuery file like it does a twig template, then, it's not going to understand how to get the route.

{"status":false,"error":"Unknown method"} error CodeIgniter RESTful API

<?php
include(APPPATH.'/libraries/REST_Controller.php');
class Quiz extends REST_Controller{
function __construct()
{
// Call the Model constructor
parent::__construct();
}
public function user_get()
{
$this->load->model('Quizmodel');
$data = $this->Quizmodel->getAll();
$this->response($data, 200);
}
function restclient()
{
$this->load->library('rest', array(
'server' => 'http://localhost/CodeIg/index.php/quiz/'
));
$userr = $this->rest->get('user','','json');
echo $userr;
}
}
?>
I am able to get JSON output if I type http://localhost/CodeIg/index.php/quiz/user in my browser, however if I type http://localhost/CodeIg/index.php/quiz/restclient it gives this error: {"status":false,"error":"Unknown method"}
I tried changing get to post but still the same error.
I referred this page https://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814 to do it.
You pinged me on GitHub, even though I haven't used or even thought about this code in at least 4 years.
https://github.com/chriskacerguis/codeigniter-restserver/blob/d19dc77f03521c7a725a4555407e1e4e7a85f6e1/application/libraries/REST_Controller.php#L680
This is where that error is being triggered. Throw a few breakpoints in there or var_dump()'s until you see what is causing the trouble.
You probably want to get off CodeIgniter though, and use something more actively maintained like SlimPHP or Lumen.
firstly I want as you have loaded rest api and created your controller quiz as an api to call , where you can only create your functions like user_get or restclient_get and access them the same manner you are doing.Just change you function name restclient to restclient_get then it will call instead it is even not running at this moment.

Silex FormServiceProvider and form.secret parameter

I am using the FormServiceProvider from Silex and reading through the documentation it explains how it has one parameter called form.secret which I assumed meant constructing the provider with this:
$app->register(new Silex\Provider\FormServiceProvider(), [
'form.secret' => 'SECRET HERE'
]);
The problem is however when I look through the source code for this file I cannot see a constructor where this parameter would get used. Only seeing it set internally within the container to md5(__DIR__).
https://github.com/silexphp/Silex/blob/master/src/Silex/Provider/FormServiceProvider.php#L48
Or would it be simply a case of not providing form.secret when constructing and simply setting $app['form.secret'] = 'SECRET HERE' after the provider has been registered?
Am I right in this assumption or I am I missing something?
You can see it being used in line 100, when $app["form.csrf_provider"] is first accessed:
$app['form.csrf_provider'] = function ($app) {
if (isset($app['session'])) {
return new SessionCsrfProvider($app['session'], $app['form.secret']);
}
return new DefaultCsrfProvider($app['form.secret']);
};
Since whatever you pass is ignored and overwritten with the md5 call you mention, correct usage would be:
$app->register(new FormServiceProvider());
$app["form.secret"] = "foo";

Categories