laravel / ideas

Issues board used for Laravel internals discussions.
939 stars 28 forks source link

[Proposal] API Controller #279

Closed seanmangar closed 7 years ago

seanmangar commented 8 years ago

I've been using Laravel to build APIs - there's many things I think can be improved in the framework to help in making easier & more enjoyable the process of building JSON REST APIs.

One first idea, would be to bundle in the framework a controller called APIController that your API controllers can then extend from. It could include all references to HTTP status codes, handle pagination, etc...

This is inspired from this Jeffrey Way course: https://laracasts.com/series/incremental-api-development

For example:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Response as IlluminateResponse;

/**
 * Class ApiController
 */
class ApiController extends Controller {

    /**
     * @var int Status Code.
     */
    protected $statusCode = 200;

    /**
     * Getter method to return stored status code.
     *
     * @return mixed
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * Setter method to set status code.
     * It is returning current object
     * for chaining purposes.
     *
     * @param mixed $statusCode
     * @return current object.
     */
    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;

        return $this;
    }

    /**
     * Function to return an unauthorized response.
     *
     * @param string $message
     * @return mixed
     */
    public function respondUnauthorizedError($message = 'Unauthorized!')
    {
        return $this->setStatusCode(IlluminateResponse::HTTP_UNAUTHORIZED)->respondWithError($message);
    }

What do you guys think? Could this be useful?

michaeldyrynda commented 8 years ago

FYI, all of the HTTP status codes are available on the Symfony\Component\HttpFoundation\Response class

seanmangar commented 8 years ago

Thanks Michael. I'm aware of this. The idea is that this class should make it easier for beginners by 1. Setting these error codes with self explanatory method names + maybe docblock explaining when to use it and 2. Including other methods that handle pagination, metadata, etc

fbingha commented 8 years ago

I would prefer that the work done on Dingo API be pulled into the core.

dugajean commented 8 years ago

I have made something similar in the past. I made a trait that handles API responses pretty nicely in Laravel. Have a look at it and maybe it will be of use:

https://gist.github.com/dugajean/3798c9d482a18f9bd8c0cb31c4b14403

skyrpex commented 7 years ago

Being able to set the status code anywhere in the controller feels very bad to me (makes harder to read, debug, etc). Don't you feel the same?

I currently use abort and authorize in my API controllers. I even created a trait that basically provides an authorizeOrNotFound method that aborts with a 404 status code if the gate denies the ability.

On the other hand, using a standard pagination would be more than useful (related issue here)

seanmangar commented 7 years ago

@skyrpex You're right. Since I posted this, I've moved to handling exceptions and returning the right formatted responses & status code in the ExceptionHandler class. Much better to debug, provide http status code, headers, etc. (esp when SymfonyHttpException is thrown).

Garbee commented 7 years ago

I don't see how this is necessary at all to be included by default. There are tons of ways to do your controllers and to structure responses. And having a setter for the response code is... needless. You can just set the status code on your returned response object using the right parameter in most methods.

What benefit is this supposed to provide in projects? Besides some "here's a sort-of default way to do this."

seanmangar commented 7 years ago

@Garbee I agree with your point of view. Please see response above. This was posted in October 2016 when I was a bit naive about such things.

Garbee commented 7 years ago

Then close the issue out?

seanmangar commented 7 years ago

How do I do that? Tried to close it, but can't see anything that lets me do that.

brunogaspar commented 7 years ago

@seanmangar Right next to the comment button you'll see a "Close Issue" button.