dingo / api

A RESTful API package for the Laravel and Lumen frameworks.
BSD 3-Clause "New" or "Revised" License
9.33k stars 1.25k forks source link

Lumen AND Laravel 5 Support #398

Closed jasonlewis closed 9 years ago

jasonlewis commented 9 years ago

Hello all, I've recently pushed quite a number of changes to the develop branch that allows you to use this package in your Lumen and Laravel 5 apps.

You can require it using 0.9.*@dev.

Please note that if you're using Lumen you'll need to be using lumen-framework 5.0.*@dev for it to work correctly. These several routing changes that are yet to make it to a stable Lumen release.

A few things to note...

  1. Much of the configuration can be done via environment variables now. You can still publish the config file in Laravel 5 and make changes that way. Lumen will require you to use the environment variables. For things that can't be set with environment variables there will be a method available on the underlying instance to change whatever it is you need.
  2. There is no internal dispatcher at this point in time. I was focusing on the core of the API for now to make that that's all sweet before moving on to the internal dispatcher.
  3. There is no route command at this point in time. It will be back.
  4. There is no URL generator at this point in time. it will be back.
  5. There's no facade at the moment. You will need to get an instance of the API router (app('api.router')) to register your routes.

Here is a very quick sample of how it's now used. In your Lumen bootstrap/app.php file you'd register the Lumen provider.

$app->register('Dingo\Api\Provider\LumenServiceProvider');

// Get an instance of the API router so we can use it in the routes.php file
$api = $app['api.router'];

Now we can register our routes in the routes.php file.

$api->version('v1', function ($api) {
    $api->resource('users', 'UserController');
});

All routing methods available in L5 are available in both L5 and Lumen. This includes standard routing with get, post, etc, as well as resource and controller routes.

You can also setup group options much like in previous options (there is also an $api->group() method).

$api->version('v1', ['namespace' => 'App', 'protected' => true], function ($api) {
    $api->resource('users', 'UserController');
});

Aside from that not a whole lot has changed but there are a few new things that I'll be talking about over time. For now, I'd love it if people could give it a whirl and let me know if they come across any issues. I'll iron things out as quick as I can.

Cheers.


Another thing to note is that a prefix or domain will be required now. You can set these via the environment variables API_PREFIX or API_DOMAIN respectively, or by publishing the config and making the appropriate changes.

pc-paul commented 9 years ago

@argia-andreas Can you post your code please.

jasonlewis commented 9 years ago

@pc-paul, please see my above comment.

pc-paul commented 9 years ago

@jasonlewis I changed it to this as per your original post, but I'm getting the same error, Class api.router.adapter does not exist

Use Dingo\Api\Provider\ApiServiceProvider;

// Get an instance of the API router

$api = app('api.router');

$api->version('v1', function ($api) {
    $api->resource('property', 'PropertyController');
});
argia-andreas commented 9 years ago

@pc-paul

In config/app.php register

// Dingo
        'Dingo\Api\Provider\LaravelServiceProvider',

then in routes.php

$api = app('api.router');
$api->version('v1',['prefix' => 'api'], function ($api) {
        // $api->resource('test','testController');

});

I also forgot to publish the config.

php artisan vendor:publish

I think that should do it.

pc-paul commented 9 years ago

Thanks @jasonlewis @argia-andreas , Spotted it now. I had my config/app.php set to ApiServiceProvider and not LaravelServiceProvider. Cheers all.

pc-paul commented 9 years ago

@argia-andreas Does the command php artisan api:routes work for you? For me it says 'There are no commands in the "api" namespace'.

If I go to url http://localhost/laravel/apiv3/public/v1/property I get a NotFoundHttpException in RouteCollection.php line 145:. Something still not right with my setup.

argia-andreas commented 9 years ago

@pc-paul Paul, I don't think commands are there yet for dingo in Laravel 5. See the first post in this issue. Correct me if I'm wrong.

I've got it working.

My routes:

$api = app('api.router');
$api->version('v1',['prefix' => 'api'], function ($api) {
                $api->resource('test','App\Http\Controllers\Api\v1\TestController');
});

Url:(perhaps in your case http://localhost/laravel/apiv3/public/api/property)

domain.com/api/test

And my controller is in:

App/Http/Controllers/Api/v1/

and has namespace:

<?php namespace App\Http\Controllers\Api\v1;
argia-andreas commented 9 years ago

@jasonlewis

The config issue was my fault, it does work without publishing it.

@jasonlewis @appkr Thanks for the tips. now I got everything working.

pc-paul commented 9 years ago

@argia-andreas Many thanks. Finally seeing some JSON data!! Although I don't really follow the version number as it isn't used in the URL. I expected it to be domain.com/api/v1/test or am I missing something?

argia-andreas commented 9 years ago

@pc-paul This video by jasonlewis explains how you can use versions pretty well. https://vimeo.com/93736144

You can have the same "url" and still serve different versions of your api depending on the headers you send in the request.

appkr commented 9 years ago

I'm with L5. I'm experimenting this package. To remedy aforementioned inconsistency in pagination by @stygiansabyss, I made a direct modification at Factory::paginator to accept LengthAwarePaginator. Was not successful to have json response. Did I do something wrong?

public function index() {
    $todos = $this->model->paginate(25);
    return $this->response->paginator($todos, new TodoTransformer());
}

It returns...

// GET /api/todo

<ul class="pagination">...</ul>

UPDATE I think I made this work. Correct me if I'm wrong.

// src/Http/Response.php

-use Illuminate\Support\Contracts\ArrayableInterface;
+use Illuminate\Contracts\Support\Arrayable;

-        } elseif (is_array($content) || $content instanceof ArrayObject || $content instanceof ArrayableInterface) {
+        } elseif (is_array($content) || $content instanceof ArrayObject || $content instanceof Arrayable) {
// src/Http/Response/Factory.php

-    public function paginator(Paginator $paginator, $transformer, array $parameters = [], Closure $after = null)
+    public function paginator($paginator, $transformer, array $parameters = [], Closure $after = null)
// src/Http/Response/Format/Json.php

-use Illuminate\Support\Contracts\ArrayableInterface;
+use Illuminate\Contracts\Support\Arrayable;

-        return $value instanceof ArrayableInterface ? $value->toArray() : $value;
+        return $value instanceof Arrayable ? $value->toArray() : $value;
// src/Transformer/Adapter/Fractal.php

+use Illuminate\Pagination\LengthAwarePaginator;

-        if ($response instanceof IlluminatePaginator) {
+        if ($response instanceof IlluminatePaginator || $response instanceof LengthAwarePaginator) {

-    protected function createPaginatorAdapter(IlluminatePaginator $paginator)
+    protected function createPaginatorAdapter($paginator)

-        if ($response instanceof IlluminatePaginator || $response instanceof IlluminateCollection) {
+        if ($response instanceof IlluminatePaginator || $response instanceof IlluminateCollection || $response instanceof LengthAwarePaginator) {
+use Illuminate\Pagination\LengthAwarePaginator;

-        return $instance instanceof Collection || $instance instanceof Paginator;
+        return $instance instanceof Collection || $instance instanceof Paginator || $instance instanceof LengthAwarePaginator;

I know this is not a good solution though, it just works. Until @jasonlewis makes an official release, someone struggling against L5 pagination, if there is any, can utilize my forked one.

// composer.json of your project.

"repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/appkr/api"
    }
  ],
"require": {
    "dingo/api": "dev-l5-paginator-fix",
    ....
  },
"minimum-stability": "dev"
simplenotezy commented 9 years ago

What's the Laravel 5 Installation / usage?

I have tried:

Use Dingo\Api\Provider\ApiServiceProvider;

$api = app('api.router');

$api->version('v1', [], function() {
    Route::get('/airports', function() {
        return ['hello world'];
    });
});

Does not function. Throws error:

Class api.router.adapter does not exist
pc-paul commented 9 years ago

@canfiax You need your config/app.php to include

'Dingo\Api\Provider\LaravelServiceProvider',

Run Composer dump-autoload

You need your .env to include

API_VENDOR=LaravelApi
API_VERSION=v1
API_PREFIX=api
API_CONDITIONAL_REQUEST=true
API_STRICT=false
API_DEBUG=true
API_DEFAULT_FORMAT=json

Then in your routes, you just need

$api = app('api.router');
$api->version('v1',['prefix' => 'api'], function ($api) {
    $api->get('airports',function() {
         return ['hello world'];
    });
});

When I go to http://localhost/laravel/apiv3/public/api/airports

I get [ "hello world" ]

camilstaps commented 9 years ago

@pc-paul you actually don't need to set all those settings in .env. You can have a look in config/api.php to see what the default values are, and only put entries in .env if you wish to override them.

pc-paul commented 9 years ago

@camilstaps I'll remove mine then. Cheers.

ortix commented 9 years ago

Out of curiosity, is the internal dispatcher making progress? Or should I create my own and a PR? (which will probably take a shitton of time) My site makes heavy use of the dispatcher and I'm in the process of upgrading to L5

jasonlewis commented 9 years ago

It's in progress. Sorry about the wait.

On Mon, 25 May 2015 02:47 Nick notifications@github.com wrote:

Out of curiousity, is the internal dispatcher making progress? Or should I create my own and a PR? My site makes heavy use of the dispatcher and I'm in the process of upgrading to L5

— Reply to this email directly or view it on GitHub https://github.com/dingo/api/issues/398#issuecomment-105034736.

ortix commented 9 years ago

@jasonlewis no worries man! Every effort is appreciated! Was just curious whether I should just start on my own dispatcher or wait out the ride. I think my upgrading process is going to take a while and in the meantime I can just fire off a curl request

jasonlewis commented 9 years ago

The closure should be inside that array just like it should be in Laravel. This is how the routing has been done in Laravel for a while now. Just make it the last value in the array after expires. It does not need a key. Just the closure.

On Mon, 25 May 2015 21:51 James Healey notifications@github.com wrote:

I'm having troubles with the Rate Limiting in Lumen. It works fine in Laravel 5.

The composer.json has the following requirements:

"require": {
    "laravel/lumen-framework": "5.0.*@dev",
    "vlucas/phpdotenv": "~1.0",
    "dingo/api": "0.9.*@dev",
    "tymon/jwt-auth": "0.5.*"
},

The routes.php file contains:

/* @var $api Dingo\Api\Routing\Router / $api = $app['api.router'];

$api->version('v1', function ($api) { $api->get('welcome', ['limit' => 100, 'expires' => 5], function () { return ['Hello' => 'World!']; }); });

Without the ['limit' => 100, 'expires' => 5] parameters, it works great.

And adding the parameters in Laravel 5 works great too, but with Lumen I get the following:

Fatal error: Uncaught exception 'ErrorException' with message 'Undefined variable: closure' in /Sites/api-lumen/vendor/laravel/lumen-framework/src/Application.php on line 1197 ErrorException: Undefined variable: closure in /Sites/api-lumen/vendor/laravel/lumen-framework/src/Application.php on line 1197

Time Memory Function Location

1 0.0983 5071928 Laravel\Lumen\Application->Laravel\Lumen{closure}( ) ../Application.php:0 2 0.0983 5072064 Laravel\Lumen\Application->handleUncaughtException( ) ../Application.php:293 3 0.0987 5072064 Dingo\Api\Exception\Handler->render( ) ../Application.php:327

The api.php has the following for throttling:

'throttling' => [],

Any ideas?

— Reply to this email directly or view it on GitHub https://github.com/dingo/api/issues/398#issuecomment-105217286.

jayhealey commented 9 years ago

@jasonlewis Yeah, all good! Cheers.

hipsterjazzbo commented 9 years ago

@jasonlewis What about using ->when() to specify conditions for the route parameters? Planned?

elsodev commented 9 years ago

@jasonlewis Hi, im on L5.1.

$api = app('api.router');
$api->version('v1',['prefix' => 'api'], function ($api) {
    $api->get('test', function(){
        return 'hello';
    });
});

when i access my url /api/test

i kept on getting a 505 internal server error.

I did setup accordingly, any idea on whats wrong?

camilstaps commented 9 years ago

@elsodev A 505 error has nothing to do with Dingo or Laravel, and is not an internal server error. It means that your web server (apache, nginx, ...) does not support the HTTP version (typically 1.1 or 1.0) your browser is using. This means you are using a very old version of your server software or messed up its settings.

More common is the 500 internal server error. The most common cause to this is a PHP error. Have a look in your server log (/var/log/{apache2,nginx}/error.log or similar), it should tell you the exact problem. If you're still experiencing problems after that, please share the relevant log with us here.

Thanks!

jasonlewis commented 9 years ago

@HipsterJazzbo Can you open a separate issue please and we'll discuss it there. Cheers!

elsodev commented 9 years ago

@camilstaps Hi, thanks for replying. I checked my logs and found out

[03-Jun-2015 02:26:16 UTC] PHP Fatal error:  Uncaught exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Class 'Dingo\Api\Auth\LeagueOAuth2Provider' not found' in /Applications/MAMP/htdocs/oauth/config/api.php:126

I changed my auth to this, and it worked.

    'auth' => [
        'oauth' => function ($app) {
            $provider = new Dingo\Api\Auth\Provider\OAuth2($app['oauth2-server.authorizer']->getChecker());

            $provider->setUserResolver(function ($id) {
                // Logic to return a user by their ID.
            });

            $provider->setClientResolver(function ($id) {
                // Logic to return a client by their ID.
            });

            return $provider;
        }
    ],

Thanks again.

jayhealey commented 9 years ago

Looks like the bump from Laravel 5.0 to 5.1 killed the Lumen compatibility for the time being.

Running a composer update on Lumen returned the following:

  Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - remove dingo/api 0.9.x-dev|keep dingo/api dev-develop
    - dingo/api 0.9.x-dev requires illuminate/routing 5.1.* -> no matching package found.
    - dingo/api dev-develop requires illuminate/routing 5.1.* -> no matching package found.
    - Installation request for dingo/api 0.9.*@dev -> satisfiable by dingo/api[0.9.x-dev].

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.

I've asked Taylor if Lumen will receive a bump from 5.0 to 5.1 as well, but had no answer yet.

jasonlewis commented 9 years ago

I thought there was an alias for 5.1 for Lumen? I'm away from my computer right now but will check it out after.

On Wed, 3 Jun 2015 13:17 James Healey notifications@github.com wrote:

Looks like the bump from Laravel 5.0 to 5.1 killed the Lumen compatibility for the time being.

Running a composer update on Lumen returned the following:

Your requirements could not be resolved to an installable set of packages.

Problem 1

  • remove dingo/api 0.9.x-dev|keep dingo/api dev-develop
  • dingo/api 0.9.x-dev requires illuminate/routing 5.1.* -> no matching package found.
  • dingo/api dev-develop requires illuminate/routing 5.1.* -> no matching package found.
  • Installation request for dingo/api 0.9.*@dev -> satisfiable by dingo/api[0.9.x-dev].

Potential causes:

I've asked Taylor if Lumen will receive a bump from 5.0 to 5.1 as well, but had no answer yet.

— Reply to this email directly or view it on GitHub https://github.com/dingo/api/issues/398#issuecomment-108176082.

kostaspt commented 9 years ago

I'm getting the same error message with @jayhealey. I'm on Laravel 5.0.31.

Anahkiasen commented 9 years ago

If development is being continued on 5.1 can we get an intermediary tag for 5.0? As it was working before but can't run composer update anymore on any 5.0 apps

jasonlewis commented 9 years ago

@Anahkiasen, it crossed my mind, however, it would fall behind in terms of any security patches and feature updates. The dispatcher wouldn't be there, etc.

From what I can gather 5.1 should be out soon and will be LTS so I'd recommend that most people still developing 5.0 apps will shift to that.

jasonlewis commented 9 years ago

And for folks having issues with Lumen (or Laravel), you may need to set your minimum stability to dev in composer.json.

camilstaps commented 9 years ago

@jasonlewis also with minimum stability dev I'm experiencing issues to update now:

Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - dingo/api dev-develop requires illuminate/support 5.1.* -> satisfiable by illuminate/support[5.1.x-dev].
    - dingo/api 0.9.x-dev requires illuminate/support 5.1.* -> satisfiable by illuminate/support[5.1.x-dev].
    - dingo/api 0.9.x-dev requires illuminate/support 5.1.* -> satisfiable by illuminate/support[5.1.x-dev].
    - Conclusion: don't install illuminate/support 5.1.x-dev
    - remove dingo/api 0.9.x-dev|keep dingo/api dev-develop
    - Installation request for dingo/api 0.9.*@dev -> satisfiable by dingo/api[0.9.x-dev].

This is my composer.json, which worked fine before:

{
    "name": "camil-staps/botleagues-api",
    "description": "",
    "authors": [
        {
            "name": "Camil Staps",
            "email": "info@camilstaps.nl"
        }
    ],
    "require": {
        "php": ">=5.5.0",
        "illuminate/support": "5.0.*",
        "dingo/api": "0.9.*@dev"
    },
    "autoload": {
        "classmap": [
            "src/migrations",
            "src/controllers"
        ],
        "psr-0": {
            "CamilStaps\\BotleaguesApi\\": "src/"
        }
    },
    "minimum-stability": "dev"
}

Any ideas?

antonioribeiro commented 9 years ago

@camilstaps, you need to change your composer.json to:

"illuminate/support": "5.1.*",

As the error says:

dingo/api dev-develop requires illuminate/support 5.1.*
sebastiaanluca commented 9 years ago

@antonioribeiro @camilstaps Yeah, but laravel/lumen-framework is on ~5.0.0@dev, not 5.1.x. Was working last week.

This seems to do it:

    "require": {
        "laravel/lumen-framework": "~5.1.0@dev",
        "dingo/api": "~0.9.0@dev"
    },

    "minimum-stability": "dev",
    "prefer-stable": true
camilstaps commented 9 years ago

@antonioribeiro @sebastiaanluca ah, right, stupid of me. I assumed it was a dingo issue while it was in my own composer.json! Thanks.

sebastiaanluca commented 9 years ago

Too bad this breaks my application with almost each composer update, as even the Lumen framework composer package is not a fixed release.

Is there a way to use the latest stable Lumen release? The problem is it requires "illuminate/support": "5.0.*", but Dingo/api needs "illuminate/support": "5.1.*@dev".

( ! ) Fatal error: Class Laravel\Lumen\Application contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Illuminate\Contracts\Foundation\Application::getCachedCompilePath, Illuminate\Contracts\Foundation\Application::getCachedServicesPath) in /var/www/api-lumen/vendor/laravel/lumen-framework/src/Application.php on line 1656

catalinux commented 9 years ago

@sebastiaanluca : you should define those two mehtods on Application class for Lumen. Just define them and it will work (i know its a monkey patch, but it works)

sebastiaanluca commented 9 years ago

@catalinux Might work locally, but whenever I would update or install packages my change would be gone as the vendor directory is volatile.

I can't really pinpoint the issue. Is this due to a dev commit in the lumen framework package or something else?

catalinux commented 9 years ago

@sebastiaanluca: True, my advice was for locally development , so you won't loose time till it will be a fix

The problem was that there were added these two methods on Container class (from Contracts package) https://github.com/laravel/framework/commit/80c277a9984174b166c3fd79ab41b52dd4db8ec4, but the Lumen did not had time to update.

yanguanglan commented 9 years ago

hi, i was composer update ,but this error show;

Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - dingo/api 0.9.x-dev requires illuminate/support 5.1.* -> satisfiable by il
luminate/support[v5.1.1].
    - dingo/api 0.9.x-dev requires illuminate/support 5.1.* -> satisfiable by il
luminate/support[v5.1.1].
    - Conclusion: don't install illuminate/support v5.1.1
    - Installation request for dingo/api 0.9.*@dev -> satisfiable by dingo/api[0
.9.x-dev].

my composer.json

{
    "name": "laravel/lumen",
    "description": "The Laravel Lumen Framework.",
    "keywords": ["framework", "laravel", "lumen"],
    "license": "MIT",
    "type": "project",
    "require": {
        "laravel/lumen-framework": "5.0.*@dev",
        "vlucas/phpdotenv": "~1.0",
        "dingo/api": "0.9.*@dev"
    },
    "require-dev": {
        "phpunit/phpunit": "~4.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/"
        ]
    },
    "autoload-dev": {
        "classmap": [
            "tests/"
        ]
    },
    "config": {
        "preferred-install": "dist"
    }
}
catalinux commented 9 years ago

@yanguanglan see https://github.com/dingo/api/issues/447

You need to put in your composer.json

    "minimum-stability": "dev",
    "prefer-stable": true
camilstaps commented 9 years ago

@yanguanglan I had this problem as well, see just a bit above for the solution:

https://github.com/dingo/api/issues/398#issuecomment-109573403

jasonlewis commented 9 years ago

NOTE: Due to some new methods in a contract that is required by Laravel 5.1 the Lumen side of things will not work until such time that the Lumen framework is updated to utilize the 5.1 components. I'll be in touch with Taylor when I can to see if he's got an ETA lined up for that.

BradleyDeLar commented 9 years ago

Lumen 5.1 is due "near the end of the month" https://twitter.com/laravelphp/status/608982072804392960

jasonlewis commented 9 years ago

Excellent, cheers for the link.

On Thu, 11 Jun 2015 23:21 Bradley De-Lar notifications@github.com wrote:

Lumen 5.1 is due "near the end of the month" https://twitter.com/laravelphp/status/608982072804392960

— Reply to this email directly or view it on GitHub https://github.com/dingo/api/issues/398#issuecomment-111133501.

daimonhunter commented 9 years ago

hi I'm getting the following error on Laravel5.1 when visit url:http://localhost/api/users

{"message":"Class UsersController does not exist","code":-1,"status_code":500,"debug":{"line":736,"file":"D:\\web\\L51_demo\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Container.php","class":"ReflectionException"} ... }

my routes.php has

$api = app('api.router');
$api->version('v1',['prefix' => 'api'], function ($api) {
    $api->resource('users','UsersController');
});

and I do have UsersController.php under the app\Http\Controllers floder

any ideas?

lightvision commented 9 years ago

The controller UsersController is namespaced or not? If is namespaced you should use full namespaced class or declare the namepace property.

I've tried with namespaced controllers found on other paths too and is working.

jasonlewis commented 9 years ago

You'll need to give the full namespace as well.

On Fri, 12 Jun 2015 14:33 daimonhunter notifications@github.com wrote:

hi i'm getting the following error on Laravel5.1 when visit url: http://localhost/api/users

{"message":"Class UsersController does not exist","code":-1,"status_code":500,"debug":{"line":736,"file":"D:\web\L51_demo\vendor\laravel\framework\src\Illuminate\Container\Container.php","class":"ReflectionException"} ... }

my routes.php has

$api = app('api.router'); $api->version('v1',['prefix' => 'api'], function ($api) { $api->resource('users','UsersController'); });

and I do have UsersController.php under the app\Http\Controllers floder

any ideas?

— Reply to this email directly or view it on GitHub https://github.com/dingo/api/issues/398#issuecomment-111353374.

daimonhunter commented 9 years ago

@lightvision @jasonlewis Thanks

It's working with namespace

murwa commented 9 years ago

Hey @jasonlewis, when are we likely to have a stable version for L5.1?