Using third-party composition packs with Laravel 4
When developers create composer packages, they must map automatic downloads using PSR-0 or PSR-4 standards. If this is not the case, you may have problems downloading the package in your Laravel application. PSR-0 standard:
{ "autoload": { "psr-0": { "Acme": "src/" } } }
And the PSR-4 standard:
{ "autoload": { "psr-4": { "Acme\\": "src/" } } }
Basically the above is the standard for describing a composer where to look for files with a filename extension. If you are not using your own namespace, you do not need to configure anything.
SCENARIO 1
Standard PSR-0 following packages (with autoload class class) in Laravel
This is simple, and for example, I will use facebook php sdk, which can be found:
https://packagist.org/packages/facebook/php-sdk
Step 1:
Include the package in the composer.json file.
"require": { "laravel/framework": "4.0.*", "facebook/php-sdk": "dev-master" }
Step 2:
run: composer update
Step 3:
Since the facebook package uses the class map in which it works, we can start using the package instantly. (An example code is provided directly from the normal view. Please save your logic from the views in your working application.)
$facebook = new Facebook(array( 'appId' => 'secret', 'secret' => 'secret' )); var_dump($facebook);
SCENARIO 2
In this example, I will use a wrapper from instagram php api. Here you need to make some settings to download the package. Let's try! The package can be found here:
https://packagist.org/packages/fishmarket/instaphp
Step 1:
Add to composer .json
"require": { "laravel/framework": "4.0.*", "fishmarket/instaphp": "dev-master" }
Then you can update normally (composer update)
Then try using the package as you did with the facebook package. Again, this is just the code in the view.
$instagramconfig = array( 'client_id' => 'secret', 'client_secret'=> 'secret', 'access_token' => 'secret' ); $api = Instaphp::Instance(null, $instagramconfig); var_dump($api);
If you try the above example, you will get this error:
FatalErrorException: Error: Class 'Instaphp' not found in ...
So, we need to fix this problem. To do this, we can learn instagram composer.json, which has its own startup, other than php facebook php sdk.
"autoload": { "psr-0": { "Instaphp": "." } }
Compared to facebook composer.json:
"autoload": { "classmap": ["src"] }
(Composer handles various types of startup, from files and class maps to PSRs. Look at your vendor/composer/ folder to see how this is done.)
Now we will need to load the class manually. Its easy, just add this (at the top of your controller, model or view):
use Instaphp\Instaphp;
dump-autoload composer and it works!
step2 (optional)
Another method (if you do not want to use the "use" statement, you can simply tell the composer to search for files directly from your code. Just change the instance like this:
// reference the name-spaced class straight in the code $api = Instaphp\Instaphp::Instance(null, $instagramconfig); var_dump($api); // It works
However, I suggest using the use statement to make it clear to other developers (and your future self) which (external) classes / packages are used in the program.
SCENARIO 3
Here we use Laravels, built into the IOC container, to register service providers. Please note that some packages may not be suitable for this method. I will use the same Instagram package as in scenario 2.
Quick and dirty
If you don't like design patterns and service providers, you can link the class as follows:
App::bind('Instaphp', function($app) { return new Instaphp\Instaphp; });
And you allow it that way.
App::make('Instaphp');
Quick and dirty end
If you are working on a larger project and using interfaces, you should probably abstract the bindings.
Step 1:
Create a folder inside the folder of your application, for example, the suppliers folder.
app/providers
Make sure Laravel automatically loads this folder, you can pass some additional information to composer.json, for example:
"autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests/TestCase.php", "app/providers" // this was added ] },
Now create a file in the new Instagram.php folder and put it inside:
<?php use Illuminate\Support\ServiceProvider; class InstagramServiceProvider extends ServiceProvider { public function register() { $this->app->bind('Instaphp', function() { return new Instaphp\Instaphp; }); } }
Now run the dump-autoload composition again and you can use the package. Note that the instagram package has final private function __construct() , which means that you cannot use this package outside the original class without changing the build method for the public. I am not saying that this is good practice, and I suggest using scenario 2 in the case of instagram package.
In any case, after that you can use the package as follows:
$instagramInstance = App::make('Instaphp'); $instagramconfig = array( 'client_id' => 'secret', 'client_secret'=> 'secret', 'access_token' => 'secret' ); $instagram = new $instagramInstance(); $userfeed = $instagram->Users->feed($instagramconfig); var_dump($userfeed);