lendable/composer-license-checker
Checks your Composer dependencies’ licenses against configurable allow rules (by SPDX license, vendor, or package) to help ensure OSS compliance and reduce legal risk. Works in CI and can read license data from Composer’s installed.json or composer licenses.
Installation Add the package via Composer:
composer require --dev lendable/composer-license-checker
Register the service provider in config/app.php (if not auto-discovered):
'providers' => [
// ...
Lendable\ComposerLicenseChecker\ComposerLicenseCheckerServiceProvider::class,
],
Basic Configuration Publish the config file:
php artisan vendor:publish --provider="Lendable\ComposerLicenseChecker\ComposerLicenseCheckerServiceProvider" --tag="config"
Edit config/composer-license-checker.php to define allowed licenses (e.g., ["MIT", "Apache-2.0"]).
First Run Execute the Artisan command to check dependencies:
php artisan license:check
This will scan composer.json and report violations against your rules.
Add a Git pre-commit hook to block commits with unapproved licenses:
#!/bin/sh
php artisan license:check --fail-on-violation
Configure in .git/hooks/pre-commit (ensure executable permissions).
CI/CD Pipeline Run checks in CI (e.g., GitHub Actions) to enforce compliance:
# .github/workflows/license-check.yml
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: php artisan license:check --fail-on-violation
Custom Rules Extend license rules via config or dynamically:
// config/composer-license-checker.php
'rules' => [
'allowed' => ['MIT', 'GPL-3.0'],
'blocked' => ['AGPL-3.0'], // Explicitly block
'custom' => [
'require-license-file' => [
'packages' => ['monolog/monolog'], // Force license file check
'message' => 'License file must be included.',
],
],
];
Artisan Command Usage
php artisan license:check --dry-run
php artisan license:check --verbose
php artisan license:check --format=json > licenses.json
Service Container Binding Bind the checker to the container for programmatic use:
$this->app->bind(LicenseChecker::class, function ($app) {
return new LicenseChecker($app['config']['composer-license-checker']);
});
Use in controllers/services:
public function checkLicenses(LicenseChecker $checker) {
$violations = $checker->check();
// Handle violations (e.g., log, notify team).
}
Event Listeners Trigger actions on license violations:
// app/Listeners/HandleLicenseViolation.php
public function handle(LicenseViolationEvent $event) {
Notification::send(
config('app.admin_email'),
new LicenseAlert($event->violations)
);
}
Register in EventServiceProvider:
protected $listen = [
LicenseViolationEvent::class => [
HandleLicenseViolation::class,
],
];
Testing Mock the checker in unit tests:
$mockChecker = Mockery::mock(LicenseChecker::class);
$mockChecker->shouldReceive('check')->andReturn([]);
$this->app->instance(LicenseChecker::class, $mockChecker);
False Positives
vendor/packageA/vendor/packageB) may trigger violations.--depth to limit scan depth:
php artisan license:check --depth=2
'whitelist' => [
'symfony/*', // Allow all Symfony packages
'doctrine/annotations', // Explicit whitelist
],
Performance
bootstrap/cache:
'cache' => true, // Enable in config
composer install via post-install-cmd in composer.json:
"scripts": {
"post-install-cmd": [
"@php artisan license:check --quiet"
]
}
License Detection
LICENSE files or use non-standard paths.'license_paths' => [
'LICENSE', 'license', 'LICENSE.txt', 'COPYING',
],
--strict to fail on undetectable licenses:
php artisan license:check --strict
Verbose Logging Enable debug mode for detailed output:
php artisan license:check --verbose --debug
Check storage/logs/laravel.log for additional context.
Dependency Tree Inspection Visualize the dependency tree to identify problematic packages:
composer why package-name
Or use the --tree flag:
php artisan license:check --tree
Config Overrides Temporarily override config via CLI:
php artisan license:check --allowed="MIT,BSD-3-Clause" --blocked="AGPL"
Custom Validators
Extend the LicenseValidator interface to add logic:
class CustomValidator implements LicenseValidator {
public function isAllowed(string $license): bool {
// Custom logic (e.g., check for "proprietary" in license text).
return str_contains($license, 'proprietary') ? false : true;
}
}
Register in ComposerLicenseCheckerServiceProvider:
$this->app->bind(LicenseValidator::class, function () {
return new CustomValidator();
});
Database Integration Store violation history in a database table:
// Migration
Schema::create('license_violations', function (Blueprint $table) {
$table->id();
$table->string('package_name');
$table->string('license');
$table->text('message');
$table->timestamp('checked_at');
});
Log violations in the LicenseViolationEvent listener.
API Endpoint Expose license status via an API route:
Route::get('/api/license-status', function (LicenseChecker $checker) {
return response()->json($checker->check());
});
Protect with middleware (e.g., auth:api).
How can I help you explore Laravel packages today?