在 Laravel 4 上使用非 laravel 包

2022-01-08 00:00:00 package php laravel laravel-4

是否可以在框架中包含不是专门为 L4 设计的包?如果是这样,它是如何完成的?我知道我需要将包添加到我的 composer.json 中,这会将它添加到 vendor 文件夹中,但是我可以在 providers 数组?还有其他必要的步骤吗?

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?

我想使用最初为 Yii 设计的 Google 结帐包

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

推荐答案

在 Laravel 4 中使用第三方 composer 包

当开发者创建 composer 包时,他们应该使用 PSR-0 或 PSR-4 标准映射自动加载.如果不是这种情况,在你的 Laravel 应用程序中加载包可能会出现问题.PSR-0 标准是:

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/" }
    }
}

还有 PSR-4 标准:

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.

场景 1

在 Laravel 中遵循 PSR-0 标准的包(带有自动加载类映射)

这是一个简单的,例如我将使用 facebook php sdk,可以找到:

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

第 1 步:

将包包含在您的 composer.json 文件中.

Include the package in your composer.json file.

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

第 2 步:

run: composer update

第 3 步:

因为 facebook 包使用了一个开箱即用的类映射,您可以立即开始使用该包.(下面的代码示例直接来自普通视图.请在生产应用程序的视图中保留您的逻辑.)

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!

场景 2

对于这个例子,我将使用来自 instagram php api 的包装器.这里需要进行一些调整才能加载包.试一试吧!包可以在这里找到:

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

第 1 步:

添加到作曲家.json

Add to composer .json

"require": {
    "laravel/framework": "4.0.*",
    "fishmarket/instaphp": "dev-master"
}

然后就可以正常更新了(composer update)

Then you can update normally (composer update)

接下来尝试像使用 facebook 包一样使用该包.同样,这只是视图中的代码.

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 ...

所以我们需要解决这个问题.为此,我们可以检查 instagram composer.json,它的自动加载与 facebook php sdk 不同.

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": "." }
    }

与 facebook composer.json 相比:

Compared to the facebook composer.json:

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

(Composer 处理不同类型的自动加载,从文件和类映射到 PSR.看看你的 vendor/composer/ 文件夹,看看它是如何完成的.)

(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 InstaphpInstaphp;

composer dump-autoload,它可以工作了!

composer dump-autoload, and it works!

第 2 步(可选)

另一种方法是(如果您不想使用use"语句,您可以简单地告诉作曲家直接从您的代码中查找文件.只需像这样更改实例:

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 = InstaphpInstaphp::Instance(null, $instagramconfig); 
var_dump($api); // It works

但是我建议使用 use 语句让其他开发人员(以及你未来的自己)清楚地了解程序中使用了哪些(外部)类/包.

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.

场景 3

这里我们使用 Laravel 内置的 IOC 容器来注册服务提供者.请注意,某些软件包可能不适合此方法.我将使用与场景 2 中相同的 Instagram 包.

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.

又快又脏

如果您不关心设计模式和服务提供者,您可以像这样绑定一个类:

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 InstaphpInstaphp;
});

然后你就这样解决了.

App::make('Instaphp');

快速而肮脏的结局

如果您正在处理一个更大的项目,并且您使用接口,您可能应该进一步抽象绑定.

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

第 1 步:

在您的应用文件夹内创建一个文件夹,例如providers"文件夹.

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

app/providers

确保 Laravel 自动加载该文件夹,您可以将一些附加信息传递给 composer.json,如下所示:

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
    ]

},

现在在名为 Instagram.php 的新文件夹中创建一个文件并将其放入:

Now create a File inside the new folder called Instagram.php and place this inside:

 <?php

    use IlluminateSupportServiceProvider;

    class InstagramServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('Instaphp', function()
        {
            return new InstaphpInstaphp;
        });

    }

}

现在再次运行composer dump-autoload,就可以使用这个包了.请注意,instagram 包有一个 final 私有函数 __construct(),这意味着您不能在不将构造方法更改为公共的情况下在原始类之外使用该包.我并不是说这是一个好习惯,我建议在使用 instagram 包的情况下使用场景 2.

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!

相关文章