3
votes

I would like to load a serviceprovider from my vendor folder. I actually added this vendor into my project

Learning Laravel PayPal SDK

Now under the folder structure

vendor/
   - paypal/
        - rest-api-sdk-php/
            - config/
                 - paypal.php
            - docs/
            - lib/
                - PayPal/
                - PayPalConfigServiceProvider.php
            - sample/
            - test/
            - composer.json

As you can see I added some items on the vendor. I added config folder and a config file under it namely paypal.php and also under lib folder I added PayPalConfigServiceProvider.php

Full path of service provider is my_project/vendor/paypal/rest-api-sdk-php/lib/PayPalConfigServiceProvider.php

Now I would like to add that PayPalConfigServiceProvider so that when I run composer update or something the PayPalConfigServiceProvider will copy a config file to myproject\config folder. So I added

'providers' => [
      Illuminate\Validation\ValidationServiceProvider::class,
      Illuminate\View\ViewServiceProvider::class,
      Illuminate\Html\HtmlServiceProvider::class,

      PayPal\PayPalServiceProvider::class,
]

on config/app.php under the providers array. But now when I try to run php artisan I get this error

PHP Fatal error:  Class 'PayPal\PayPalServiceProvider' not found in myproject/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php

So I assumed that this has something to do with my composer.json on my root directory and this is the content of it

{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.1.*",
    "illuminate/html": "^5.0",
    "doctrine/dbal": "^2.5",
    "paypal/rest-api-sdk-php": "*"
},
"require-dev": {
    "fzaninotto/faker": "~1.4",
    "mockery/mockery": "0.9.*",
    "phpunit/phpunit": "~4.0",
    "phpspec/phpspec": "~2.1"
},
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php"
    ]
}
}

It seems the paypal is already included now I'm not sure what I need to add for it to be recognized. I just need my PayPalServiceProvider to be initialized so that this code will be run

PayPalServiceProvider.php

namespace PayPal;
use Illuminate\Support\ServiceProvider;

class PayPalServiceProvider extends ServiceProvider {

/**
 * Register the service provider.
 *
 * @return void
 */
public function register()
{
    // TODO: Implement register() method.

}

public function boot()
{
    $this->mergeConfigFrom(__DIR__ . '../config/paypal.php', 'paypal');
}
}

I also checked the paypal vendor folder and checked its composer.json and here's the content

{
"name": "paypal/rest-api-sdk-php",
"description": "PayPal's PHP SDK for REST APIs",
"keywords": ["paypal", "payments", "rest", "sdk"],
"type": "library",
"license": "Apache2",
"homepage": "http://paypal.github.io/PayPal-PHP-SDK/",
"authors": [
    {
        "name": "PayPal",
        "homepage": "https://github.com/paypal/rest-api-sdk-php/contributors"
    }
],
"require": {
    "php": ">=5.3.0",
    "ext-curl": "*",
    "ext-json": "*"
},
"require-dev": {
    "phpunit/phpunit": "3.7.*"
},
"autoload": {
    "psr-0": {
        "PayPal": "lib/"
    }
}
}

I know I can always add something like this on the composer.json on my root directory

"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/",
        "PayPal\\": "vendor/paypal/rest-api-sdk-php/lib",
    }
}

And this will work when I run composer dumpautoload. But I don't want this kind of approach I see many libraries but non of them did something like this. Is there any approach where I can load my serviceprovider without adding an entry on my autoload under my composer.json on root directory? Its ok if I'll add something on the composer.json of the vendor folder. But how will I accomplish this? please help on this. Thanks

3
What is the file path of PayPalServiceProvider.php? Show also the line on config/app.php where you register your service providerMoppo
Ok I'll add that to the questionMadzQuestioning
The package has wrong configuration, it should use psr-4 instead of psr-0Wouter J

3 Answers

2
votes

You should not add files into the package folder.

You can move your config files into the config folder and move your Paypal service provider (I think you write it by yourself) to the app/Providers folder and use your application namespace for that class.

However, if you still want to load your created class from the lib folder (again, I do not recommend to do that), put your service provider class into the lib/Paypal instead of lib. The reason is this class use PSR-0 class loading standard, you can see a clear explanation about the different between PSR-0 and PSR-4 in this answer on Stack Overflow.

1
votes

If you place your service provider inside your vendor folder you have to tell laravel where it is, and, as you said, putting this line in your composer.json:

"psr-4": {
        "App\\": "app/",
        "PayPal\\": "vendor/paypal/rest-api-sdk-php/lib",
    }

will do that.

Anyhow, Beware of putting your code in the vendor folder: this is a very bad practice, as the vendor folder is reserved for the external packages of the progect. You can, and should, consider putting your service provider inside your App Folder, i.e: App\Providers\PayPalServiceProvider.php

And set the namespace this way:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class PayPalServiceProvider extends ServiceProvider {

//... 

}

This way in your app.php you could set:

App\Providers\PayPalServiceProvider::class,

without adding anything in your composer.json file

0
votes

First, please don't try to modify things under package folder (vendor) unless you know what you are doing, it's generated and should not be included into VCS like git.

So put your service provider under app/Providers and define it under App\Provider namespace.

As for your PaypalServiceProvider, it should be given a full class name as App\Providers\PaypalServiceProvider and put in my_project/app/Providers.

If you want to create a package, you should learn something about Composer (getcomposer.org) and Packagist (packagist.org)

Secondary, about why your PaypalServiceProvider could not be found, you should learn something about PSR-4 (www.php-fig.org/psr/psr-4/).