I encourage everyone to contribute to the Slim Framework project. You can find the latest code on GitHub at https://github.com/slimphp/Slim.
-
-
Issue Tracker
-
-
You can find outstanding issues on the GitHub Issue Tracker. If you intend to work on a specific issue, leave a comment on the appropriate thread to inform other project contributors.
-
-
Pull Requests
-
-
-
Each pull request should contain only one new feature or improvement.
-
Pull requests should be submitted to the master branch
There MUST NOT be a hard limit on line length; the soft limit MUST be 120 characters; lines SHOULD be 80 characters or less.
-
There MUST be one blank line after the namespace declaration, and there MUST be one blank line after the block of use declarations.
-
Opening braces for classes MUST go on the next line, and closing braces MUST go on the next line after the body.
-
Opening braces for methods MUST go on the next line, and closing braces MUST go on the next line after the body.
-
Visibility MUST be declared on all properties and methods; abstract and final MUST be declared before the visibility; static MUST be declared after the visibility.
-
Control structure keywords MUST have one space after them; method and function calls MUST NOT.
-
Opening braces for control structures MUST go on the same line, and closing braces MUST go on the next line after the body.
-
Opening parentheses for control structures MUST NOT have a space after them, and closing parentheses for control structures MUST NOT have a space before.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/contributors/guidelines.html/index.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/contributors/guidelines.html/index.html
deleted file mode 100644
index 602a140..0000000
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/contributors/guidelines.html/index.html
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
- Page not found · GitHub Pages
-
-
-
-
-
-
-
404
-
File not found
-
-
- The site configured at this address does not
- contain the requested file.
-
-
-
- If this is your site, make sure that the filename case matches the URL.
- For root URLs (like http://example.com/) you must provide an
- index.html file.
-
You don’t always need a kitchen-sink solution like Symfony or Laravel.
These are great tools, for sure. But they are often overkill. Instead, Slim
provides only a minimal set of tools that do what you need and nothing else.
How does it work?
-
First, you need a web server like Nginx or Apache. You should configure
+
-
-Figure 1: Example Slim application
+$app->run();
+
+ Figure 1: Example Slim application
Request and response
@@ -106,7 +108,7 @@
PSR 7 interfaces. The Slim app route can inspect
+to its callback routine. These objects implement the popular PSR 7 interfaces. The Slim app route can inspect
or manipulate these objects as necessary. Ultimately, each Slim app route
MUST return a PSR 7 Response object.
The Slim Framework’s router is built on top of the nikic/fastroute component, and it is remarkably fast and stable.
-
-
How to create routes
-
-
You can define application routes using proxy methods on the \Slim\App instance. The Slim Framework provides methods for the most popular HTTP methods.
-
-
GET Route
-
-
You can add a route that handles only GET HTTP requests with the Slim
-application’s get() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
POST Route
-
-
You can add a route that handles only POST HTTP requests with the Slim
-application’s post() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
PUT Route
-
-
You can add a route that handles only PUT HTTP requests with the Slim
-application’s put() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
DELETE Route
-
-
You can add a route that handles only DELETE HTTP requests with the Slim
-application’s delete() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
OPTIONS Route
-
-
You can add a route that handles only OPTIONS HTTP requests with the Slim
-application’s options() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
PATCH Route
-
-
You can add a route that handles only PATCH HTTP requests with the Slim
-application’s patch() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
Any Route
-
-
You can add a route that handles all HTTP request methods with the Slim application’s any() method. It accepts two arguments:
-
-
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
Note that the second parameter is a callback. You could specify a Class (which need a __invoke() implementation) instead of a Closure. You can then do the mapping somewhere else:
-
-
-
-
Custom Route
-
-
You can add a route that handles multiple HTTP request methods with the Slim application’s map() method. It accepts three arguments:
-
-
-
Array of HTTP methods
-
The route pattern (with optional named placeholders)
-
The route callback
-
-
-
-
-
Route callbacks
-
-
Each routing method described above accepts a callback routine as its final argument. This argument can be any PHP callable, and by default it accepts three arguments.
-
-
-
Request
-
The first argument is a Psr\Http\Message\ServerRequestInterface object that represents the current HTTP request.
-
Response
-
The second argument is a Psr\Http\Message\ResponseInterface object that represents the current HTTP response.
-
Arguments
-
The third argument is an associative array that contains values for the current route’s named placeholders.
-
-
-
Writing content to the response
-
-
There are two ways you can write content to the HTTP response. First, you can simply echo() content from the route callback. This content will be appended to the current HTTP response object. Second, you can return a Psr\Http\Message\ResponseInterface object.
-
-
Closure binding
-
-
If you use a Closure instance as the route callback, the closure’s state is bound to the Container instance. This means you will have access to the DI container instance inside of the Closure via the $this keyword:
-
-
-
-
Route strategies
-
-
The route callback signature is determined by a route strategy. By default, Slim expects route callbacks to accept the request, response, and an array of route placeholder arguments. This is called the RequestResponse strategy. However, you can change the expected route callback signature by simply using a different strategy. As an example, Slim provides an alternative strategy called RequestResponseArgs that accepts request and response, plus each route placeholder as a separate argument. Here is an example of using this alternative strategy; simply replace the foundHandler dependency provided by the default \Slim\Container:
-
-
-
-
You can provide your own route strategy by implementing the \Slim\Interfaces\InvocationStrategyInterface.
-
-
Route placeholders
-
-
Each routing method described above accepts a URL pattern that is matched against the current HTTP request URI. Route patterns may use named placeholders to dynamically match HTTP request URI segments.
-
-
Format
-
-
A route pattern placeholder starts with a {, followed by the placeholder name, ending with a }. This is an example placeholder named name:
-
-
-
-
Optional segments
-
-
To make a section optional, simply wrap in square brackets:
-
-
-
-
Multiple optional parameters are supported by nesting:
-
-
-
-
For “Unlimited” optional parameters, you can do this:
-
-
-
-
In this example, a URI of /news/2016/03/20 would result in the $params array
-containing three elements: ['2016', '03', '20'].
-
-
Regular expression matching
-
-
By default the placeholders are written inside {} and can accept any
-values. However, placeholders can also require the HTTP request URI to match a particular regular expression. If the current HTTP request URI does not match a placeholder regular expression, the route is not invoked. This is an example placeholder named id that requires one or more digits.
-
-
-
-
Route names
-
-
Application routes can be assigned a name. This is useful if you want to programmatically generate a URL to a specific route with the router’s pathFor() method. Each routing method described above returns a \Slim\Route object, and this object exposes a setName() method.
-
-
-
-
You can generate a URL for this named route with the application router’s pathFor() method.
-
-
-
-
The router’s pathFor() method accepts two arguments:
-
-
-
The route name
-
Associative array of route pattern placeholders and replacement values
-
-
-
Route groups
-
-
To help organize routes into logical groups, the \Slim\App also provides a group() method. Each group’s route pattern is prepended to the routes or groups contained within it, and any placeholder arguments in the group pattern are ultimately made available to the nested routes:
-
-
-
-
Note inside the group closure, $this is used instead of $app. Slim binds the closure to the application instance for you, just like it is the case with route callback binds with container instance.
-
-
-
inside group closure, $this is bound to the instance of Slim\App
-
inside route closure, $this is bound to the instance of Slim\Container
-
-
-
Route middleware
-
-
You can also attach middleware to any route or route group. Learn more.
-
-
Router caching
-
-
It’s possible to enable router cache by setting valid filename in default Slim settings. Learn more.
-
-
Container Resolution
-
-
You are not limited to defining a function for your routes. In Slim there are a few different ways to define your route action functions.
-
-
In addition to a function, you may use:
- - An invokable class
- - Class:method
-
-
This function is enabled by Slim’s Callable Resolver Class. It translates a string entry into a function call.
-Example:
-
-
-
-
In this code above we are defining a /home route and telling Slim to execute the home() method on the \HomeController class.
-
-
Slim first looks for an entry of \HomeController in the container, if it’s found it will use that instance otherwise it will call it’s constructor with the container as the first argument. Once an instance of the class is created it will then call the specified method using whatever Strategy you have defined.
-
-
Alternatively, you can use an invokable class, such as:
-
-
-
-
You can use this class like so.
-
-
-
-
In a more traditional MVC approach you can construct controllers with many actions instead of an invokable class which only handles one action.
If you are upgrading from version 2 to version 3, these are the significant changes that
-you need to be aware of.
-
-
New PHP version
-
Slim 3 requires PHP 5.5+
-
-
New Route Function Signature
-
-
-
-
Getting _GET and _POST variables
-
-
-
-
Hooks
-
Hooks are no longer part of Slim as of v3. You should consider reimplementing any functionality associated with the default hooks in Slim v2 as middleware instead. If you need the ability to apply custom hooks at arbitrary points in your code (for example, within a route), you should consider a third-party package such as Symfony’s EventDispatcher or Zend Framework’s EventManager.
-
-
Removal HTTP Cache
-
In Slim v3 we have removed the HTTP-Caching into its own module Slim\Http\Cache.
-
-
Removal of Stop/Halt
-
Slim Core has removed Stop/Halt.
-In your applications, you should transition to using the withStatus() and withBody() methods.
-
-
Changed Redirect
-
In Slim v2.x one would use the helper function $app->redirect(); to trigger a redirect request.
-In Slim v3.x one can do the same with using the Response class like so.
-
-
Example:
-
-
-
-
Middleware Signature
-
The middleware signature has changed from a class to a function.
-
-
New signature:
-
-
-
-
You can still use a class:
-
-
-
-
Middleware Execution
-
Application middleware is executed as Last In First Executed (LIFE).
-
-
Flash Messages
-
Flash messages are no longer a part of the Slim v3 core but instead have been moved to seperate Slim Flash package.
-
-
Cookies
-
In v3.0 cookies has been removed from core. See FIG Cookies for a PSR-7 compatible cookie component.
-
-
Removal of Crypto
-
In v3.0 we have removed the dependency for crypto in core.
-
-
New Router
-
Slim now utilizes FastRoute, a new, more powerful router!
-
-
This means that the specification of route patterns has changed with named parameters now in braces and square brackets used for optional segments:
-
-
-
-
Route Middleware
-
The syntax for adding route middleware has changed slightly.
-In v3.0:
-
-
-
-
Getting the current route
-
The route is an attribute of the Request object in v3.0:
-
-
-
-
When getting the current route in middleware, the value for
-determineRouteBeforeAppMiddleware must be set to true in the Application
-configuration, otherwise the getAttribute call returns null.
-
-
urlFor() is now pathFor() in the router
-
-
urlFor() has been renamed pathFor() and can be found in the router object:
-
-
-
-
Also, pathFor() is base path aware.
-
-
Container and DI … Constructing
-
Slim uses Pimple as a Dependency Injection Container.
-
-
-
-
PSR-7 Objects
-
-
Request, Response, Uri & UploadFile are immutable.
-
This means that when you change one of these objects, the old instance is not updated.
-
-
-
-
Message bodies are streams
-
-
-
-
For text:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/concepts/di.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/concepts/di.html
similarity index 70%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/concepts/di.html
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/concepts/di.html
index 5169ba6..4e20bea 100644
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/concepts/di.html
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/concepts/di.html
@@ -1,5 +1,5 @@
-
+
@@ -13,9 +13,9 @@
-
-
-
+
+
+
@@ -33,10 +33,11 @@
Slim uses a dependency container to prepare, manage, and inject application
-dependencies. Slim supports containers that implement the Container-Interop interface. You can use Slim’s built-in container (based on Pimple)
+dependencies. Slim supports containers that implement PSR-11 or the Container-Interop interface. You can use Slim’s built-in container (based on Pimple)
or third-party containers like Acclimate
or PHP-DI.
You can run code before and after your Slim application to manipulate the
Request and Response objects as you see fit. This is called middleware.
@@ -87,7 +88,7 @@
To use this class as a middleware, you can use ->add( new ExampleMiddleware() ); function chain after the $app, Route, or group(), which in the code below, any one of these, could represent $subject.
Route middleware is invoked only if its route matches the current HTTP request method and URI. Route middleware is specified immediately after you invoke any of the Slim application’s routing methods (e.g., get() or post()). Each routing method returns an instance of \Slim\Route, and this class provides the same middleware interface as the Slim application instance. Add middleware to a Route with the Route instance’s add() method. This example adds the Closure middleware example above:
In addition to the overall application, and standard routes being able to accept middleware, the group() multi-route definition functionality, also allows individual routes internally. Route group middleware is invoked only if its route matches one of the defined HTTP request methods and URIs from the group. To add middleware within the callback, and entire-group middleware to be set by chaining add() after the group() method.
Sample Application, making use of callback middleware on a group of url-handlers
I encourage everyone to contribute to the Slim Framework project. You can find the latest code on GitHub at https://github.com/slimphp/Slim.
-
A good flowchart for implementing CORS support Reference: http://www.html5rocks.com/static/images/cors_server_flowchart.png
+
Issue Tracker
-
You can test your CORS Support here: http://www.test-cors.org/
+
You can find outstanding issues on the GitHub Issue Tracker. If you intend to work on a specific issue, leave a comment on the appropriate thread to inform other project contributors.
-
You can read the specification here: https://www.w3.org/TR/cors/
+
Pull Requests
-
The simple solution
+
+
Each pull request should contain only one new feature or improvement.
+
Pull requests should be submitted to the master branch
+
-
For simple CORS requests, the server only needs to add the following header to its response:
There MUST NOT be a hard limit on line length; the soft limit MUST be 120 characters; lines SHOULD be 80 characters or less.
+
There MUST be one blank line after the namespace declaration, and there MUST be one blank line after the block of use declarations.
+
Opening braces for classes MUST go on the next line, and closing braces MUST go on the next line after the body.
+
Opening braces for methods MUST go on the next line, and closing braces MUST go on the next line after the body.
+
Visibility MUST be declared on all properties and methods; abstract and final MUST be declared before the visibility; static MUST be declared after the visibility.
+
Control structure keywords MUST have one space after them; method and function calls MUST NOT.
+
Opening braces for control structures MUST go on the same line, and closing braces MUST go on the next line after the body.
+
Opening parentheses for control structures MUST NOT have a space after them, and closing parentheses for control structures MUST NOT have a space before.
The Slim Framework uses a simple branching strategy. There is a 3.x branch, and the 3.x branch HEAD reference points to the latest unstable code. Each stable release is denoted with a numeric tag (e.g., 3.0.0).
In this post, I’ll show how to refactor the Slim tutorial application to more closely follow the Action-Domain-Responder pattern.
+
+
One nice thing about Slim (and most other HTTP user interface frameworks) is that they are already “action” oriented. That is, their routers do not presume a controller class with many action methods. Instead, they presume an action closure or a single-action invokable class.
+
+
So the Action part of Action-Domain-Responder already exists for Slim. All that is needed is to pull extraneous bits out of the Actions, to more clearly separate the Action behaviors from Domain and the Responder behaviors.
+
+
Extract Domain
+
+
Let’s begin by extracting the Domain logic. In the original tutorial, the Actions use two data-source mappers directly, and embed some business logic as well. We can create a Service Layer class called TicketService and move those operations from the Actions into the Domain. Doing so gives us this class:
One benefit here is that we can now test the domain activities separately from the actions. We can begin to do something more like integration testing, even unit testing, instead of end-to-end system testing.
+
+
Extract Responder
+
+
In the case of the tutorial application, the presentation work is so straightforward as to not require a separate Responder for each action. A relaxed variation of a Responder layer is perfectly suitable in this simple case, one where each Action uses a different method on a common Responder.
+
+
Extracting the presentation work to a separate Responder, so that response-building is completely removed from the Action, looks like this:
Now we can test the response-building work separately from the domain work.
+
+
Some notes:
+
+
Putting all the response-building in a single class with multiple methods, especially for simple cases like this tutorial, is fine to start with. For ADR, is not strictly necessary to have one Responder for each Action. What is necessary is to extract the response-building concerns out of the Action.
+
+
But as the presentation logic complexity increases (content-type negotiation? status headers? etc.), and as dependencies become different for each kind of response being built, you will want to have a Responder for each Action.
+
+
Alternatively, you might stick with a single Responder, but reduce its interface to a single method. In that case, you may find that using a Domain Payload (instead of “naked” domain results) has some significant benefits.
+
+
Conclusion
+
+
At this point, the Slim tutorial application has been converted to ADR. We have separated the domain logic to a TicketService, and the presentation logic to a TicketResponder. And it’s easy to see how each Action does pretty much the same thing:
+
+
+
Marshals input and passes it into the Domain
+
Gets back a result from the Domain and passes it to the Responder
+
Invokes the Responder so it can build and return the Response
+
+
+
Now, for a simple case like this, using ADR (or even webbishy MVC) might seem like overkill. But simple cases become complex quickly, and this simple case shows how the ADR separation-of-concerns can be applied as a Slim-based application increases in complexity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/database-atlas.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/database-atlas.html
new file mode 100644
index 0000000..0b7be00
--- /dev/null
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/database-atlas.html
@@ -0,0 +1,774 @@
+
+
+
+
+
+
+ Using Atlas 3 with Slim - Slim Framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This cookbook entry describes how to use the Atlas 3 ORM
+and its command-line tooling with Slim.
+
+
Installation
+
+
Install Atlas using Composer. The ORM and CLI packages are delivered separately,
+since you are likely to need the command line tooling only in development:
Now you need to add some database connection settings to your configuration.
+You can add them under any array key you like; the following example uses
+['settings']['atlas']:
The pdo elements are used as arguments for your
+PDO connection.
+
+
The namespace and directory elements specify the namespace for your Atlas
+data source classes, and the directory where they will be saved by the skeleton
+generator. Your composer.json will need have a PSR autoloader entry for these;
+the above example corresponds to the Slim
+tutorial application.
+
+
Generating Skeleton Classes
+
+
Now you can generate your skeleton data source classes with the Atlas CLI
+tooling. First, create the target directory, then issue the skeleton command:
The first argument to atlas-skeleton is the path to your Slim config file. The
+second argument is a dot-separated list of the keys leading to the Atlas array
+within the settings.
+
+
With that command, Atlas will examine your database and generate a series of
+classes and traits for each table in the schema. You can see the files generated
+for each table here.
+
+
Container Service Definition
+
+
With the data mapper classes in place, you can now add the Atlas ORM as a
+service in the Slim container:
This uses the AtlasBuilder class to create and return a new ORM instance, with
+the PDO connection arguments from your settings configuration.
+
+
+
Note:
+
+
This service definition tells Atlas to use the Container itself as a factory
+for certain class constructions. If you have Atlas TableEvent or MapperEvent
+classes defined as services in the Container, Atlas will use the Container
+to build them for you.
+
+
+
Using the ORM
+
+
At this point, you can use the full power of the Atlas ORM in your action code.
+The following examples are adapted from the
+tutorial application:
This cookbook entry describes how to integrate from scratch the widely used Doctrine ORM into a Slim application.
+
+
Adding Doctrine to your application
+
+
The first step is importing the library into the vendor directory of your project using composer.
+
+
+
composer require doctrine/orm:^2
+
+ Figure 1: Require doctrine in your application.
+
+
+
Provide database credentials
+
+
Next, add the Doctrine settings alongside your Slim configuration.
+
+
+
<?php
+
+// settings.php
+
+define('APP_ROOT',__DIR__);
+
+return[
+ 'settings'=>[
+ 'displayErrorDetails'=>true,
+ 'determineRouteBeforeAppMiddleware'=>false,
+
+ 'doctrine'=>[
+ // if true, metadata caching is forcefully disabled
+'dev_mode'=>true,
+
+ // path where the compiled metadata info will be cached
+// make sure the path exists and it is writable
+'cache_dir'=>APP_ROOT.'/var/doctrine',
+
+ // you should add any other path containing annotated entity classes
+'metadata_dirs'=>[APP_ROOT.'/src/Domain'],
+
+ 'connection'=>[
+ 'driver'=>'pdo_mysql',
+ 'host'=>'localhost',
+ 'port'=>3306,
+ 'dbname'=>'mydb',
+ 'user'=>'user',
+ 'password'=>'secret',
+ 'charset'=>'utf-8'
+ ]
+ ]
+ ]
+];
+
+ Figure 2: Slim settings array.
+
+
+
Define the EntityManager service
+
+
Now we define the EntityManager service, which is the primary way to interact with Doctrine.
+Here we show how to configure the metadata reader to work with PHP annotations, which is at the
+same time the most used mode and the most tricky to set up. Alternatively, XML or YAML can also
+be used to describe the database schema.
+ Figure 3: Defining the EntityManager service.
+
+
+
Create the Doctrine console
+
+
To run database migrations, validate class annotations and so on you will use the doctrine CLI application that is
+already present at vendor/bin. But in order to work, this script needs a cli-config.php
+file at the root of the project telling it how to find the EntityManager we just set up:
Take a moment to verify that the console app works. When properly configured, its output will look more or less like this:
+
+
+
$ php vendor/bin/doctrine
+Doctrine Command Line Interface 2.5.12
+
+Usage:
+ command[options] [arguments]
+
+Options:
+ -h, --help Display this help message
+ -q, --quiet Do not output any message
+ -V, --version Display this application version
+ --ansi Force ANSI output
+ --no-ansi Disable ANSI output
+ -n, --no-interaction Do not ask any interactive question
+ -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
+
+Available commands:
+ help Displays help for a command
+ list Lists commands
+ dbal
+ dbal:import Import SQL file(s) directly to Database.
+ dbal:run-sql Executes arbitrary SQL directly from the command line.
+ orm
+ orm:clear-cache:metadata Clear all metadata cache of the various cache drivers.
+ orm:clear-cache:query Clear all query cache of the various cache drivers.
+ orm:clear-cache:result Clear all result cache of the various cache drivers.
+ orm:convert-d1-schema [orm:convert:d1-schema] Converts Doctrine 1.X schema into a Doctrine 2.X schema.
+ orm:convert-mapping [orm:convert:mapping] Convert mapping information between supported formats.
+ orm:ensure-production-settings Verify that Doctrine is properly configured for a production environment.
+ orm:generate-entities [orm:generate:entities] Generate entity classes and method stubs from your mapping information.
+ orm:generate-proxies [orm:generate:proxies] Generates proxy classes for entity classes.
+ orm:generate-repositories [orm:generate:repositories] Generate repository classes from your mapping information.
+ orm:info Show basic information about all mapped entities
+ orm:mapping:describe Display information about mapped objects
+ orm:run-dql Executes arbitrary DQL directly from the command line.
+ orm:schema-tool:create Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.
+ orm:schema-tool:drop Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output.
+ orm:schema-tool:update Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata.
+ orm:validate-schema Validate the mapping files.
+
// Catch-all route to serve a 404 Not Found page if none of the routes match
+// NOTE: make sure this route is defined last
+$app->map(['GET','POST','PUT','DELETE','PATCH'],'/{routes:.+}',function($req,$res){
+ $handler=$this->notFoundHandler;// handle using the default Slim page not found handler
+return$handler($req,$res);
+});
+
+
+
Access-Control-Allow-Methods
+
+
The following middleware can be used to query Slim’s router and get a list of methods a particular pattern implements.
+
+
Here is a complete example application:
+
+
require__DIR__."/vendor/autoload.php";
+
+// This Slim setting is required for the middleware to work
+$app=newSlim\App([
+ "settings"=>[
+ "determineRouteBeforeAppMiddleware"=>true,
+ ]
+]);
+
+// This is the middleware
+// It will add the Access-Control-Allow-Methods header to every request
+
+$app->add(function($request,$response,$next){
+ $route=$request->getAttribute("route");
+
+ $methods=[];
+
+ if(!empty($route)){
+ $pattern=$route->getPattern();
+
+ foreach($this->router->getRoutes()as$route){
+ if($pattern===$route->getPattern()){
+ $methods=array_merge_recursive($methods,$route->getMethods());
+ }
+ }
+ //Methods holds all of the HTTP Verbs that a particular route handles.
+}else{
+ $methods[]=$request->getMethod();
+ }
+
+ $response=$next($request,$response);
+
+
+ return$response->withHeader("Access-Control-Allow-Methods",implode(",",$methods));
+});
+
+$app->get("/api/{id}",function($request,$response,$arguments){
+});
+
+$app->post("/api/{id}",function($request,$response,$arguments){
+});
+
+$app->map(["DELETE","PATCH"],"/api/{id}",function($request,$response,$arguments){
+});
+
+// Pay attention to this when you are using some javascript front-end framework and you are using groups in slim php
+$app->group('/api',function(){
+ // Due to the behaviour of browsers when sending PUT or DELETE request, you must add the OPTIONS method. Read about preflight.
+$this->map(['PUT','OPTIONS'],'/{user_id:[0-9]+}',function($request,$response,$arguments){
+ // Your code here...
+});
+});
+
+$app->run();
+
+
+
A big thank you to tuupola for coming up with this!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/cookbook/environment.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/environment.html
similarity index 72%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/cookbook/environment.html
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/environment.html
index f88fe7f..51d8204 100644
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/cookbook/environment.html
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/cookbook/environment.html
@@ -1,5 +1,5 @@
-
+
@@ -13,9 +13,9 @@
-
-
-
+
+
+
@@ -33,11 +33,14 @@
The Environment object encapsulates the $_SERVER superglobal array and decouples the Slim application from the PHP global environment. Decoupling the Slim application from the PHP global environment lets us create HTTP requests that may (or may not) resemble the global environment. This is particuarly useful for unit testing and initiating sub-requests. You can fetch the current Environment object anywhere in your Slim application like this:
+
The Environment object encapsulates the $_SERVER superglobal array and decouples the Slim application from the PHP global environment. Decoupling the Slim application from the PHP global environment lets us create HTTP requests that may (or may not) resemble the global environment. This is particularly useful for unit testing and initiating sub-requests. You can fetch the current Environment object anywhere in your Slim application like this:
Each Slim application instantiates an Environment object using information from the current global environment. However, you may also create mock environment objects with custom information. Mock Environment objects are only useful when writing unit tests.
If you ever need to get access to the current route within your application all you have to do is call the request class’ getAttribute method with an argument of 'route' and it will return the current route, which is an instance of the Slim\Route class.
From there you can get the route’s name by using getName() or get the methods supported by this route via getMethods(), etc.
-
Note: If you need to access the route from within your app middleware you must set 'determineRouteBeforeAppMiddleware' to true in your configuration otherwise getAttribute('route') will return null. The route is always available in route middleware.
+
Note: If you need to access the route from within your app middleware you must set 'determineRouteBeforeAppMiddleware' to true in your configuration otherwise getAttribute('route') will return null. Also getAttribute('route') will return null on non existent routes.
Example:
-
-
use Slim\Http\Request;
-use Slim\Http\Response;
-use Slim\App;
-
-$app = new App([
- 'settings' => [
- // Only set this if you need access to route within middleware
- 'determineRouteBeforeAppMiddleware' => true
- ]
-])
-
-// routes...
-$app->add(function (Request $request, Response $response, callable $next) {
- $route = $request->getAttribute('route');
- $name = $route->getName();
- $groups = $route->getGroups();
- $methods = $route->getMethods();
- $arguments = $route->getArguments();
-
- // do something with that information
-
- return $next($request, $response);
-});
-
+
useSlim\App;
+useSlim\Exception\NotFoundException;
+useSlim\Http\Request;
+useSlim\Http\Response;
+
+$app=newApp([
+ 'settings'=>[
+ // Only set this if you need access to route within middleware
+'determineRouteBeforeAppMiddleware'=>true
+ ]
+]);
+
+// routes...
+$app->add(function(Request$request,Response$response,callable$next){
+ $route=$request->getAttribute('route');
+
+ // return NotFound for non existent route
+if(empty($route)){
+ thrownewNotFoundException($request,$response);
+ }
+
+ $name=$route->getName();
+ $groups=$route->getGroups();
+ $methods=$route->getMethods();
+ $arguments=$route->getArguments();
+
+ // do something with that information
+
+ return$next($request,$response);
+});
+
Slim treats a URL pattern with a trailing slash as different to one without. That is, /user and /user/ are different and so can have different callbacks attached.
-
If you want to redirect all URLs that end in a / to the non-trailing / equivalent, then you can add this middleware:
+
For GET requests a permanent redirect is fine, but for other request methods like POST or PUT the browser will send the second request with the GET method. To avoid this you simply need to remove the trailing slash and pass the manipulated url to the next middleware.
-
use Psr\Http\Message\RequestInterface as Request;
-use Psr\Http\Message\ResponseInterface as Response;
+
If you want to redirect/rewrite all URLs that end in a / to the non-trailing / equivalent, then you can add this middleware:
Files that are uploaded using forms in POST requests can be retrieved with the
+getUploadedFiles method of the
+Request object.
+
+
When uploading files using a POST request, make sure your file upload form has the
+attribute enctype="multipart/form-data" otherwise getUploadedFiles() will return an empty array.
+
+
If multiple files are uploaded for the same input name, add brackets after the input name in the HTML, otherwise
+only one uploaded file will be returned for the input name by getUploadedFiles().
+
+
Below is an example HTML form that contains both single and multiple file uploads.
+
+
+
<!-- make sure the attribute enctype is set to multipart/form-data -->
+<formmethod="post"enctype="multipart/form-data">
+ <!-- upload of a single file -->
+ <p>
+ <label>Add file (single): </label><br/>
+ <inputtype="file"name="example1"/>
+ </p>
+
+ <!-- multiple input fields for the same input name, use brackets -->
+ <p>
+ <label>Add files (up to 2): </label><br/>
+ <inputtype="file"name="example2[]"/><br/>
+ <inputtype="file"name="example2[]"/>
+ </p>
+
+ <!-- one file input field that allows multiple files to be uploaded, use brackets -->
+ <p>
+ <label>Add files (multiple): </label><br/>
+ <inputtype="file"name="example3[]"multiple="multiple"/>
+ </p>
+
+ <p>
+ <inputtype="submit"/>
+ </p>
+</form>
+
+ Figure 1: Example HTML form for file uploads
+
+
+
Uploaded files can be moved to a directory using the moveTo method. Below is an example application
+that handles the uploaded files of the HTML form above.
+
+
+
<?php
+
+require_once__DIR__.'/vendor/autoload.php';
+
+useSlim\Http\Request;
+useSlim\Http\Response;
+useSlim\Http\UploadedFile;
+
+$app=new\Slim\App();
+
+$container=$app->getContainer();
+$container['upload_directory']=__DIR__.'/uploads';
+
+$app->post('/',function(Request$request,Response$response){
+ $directory=$this->get('upload_directory');
+
+ $uploadedFiles=$request->getUploadedFiles();
+
+ // handle single input with single file upload
+$uploadedFile=$uploadedFiles['example1'];
+ if($uploadedFile->getError()===UPLOAD_ERR_OK){
+ $filename=moveUploadedFile($directory,$uploadedFile);
+ $response->write('uploaded '.$filename.'<br/>');
+ }
+
+
+ // handle multiple inputs with the same key
+foreach($uploadedFiles['example2']as$uploadedFile){
+ if($uploadedFile->getError()===UPLOAD_ERR_OK){
+ $filename=moveUploadedFile($directory,$uploadedFile);
+ $response->write('uploaded '.$filename.'<br/>');
+ }
+ }
+
+ // handle single input with multiple file uploads
+foreach($uploadedFiles['example3']as$uploadedFile){
+ if($uploadedFile->getError()===UPLOAD_ERR_OK){
+ $filename=moveUploadedFile($directory,$uploadedFile);
+ $response->write('uploaded '.$filename.'<br/>');
+ }
+ }
+
+});
+
+/**
+ * Moves the uploaded file to the upload directory and assigns it a unique name
+ * to avoid overwriting an existing uploaded file.
+ *
+ * @param string $directory directory to which the file is moved
+ * @param UploadedFile $uploadedFile file uploaded file to move
+ * @return string filename of moved file
+ */
+functionmoveUploadedFile($directory,UploadedFile$uploadedFile)
+{
+ $extension=pathinfo($uploadedFile->getClientFilename(),PATHINFO_EXTENSION);
+ $basename=bin2hex(random_bytes(8));// see http://php.net/manual/en/function.random-bytes.php
+$filename=sprintf('%s.%0.8s',$basename,$extension);
+
+ $uploadedFile->moveTo($directory.DIRECTORY_SEPARATOR.$filename);
+
+ return$filename;
+}
+
+$app->run();
+
+ Figure 2: Example Slim application to handle the uploaded files
+
+
+
Things go wrong. You can’t predict errors, but you can anticipate them. Each Slim Framework application has an error handler that receives all uncaught PHP exceptions. This error handler also receives the current HTTP request and response objects, too. The error handler must prepare and return an appropriate Response object to be returned to the HTTP client.
+
Congratulations! if you have made it this far, that means you have successfully built something
+awesome using Slim. However, the time to party has not come yet. We still have to push our
+application to the production server.
-
Default error handler
+
There are many ways to do this that are beyond the scope of this documentation. In
+this section, we provide some notes for various set-ups.
-
The default error handler is very basic. It sets the Response status code to 500, it sets the Response content type to text/html, and appends a generic error message into the Response body.
+
Disable error display in production
-
This is probably not appropriate for production applications. You are strongly encouraged to implement your own Slim application error handler.
+
The first thing to do is to tweak your settings (src/settings.php in the
+skeleton application) and ensure that you do not display full error details to the
+public.
-
The default error handler can also include detailed error diagnostic information. To enable this you need to set the displayErrorDetails setting to true:
+
'displayErrorDetails'=>false,// set to false in production
+
You should also ensure that your PHP installation is configured to not display
+errors with the php.ini setting:
-
Custom error handler
+
display_errors=0
+
-
A Slim Framework application’s error handler is a Pimple service. You can substitute your own error handler by defining a custom Pimple factory method with the application container.
+
Deploying to your own server
-
There are two ways to inject handlers:
+
If you control your server, then you should set up a deployment process using any
+one of the many deployment system such as:
-
Pre App
-
-
$c = new \Slim\Container();
-$c['errorHandler'] = function ($c) {
- return function ($request, $response, $exception) use ($c) {
- return $c['response']->withStatus(500)
- ->withHeader('Content-Type', 'text/html')
- ->write('Something went wrong!');
- };
-};
-$app = new \Slim\App($c);
-
-
Post App
-
-
$app = new \Slim\App();
-$c = $app->getContainer();
-$c['errorHandler'] = function ($c) {
- return function ($request, $response, $exception) use ($c) {
- return $c['response']->withStatus(500)
- ->withHeader('Content-Type', 'text/html')
- ->write('Something went wrong!');
- };
-};
+
+
Deploybot
+
Capistrano
+
Script controlled with Phing, Make, Ant, etc.
+
-
In this example, we define a new errorHandler factory that returns a callable. The returned callable accepts three arguments:
+
Review the Web Servers documentation to configure your webserver.
-
-
A \Psr\Http\Message\ServerRequestInterface instance
-
A \Psr\Http\Message\ResponseInterface instance
-
A \Exception instance
-
+
Deploying to a shared server
-
The callable MUST return a new \Psr\Http\Message\ResponseInterface instance as is appropriate for the given exception.
+
If your shared server runs Apache, then you need to create a .htaccess file
+in your web server root directory (usually named htdocs, public, public_html
+or www) with the following content:
-
Please note: The following three types of exceptions will not be handled by a custom errorHandler:
Slim\Exception\MethodNotAllowedException: This can be handled via a custom notAllowedHandler.
-
Slim\Exception\NotFoundException: This can be handled via a custom notFoundHandler.
-
Slim\Exception\SlimException: This type of exception is internal to Slim, and its handling cannot be overridden.
-
+
(replace ‘public’ with the correct name of your domain name e.g. example.com/$1)
-
Disabling
+
Now upload all the files that make up your Slim project to the webserver. As you
+are on shared hosting, this is probably done via FTP and you can use any FTP client,
+such as Filezilla to do this.
-
To completely disable Slim’s error handling, simply remove the error handler from the container:
-
-
unset($app->getContainer()['errorHandler']);
-
-
You are now responsible for handling any exceptions that occur in your application as they will not be handled by Slim.
Slim 3 uses the optional standalone slimphp/Slim-HttpCache PHP component
for HTTP caching. You can use this component to create and return responses that
contain Cache, Expires, ETag, and Last-Modified headers that control
-when and how long application output is retained by client-side caches.
+when and how long application output is retained by client-side caches. You may have to set your php.ini setting “session.cache_limiter” to an empty string in order to get this working without interferences.
Installation
Execute this bash command from your project’s root directory:
-
composer require slim/http-cache
+
composer require slim/http-cache
+
Usage
The slimphp/Slim-HttpCache component contains a service provider and an application
middleware. You should add both to your application like this:
-
// Register service provider with the container
-$container = new \Slim\Container;
-$container['cache'] = function () {
- return new \Slim\HttpCache\CacheProvider();
-};
+
// Register service provider with the container
+$container=new\Slim\Container;
+$container['cache']=function(){
+ returnnew\Slim\HttpCache\CacheProvider();
+};
-// Add middleware to the application
-$app = new \Slim\App($container);
-$app->add(new \Slim\HttpCache\Cache('public', 86400));
+// Add middleware to the application
+$app=new\Slim\App($container);
+$app->add(new\Slim\HttpCache\Cache('public',86400));
-// Create your application routes...
-
-// Run application
-$app->run();
+// Create your application routes...
+
+// Run application
+$app->run();
+
ETag
@@ -72,11 +75,12 @@
ETag
with the desired ETag header. This method accepts a PSR7 response object,
and it returns a cloned PSR7 response with the new HTTP header.
-
The slimphp/Slim-Csrf component contains an application middleware. Add it
to your application like this:
-
// Add middleware to the application
-$app = new \Slim\App;
-$app->add(new \Slim\Csrf\Guard);
+
// Add middleware to the application
+$app=new\Slim\App;
+$app->add(new\Slim\Csrf\Guard);
-// Create your application routes...
-
-// Run application
-$app->run();
+// Create your application routes...
+
+// Run application
+$app->run();
+
$app->get('/foo',function($req,$res,$args){
+ // CSRF token name and value
+$nameKey=$this->csrf->getTokenNameKey();
+ $valueKey=$this->csrf->getTokenValueKey();
+ $name=$req->getAttribute($nameKey);
+ $value=$req->getAttribute($valueKey);
+
+ // Render HTML form which POSTs to /bar with two hidden input fields for the
+// name and value:
+// <input type="hidden" name="<?= $nameKey ?>" value="<?= $name ?>">
+// <input type="hidden" name="<?= $valueKey ?>" value="<?= $value ?>">
+});
+
+$app->post('/bar',function($req,$res,$args){
+ // CSRF protection successful if you reached
+// this far.
+});
+
You should pass the CSRF token name and value to the template so they
may be submitted with HTML form POST requests. They are often stored as a hidden
field with HTML forms.
+
For more use cases and documentation please check slimphp/Slim-Csrf’s page.
// Start PHP session
+session_start();//by default requires session storage
+
+$app=new\Slim\App();
-$app = new \Slim\App();
+// Fetch DI Container
+$container=$app->getContainer();
-// Fetch DI Container
-$container = $app->getContainer();
+// Register provider
+$container['flash']=function(){
+ returnnew\Slim\Flash\Messages();
+};
-// Register provider
-$container['flash'] = function () {
- return new \Slim\Flash\Messages();
-};
+$app->get('/foo',function($req,$res,$args){
+ // Set flash message for next request
+$this->flash->addMessage('Test','This is a message');
-$app->get('/foo', function ($req, $res, $args) {
- // Set flash message for next request
- $this->flash->addMessage('Test', 'This is a message');
+ // Redirect
+return$res->withStatus(302)->withHeader('Location','/bar');
+});
- // Redirect
- return $res->withStatus(302)->withHeader('Location', '/bar');
-});
+$app->get('/bar',function($req,$res,$args){
+ // Add message to be used in current request
+$this->flash->addMessageNow('Test','This is another message');
-$app->get('/bar', function ($req, $res, $args) {
- // Get flash messages from previous request
- $messages = $this->flash->getMessages();
- print_r($messages);
-});
+ // Get flash messages from previous request
+$messages=$this->flash->getMessages();
-$app->run();
-
Us
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/features/templates.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/features/templates.html
similarity index 61%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/features/templates.html
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/features/templates.html
index b733c78..563fe3a 100644
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/features/templates.html
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/features/templates.html
@@ -1,5 +1,5 @@
-
+
@@ -13,9 +13,9 @@
-
-
-
+
+
+
@@ -33,7 +33,8 @@
Slim does not have a view layer like traditional MVC frameworks. Instead,
Slim’s “view” is the HTTP response. Each Slim application route is responsible
@@ -54,18 +55,16 @@
+ // Instantiate and add Slim specific extension
+$router=$container->get('router');
+ $uri=\Slim\Http\Uri::createFromEnvironment(new\Slim\Http\Environment($_SERVER));
+ $view->addExtension(new\Slim\Views\TwigExtension($router,$uri));
-Figure 2: Register slim/twig-view component with container.
+ return$view;
+};
+
+ Figure 2: Register slim/twig-view component with container.
-
Note : “cache” could be set to false to disable it, see also ‘auto_reload’ option, useful in development environment. For more information, see Twig environment options
+
Note : “cache” could be set to false to disable it, see also ‘auto_reload’ option, useful in development environment. For more information, see Twig environment options
Now you can use the slim/twig-view component service inside an app route
to render a template and write it to a PSR 7 Response object like this:
The slim/twig-view component exposes a custom path_for() function
to your Twig templates. You can use this function to generate complete
@@ -131,14 +130,66 @@
Things go wrong. You can’t predict errors, but you can anticipate them. Each Slim Framework application has an error handler that receives all uncaught PHP exceptions. This error handler also receives the current HTTP request and response objects, too. The error handler must prepare and return an appropriate Response object to be returned to the HTTP client.
+
+
Default error handler
+
+
The default error handler is very basic. It sets the Response status code to 500, it sets the Response content type to text/html, and appends a generic error message into the Response body.
+
+
This is probably not appropriate for production applications. You are strongly encouraged to implement your own Slim application error handler.
+
+
The default error handler can also include detailed error diagnostic information. To enable this you need to set the displayErrorDetails setting to true:
A Slim Framework application’s error handler is a Pimple service. You can substitute your own error handler by defining a custom Pimple factory method with the application container.
If your Slim Framework application has a route that matches the current HTTP request URI but NOT the HTTP request method, the application invokes its Not Allowed handler and returns a HTTP/1.1 405 Not Allowed response to the HTTP client.
If your Slim Framework application does not have a route that matches the current HTTP request URI, the application invokes its Not Found handler and returns a HTTP/1.1 404 Not Found response to the HTTP client.
@@ -43,24 +44,24 @@
Custom Not Found handler
-
A Slim Framework application’s Not Found handler is a Pimple service. You can substitute your own Not Found handler by defining a custom Pimple factory method with the application container.
+
A Slim Framework application’s Not Found handler is a Pimple service. You can substitute your own Not Found handler by defining a custom Pimple factory method with the application container before you instantiate the App object.
-
$c = new \Slim\Container(); //Create Your container
+
$c=new\Slim\Container();//Create Your container
+
+//Override the default Not Found Handler before creating App
+$c['notFoundHandler']=function($c){
+ returnfunction($request,$response)use($c){
+ return$response->withStatus(404)
+ ->withHeader('Content-Type','text/html')
+ ->write('Page not found');
+ };
+};
-//Override the default Not Found Handler
-$c['notFoundHandler'] = function ($c) {
- return function ($request, $response) use ($c) {
- return $c['response']
- ->withStatus(404)
- ->withHeader('Content-Type', 'text/html')
- ->write('Page not found');
- };
-};
+//Create Slim
+$app=new\Slim\App($c);
-//Create Slim
-$app = new \Slim\App($c);
-
-//... Your code
+//... Your code
+
In this example, we define a new notFoundHandler factory that returns a callable. The returned callable accepts two arguments:
If you wish to override the default Not Found handler after you instantiate the App object you can unset the default handler then overwrite it.
+
+
$c=new\Slim\Container();//Create Your container
+
+//Create Slim
+$app=new\Slim\App($c);
+
+//... Your code
+
+//Override the default Not Found Handler after App
+unset($app->getContainer()['notFoundHandler']);
+$app->getContainer()['notFoundHandler']=function($c){
+ returnfunction($request,$response)use($c){
+ $response=new\Slim\Http\Response(404);
+ return$response->write("Page not found");
+ };
+};
+
If your Slim Framework application throws a
+PHP Runtime error (PHP 7+ only),
+the application invokes its PHP Error handler and returns a
+HTTP/1.1 500 Internal Server Error response to the HTTP client.
+
+
Please note that Warnings and Notices are not caught by default. If you wish your application to display an error page when they happen, you have to run the following code before the app starts. In most cases that means adding it to the very top of index.php.
This way all Warnings and Notices will be treated as Errors and as such will trigger the defined handlers.
+
+
Default PHP Error handler
+
+
Each Slim Framework application has a default PHP Error handler. This handler
+sets the Response status to 500, it sets the content type to text/html,
+and it writes a simple explanation to the Response body.
+
+
Custom PHP Error handler
+
+
A Slim Framework application’s PHP Error handler is a Pimple service. You can
+substitute your own PHP Error handler by defining a custom Pimple factory
+method with the application container.
+
+
// Create Slim
+$app=new\Slim\App();
+// get the app's di-container
+$c=$app->getContainer();
+$c['phpErrorHandler']=function($c){
+ returnfunction($request,$response,$error)use($c){
+ return$response->withStatus(500)
+ ->withHeader('Content-Type','text/html')
+ ->write('Something went wrong!');
+ };
+};
+
+
+
+
N.B Check out Not Found docs for
+pre-slim creation method using a new instance of \Slim\Container
+
+
+
In this example, we define a new phpErrorHandler factory that returns a
+callable. The returned callable accepts three arguments:
+
+
+
A \Psr\Http\Message\ServerRequestInterface instance
+
A \Psr\Http\Message\ResponseInterface instance
+
A \Throwable instance
+
+
+
The callable MUST return a new \Psr\Http\Message\ResponseInterface
+instance as is appropriate for the given error.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/images/middleware.png b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/images/middleware.png
similarity index 100%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/images/middleware.png
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/images/middleware.png
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/objects/application.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/objects/application.html
similarity index 65%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/objects/application.html
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/objects/application.html
index 10b1846..c328e68 100644
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/objects/application.html
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/objects/application.html
@@ -1,5 +1,5 @@
-
+
@@ -13,9 +13,9 @@
-
-
-
+
+
+
@@ -33,20 +33,22 @@
The Application, (or Slim\App) is the entry point to your Slim application and is used to register the route that link to your callbacks or controllers.
+
The Application, (or Slim\App) is the entry point to your Slim application and is used to register the routes that link to your callbacks or controllers.
-
// instantiate the App object
-$app = new \Slim\App();
+
If you need to add or update settings stored in the DI container after the container is initialized,
+you can use the replace method on the settings container. For example:
Your Slim app’s routes and middleware are given a PSR 7 request object that
represents the current HTTP request received by your web server. The request
@@ -46,8 +47,7 @@
The file uploads in $_FILES are available from the Request object’s
+getUploadedFiles() method. This returns an array keyed by the name of the
+<input> element.
+
+
+
$files=$request->getUploadedFiles();
+
+ Figure 11: Get uploaded files
+
+
+
Each object in the $files array is a instance of
+\Psr\Http\Message\UploadedFileInterface and supports the following methods:
+
+
+
getStream()
+
moveTo($targetPath)
+
getSize()
+
getError()
+
getClientFilename()
+
getClientMediaType()
+
+
+
See the cookbook on how to upload files using a POST form.
+
Request Helpers
Slim’s PSR 7 Request implementation provides these additional proprietary methods
@@ -335,49 +354,54 @@
You can fetch the HTTP request content type with the Request object’s getContentType() method. This returns the Content-Type header’s full value as provided by the HTTP client.
-
$contentType = $request->getContentType();
+
$contentType=$request->getContentType();
+
Media Type
You may not want the complete Content-Type header. What if, instead, you only want the media type? You can fetch the HTTP request media type with the Request object’s getMediaType() method.
-
$mediaType = $request->getMediaType();
+
$mediaType=$request->getMediaType();
+
You can fetch the appended media type parameters as an associative array with the Request object’s getMediaTypeParams() method.
-
$mediaParams = $request->getMediaTypeParams();
+
$mediaParams=$request->getMediaTypeParams();
+
Character Set
One of the most common media type parameters is the HTTP request character set. The Request object provides a dedicated method to retrieve this media type parameter.
-
$charset = $request->getContentCharset();
+
$charset=$request->getContentCharset();
+
Content Length
You can fetch the HTTP request content length with the Request object’s getContentLength() method.
With PSR-7 it is possible to inject objects/values into the request object for further processing. In your applications middleware often need to pass along information to your route closure and the way to do is it is to add it to the request object via an attribute.
+
+
Example, Setting a value on your request object.
- return $next($request, $response);
-});
+
$app->add(function($request,$response,$next){
+ $request=$request->withAttribute('session',$_SESSION);//add the session storage to your request as [READ-ONLY]
+return$next($request,$response);
+});
+
+
+
Example, how to retrieve the value.
+
+
$app->get('/test',function($request,$response,$args){
+ $session=$request->getAttribute('session');//get the session from the request
+
+ return$response->write('Yay, '.$session['name']);
+});
+
+
The request object also has bulk functions as well. $request->getAttributes() and $request->withAttributes()
Your Slim app’s routes and middleware are given a PSR 7 response object that
represents the current HTTP response to be returned to the client. The response
@@ -46,8 +47,7 @@
Slim’s Response object has a custom method withRedirect($url, $status = null) when you wish to return a redirect to another URL. You provide the $url where you wish the client to be redirected to along with an optional $status code. The status code defaults to 302 if not provided.
+
+
+
return$response->withRedirect('/new-url',301);
+
+ Figure 17: Returning a redirect with an optional status code.
+
The Slim Framework’s router is built on top of the nikic/fastroute component, and it is remarkably fast and stable.
+
+
How to create routes
+
+
You can define application routes using proxy methods on the \Slim\App instance. The Slim Framework provides methods for the most popular HTTP methods.
+
+
GET Route
+
+
You can add a route that handles only GET HTTP requests with the Slim
+application’s get() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->get('/books/{id}',function($request,$response,$args){
+ // Show book identified by $args['id']
+});
+
+
+
POST Route
+
+
You can add a route that handles only POST HTTP requests with the Slim
+application’s post() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->post('/books',function($request,$response,$args){
+ // Create new book
+});
+
+
+
PUT Route
+
+
You can add a route that handles only PUT HTTP requests with the Slim
+application’s put() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->put('/books/{id}',function($request,$response,$args){
+ // Update book identified by $args['id']
+});
+
+
+
DELETE Route
+
+
You can add a route that handles only DELETE HTTP requests with the Slim
+application’s delete() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->delete('/books/{id}',function($request,$response,$args){
+ // Delete book identified by $args['id']
+});
+
+
+
OPTIONS Route
+
+
You can add a route that handles only OPTIONS HTTP requests with the Slim
+application’s options() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
You can add a route that handles only PATCH HTTP requests with the Slim
+application’s patch() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->patch('/books/{id}',function($request,$response,$args){
+ // Apply changes to book identified by $args['id']
+});
+
+
+
Any Route
+
+
You can add a route that handles all HTTP request methods with the Slim application’s any() method. It accepts two arguments:
+
+
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->any('/books/[{id}]',function($request,$response,$args){
+ // Apply changes to books or book identified by $args['id'] if specified.
+// To check which method is used: $request->getMethod();
+});
+
+
+
Note that the second parameter is a callback. You could specify a Class (which need a __invoke() implementation) instead of a Closure. You can then do the mapping somewhere else:
+
+
$app->any('/user','MyRestfulController');
+
+
+
Custom Route
+
+
You can add a route that handles multiple HTTP request methods with the Slim application’s map() method. It accepts three arguments:
+
+
+
Array of HTTP methods
+
The route pattern (with optional named placeholders)
+
The route callback
+
+
+
$app=new\Slim\App();
+$app->map(['GET','POST'],'/books',function($request,$response,$args){
+ // Create new book or list all books
+});
+
+
+
Route callbacks
+
+
Each routing method described above accepts a callback routine as its final argument. This argument can be any PHP callable, and by default it accepts three arguments.
+
+
+
Request
+
The first argument is a Psr\Http\Message\ServerRequestInterface object that represents the current HTTP request.
+
Response
+
The second argument is a Psr\Http\Message\ResponseInterface object that represents the current HTTP response.
+
Arguments
+
The third argument is an associative array that contains values for the current route’s named placeholders.
+
+
+
Writing content to the response
+
+
There are two ways you can write content to the HTTP response. First, you can simply echo() content from the route callback. This content will be appended to the current HTTP response object. Second, you can return a Psr\Http\Message\ResponseInterface object.
+
+
Closure binding
+
+
If you use a Closure instance as the route callback, the closure’s state is bound to the Container instance. This means you will have access to the DI container instance inside of the Closure via the $this keyword:
+
+
$app=new\Slim\App();
+$app->get('/hello/{name}',function($request,$response,$args){
+ // Use app HTTP cookie service
+$this->get('cookies')->set('name',[
+ 'value'=>$args['name'],
+ 'expires'=>'7 days'
+ ]);
+});
+
+
+
Redirect helper
+
+
You can add a route that redirects GET HTTP requests to a different URL with
+the Slim application’s redirect() method. It accepts three arguments:
+
+
+
The route pattern (with optional named placeholders) to redirect from
redirect() routes respond with the status code requested and a Location
+header set to the second argument.
+
+
Route strategies
+
+
The route callback signature is determined by a route strategy. By default, Slim expects route callbacks to accept the request, response, and an array of route placeholder arguments. This is called the RequestResponse strategy. However, you can change the expected route callback signature by simply using a different strategy. As an example, Slim provides an alternative strategy called RequestResponseArgs that accepts request and response, plus each route placeholder as a separate argument. Here is an example of using this alternative strategy; simply replace the foundHandler dependency provided by the default \Slim\Container:
You can provide your own route strategy by implementing the \Slim\Interfaces\InvocationStrategyInterface.
+
+
Route placeholders
+
+
Each routing method described above accepts a URL pattern that is matched against the current HTTP request URI. Route patterns may use named placeholders to dynamically match HTTP request URI segments.
+
+
Format
+
+
A route pattern placeholder starts with a {, followed by the placeholder name, ending with a }. This is an example placeholder named name:
To make a section optional, simply wrap in square brackets:
+
+
$app->get('/users[/{id}]',function($request,$response,$args){
+ // responds to both `/users` and `/users/123`
+// but not to `/users/`
+});
+
+
+
Multiple optional parameters are supported by nesting:
+
+
$app->get('/news[/{year}[/{month}]]',function($request,$response,$args){
+ // reponds to `/news`, `/news/2016` and `/news/2016/03`
+});
+
+
+
For “Unlimited” optional parameters, you can do this:
+
+
$app->get('/news[/{params:.*}]',function($request,$response,$args){
+ $params=explode('/',$args['params']);
+
+ // $params is an array of all the optional segments
+});
+
+
+
In this example, a URI of /news/2016/03/20 would result in the $params array
+containing three elements: ['2016', '03', '20'].
+
+
Regular expression matching
+
+
By default the placeholders are written inside {} and can accept any
+values. However, placeholders can also require the HTTP request URI to match a particular regular expression. If the current HTTP request URI does not match a placeholder regular expression, the route is not invoked. This is an example placeholder named id that requires one or more digits.
+
+
$app=new\Slim\App();
+$app->get('/users/{id:[0-9]+}',function($request,$response,$args){
+ // Find user identified by $args['id']
+});
+
+
+
Route names
+
+
Application routes can be assigned a name. This is useful if you want to programmatically generate a URL to a specific route with the router’s pathFor() method. Each routing method described above returns a \Slim\Route object, and this object exposes a setName() method.
The router’s pathFor() method accepts two arguments:
+
+
+
The route name
+
Associative array of route pattern placeholders and replacement values
+
+
+
Route groups
+
+
To help organize routes into logical groups, the \Slim\App also provides a group() method. Each group’s route pattern is prepended to the routes or groups contained within it, and any placeholder arguments in the group pattern are ultimately made available to the nested routes:
+
+
$app=new\Slim\App();
+$app->group('/users/{id:[0-9]+}',function(App$app){
+ $app->map(['GET','DELETE','PATCH','PUT'],'',function($request,$response,$args){
+ // Find, delete, patch or replace user identified by $args['id']
+})->setName('user');
+ $app->get('/reset-password',function($request,$response,$args){
+ // Route for /users/{id:[0-9]+}/reset-password
+// Reset the password for user identified by $args['id']
+})->setName('user-password-reset');
+});
+
+
+
The group pattern can be empty, enabling the logical grouping of routes that do not share a common pattern.
+
+
$app->group('',function(App$app){
+ $app->get('/billing',function($request,$response,$args){
+ // Route for /billing
+});
+ $this->get('/invoice/{id:[0-9]+}',function($request,$response,$args){
+ // Route for /invoice/{id:[0-9]+}
+});
+})->add(newSharedMiddleware());
+
+
+
Note inside the group closure, $this can be used instead of $app. Slim binds the closure to the application instance for you, just like it is the case with route callback binds with container instance.
+
+
+
inside group closure, $this is bound to the instance of Slim\App
+
inside route closure, $this is bound to the instance of Slim\Container
+
+
+
Route middleware
+
+
You can also attach middleware to any route or route group. Learn more.
+
+
Router caching
+
+
It’s possible to enable router cache by setting valid filename in default Slim settings. Learn more.
+
+
Container Resolution
+
+
You are not limited to defining a function for your routes. In Slim there are a few different ways to define your route action functions.
+
+
In addition to a function, you may use:
+
+
+
container_key:method
+
Class:method
+
An invokable class
+
container_key
+
+
+
This functionality is enabled by Slim’s Callable Resolver Class. It translates a string entry into a function call.
+Example:
+
+
$app->get('/','\HomeController:home');
+
+
+
Alternatively, you can take advantage of PHP’s ::class operator which works well with IDE lookup systems and produces the same result:
+
+
$app->get('/',\HomeController::class.':home');
+
+
+
In this code above we are defining a / route and telling Slim to execute the home() method on the HomeController class.
+
+
Slim first looks for an entry of HomeController in the container, if it’s found it will use that instance otherwise it will call it’s constructor with the container as the first argument. Once an instance of the class is created it will then call the specified method using whatever Strategy you have defined.
+
+
Registering a controller with the container
+
+
Create a controller with the home action method. The constructor should accept
+the dependencies that are required. For example:
+
+
classHomeController
+{
+ protected$view;
+
+ publicfunction__construct(\Slim\Views\Twig$view){
+ $this->view=$view;
+ }
+ publicfunctionhome($request,$response,$args){
+ // your code here
+// use $this->view to render the HTML
+return$response;
+ }
+}
+
+
+
Create a factory in the container that instantiates the controller with the dependencies:
+
+
$container=$app->getContainer();
+$container['HomeController']=function($c){
+ $view=$c->get("view");// retrieve the 'view' from the container
+returnnewHomeController($view);
+};
+
+
+
This allows you to leverage the container for dependency injection and so you can
+inject specific dependencies into the controller.
+
+
Allow Slim to instantiate the controller
+
+
Alternatively, if the class does not have an entry in the container, then Slim
+will pass the container’s instance to the constructor. You can construct controllers
+with many actions instead of an invokable class which only handles one action.
+
+
usePsr\Container\ContainerInterface;
+
+classHomeController
+{
+ protected$container;
+
+ // constructor receives container instance
+publicfunction__construct(ContainerInterface$container){
+ $this->container=$container;
+ }
+
+ publicfunctionhome($request,$response,$args){
+ // your code
+// to access items in the container... $this->container->get('');
+return$response;
+ }
+
+ publicfunctioncontact($request,$response,$args){
+ // your code
+// to access items in the container... $this->container->get('');
+return$response;
+ }
+}
+
You do not have to specify a method in your route callable and can just set it to be an invokable class such as:
+
+
usePsr\Container\ContainerInterface
+
+classHomeAction
+{
+ protected$container;
+
+ publicfunction__construct(ContainerInterface$container){
+ $this->container=$container;
+ }
+
+ publicfunction__invoke($request,$response,$args){
+ // your code
+// to access items in the container... $this->container->get('');
+return$response;
+ }
+}
+
+
+
You can use this class like so.
+
+
$app->get('/',\HomeAction::class);
+
+
+
Again, as with controllers, if you register the class name with the container, then you
+can create a factory and inject just the specific dependencies that you require into your
+action class.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/start/installation.html b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/start/installation.html
similarity index 79%
rename from Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/start/installation.html
rename to Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/start/installation.html
index d260a1e..99e76a5 100644
--- a/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/start/installation.html
+++ b/Slim_Framework.docset/Contents/Resources/Documents/www.slimframework.com/docs/v3/start/installation.html
@@ -1,5 +1,5 @@
-
+
@@ -13,9 +13,9 @@
-
-
-
+
+
+
@@ -33,7 +33,8 @@
Request and response objects are no longer accessible via the Application object
+
As mentioned above, Slim 3 passes the Request and Response objects as arguments to the route handling function. Since they are now accessible directly in the body of a route function, request and response are no longer properties of the /Slim/App (Application object) instance.
Hooks are no longer part of Slim as of v3. You should consider reimplementing any functionality associated with the default hooks in Slim v2 as middleware instead. If you need the ability to apply custom hooks at arbitrary points in your code (for example, within a route), you should consider a third-party package such as Symfony’s EventDispatcher or Zend Framework’s EventManager.
+
+
Removal HTTP Cache
+
In Slim v3 we have removed the HTTP-Caching into its own module Slim\Http\Cache.
+
+
Removal of Stop/Halt
+
Slim Core has removed Stop/Halt.
+In your applications, you should transition to using the withStatus() and withBody() methods.
+
+
Removal of autoloader
+
Slim::registerAutoloader() have been removed, we have fully moved to composer.
+
+
Changes to container
+
$app->container->singleton(...) is now $container = $app->getContainer(); $container['...'] = function () {}; Please read Pimple docs for more info
+
+
Removal of configureMode()
+
$app->configureMode(...) has been removed in v3.
+
+
Removal of PrettyExceptions
+
PrettyExceptions cause lots of issues for many people, so these have been removed.
+
+
Route::setDefaultConditions(…) has been removed
+
We have switched routers which enable you to keep the default conditions regex inside of the route pattern.
+
+
Changes to redirect
+
In Slim v2.x one would use the helper function $app->redirect(); to trigger a redirect request.
+In Slim v3.x one can do the same with using the Response class like so.
Alternatively, if you want a route to redirect without any other handling, you
+can use the shortcut helper function $app->redirect() as the route
+definition:
+
+
$app->redirect('/','your-new-uri');
+
+
+
Middleware Signature
+
The middleware signature has changed from a class to a function.
+
+
New signature:
+
+
usePsr\Http\Message\RequestInterfaceasRequest;
+usePsr\Http\Message\ResponseInterfaceasResponse;
+
+$app->add(function(Request$req,Response$res,callable$next){
+ // Do stuff before passing along
+$newResponse=$next($req,$res);
+ // Do stuff after route is rendered
+return$newResponse;// continue
+});
+
+
+
You can still use a class:
+
+
namespaceMy;
+
+usePsr\Http\Message\RequestInterfaceasRequest;
+usePsr\Http\Message\ResponseInterfaceasResponse;
+
+classMiddleware
+{
+ function__invoke(Request$req,Response$res,callable$next){
+ // Do stuff before passing along
+$newResponse=$next($req,$res);
+ // Do stuff after route is rendered
+return$newResponse;// continue
+}
+}
+
+
+// Register
+$app->add(newMy\Middleware());
+// or
+$app->add(My\Middleware::class);
+
+
+
+
Middleware Execution
+
Application middleware is executed as Last In First Executed (LIFE).
+
+
Flash Messages
+
Flash messages are no longer a part of the Slim v3 core but instead have been moved to seperate Slim Flash package.
+
+
Cookies
+
In v3.0 cookies has been removed from core. See FIG Cookies for a PSR-7 compatible cookie component.
+
+
Removal of Crypto
+
In v3.0 we have removed the dependency for crypto in core.
+
+
New Router
+
Slim now utilizes FastRoute, a new, more powerful router!
+
+
This means that the specification of route patterns has changed with named parameters now in braces and square brackets used for optional segments:
+
+
// named parameter:
+$app->get('/hello/{name}',/*...*/);
+
+// optional segment:
+$app->get('/news[/{year}]',/*...*/);
+
+
+
Route Middleware
+
The syntax for adding route middleware has changed slightly.
+In v3.0:
+
+
$app->get(…)->add($mw2)->add($mw1);
+
+
+
Getting the current route
+
The route is an attribute of the Request object in v3.0:
+
+
$request->getAttribute('route');
+
+
+
When getting the current route in middleware, the value for
+determineRouteBeforeAppMiddleware must be set to true in the Application
+configuration, otherwise the getAttribute call returns null.
+
+
urlFor() is now pathFor() in the router
+
+
urlFor() has been renamed pathFor() and can be found in the router object:
Slim uses Pimple as a Dependency Injection Container.
+
+
+// index.php
+$app=newSlim\App(
+ new\Slim\Container(
+ include'../config/container.config.php'
+ )
+);
+
+// Slim will grab the Home class from the container defined below and execute its index method.
+// If the class is not defined in the container Slim will still contruct it and pass the container as the first arugment to the constructor!
+$app->get('/',Home::class.':index');
+
+
+// In container.config.php
+// We are using the SlimTwig here
+return[
+ 'settings'=>[
+ 'viewTemplatesDirectory'=>'../templates',
+ ],
+ 'twig'=>[
+ 'title'=>'',
+ 'description'=>'',
+ 'author'=>''
+ ],
+ 'view'=>function($c){
+ $view=newTwig(
+ $c['settings']['viewTemplatesDirectory'],
+ [
+ 'cache'=>false// '../cache'
+]
+ );
+
+ // Instantiate and add Slim specific extension
+$view->addExtension(
+ newTwigExtension(
+ $c['router'],
+ $c['request']->getUri()
+ )
+ );
+
+ foreach($c['twig']as$name=>$value){
+ $view->getEnvironment()->addGlobal($name,$value);
+ }
+
+ return$view;
+ },
+ Home::class=>function($c){
+ returnnewHome($c['view']);
+ }
+];
+
+
+
+
PSR-7 Objects
+
+
Request, Response, Uri & UploadFile are immutable.
+
This means that when you change one of these objects, the old instance is not updated.
+
+
// This is WRONG. The change will not pass through.
+$app->add(function(Request$request,Response$response,$next){
+ $request->withAttribute('abc','def');
+ return$next($request,$response);
+});
+
+// This is correct.
+$app->add(function(Request$request,Response$response,$next){
+ $request=$request->withAttribute('abc','def');
+ return$next($request,$response);
+});
+
It is typical to use the front-controller pattern to funnel appropriate HTTP
requests received by your web server to a single PHP file. The instructions
@@ -45,7 +46,8 @@
front-controller file should be in this directory.
-
server {
+
server {
listen 80;
server_name example.com;
index index.php;
@@ -89,18 +92,19 @@
HipHop Virtual Machine
Your HipHop Virtual Machine configuration file should contain this code (along with other settings you may need). Be sure you change the SourceRoot setting to point to your Slim app’s document root directory.
-
Server {
+
Server {
SourceRoot = /path/to/public/directory
}
@@ -119,13 +123,14 @@
IIS
Ensure the Web.config and index.php files are in the same public-accessible directory. The Web.config file should contain this code:
If you’re looking for a tour through all the ingredients for setting up a very simple Slim application (this one doesn’t use Twig, but does use Monolog and a PDO database connection) then you’re in the right place. Either walk through the tutorial to build the example application, or adapt each step for your own needs.
Composer is the best way to install Slim Framework. If you don’t have it already, you can follow the installation instructions, in my project I’ve just downloaded the composer.phar into my src/ directory and I’ll use it locally. So my first command looks like this (I’m in the src/ directory):
This will make your application available at http://localhost:8080 (if you’re already using port 8080 on your machine, you’ll get a warning. Just pick a different port number, PHP doesn’t care what you bind it to).
We’ll be able to access any settings we put into that $config array from our application later on.
Set up Autoloading for Your Own Classes
-
We already added the composer autoloader file, but what about the code that we write that isn’t part of the composer libraries? One option is to use Composer to manage autoloading rules which is a great solution, but you can also add your own autoloader if you want to.
-
-
My setup is pretty simple since I only have a few extra classes, they’re just in the global namespace, and the files are in the src/classes/ directory. So to add the autoloader, I have this block of code after the vendor/autoload.php file is required:
The spl_autoload_register function accepts the (namespaced) class name and then by the end of the function, the class code should have been included.
+
Composer can handle the autoloading of your own classes just as well as the vendored ones. For an in-depth guide, take a look at using Composer to manage autoloading rules.
+
+
My setup is pretty simple since I only have a few extra classes, they’re just in the global namespace, and the files are in the src/classes/ directory. So to autoload them, I add this autoload section to my composer.json file:
We’re adding an element to the container, which is itself an anonymous function (the $c that is passed in is the container itself so you can acess other dependencies if you need to). This will be called when we try to access this dependency for the first time; the code here does the setup of the dependency. Next time we try to access the same dependence, the same object that was created the first time will be used the next time.
+
We’re adding an element to the container, which is itself an anonymous function (the $c that is passed in is the container itself so you can access other dependencies if you need to). This will be called when we try to access this dependency for the first time; the code here does the setup of the dependency. Next time we try to access the same dependency, the same object that was created the first time will be used the next time.
My Monolog config here is fairly light; just setting up the application to log all errors to a file called logs/app.log (remember this path is from the point of view of where the script is running, i.e. index.php).
With the logger in place, I can use it from inside my route code with a line like this:
Having good application logging is a really important foundation for any application so I’d always recommend putting something like this in place. This allows you to add as much or as little debugging as you want, and by using the appropriate log levels with each message, you can have as much or as little detail as is appropriate for what you’re doing in any one moment.
Remember the config that we added into our app earlier? Well, this is where we use it - the container knows how to access our settings, and so we can grab our configuration very easily from here. With the config, we create the PDO object (remember this will throw a PDOException if it fails and you might like to handle that here) so that we can connect to the database. I’ve included two setAttribute() calls that really aren’t necessary but I find these two settings make PDO itself much more usable as a library so I left the settings in this example so you can use them too! Finally, we return our connection object.
Again, we can access our dependencies with just $this-> and then the name of the dependency we want which in this case is $this->db, so there is code in my application that looks something like:
-
$mapper = new TicketMapper($this->db);
+
$mapper=newTicketMapper($this->db);
+
This will fetch the db dependency from the DIC, creating it if necessary, and in this example just allows me to pass the PDO object straight into my mapper class.
which lists the tickets in my bug tracker example application. It just spits out the variables since we haven’t added any views to our application yet:
-
$app->get('/tickets', function (Request $request, Response $response) {
- $this->logger->addInfo("Ticket list");
- $mapper = new TicketMapper($this->db);
- $tickets = $mapper->getTickets();
+
The use of $app->get() here means that this route is only available for GET requests; there’s an equivalent $app->post() call that also takes the route pattern and a callback for POST requests. There are also methods for other verbs - and also the map() function for situations where more than one verb should use the same code for a particular route.
to refer to the ticket - and Slim has an easy way of parsing out the “42” bit and making it available for easy use in the code. Here’s the route that does exactly that:
-
Look at where the route itself is defined: we write it as /ticket/{id}. When we do this, the route will take the portion of the URL from where the {id} is declared, and it becomes available as $args['id'] inside the callback.
+
Look at where the route itself is defined: we write it as /ticket/{id}. When we do this, the route will take the portion of the URL from where the {id} is declared, and it becomes available as $args['id'] inside the callback.
The call to $request->getParsedBody() asks Slim to look at the request and the Content-Type headers of that request, then do something smart and useful with the body. In this example it’s just a form post and so the resulting $data array looks very similar to what we’d expect from $_POST - and we can go ahead and use the filter extension to check the value is acceptable before we use it. A huge advantage of using the built in Slim methods is that we can test things by injecting different request objects - if we were to use $_POST directly, we aren’t able to do that.
What’s really neat here is that if you’re building an API or writing AJAX endpoints, for example, it’s super easy to work with data formats that arrive by POST but which aren’t a web form. As long as the Content-Type header is set correctly, Slim will parse a JSON payload into an array and you can access it exactly the same way: by using $request->getParsedBody().
In order to be able to render the view, we’ll first need to create a view and make it available to our application; we do that by adding it to the DIC. The code we need goes with the other DIC additions near the top of src/public/index.php and it looks like this:
-
$container['view'] = new \Slim\Views\PhpRenderer("../templates/");
Now we have a view element in the DIC, and by default it will look for its templates in the src/templates/ directory. We can use it to render templates in our actions - here’s the ticket list route again, this time including the call to pass data into the template and render it:
-
$app->get('/tickets', function (Request $request, Response $response) {
- $this->logger->addInfo("Ticket list");
- $mapper = new TicketMapper($this->db);
- $tickets = $mapper->getTickets();
+
The only new part here is the penultimate line where we set the $response variable. Now that the view is in the DIC, we can refer to it as $this->view. Calling render() needs us to supply three arguments: the $response to use, the template file (inside the default templates directory), and any data we want to pass in. Response objects are immutable which means that the call to render() won’t update the response object; instead it will return us a new object which is why it needs to be captured like this. This is always true when you operate on the response object.
In this case, $tickets is actually a TicketEntity class with getters and setters, but if you passed in an array, you’d be able to access it using array rather than object notation here.
on the route object. In this case, I am adding the name to the route that lets me view an individual ticket so that I can quickly create the right URL for a ticket by just giving the name of the route, so my code now looks something like this (just the changed bits shown here):
-
To use this in my template, I need to make the router available in the template that’s going to want to create this URL, so I’ve amended the tickets/ route to pass a router through to the template by changing the render line to look like this:
With the /tickets/{id} route having a friendly name, and the router now available in our template, this is what makes the pathFor() call in our template work. By supplying the id, this gets used as a named placeholder in the URL pattern, and the correct URL for linking to that route with those values is created. This feature is brilliant for readable template URLs and is even better if you ever need to change a URL format for any reason - no need to grep templates to see where it’s used. This approach is definitely recomended, especially for links you’ll use a lot.
+
With the /tickets/{id} route having a friendly name, and the router now available in our template, this is what makes the pathFor() call in our template work. By supplying the id, this gets used as a named placeholder in the URL pattern, and the correct URL for linking to that route with those values is created. This feature is brilliant for readable template URLs and is even better if you ever need to change a URL format for any reason - no need to grep templates to see where it’s used. This approach is definitely recommended, especially for links you’ll use a lot.
Where Next?
@@ -426,7 +443,6 @@
Middleware section - this technique is how we layer up our application and add functionality such as authentication which can be applied to multiple routes.
-