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
Related
I'm very new in the field and I'm trying to create my first composer package. I'm following the structure mentioned here but for some reason I always get that the class is not found.
My directory structure is
Project
- src/
-- project
index.php
- vendor/
-- composer/
autoload.php
index.php
So in the main directory Project I have index.php with
<?php
use App\project;
// Autoload files using the Composer autoloader.
require_once __DIR__ . '/vendor/autoload.php';
$entry = new simplePrint();
echo($entry->printHome());
In the directory src/project/ I have index.php with
<?php
namespace App\project;
class simplePrint {
public function printHome() {
return "Hey";
}
}
in composer.json
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
After I create the files, I've made
composer install
composer dump-autoload
What I'm missing here?
Update: after composer update it is still same. The output of the composer update
$ composer update
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Generating autoload files
127.0.0.1:45046 [500]: GET / - Uncaught Error: Class "App\project" not found in ...
PSR-4 says following: The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
So you must call your filename simplePrint.php and not index.php.
Here you can read some more information about PSR-4: https://www.php-fig.org/psr/psr-4/
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.
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;
I'm trying to use a vendor lib that I created my self. For now I am not able to put it in GIT or SVN so I am trying to get it running without.
This is my directory structure(borrowed from an answer below):
vendor/
ISTlibraries/
Saml2Handler/
src/
Saml2Handler/
In my composer.json I have added
"autoload": {
"psr-0": {
"": "src/",
"Saml2Handler": "vendor/ISTlibraries/Saml2Handler/src/"
}
},
vendor/ISTlibraries/Saml2Handler/src/ is the path to my sourcecode. The class I am trying to get is called Saml2Controller which have this namespace defined
namespace Saml2Handler;
When I try from inside my symfony2 controller to initiate the class I get an error:
FatalErrorException: Error: Class 'Saml2Handler\Saml2Controller' not found in ...
In the controller I try a simple new Saml2Controller and I have written
use Saml2Handler\Saml2Controller;
Where am I going wrong?
The error is expected. I believe that you need the following directory structure:
vendor/
ISTlibraries/
Saml2Handler/
src/
Saml2Handler/ <--- you don't have this
Saml2Controller.php
... in order to have namespace Saml2Handler within your Saml2Handler.php.
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.