dongliang1996 2013-03-03 20:57
浏览 30
已采纳

在Laravel 4上使用非laravel包

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

  • 写回答

2条回答 默认 最新

  • dqd3690 2013-03-05 13:36
    关注

    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!
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿