When creating a package in Laravel, the packages use "\Illuminate\Support\ServiceProvider" in their *ServiceProvider.php. Which is located in the package \vendor directory.
public function boot()
{
$this->package('faiawuks/articles');
include __DIR__.'/../../../routes.php';
}
As you see I need Illuminate: $this->package to register my package specific routes.
I've noticed that Illuminate also exists inside the main vendor directory. Is it possible to remove the Illuminate vendor package for my created workbench package and use the main vendor\Illuminate package? I'ts going to be a private workbench package anyway?
I want to create 5+ packages for my application, so I can split it into 'modules'.
Solved it for now by creating my own directory structure in the directory ./modules and using this in composer.json:
"psr-0": {
"Articles": "modules/"
}
inside the "autoload": { part. So my structure is as following:
mylaravelproject
- modules
- Articles
- *othermodules
The PSR-0 autoloader looks for classes inside ./modules/Articles. The namespace to use in the Articles directory is:
namespace Articles;
Related
Problem
I'm trying to setup a custom directory structure
for some shared classes in my Symfony project. I
want to create a custom folder in the root of my
project and I want to use the Symfony auto-load
feature to automatically register services from
that folder.
So I added a custom services namespace to the
services.yaml file:
# src ./config/services.yaml
services:
...
TestNamespace\:
resource: '../TestNamespace/*'
...
And I added an empty class in the custom folder:
# src ./TestNamespace/TestClass.php
namespace TestNamespace;
class TestClass
{
}
When I run the app I get the following error:
(1/2) InvalidArgumentException
Expected to find class "TestNamespace\TestClass" in file
"/path/to/ClassLoadErrorDemo/demo/TestNamespace/TestClass.php"
while importing services from resource
"../TestNamespace/*", but it was not found! Check the
namespace prefix used with the resource.
(2/2) FileLoaderLoadException
Expected to find class "TestNamespace\TestClass" in file
"/path/to/ClassLoadErrorDemo/demo/TestNamespace/TestClass.php" while
importing services from resource "../TestNamespace/*", but it was not
found! Check the namespace prefix used with the resource in
/path/to/ClassLoadErrorDemo/demo/config/services.yaml (which is loaded
in resource "/path/to/ClassLoadErrorDemo/demo/config/services.yaml").
I double checked the paths, namespace and the class
name multiple times and everything seems fine and I
don't understand why I still get the error.
Controllers in the ./src folder seem to load fine.
What am I doing wrong here?
Steps to reproduce
I created a demo repo to isolate the problem.
git clone https://github.com/smoelker/SymfonyClassLoadErrorDemo.git
cd SymfonyClassLoadErrorDemo/demo
composer install
mv TestNamespace/TestClass.php_ TestNamespace/TestClass.php
php bin/console server:start
Update your composer.json autoload setup
{
[...]
"autoload": {
"psr-4": {
"TestNamespace\\": "TestNamespace/",
"": "src/"
}
},
[...]
}
After run: composer dump-autoload and try again.
composer dump-autoload --classmap-authoritative will only work if your src directory is present at the time you run the command.
This can be an issue with multi-stage Docker builds in particular, when you are normally only copying the composer.json/composer.lock into the build image.
I'm creating a composer installable project inside vendor.
This is my service provider file,
<?php
namespace vimuths123\gitpack;
use Illuminate\Support\ServiceProvider;
class GitpackServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind('gitpack', function ($app) {
return new Gitpack;
});
}
public function boot() {
// loading the routes file
require __DIR__ . '/Http/routes.php';
// define the path for the view files
$this->loadViewsFrom(__DIR__ . '/../views', 'gitpack');
}
}
This is the structure,
vendor
|
vimuths123
|-gitpack
|-src
| |-GitpackServiceProvider.php
|
|-composer.json
I already added my service provider in app/config.php
vimuths123\gitpack\GitpackServiceProvider::class,
and my root composer.json I have following code.
"psr-4": {
"App\\": "app/",
"vimuths123\\gitpack\\" : "vendor/vimuths123/gitpack/src"
}
This is my package composer file,
{
"name": "vimuths123/gitpack",
"autoload": {
"psr-4" : {
"vimuths123\\gitpack\\" : "src"
}
},
"require": {
"composer/installers": "~1.2"
}
}
but all I'm getting is this error,
Class 'vimuths123\gitpack\GitpackServiceProvider' not found
It would be great help someone can help me on this.
You should not put any files into vendor/ by hand. If you are developing a library it must be composer installable library (which once installed end up in vendor/.
Your composer.json seems wrong, especially vendor/vimuths123/gitpack/src name space in psr4. This's smells from a mile as I'd bet you not using vendor/vimuths123/gitpack/src namespace.
Finally, after adding new class you should update class loader to let it know about that:
composer dumpautoload
which solves most of problems with "cannot find my class" issues.
EDIT
It seems your problems are in your library package, not the project using it. From comments it looks that you need to edit your package's composer.json. Assuming package is using vimuths123\gitpack namespace (note, namespace does NOT have to be the same as package name - these are two different things) and its sources sit in src subfolder (so it would be <project>/vendor/vimuths123/gitpack/src) then I'd rework autoload section to look like this:
"autoload": {
"psr-4" : {
"vimuths123\\gitpack\\" : "src"
}
}
and then composer dumpautoload.
Run the following artisan command:
php artisan optimize
Then see if the class can be found by Laravel.
I am just trying to create a package for packagist, a zend framework 2 user authentication module, https://packagist.org/packages/tahmina8765/zf2auth
When I keep this zf2auth folder in my modules folder, it works. But when I download it with composer, it downloaded in vendor/tahmina8765/zf2auth.
In this folder, it does not work. I mean, I have added this module in application.config.php -
'modules' => array(
...
'Zf2auth'
),
but here it does not work. If I keep it on step ahead, ie. vendor/zf2auth it works again.
How can I make it workable in vendor/tahmina8765/zf2auth folder?
I think there's a problem with the composer.json file in your module. It says:
"autoload": {
"psr-0": {
"Zf2auth": "./"
}
}
and looking at the directory structure it should be:
"autoload": {
"psr-0": {
"Zf2auth\\": "src"
}
}
It works in your ./modules/ dir because of the getAutoloaderConfig you have in your module class -- that's done by ZF2. When you download the module through composer however, the autoloading (probably) get's done by composer and the autoload (invalid) definition in your composer manifest is used. You might also want to run composers dump command afterwords, to refresh the autoloading classes.
using composer in a Php project, with Twig and my own framework.
I would like to "override" the Twig_Node_Expression_GetAttr class from Twig with my own class.
Everything it's working fine, but I have to manually add in composer autoload_classmap.php file :
'Twig_Node_Expression_GetAttr' => 'ebuildy/ebuildy/src/eBuildy/Templating/Twig_Node_Expression_GetAttr.php',
How can I declare this in my composer.json description file ?
Thanks,
You can just define the classmap entry in your project's composer.json, or using PSR-0 mapping as well. See the composer docs on autoloading for details. If you define the PSR-0 namespace with a more restrictive namespace than what Twig has, then you're sure yours will take over, .e.g:
{
"autoload": {
"psr-0": {
"Twig_Node_": "path/to/src/"
}
}
}
This however only works if in this src/ dir you have a file called: src/Twig/Node/Expression/GetAttr.php.
I have created a package following the "Creating a Package" instructions in the Laravel 4 documentation. After creating the package I have created a "controllers" folder and a routes file. The new file structure is:
/src
/Vendor
/Package
PackageServiceProvider.php
/config
/controllers
/lang
/migrations
/views
routes.php
/tests
/public
I added the routes file to the boot portion of the package service provider:
public function boot()
{
$this->package('vendor/package');
include __DIR__ . '/../../routes.php';
}
Then added a basic route to the routes file:
Route::get('/package', function() {
return "Package route test";
});
Visiting my application at the specified route (app.dev/package) returns the expected:
Package route test
Then adding a basic controller call to the route (using the default Laravel controller, "HomeController") works:
Route::get('/package', 'HomeController#showWelcome');
I then followed this SO answer for setting up the controller for the package. I added the src/controllers folder to the composer classmap, then I dumped the autoloader and checked vendor/composer/autoload_classmap.php and found the class is successfully loaded by composer:
<?php
// autoload_classmap.php generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'HomeController' => $baseDir . '/src/controllers/HomeController.php',
);
Now I added the new package controller to the route using the namespace:
Route::get('/package', 'Vendor\Package\Controllers\HomeController#showWelcome');
but this produces an error about not finding the class:
ReflectionException: Class Vendor\Package\Controllers\HomeController does not exist
I've also tried calling it using the package name:
Route::get('/package', 'Package::HomeController#showWelcome');
which produces the same error:
ReflectionException: Class Vendor\Package\Controllers\HomeController does not exist
No matter what I try the package cannot access its own controller, which composer confirms is loaded (by viewing vendor/package/autoload_classmap.php).
Any ideas? I'm not sure if the issue is composer not loading the class, I'm not sure where to start with debugging the problem. I've created another package and repeated the steps here and get the same problem.
I can access the package views from both the package and the app, eg:
View::make('package::view');
The problem seems to be between composer loading the controller and Laravel being able to access it.
The mistake was including the controllers path in the route. I had the following:
Route::get('/package', 'Vendor\Package\Controllers\HomeController#showWelcome');
The correct usage is:
Route::get('/package', 'Vendor\Package\HomeController#showWelcome');
With the namespace included in the controller:
namespace Vendor\Package;
Controller should extend illuminate:
\Illuminate\Routing\Controllers\Controller
Still can't use the package name (eg: Package::HomeController#showWelcome), but I can using the namespace. yay.
Problem solved.
You may try edit your Vendor/Package/composer.json and insert the controllers dir to autoload/classmap:
....
"autoload": {
"classmap": [
"src/migrations",
"src/controllers",
"src/models"
],
"psr-0": {
"Package\\Controller": "src/"
}
}
....
After that, open your terminal and from your package root dir do a composer dump-autoload
Works for me...
have a look into this git article might be of help
https://github.com/jaiwalker/setup-laravel4-package