Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a non-laravel package on Laravel 4

Is it possible to include a package that was not specifically designed for L4 in the framework? If so, how is it done? I know I need to add the package to my composer.json which adds it to the vendor folder, but can I register it somehow in the providers array? are there any other steps necessary?

I would like to use the Google checkout package originally designed for Yii

like image 652
Matanya Avatar asked Mar 03 '13 20:03

Matanya


People also ask

Can I use Composer without Laravel?

Not at all. You can run Composer on the server as well if you like, but you can just as easily upload your local project wherever you want after running any Composer installs/updates locally. @Dwight: Does this also apply to servers without shell access?

What is Composer require in Laravel?

composer is a tool for dependency management in PHP. create-project is command to create a new laravel project. laravel/laravel is for the skeleton application you get when creating a new project.

What is a Laravel package?

Packages are the primary way of adding functionality to Laravel. Packages might be anything from a great way to work with dates like Carbon or a package that allows you to associate files with Eloquent models like Spatie's Laravel Media Library. There are different types of packages.


1 Answers

Using third party composer packages with Laravel 4

When developers create composer packages, they should map the auto-loading using PSR-0 or PSR-4 standards. If this is not the case there can be issues loading the package in your Laravel application. The PSR-0 standard is:

{     "autoload": {         "psr-0": { "Acme": "src/" }     } } 

And the PSR-4 standard:

{     "autoload": {          "psr-4": { "Acme\\": "src/" }     } } 

Basically the above is a standard for telling composer where to look for name-spaced files. If you are not using your own namespaces you dont have to configure anything else.

SCENARIO 1

PSR-0 standard following packages (with autoload classmap) in Laravel

This is a simple one, and for example i will use the facebook php sdk, that can be found:

https://packagist.org/packages/facebook/php-sdk

Step 1:

Include the package in your composer.json file.

"require": {     "laravel/framework": "4.0.*",     "facebook/php-sdk": "dev-master" } 

Step 2:

run: composer update 

Step 3:

Because the facebook package uses a class map its working out of the box, you can start using the package instantly. (The code example below comes straight from a normal view. Please keep your logic out from views in your production app.)

$facebook = new Facebook(array(     'appId'  => 'secret',     'secret' => 'secret' )); var_dump($facebook); // It works! 

SCENARIO 2

For this example i will use a wrapper from the instagram php api. Here there need to be made some tweaks to get the package loaded. Lets give it a 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)

Next try to use the package like you did with the facebook package. Again, this is just code in a view.

$instagramconfig = array(     'client_id' => 'secret',     'client_secret'=> 'secret',     'access_token' => 'secret' );  $api = Instaphp::Instance(null, $instagramconfig);                 var_dump($api); // Epic fail! 

If you try the above example you will get this error:

FatalErrorException: Error: Class 'Instaphp' not found in ... 

So we need to fix this issue. To do this we can examine the instagram composer.json, that has its autoload diffrent than the facebook php sdk had.

"autoload": {          "psr-0": { "Instaphp": "." }     } 

Compared to the facebook composer.json:

"autoload": {         "classmap": ["src"]     } 

(Composer handles different kinds of autoloading, from files and class-maps to PSR. Take a look at your vendor/composer/ folder to see how its done.)

Now we will have to load the class, manually. Its easy, just add this (top of your controller, model or view):

use Instaphp\Instaphp; 

composer dump-autoload, and it works!

step2 (optional)

Another method is (if you dont want to use the "use" statement, you can simply tell composer to look for the files straight from your code. Just change the Instance like so:

// 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 usestatement to make it clear to other developers (and your future self) what (external) classes/packages are used in the program.

SCENARIO 3

Here we use the Laravels built in IOC container to register service providers. Please note that some packages might not be suitable for this method. I will use the same Instagram package as in scenario 2.

Quick and dirty

If you don't care about design patterns and service providers you can bind a class like this:

App::bind('Instaphp', function($app) {     return new Instaphp\Instaphp; }); 

And you resolve it like this.

App::make('Instaphp'); 

Quick and dirty end

If you're working on a bigger project, and you make use of interfaces you should probably abstract the bindings further.

Step 1:

Create a folder inside your app folder, for example a 'providers' folder.

app/providers 

Make sure Laravel auto-loads that folder, you can pass in some additional info to composer.json, like this:

"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 inside the new folder called Instagram.php and place this inside:

 <?php      use Illuminate\Support\ServiceProvider;      class InstagramServiceProvider extends ServiceProvider {      public function register()     {         $this->app->bind('Instaphp', function()         {             return new Instaphp\Instaphp;         });      }  } 

Now run composer dump-autoload again, and you can use the package. Note that the instagram package has a final private function __construct(), this means you cannot use that package outside the original class without changing the construct method to public. I'm not saying this is a good practice, and i suggest to use the scenario 2, in the case of the instagram package.

Anyway, after this you can use the package like this:

$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); // It works! 
like image 114
pat Avatar answered Sep 17 '22 07:09

pat