Serving Static Files with Slim Application v3 Using Built In PHP Server - php

I'm starting a new project using Slim framework. So far it's going decently, everything I'm looking for in a micro framework. I have been away from the PHP world for a while so I am now getting to know the built in PHP web server. The only issue is this: How do I serve my static content?
For reference, here is my project layout:
project:
public folder
index.php
static/css/style.css
templates/index.html . # I'm using twig (coming from python Flask)
My template:
<html>
<link href="{{ base_url() }}/css/agency.css" rel="stylesheet">
<!-- other cool layout stuff -->
and my index.php (very minimal)
require 'vendor/autoload.php';
$app = new \Slim\App();
$app->get('/', function ($request, $response, $args) {
$response = $this->view->render($response, 'base.html');
return $response->write("Hello ");
});
$app->run();
When I start the built in php server from the command line, I do this:
php -S localhost:8080 -t public public/index.php
While this works great, when I try to access my static content, it just returns the rendered base.html file
Please let me know the best way to start this so static content is rendered correctly. Your help is appreciated.

So based on the documentation as pointed out by kuh-chan and Nima, I expanded it for both Slim purposes, as well as returning a 404 response if the file did not exist.
if (PHP_SAPI == 'cli-server') {
$url = parse_url($_SERVER['REQUEST_URI']);
$file = __DIR__ . $url['path'];
// check the file types, only serve standard files
if (preg_match('/\.(?:png|js|jpg|jpeg|gif|css)$/', $file)) {
// does the file exist? If so, return it
if (is_file($file))
return false;
// file does not exist. return a 404
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
printf('"%s" does not exist', $_SERVER['REQUEST_URI']);
return false;
}
}

Related

Slim Php not recognizing gets

I am just starting to work with Slim PHP. What could be the reason that get is not recognized on server?
This route works: it returns required text https://mywebsite/back/public
This route doesn't work (Not Found): https://mywebsite/back/public/countries
I have just installed slim framework and added new index.php file.
<?php
require '../vendor/autoload.php';
$app = new \Slim\App();
$app->get('/', function($request, $response, $arg) {
$response->write("This route works");
});
$app->get('/countries', function($request, $response, $arg) {
$response->write("This route doesnt");
});
$app->run();
?>
What version are you using? If you are using version 4, you need to set the basePath.
$app->setBasePath('/back/public');
Also enable mod_rewrite and configure your .htaccess file.
I recommend you check this project on github slimphp/Slim-Skeleton. This is a boilerplate code for Slim 4 applications.

Slim framework 3 path/route for images

I have the following structure:
index.php
/app
/images
I have routes setup for all the different pages and whatnot but when I try to access an image directly it tries to pick that route up as one of my dynamic routes.
So for context, I am converting this from a pre-existing app and to maintain the links/paths that it had, I have a completely dynamic route at the end of the index:
$app->get('/{page}', 'HomeController:processRequest');
$app->get('/{page}/{id}', 'ProductController:viewProduct');
$app->get('/{page}/{id}/{show}', 'ProductController:viewProduct');
So when I do the following in an image tag:
https://example.com/images/nav/tinycheck.png
That route kicks in and it fails. Is there any way to tell Slim to ignore anything with 'images' in the path and just serve up the image?
I have tried looking at a bunch of other threads on here but nothing is pointing me to the answer.
I seem to have resolved it with the following:
$app->get('/images/nav/{data}', function($request, $response, $args) {
$data = $args['data'];
$image = #file_get_contents("/mypath/images/nav/".$data);
if($image === FALSE) {
$handler = $this->notFoundHandler;
return $handler($request, $response);
}
$response->write($image);
return $response->withHeader('Content-Type', FILEINFO_MIME_TYPE);
});

PHP built-in server shows index page instead of static file

I created a project with Slim 3 and Twig using their simplest examples.
Folder structure is as follows:
- public
- index.php
- style.css
App code in index.php is as follows:
<?php
require 'vendor/autoload.php';
$app = new \Slim\App();
$container = $app->getContainer();
// Twig
$container['view'] = function ($container) {
$view = new \Slim\Views\Twig('src/views', [
'cache' => false // TODO
]);
// Instantiate and add Slim specific extension
$basePath = rtrim(str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()), '/');
$view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));
return $view;
};
$app->get('/', function ($request, $response, $args) {
return $this->view->render($response, 'index/index.html.twig');
})->setName('index');
$app->run();
Now, the problem is that trying to load /style.css shows the main page instead (index/index.html.twig). Why can I not access the style.css file?
The server I use it the PHP built-in development server, using the command:
php -S localhost:8000 -t public public/index.php
How can I load the assets? What's the issue here?
The cause was the PHP built-in development server being 'dumb'.
I had to include this check as the very first thing in the index.php file.
// To help the built-in PHP dev server, check if the request was actually for
// something which should probably be served as a static file
if (PHP_SAPI == 'cli-server') {
$url = parse_url($_SERVER['REQUEST_URI']);
$file = __DIR__ . $url['path'];
if (is_file($file)) return false;
}
Source: https://github.com/slimphp/Slim-Skeleton/blob/master/public/index.php
Another option I checked an works is run server inside public folder. You will not need that script:
cd public
php -S localhost:8000

PHP routing a page using the Slim Framework

I haven't found many questions and answers relating to this so far, so thought I would ask the question as it will greatly help me out as a beginner learning PHP and the Slim framework. It's pretty straightforward (i think).
So, I want to route my home page to another page called about.php. I'm using the Slim/Slim framework which is installed in my vendor folder. And I have an index.php file with the following code:
<?php
require '/vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/', function() use($app){
$app->render('about.php');
});
$app->run();
?>
I also have an about.php file, which does exist.
This is what's currently in my composer.json file:
"require": {
"monolog/monolog": "^1.22",
"slim/slim": "^3.7",
"twig/twig": "^1.32",
"slim/views": "^0.1.3"
}
When I run MAMP (set-up to access the project I am working on) to see the page, it's blank. Can anyone help me understand what I'm doing wrong?
I've then run this (removing the leading '/' from the require statement, and adding a line to display errors), and it displayed a 500 error:
<?php
ini_set('display_errors', 1);
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$view = $app->view();
$view->parserOptions = array(
'debug' => true
$app->get('/', function() use($app){
$app->render('about.php');
});
$app->run();
?>
I'm unclear if you want about.php to be separate from your Slim application or not.
i.e. when someone goes to http://example.com/ do you want the browser's URL to change to http://example.com/about.php where about.php is a completely independent PHP file in the same directory as your index.php?
If you do then you need to redirect:
$app->get('/', function ($request, $response) {
return $response->withRedirect('/about.php');
});
More usually, Slim is used to route to and display all pages in your application and in this situation, you wouldn't see the .php in the URL. This is because our app always runs index.php regardless of the actual URL in the the browser's address bar.
In this situation, you would probably still redirect, but without the .php:
$app->get('/', function ($request, $response) {
return $response->withRedirect('/about');
});
You would also need a handler for /about otherwise Slim won't know what to do:
$app->get('/about', function ($request, $response) {
return $response->write("This is my about page");
});
We don't actually tend to write the HTML directly in our handler though. We use a renderer. There's two in the Slim project: PhpView and TwigView. The Skeleton application shows how the PhpView version works. You may also find the tutorial in the documentation useful.
Finally, if you see a 500, then you have a PHP error somewhere. The easiest way to find this is to ensure that the php.ini setting error_reporting is set to E_ALL and that display_errors is set to On.
As you've already discovered, Slim 3's main class is called App. You can also enable detailed error displays within Slim using:
$app = new Slim\App(['settings' => ['displayErrorDetails' => true]]);
Again, usually we have a separate settings.php file containing this configuration information as shown in the skeleton application.

File extensions in Slim routes

Why does Slim 404 when I try to add an extension to the route?
<?php
require_once 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/test', function () {
echo 'route 1';
});
$app->get('/test.html', function () {
echo 'route 2';
});
$app->run();
http://localhost:8080/test works
http://localhost:8080/test.html throws a 404
I assume you are running the example using internal PHP webserver. Built-in server will consider request as a static file request if there is a dot in the SCRIPT_NAME. It is considered a feature and not a bug. See PHP bug #61286 for more info.
Your code should work fine with Apache or other webservers, assuming rewrite rules are set up correctly.

Categories