skip to Main Content

I’m working on Laravel 10 project and I want to add some data to database when I run the composer install <package_name>. To do that, I have created a custom PHP file and call that postPackageInstall function in composer.json file.

Here how I add that to my composer.json file

    {
    
    <-- OTHER COMPOSER JSON DATA -->

    "scripts": {
        "post-package-install": [
            "Widgets\PackageInstaller::postPackageInstall"
        ]
      },
    <-- OTHER COMPOSER JSON DATA -->
    }

And here is my custom PHP file look like.

<?php

namespace Widgets;

use ComposerInstallerPackageEvent;
use ComposerScriptEvent;
use IlluminateSupportFacadesDB;

class PackageInstaller
{
    protected static $packageName = "";

    public static function postPackageInstall(PackageEvent $event)
    {
        // Get installing package
        $operation = $event->getOperation();

        $package = method_exists($operation, 'getPackage')
            ? $operation->getPackage()
            : $operation->getInitialPackage();

        DB::table('widgets')->insert(['name' => $package->getName()]);
    }
}

In here my idea is getting package name and store that name in database after I run composer install command. But the issue is, it throws an error

In Facade.php line 350:           
  A facade root has not been set.

I assumed that because Laravel is not fully loaded when it comes to this stage. Also, I have tried to run an Artisan command in the post-package-install script. DB queries are working in the command, but I was unable to get the package name inside the command like script.

Is there any other way to achieve this or fix these issues?

3

Answers


  1. Chosen as BEST ANSWER

    I figured it like this. Since Laravel isn't fully loaded in that post-package-uninstall stage, I used row PHP database queries to store data.

    public static function postPackageInstall(PackageEvent $event)
        {
            // Get installing package
            $operation = $event->getOperation();
            $package = method_exists($operation, 'getPackage')
                ? $operation->getPackage()
                : $operation->getInitialPackage();
    
            // Extract package name
            $packageName = $package->getName();
    
            // Perform database operation
            $pdo = new PDO('mysql:host=127.0.0.1;dbname=my_database', 'username', 'password');
            $stmt = $pdo->prepare('INSERT INTO widgets (name) VALUES (:name)');
            $stmt->bindParam(':name', $packageName);
            $stmt->execute();
        }
    

    This method is not clean. But it does work in "post-package-uninstall" scripts in Laravel.


    1. Create a custom artisan command with the DB logic.
    2. Allow passing data to it via CLI arguments.
    3. Update postPackageInstall() to run the command via exec().
    Login or Signup to reply.
  2. You can try this (Using Laravel DB facade):

    namespace Widgets;
    
    require __DIR__.'/../vendor/autoload.php';
    
    use ComposerInstallerPackageEvent;
    use IlluminateContractsConsoleKernel;
    use IlluminateSupportFacadesDB;
    
    class PackageInstaller
    {
        protected static $packageName = "";
    
        public static function postPackageInstall(PackageEvent $event)
        {
            $app = require_once __DIR__.'/../bootstrap/app.php';
        
            $operation = $event->getOperation();
    
            $package = method_exists($operation, 'getPackage')
                ? $operation->getPackage()
                : $operation->getInitialPackage();
    
    
            $app->make(Kernel::class)->bootstrap();
    
            DB::table('widgets')->insert(
                ['name' => $package->getName()]
            );
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search