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.

develpr commented 9 years ago

<3 Thank you Jason!

jinqibu commented 9 years ago

thanks a lot!

devmark commented 9 years ago

thanks!

bweston92 commented 9 years ago

Happiest day of my life. Can't wait for work tomorrow aha!!

— Sent from Mailbox

On Sun, May 17, 2015 at 7:13 AM, Mark notifications@github.com wrote:

thanks!

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

akhedrane commented 9 years ago

Thank you. can we use one routing syntax in both illuminate & fastroute?

jasonlewis commented 9 years ago

Correct. All routing methods are available for both Lumen and L5.

On Sun, 17 May 2015 17:31 Atallah khedrane notifications@github.com wrote:

Thank you. can we use one routing syntax in both illuminate & fastroute?

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

irazasyed commented 9 years ago

Awesome Jason, Thanks :+1:

jasonlewis commented 9 years ago

Update. All routing methods now work in Lumen. There were issues with resource and controller routes that have now hopefully be resolved. :smile:

bslinger commented 9 years ago

Great work Jason, I've been looking forward to using Dingo for a new project so I'm glad to see this moving forward. Thanks for being patient through the constant storm of 'when is this coming' and '+1' !

xLink commented 9 years ago

Ah awesome @jasonlewis been waiting for this so I can finish my Base Upgrade :D

Will get it tested out and throw any issues I find back :)

Thanks Dude

moltar commented 9 years ago

How do I use this? It seems like the latest tag is 0.8? Did you forget to push?

vinkla commented 9 years ago

@moltar You can use it as 0.9.*@dev since this release is still an alpha version

moltar commented 9 years ago

I get the following error:

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

  Problem 1
    - Can only install one of: league/fractal[0.11.0, 0.12.0].
    - Can only install one of: league/fractal[0.12.0, 0.11.0].
    - Can only install one of: league/fractal[0.11.0, 0.12.0].
    - dingo/api 0.9.x-dev requires league/fractal 0.11.* -> satisfiable by league/fractal[0.11.0].
    - Installation request for dingo/api 0.9.*@dev -> satisfiable by dingo/api[0.9.x-dev].
    - Installation request for league/fractal == 0.12.0.0 -> satisfiable by league/fractal[0.12.0].

As I had league/fractal installed via another package. And even after removing that dep, I still get this error. Any chance just updating league/fractal to 0.12?

vinkla commented 9 years ago

@moltar This will be fixed in https://github.com/dingo/api/pull/401. Out of curiosity, what other package do you have installed that uses Fractal?

ucheng commented 9 years ago

this is awesome! Thank you!

kostaspt commented 9 years ago

Good job, thanks! :+1:

otherjohn commented 9 years ago

How do you register for laravel. I see a LaravelServiceProvider and the APIServiceProvider. Which one do I put in the Laravel 5 App Config?

vinkla commented 9 years ago

@otherjohn The LaravelServiceProvider is the only one required for a Laravel 5 application.

otherjohn commented 9 years ago

Thanks

vinkla commented 9 years ago

@otherjohn Maybe you could create a separate issue for your error?

otherjohn commented 9 years ago

Thanks, did.

oriceon commented 9 years ago
$api->version('v1', function($api) {
    $api->get('users', function() {
        return ['users' => 'all'];
    });
});

What`s wrong here? I call api via http://lumen.dev/api/users and get

{
    message: "404 Not Found",
    status_code: 404
}
jasonlewis commented 9 years ago

Need to add the prefix to your route group as well.

I should probably automate that...

On Tue, 19 May 2015 17:03 Valentin Ivaşcu notifications@github.com wrote:

$api->version('v1', function($api) { $api->get('users', function() { return ['users' => 'all']; }); });

What`s wrong here? I call api via http://lumen.dev/api/users and get

{ message: "404 Not Found", status_code: 404 }

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

oriceon commented 9 years ago

I added prefix because i used it in .env file

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

Edit:

Ah, i got it:

$api->version(['version' => 'v1'], function($api) {
    $api->group(['prefix' => 'api'], function ($api) {

        $api->get('users', function() {
            return ['users' => 'all'];
        });

    });
});
jasonlewis commented 9 years ago

Yeah you'll need to specify it in your route as part of the URI or add it to the group as a prefix. It doesn't automatically add the prefix to the routes.

On Tue, 19 May 2015 at 17:30 Valentin Ivaşcu notifications@github.com wrote:

I added prefix because i used it in .env file

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

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

catalinux commented 9 years ago

@oriceon: What url does work for the code above?

My route: /api/users it says: NotFoundHttpException in Application.php line 1136:

Does the API_VENDOR=LumenApi has to match some namespace from your code?

UPDATE : I use Lumen

jasonlewis commented 9 years ago

@oriceon, change your code to this:

$api->version('v1', ['prefix' => 'api'], function($api) {
        $api->get('users', function() {
            return ['users' => 'all'];
        });
});

The first argument for version should always be a version (or array of versions), the second argument can be an array of options (or the closure), and the third is the closure if you supplied the array of options.

API_VENDOR is the vendor name used when building the Accept header. This is usually a shorthand name like app or github. Keep it short and simple.

vinkla commented 9 years ago

In version 0.8.* we had a ControllerTrait to handle responses, how do we handle responses in Laravel 5? Like this new Response()?

jasonlewis commented 9 years ago

There is a Helpers trait in the routing namespace. Have a flick through that. It's much the same as the old trait.

On Tue, 19 May 2015 20:25 Vincent Klaiber notifications@github.com wrote:

In version 0.8.* we had a ControllerTrait to handle responses, how do we handle responses in Laravel 5? Like this new Response()?

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

pc-paul commented 9 years ago

Trying to install Laravel 5, along with the API. Looks like people have this working. What am I doing wrong? Here is my composer.json and the output I'm getting. What should my require be?

{ "name": "laravel/laravel", "description": "The Laravel Framework.", "keywords": ["framework", "laravel"], "license": "MIT", "type": "project", "require": { "laravel/lumen-framework": "5.0.@dev", "dingo/api": "0.9.@dev", "league/fractal": "0.13.*@dev"
}, "require-dev": { "phpunit/phpunit": "~4.0", "phpspec/phpspec": "~2.1" }, "autoload": { "classmap": [ "database" ], "psr-4": { "App\": "app/" } }, "autoload-dev": { "classmap": [ "tests/TestCase.php" ] }, "scripts": { "post-install-cmd": [ "php artisan clear-compiled", "php artisan optimize" ], "post-update-cmd": [ "php artisan clear-compiled", "php artisan optimize" ], "post-create-project-cmd": [ "php -r \"copy('.env.example', '.env');\"", "php artisan key:generate" ] }, "config": { "preferred-install": "dev" } }

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

Potential causes:

Read https://getcomposer.org/doc/articles/troubleshooting.md for further commo n problems.

vinkla commented 9 years ago

@jasonlewis Aah, thanks!

@pc-paul You've to remove "league/fractal": "0.13.*@dev" from your required dependencies.

pc-paul commented 9 years ago

@vinkla Thanks for help, removed fractal, but still an error:-

Loading composer repositories with package information Updating dependencies (including require-dev)

dingo/api suggests installing tymon/jwt-auth (Protect your API with JSON Web Tok ens) dingo/api suggests installing lucadegasperi/oauth2-server-laravel (Protect your API with OAuth 2.0.) Writing lock file Generating autoload files

[Symfony\Component\Debug\Exception\FatalErrorException] Call to undefined method Illuminate\Foundation\Application::getCachedCompil ePath()

Script php artisan clear-compiled handling the post-update-cmd event returned wi th an error

[RuntimeException] Error Output:

update [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--lock] [--no-plugins] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no- progress] [--with-dependencies] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [packages1] ... [p ackagesN]

pc-paul commented 9 years ago

@vinkla Fixed it, I originally created my project using "Composer create-project laravel/laravel ... ", when I deleted this project and recreated with "Composer create-project laravel/lumen ..." and then setup my require to

"laravel/lumen-framework": "5.0.*@dev",
"vlucas/phpdotenv": "~1.0",
"dingo/api": "0.9.*@dev"

everything worked. Thanks for your help.

vinkla commented 9 years ago

@pc-paul :+1:

pc-paul commented 9 years ago

Spoke too soon. Lumen is too light weight. I need Laravel 5. I've created a new Laravel 5 installation, then set my "require" to as below, but getting the following messages

"require": {
    "laravel/framework": "5.0.*",
    "vlucas/phpdotenv": "~1.0",
    "dingo/api": "0.9.*@dev"
    }

Output from Composer update

Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files

[Symfony\Component\Debug\Exception\FatalErrorException] Call to undefined method Illuminate\Foundation\Application::getCachedCompil ePath()

Script php artisan clear-compiled handling the post-update-cmd event returned wi th an error

[RuntimeException] Error Output:

update [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--lock] [--no-plugins] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no- progress] [--with-dependencies] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [packages1] ... [p ackagesN]

pc-paul commented 9 years ago

To answer my own question, Deleting the vendor/compiled.php fixed this issue.

KIVagant commented 9 years ago

About transformers in L5

ErrorException in Factory.php line 75:
collection() expects at least 2 parameters, 1 given

Why I always must send 'new Transformer' to collection() and other methods? From wiki: "Transformers allow you to easily and consistently transform objects into an array." But collection can be transformed into array with ->toArray() method.

How I can create MyCustomTransformer in Laravel 5? TransformerInterface does not exists.

UP: Hints from me to myself:

  1. Use return $this->response()->array($objects_collection->toArray()); instead of return $this->response()->collection($objects_collection, new MyTransformer($forecasts));
  2. Use class MyTransformer extends TransformerAbstract {} instead of implements TransformerInterface
stygiansabyss commented 9 years ago

Anyone else getting

Fatal error: Uncaught exception 'ErrorException' with message 'Argument 1 passed to Dingo\Api\Http\Response\Factory::paginator() must be an instance of Illuminate\Pagination\Paginator, instance of Illuminate\Pagination\LengthAwarePaginator given

In lumen? The code that is generating that is as follows.

    public function index()
    {
        $videos = $this->model->paginate(20);

        return $this->response->paginator($videos, new VideoTransformer);
    }

Update

Switching the call to simplePaginate fixes the Dingo error, but Fractal wants a LengthAwarePaginator. There is a disconnect between Dingo\Api\Http\Response\Factory and League\Fractal\Pagination\IlluminatePaginatorAdapter.

jasonlewis commented 9 years ago

I'll probably need to update the pagination code.

On Wed, 20 May 2015 04:34 Stygian notifications@github.com wrote:

Anyone else getting

Fatal error: Uncaught exception 'ErrorException' with message 'Argument 1 passed to Dingo\Api\Http\Response\Factory::paginator() must be an instance of Illuminate\Pagination\Paginator, instance of Illuminate\Pagination\LengthAwarePaginator given

In lumen? The code that is generating that is as follows.

public function index()    {        $videos = $this->model->paginate(20);        return $this->response->paginator($videos, new VideoTransformer);    }

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

stygiansabyss commented 9 years ago

Added a PR. Hope it helps.

pc-paul commented 9 years ago

Laravel 5 API - Added this to bootstrap\app.php

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

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

My .env set to

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

My route set as

$api->version('v1', function ($api) {
    $api->group(['prefix' => 'api'], function ($api) {
        $api->resource('property', 'PropertyController');
    });
});

I'm getting the following error:-

[20-May-2015 16:05:40 Europe/Berlin] PHP Fatal error: Uncaught exception 'ReflectionException' with message 'Class log does not exist' in C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php:776 Stack trace:

0 C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php(776): ReflectionClass->__construct('log')

1 C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php(656): Illuminate\Container\Container->build('log', Array)

2 C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Foundation\Application.php(644): Illuminate\Container\Container->make('log', Array)

3 C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php(887): Illuminate\Foundation\Application->make('Psr\Log\LoggerI...')

4 C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php(848): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter))

5 C:\xampp\htdocs\laravel\apiv2\ven in C:\xampp\htdocs\laravel\apiv2\vendor\laravel\framework\src\Illuminate\Container\Container.php on line 776

argia-andreas commented 9 years ago

@pc-paul I'm getting the same error as you trying to get it to work with homestead/laravel5.

Has anyone got it to work with Laravel 5?

This is my composer:

"require": {
        "laravel/framework": "5.0.*",
        "dingo/api": "0.9.*@dev"
    },

and this is my bootstrap/app.php

// This is when everything breaks :-(
$app->register('Dingo\Api\Provider\LaravelServiceProvider'); 
// Get an instance of the API router so we can use it in the routes.php file
$api = $app['api.router'];
return $app;

And this is my .env

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

If any of you have it working with L5 what did you do different?

jasonlewis commented 9 years ago

Register the package in your config/app.php. You're using Laravel 5 you don't need to register it in the bootstrap file. That's probably my bad, but the demo I posted in my OP was for Lumen.

You'll also need to get the router instance in your routes.php file and not the bootstrap file.

Sorry I should've noted that.

appkr commented 9 years ago

@argia-andreas Been there. I could get router instance like this: $api = app('api.router'); at routes.php

argia-andreas commented 9 years ago

@appkr Thanks, but i get the following error:

ErrorException in Handler.php line 53:
Argument 2 passed to Dingo\Api\Exception\Handler::__construct() must be of the type array, null given, called in /home/vagrant/Code/api/vendor/dingo/api/src/Provider/ApiServiceProvider.php on line 97 and defined in Handler.php line 53

I'm registering the service provider in config/app.php.

Did you get that as well?

jasonlewis commented 9 years ago

@argia-andreas Sounds like some configuration is getting mixed up. Have you done anything to any of the configuration values?

pc-paul commented 9 years ago

Config/app.php now has

'Dingo\Api\Provider\ApiServiceProvider',

with no Aliases as Facade not available.

Routes.php :

Use Dingo\Api\Provider\ApiServiceProvider;

// Get an instance of the API router
$api = app('api.router');
Route::API('v1', function () {
    Route::resource('property', 'PropertyController');
});

Composer.json

"laravel/framework": "5.0.*",
"vlucas/phpdotenv": "~1.0",
"dingo/api": "0.9.*@dev"

Getting the following error:

ReflectionException in Container.php line 776: Class api.router.adapter does not exist in Container.php line 776

at ReflectionClass->__construct('api.router.adapter') in Container.php line 776 at Container->build('api.router.adapter', array()) in Container.php line 656 at Container->make('api.router.adapter', array()) in Application.php line 644 at Application->make('api.router.adapter') in Container.php line 1231 at Container->offsetGet('api.router.adapter') in ApiServiceProvider.php line 140 at ApiServiceProvider->Dingo\Api\Provider{closure}(object(Application), array()) in Container.php line 773 at Container->build(object(Closure), array()) in Container.php line 656 at Container->make('api.router', array()) in Application.php line 644 at Application->make('api.router', array()) in helpers.php line 53 at app('api.router') in routes.php line 18 at require('C:\xampp\htdocs\laravel\apiv3\app\Http\routes.php') in RouteServiceProvider.php line 40

jasonlewis commented 9 years ago

@pc-paul You're using the wrong syntax to add routes. Refer to my original post. You're supposed to be using the $api variable which is now an instance of the router to create the route group (with version) and then use $api->get() or whichever method to add your routes.

argia-andreas commented 9 years ago

@jasonlewis Thank you for your help!

I'm no longer getting errors. I hadn't published the config!!

jasonlewis commented 9 years ago

@argia-andreas, hm, I was under the impression it should work without publishing. I'll look into that as it sounds like an issue.