Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slim 4 Alpha Release Feedback #2653

Closed
l0gicgate opened this issue Apr 23, 2019 · 50 comments
Closed

Slim 4 Alpha Release Feedback #2653

l0gicgate opened this issue Apr 23, 2019 · 50 comments

Comments

@l0gicgate
Copy link
Member

l0gicgate commented Apr 23, 2019

Slim 4 Alpha Release
See the full release notes

Before doing anything read the docs
I just finished the first draft of the docs for Slim 4 which are available here. I need feedback please:
http://dev.slimframework.com/docs/v4

Download an test the 4.0.0-alpha release
You may also play around with the 4.x branch and create a simple app with it to test things out.
composer require slim/slim:4.0.0-alpha

Install a PSR-7 Implementation
You will also need to install a PSR-7 implementation and ServerRequestCreator combo. You can use Slim's PSR-7 Implementation or choose one of the ones described on the 4.x branch README: https://github.com/slimphp/Slim/blob/4.x/README.md
composer require slim/psr7:dev-master

Slim 4 DDD API Skeleton Prototype
I also just created a Slim4 Skeleton with a DDD style directory structure with example files and test coverage for everything. I'm not sure if it's the right fit yet as it may be a bit too opinionated but I'd love some feedback:

git clone https://github.com/l0gicgate/Slim-Skeleton
git checkout 4.x

If you have any questions don't hesitate to ping me on Slack or ask questions in this thread directly, I'm available to help!

@RyanNerd
Copy link
Contributor

@l0gicgate Just a little nitpik:
The link to "contributing: Branching Strategy" on this page: http://slim-website.lgse.com/docs/v4/cookbook/uploading-files.html -- Links to version 3 (http://slim-website.lgse.com/docs/v3/contributors/strategy.html)

@l0gicgate
Copy link
Member Author

l0gicgate commented Apr 25, 2019

Good catch @RyanNerd! Fixed

@RyanNerd
Copy link
Contributor

@l0gicgate Version 3 has a Tutorial link with a guide to creating a "first application". Slim 4 with all the decoupling and plug-in choices (PSR-7, Containers, Route & ErrorHandling as middleware, etc.) is much more complex than Slim 3. This can be overwhelming to someone new to Slim (and even those like myself that are familiar with version 3).
Perhaps the docs could include a Tutorial for v4 showing how to create a "first application" using bare bones concepts and the plug-in defaults.

@l0gicgate
Copy link
Member Author

l0gicgate commented Apr 25, 2019

@RyanNerd I removed the tutorial from the v4 docs for now. It does need to be written and will be added to the docs later. In the mean time someone can look at the skeleton repository to see how things are implemented in a "real life" scenario.

I also think that a video tutorial would be much better. I just need time to get it done.

@l0gicgate l0gicgate changed the title Slim 4 Pre-Beta Testing Slim 4 Alpha Release Feedback Apr 25, 2019
@Antnee
Copy link

Antnee commented Apr 25, 2019

Install a PSR-7 Implementation
You will also need to install a PSR-7 implementation and ServerRequestCreator combo. You can use Slim's PSR-7 Implementation or choose one of the ones described on the 4.x branch README: https://github.com/slimphp/Slim/blob/4.x/README.md
composer slim/psr-7:dev-master

composer require slim/psr-7:dev-master 😉

@bednic
Copy link
Contributor

bednic commented Apr 26, 2019

Install a PSR-7 Implementation
You will also need to install a PSR-7 implementation and ServerRequestCreator combo. You can use Slim's PSR-7 Implementation or choose one of the ones described on the 4.x branch README: https://github.com/slimphp/Slim/blob/4.x/README.md
composer slim/psr-7:dev-master

composer require slim/psr-7:dev-master 😉

composer require slim/psr7:dev-master it's not "psr-7"

@Antnee
Copy link

Antnee commented Apr 26, 2019

See if you can tell who didn't run it but commented anyway... 😆

@l0gicgate
Copy link
Member Author

@RyanNerd simply return a response object without calling $handler->handle($request)

@davidbyoung
Copy link

It looks like ErrorHandler will only catch exceptions thrown from further down the middleware stack. What about exceptions/errors thrown before then, eg a misconfiguration throwing an exception when initializing everything? Would you just register methods within ErrorHandler to the PHP exception and error handlers via set_error_handler() and set_exception_handler() to handle those?

@l0gicgate
Copy link
Member Author

@davidbyoung I documented on how to handle all errors in the docs under Notices & Warnings handling. This shows a more advanced way of handling all errors. See http://dev.slimframework.com/docs/v4/objects/application.html#notices-and-warnings-handling

@holtkamp
Copy link

Note the "Edit this page" links in the documentation refer to something like:

https://github.com/slimphp/Slim-Website/tree/gh-pages/docs/v4/objects/routing.md

which does not exist, while

https://github.com/slimphp/Slim-Website/tree/gh-pages-4.x/docs/v4/objects/routing.md

Should I create an issue for this? Or is it expected "for now"... 😄

@l0gicgate
Copy link
Member Author

@holtkamp thanks for reporting this. It has to stay the same until I merge the gh-pages-4.x branch into gh-pages which won't be until Slim 4 is released. It'll have to stay broken for a bit 😂

@sander-bol
Copy link
Contributor

In the documentation and the readme file, index.php refers to '/vendor/autoload.php'. This seems to suggest that the vendor directory should be placed within the public directory, where index.php lives. That seems pretty dangerous. Would it make sense to change to this to refer to __DIR__ . '/../vendor/autoload.php' instead?

@michaelbiberich
Copy link
Contributor

How about adding suggestions for the PSR-7 implementations mentioned in the README.md to composer.json?

{
    "suggest": {
        "slim/psr7": "This is the Slim Framework projects PSR-7 implementation.",
        ...
    }
}

See: https://getcomposer.org/doc/04-schema.md#suggest

@bednic
Copy link
Contributor

bednic commented Apr 28, 2019

Hi, I have a question about default middleware implementation. But first I need to clear my understanding the idea abou using this framework. When I look at your setup of App, it seems like whole idea is setup app via DI, cause the factories etc., is that right? Second is about middleware, I get idea, like all is middleware so everything is implemented same way. But It seems like I need to setup everyting by myself, is it right conclusion? And at the end, wouldn't be better if basic middlewares, like RouteMiddleware and ErrorMiddleware has been setup automaticly?

@l0gicgate
Copy link
Member Author

l0gicgate commented Apr 28, 2019

@bednic the App can run without a container. It sure makes one’s life a lot easier to provide one though.

RoutingMiddleware is added by default if the user does not add it to the middleware queue. It will run last however, which means that the routing data won’t be available through the middleware stack if you have other middleware that depends on it.

As for ErrorMiddleware you need to place it at the outer most edge of your application (add it last, right before run, so it runs first) and we can’t automatically add it based on assumptions otherwise it wouldn’t behave correctly.

@danielspk
Copy link

Hello.

Missing an example of using sessions with cookies

@l0gicgate
Copy link
Member Author

@danielspk I'm not sure exactly how to show an example of that since Slim doesn't handle sessions. That's typically something you'd implement via middleware or if you want sessions turned on at all times just use session_start() after the require __DIR__ . '/../vendor/autoload.php';

@Serdan
Copy link

Serdan commented May 3, 2019

I can't get the middleware examples to work.
e.g.: http://dev.slimframework.com/docs/v4/concepts/middleware.html#application-middleware
From what I can tell, the 'BEFORE' middleware prevents the route from being called.. somehow.

EDIT: I've figured out how it works, but the example remains incredibly confusing. As far as I can tell there's no way to write to the body in middleware before the route does its thing.

@adriansuter
Copy link
Contributor

Hi, I made a simple repository that uses travis-ci to automatically test the slim4 framework against multiple PSR-7 implementations. See https://github.com/adriansuter/Slim4-CI

Currently, all are working fine!

@l0gicgate
Copy link
Member Author

Awesome @adriansuter thank you. You should join our Slack so we can chat

@RyanNerd
Copy link
Contributor

RyanNerd commented May 7, 2019

I'm having trouble with POST requests always returning null for getParsedBody()
I'm testing using Insomnia POST payload like {"test":"test"}

Here's the code:

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Middleware\ErrorMiddleware;
use Slim\Middleware\RoutingMiddleware;

require __DIR__ . '/vendor/autoload.php';

$app = AppFactory::create();

// Add Routing Middleware
$routeResolver = $app->getRouteResolver();
$routingMiddleware = new RoutingMiddleware($routeResolver);
$app->add($routingMiddleware);

// Error middleware
$callableResolver = $app->getCallableResolver();
$responseFactory = $app->getResponseFactory();
$errorMiddleware = new ErrorMiddleware($callableResolver, $responseFactory, true, true, true);
$app->add($errorMiddleware);

// Define app routes
$app->post('/posttest', function (Request $request, Response $response, $args) {
    $content = $request->getParsedBody();
    if ($content === null) {
          $response->getBody()->write('Error no JSON in request body or something else?!?!?!?!?');
    } else {
        $response->getBody()->write('getParsedBody() actually worked');
    }
    return $response;
});

// Run app
$app->run();

@Serdan
Copy link

Serdan commented May 7, 2019

@RyanNerd - parsedBody gets populated with $_POST, but in PHP you have to get JSON data from php://input
As far as I can tell there's no method in Slim to retrieve JSON, so you'll have to do it manually I guess.

@holtkamp
Copy link

holtkamp commented May 7, 2019

@RyanNerd maybe related to this:

slimphp/Slim-Psr7#38, which is fixed already.

When doing your POST request, what headers are sent in the request?

@RyanNerd
Copy link
Contributor

RyanNerd commented May 7, 2019

@Serdan The docs state differently :

Every HTTP request has a body. If you are building a Slim application that consumes JSON or XML data, you can use the PSR-7 Request object’s getParsedBody() method to parse the HTTP request body into a native PHP format. Slim can parse JSON, XML, and URL-encoded data out of the box.

$parsedBody = $request->getParsedBody();

@RyanNerd
Copy link
Contributor

RyanNerd commented May 7, 2019

@l0gicgate I think the docs need to be corrected. Not every HTTP request has a body (per the HTTP spec all requests MAY have a body),
For a GET request for example $request->getParsedBody() should return a null if no body exists.

@holtkamp
Copy link

holtkamp commented May 7, 2019

#2653 (comment)

To get parsed, I think the ContentType header in the POST request should contains something like:

  • application/x-www-form-urlencoded
  • multipart/form-data

Also see this line https://github.com/slimphp/Slim-Psr7/blob/bd3737bc6fe94d4ba30febe3aa7bc25d3f07f6ca/src/Factory/ServerRequestFactory.php#L105

@l0gicgate
Copy link
Member Author

l0gicgate commented May 7, 2019

@RyanNerd I need to update the docs for sure. Slim PSR-7 does not parse the body like Slim 3 used to. All that functionality has been moved over to Slim-Http. However you can write simple middleware to parse the body and append it to the incoming Request object.

In case of application/json content type, it's not valid $_POST data, hence why you can't retrieve it from there.

In order for actual form data to be parsed it needs to be a POST request and the Content-Type header needs to be application/x-www-form-urlencoded or multipart/form-data.

Note that this is very basic middleware and you could add more content types.

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as RequestInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class JsonBodyParserMiddleware implements MiddlewareInterface {
    public function process(Request $request, RequestHandler $handler): Response
    {
        $contentType = $request->getHeaderLine('Content-Type');

        if (strstr($contentType, 'application/json')) {
            $contents = json_decode(file_get_contents('php://input'));
            if (json_last_error() !== JSON_ERROR_NONE) {
                $request = $request->withParsedBody($contents);
            }
        }

        return $handler->handle($request);
    }
}

In any case, I will update the docs to remove the outdated portion of the docs about parsing the body.

@magikstm
Copy link

magikstm commented May 7, 2019

Is there a release schedule of Slim's 4.x branch available?

Until when is Slim's 3.x branch planned to be maintained?

I'm about to start a new project and I'm hesitating between which branch to use for it.

@RyanNerd
Copy link
Contributor

RyanNerd commented May 7, 2019

@magikstm I don't know the scope of your project but I've started a new project using 4.x alpha and other than one misunderstanding (on my part, and partly because the docs were unclear) I've not had any issues.
One of the big differences between 3 and 4 is the amount of setup of middleware you need to have in place -- even the error handling is middleware (this is a good thing) just something to know going in: There's some configurations you need to set up in 4.x that were already in place with version 3.x.
Slim 4 is in alpha so there's a risk that things could change. I'm aware of this risk and that my project must play along with Slim until it is production ready.
One of the reasons I decided to go this route (no pun intended) was to help test 4.x and post issues here as I came upon them.
Issues have mostly been with the documentation differing with how 3.x did things and not issues with the Slim 4.x app itself.
HTH

@RyanNerd
Copy link
Contributor

RyanNerd commented May 8, 2019

Question: Is there a performance or other advantages to have a middleware class implements MiddlewareInterface as opposed to using the __invoke() method?

@l0gicgate
Copy link
Member Author

@magikstm the 4.x branch is pretty stable despite being in alpha. I'd go with Slim 4 if you're starting a new project.

@l0gicgate
Copy link
Member Author

@RyanNerd no significant difference between the two.

@adriansuter
Copy link
Contributor

adriansuter commented May 8, 2019

As @Serdan mentioned already, the example code in the documentation is not working as expected.

I can't get the middleware examples to work.
e.g.: http://dev.slimframework.com/docs/v4/concepts/middleware.html#application-middleware
From what I can tell, the 'BEFORE' middleware prevents the route from being called.. somehow.

EDIT: I've figured out how it works, but the example remains incredibly confusing. As far as I can tell there's no way to write to the body in middleware before the route does its thing.

I just created an issue for that. slimphp/Slim-Website#356

@tfukuda-ww
Copy link

I would like to ask Slim 4.x support Doctrine ORM?

@l0gicgate
Copy link
Member Author

@engineer-log you can use Doctrine ORM, Eloquent, or any other persistence library alongside with Slim.

@bednic
Copy link
Contributor

bednic commented May 9, 2019

I was thinking what probably most of you are dealing with and I presume that most scenario is building some API, probably REST. Whole back-end based on SlimPHP maybe with Doctrine, maybe with Eloquent. I'm currently working on library for the API part. It's implementation of JSON API ,but annotation based. So if you are using Doctrine, you get my idea rly quick. So if is someone interested, I would appreciate every idea or help. It's my first library, so i don't know how to get feedback.

I don't know if this isn't too unpolite 🤔, advertise my library here. But I'm using combo Slim + Doctrine + API some time, and I think maybe it will help someone. But if this doesn't belong here I will delete it and of course I'm sorry.

P.S.: Good work, this is most clean and straightforward framework I ever seen. I was searching for this kind of framework for a years! Thank you, all of you.👍

@l0gicgate
Copy link
Member Author

@bednic that's cool! I went through the README of your repo and I understand what you're doing. I'd like to see an example of a route with Slim 4 😄 you should put a skeleton repository together with Doctrine, Slim and your JSON API library!

@RyanNerd
Copy link
Contributor

Like @bednic I've been working on a framework as well called Willow.
Willow is a marriage between Slim 4 & Eloquent. Documentation is here.
Let me know what you think.

@holtkamp
Copy link

holtkamp commented May 10, 2019

a bit off-topic (sorry), but @bednic: you check these libraries for usage with JSON-API by @kocsismate, very elegant and clean!

@bednic
Copy link
Contributor

bednic commented May 10, 2019

@holtkamp

a bit off-topic (sorry), but @bednic: you check these libraries for usage with JSON-API by @kocsismate, very elegant and clean!

That kind of library is the reason why I make my own. Almost in every library it's necessary to create some ResourceObject, then gather all attributes and relationships, pass them to object, or schema and then serialize object to valid JSON. My library map all attributes and relationships by annotations, same as Doctrine. I'm gathering most of needed informations by reflection. If you are writing code standardized like object with private props with getters and setters, then I don't need anything else and just make valid JSON-API document for you from your object(s). It's much less writing.

@Incisakura
Copy link

Incisakura commented May 15, 2019

HomeController:

class HomeController
{
    public function __construct()
    {
        $renderer = new \Slim\Views\PhpRenderer();
        // other codes...
        return $renderer;
    }

    public function index(Request $request, Response $response, $args): Response
    {
        return $this->renderer->render([$response], 'index.phtml');
    }
    // other functions...
}
  • The [$response] is expected to be $response.

Middleware:

$callableResolver = $app->getCallableResolver();
$responseFactory = $app->getResponseFactory();
$errorMiddleware = new ErrorMiddleware($callableResolver, $responseFactory, false, false, false);
$handler = function ($request, $exception, $displayErrorDetails, $logErrors, $logErrorDetails) {
    $code = $exception->getCode();
    $response = new Slim\Psr7\Response();
    switch ($code) {
        case 404:
            return $response->withHeader('Location', '/404')->withStatus(302);
        case 405:
            return $response->withHeader('Location', '/405')->withStatus(302);
        case 500:
            return $response->withHeader('Location', '/500')->withStatus(302);
    }
};
$errorMiddleware->setDefaultErrorHandler($handler);
$app->add($errorMiddleware);

Route:

$app->get('/', \HomeController::class . ':index');

I expected to get a Slim 500 error with details and trace.
But i actually got...

Fatal error:  Uncaught TypeError: Return value of Slim/Middleware/ErrorMiddleware::handleException() must implement interface Psr/Http/Message/ResponseInterface, null returned in /path/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php:109
Stack trace:
#0 /path/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php(91): Slim/Middleware/ErrorMiddleware->handleException(Object(Slim/Psr7/Request), Object(TypeError))
#1 /path/vendor/slim/slim/Slim/MiddlewareDispatcher.php(123): Slim/Middleware/ErrorMiddleware->process(Object(Slim/Psr7/Request), Object(class@anonymous))
#2 /path/vendor/slim/slim/Slim/MiddlewareDispatcher.php(64): class@anonymous->handle(Object(Slim/Psr7/Request))
#3 /path/vendor/slim/slim/Slim/App.php(136): Slim/MiddlewareDispatcher->handle(Object(Slim/Psr7/Request))
#4 /path/vendor/slim/slim/Slim/App.php(120): in /path/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php on line 109

@bednic
Copy link
Contributor

bednic commented May 15, 2019

It might be problem with Eception::getCode(), maybe it's not Slim HttpException and therefore getCode might return 0, in which case return value from handler will be null.

@Incisakura
Copy link

Yeah..You are right...Sorry for my bother.

@l0gicgate
Copy link
Member Author

@SakuraSa233 hence why you should always handle default cases, this is a prime example of it.

@Incisakura
Copy link

Here is another question is that my Slim 3 code always get undefined method Slim\Psr7\Request::getParam() in Slim 4.

public function update($request, $response, $args)
{
    $data = $request->getParam('data');
    // ...
}

I have known that getParam() is in SlimHttp, how can I use it to adapt my project?

@l0gicgate
Copy link
Member Author

l0gicgate commented May 19, 2019

@SakuraSa233 do you have Slim-Http decorators installed?

Also you may need to require the 4.x branch right now instead of the 4.0.0-alpha pre-release since the automatic detection for Slim-Http decorators isn’t in the 4.0.0-alpha release.

@l0gicgate
Copy link
Member Author

Closing this. Follow thread in Slim 4 Beta Release Feedback Thread.

@http200it
Copy link

There is some mistake. The HTTP 200 status is returned with the middleware of the example and the HTTP 404 return code

`
$app->add(function (Request $request, RequestHandler $handler) {
$response = $handler->handle($request);
$existingContent = (string) $response->getBody();

$response = new Response();
$response->getBody()->write('BEFORE-' . $existingContent);
return $response;

});

$app->add(function (Request $request, RequestHandler $handler) {
$response = $handler->handle($request);
$response->getBody()->write('AFTER ');
return $response;
});

$app->get('/', function (Request $request, Response $response, $args) {

$response->getBody()->write('-Hello World  -');
//throw new Slim\Exception\HttpNotFoundException($request, "Product not found..."); // Does not work returns 200
return $response->withStatus(404); // <<<  Does not work returns 200
//return $response;

});

$app->run();

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests