Composer, Laravel and local packages
Asked Answered
N

3

12

My issue is I have a package which isn't a repository and I am trying to get it to play nice with Laravel and composer. It is still located under the vendor folder, the only issue is that if I simply set:

"psr-0": {
        "Test\\Test": "vendor/test/test/src/"
    }

This will load the service provider but none of the controllers etc will autoload. What is the correct way to implement a package with larval that does not have it's own repository. Or does this go against the nature of packages and this should simply be structured under the applications controllers.

The package was created by me using workbench but I found i did not really need this as a separate repository but it would still be good to keep it as a package. Therefore the structure is exactly the same as a regular package:

vendor
    testvendor
        testpackage
            public
            src
            tests
            .gitignore
            composer.json
            phpunit.xml

UPDATE:

As a solution for the time being I am using:

"autoload": {
    "classmap": [
        "app/commands",
        "app/controllers",
        "app/models",
        "app/database/migrations",
        "app/database/seeds",
        "app/tests/TestCase.php",
        "vendor/package"
    ]
},

As an entry in the class map. Looking forward I will probably refactor this into the app folder or create a repository for this package.

Nimrod answered 19/3, 2014 at 14:54 Comment(5)
We need more information about this. What is this package? It's just a bunch of files you copy to your vendor or is something stored in a server you can download? Does it have a composer package structure? Who created this package? Can you make it a composer package and store it in house? Could you at least show us the directory structure of this package?Filiate
Why is there a non composer package in the vendor folder??Paresthesia
Would you recommend moving it to app/vendor or similar? I will update the question now in regards the other things.Nimrod
I think you should creat a workbench for your package instead of putting it inside the vendor folder. Your custom package should formated as workbenchInhaler
I did initially have it under workbench (whilst developing) but a workbench package should not be used in a production environment was my understanding? If I was to create a package out of it then yes I would move it into workbench whilst developing, if I am missing something here let me know.Nimrod
F
16

If you have some classes that you're calling "package", you're not supposed to add those files to your vendor folder. This folder is managed by composer and at any time you might loose it. Create a subfolder in your application and put those files there.

You have to be sure your PSR-0 autoloading will work for every single file in your folder structure. So, if your root is vendor/test/test/src/ and your namespace is

Test\\Test

All your files must be in

vendor/test/test/src/Test/Test/ClassFileName.php

PSR-4 is easier to deal and understand, this

"psr-4": {
    "Test\\Test\\": "vendor/test/test/src/"
}

Means that your files would have to be like:

vendor/test/test/src/ClassFileName.php

Doublecheck your namespaces. It's easy to make mistakes when using namespaces with PSR-0 and remember that

composer dump-autoload

Must be ran every time you change things in composer.json or create new files. If it's a simple class autoloading, every time you create a file, if it's a PSR-X autoloading, everytime you create or update a namespace in your composer.json file.

If what you have is is really a package you should use Composer: when your package is structured as a composer package (check Laravel's composer.json as an example), the correct way of adding it to your application, if it's not list in Packagist, is via repositories.

You can have (non-packagist) packages in a public VCS repository:

{
    "require": {
        "monolog/monolog": "dev-bugfix"
    },

    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/igorw/monolog"
        }
    ]
}

You can have (non-packagist) packages in a protected by password VCS repository (git, bitbucket...):

{
    "require": {
        "vendor/my-private-repo": "dev-master"
    },
    "repositories": [
        {
            "type": "vcs",
            "url":  "[email protected]:vendor/my-private-repo.git"
        }
    ]
}

You can have your packages zipped in your hard drive and load them via the artifact repository type:

"repositories": [
    {
        "type": "artifact",
        "url": "path/to/directory/with/zips/"
    }
],
Filiate answered 19/3, 2014 at 15:26 Comment(3)
Thank you for the detailed reply. I read the docs and the issue is with it not being a repository. My current solution is I add vendor/odeon to the class map and now everything works fine. I'm not 100% this is the correct method to solve my issue everything is functioning properly.Nimrod
If you are mixing more than one autoloading method for the same package, it's not ideal. But if you are just using classmaps now, yeah, it will work, it's just that you probably will have to execute composer dump-autoload everytime you create a new class.Filiate
I will keep it like this for the time being but going by comments I should either refactor this into the app folder or make this package a repository. I will accept this as the solution as it does explain what is 'the right way'.Nimrod
B
7

Though @Antonio Carlos Ribeiro's answer is really nice, I had problem with installing custom packages locally(which is also stated in the last part of his answer)

Let's assume this is the directory structure of the package we are trying to install:

D:/test_pack
    src/
    composer.json

If you do not want to upload your custom package (that most likely you have developed, yourself) to online repositories you can use one of the following two methods:

Method I

(You have to specify version for your package, otherwise you'll get this error: The requested package could not be found in any version, there may be a typo in the package name.)

1) In composer.json, Add version to your package. your package's json should look something like this:

{
"name": "gandalf/test_pack",//This is your package's name
"description": "some desc",
"version": "1.0.0",//This is the version that you have to specify
"authors": [
    {
        "name": "gandalf the grey",
        "email": "[email protected]"
    }
],
"minimum-stability": "dev",
"require": {
    "laravel/framework": "~5.4"
},
"autoload": {
    "psr-4": {
        "Gandalf\\BotPack\\": "src/"
    }
} }

2) zip your package(let's assume the zip file is in D:/test_pack/test_packa.zip)

3) In laravel's composer.json add your package name (in our case gandalf/test_pack into require part of json) and add the repository array to the composer.json file and in that array specify the directory in which your package's zip file exists(in our case D:/test_pack) . like this

{
    ...,
    "require": {//adding our package name to laravel's composer.json
        ...,
        "gandalf/test_pack": "*"//package's name
    },
    ...,

    "repositories": [
        {
            "type": "artifact",
            "url": "D:/test_pack"
        }
    ]
}

Method II(My Favorite method, You have to initialize your package directory as git local repository using git init and then git add . and git commit -m "your message")

1) initialize the package directory as git directory and commit all your changes to the local repository

(let's say D:/test_pack is the directory that contains your package(src/ directory and composer.json))

go to D:/test_pack directory and run these commands

git init
git add .
git commit -m "your message for this commit"

2) In your packages composer.json file add minimum-stability

    {
        "name": "gandalf/test_pack",
        "description": "some desc",
        "authors": [
            {
                "name": "gandalf the grey",
                "email": "[email protected]"
            }
        ],
        "minimum-stability": "dev",//setting minimum-stability
        "require": {
               //dependencies that your package needs
        },
        "autoload": {
            "psr-4": {
                "Gandalf\\BotPack\\": "src/"
            }
        }
    }

3)In laravel's composer.json file require the "dev-master" of your package

{
    ...,
    "require": {
        ...,//some dependencies that laravel needs
        "gandalf/test_pack": "dev-master"//requiring dev-master from repository
    },

    "repositories": [
        {
            "type": "git",
            "url": "D:/test_pack"//path of the local repository directory which contains your package
        }
    ]
}
Brisson answered 22/10, 2017 at 16:44 Comment(1)
for more detail about Package install from Local System (Offline) see this, getcomposer.org/doc/05-repositories.md#artifactOvertly
S
1

To any Laravel project load local packages. which is stored in your machine.

In laravel's (Project) composer.json file add

  "autoload": {
    "psr-4": {
      "YourPackage\\Namespace\\": "./local_Package_path/src"
    }
  },

and fire command in Laravel Project directory

composer dump-autoload

Optional

If package is still not available in your Project. then Register your package's Service Provider.

To register your service provider, you just need to add an entry to the array of service providers in the config/app.php file.


'providers' => [

    /*
     * Laravel Framework Service Providers...
     */
    ...

    YourPackage\Namespace\PackageServiceProvider::class,
], 

Hope now your package loaded successfully in your laravel project.

Safeguard answered 16/6, 2020 at 7:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.