Symfony2 Composer Bundle Namespace - php

I'm trying for a while to import an own bundle via composer but I got a few problems. I got following bundle:
<?php
namespace Platform\Bundle\PollBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class PlatformPollBundle extends Bundle
{
}
The bundle is in vendor/platform/pollbundle/.
In the "main" composer.json I definied the namespace for autoloading:
"autoload": {
"psr-0": {
"": "src/" ,
"Platform\\": "vendor/platform"
}
},
and in the composer.json from the bundle I definied:
{
"name" : "platform/pollbundle",
"type": "symfony-bundle",
"extra": {
"servicePath": ""
},
"autoload": {
"psr-0": {
"Platform\\Bundle\\PollBundle": ""
}
},
"target-dir": "pollbundle"
}
In the autoload_namespaces there is correctly following line:
'Platform\\' => array($vendorDir . '/platform'),
But I got the error:
Fatal error: Class 'Platform\Bundle\PollBundle\PlatformPollBundle' not found in ........Controller.php on line 13
I tried about 100 solutions but nothing works. Would be great if somebody can help me.

Bundles aren't loaded by composer, but instead are handled by the Symfony kernel itself. In the app directory, edit AppKernel.php like this:
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
...,
new Platform\Bundle\PollBundle\PlatformPollBundle()//<-- add this
);
}
In the app/autoload.php file, meanwhile, register the new namesepace. It used to be done through the $loader instance, by calling $loader->registerNameSpaces(), but now, you have to call a static method on the AnnotationRegistry class:
AnnotationRegistry::registerAutoloadNamespace('PollBundle', 'path/to/PollBundle');
A hacky fix I suggested, which is apparently what fixed it for you, would be to run php app/console generate:bundle in the console, to generate a new bundle with the same name, and then simply replace that bundle's directory (in src/) with your bundle.

It is wrong to define ANY autoloading in the main application for anything pointing into the vendor folder! That's what composer is for. Composer will read the autoload declaration for every package contained in there and add the appropriate autoloading automatically. There is no need to add this yourself.
And even if you have to use software that didn't yet add a composer.json file, the autoloading of only that package should go into the package definition block, not into the autoload definition.

Related

Class not found after auto loading in Laravel

I am struggling with PHP Namespaces and Auto loading in Laravel 5.4. I actually decided to put the models that I need to use in a definite and named folder as app/Models:
php artisan make:model Models/Customer
I have set Customer model's namespace to namespace Models;
Then, I created a route as follows:
Route::get('customer', function () {
$customer = \App\Models\Cutomer::find(1);
echo $customer;
});
To do auto loading work I opened the composer.json file located in the very root folder of the Laravel project and made the autoload to be as follows:
"autoload": {
"classmap": [
"database",
"app/Models"
],
"psr-4": {
"App\\": "app/",
"App\\Models\\": "App/Models"
}
},
After all of this I checked if my composer is an update version and ran dump-autoload:
composer self-update
composer dump-autoload -o
There is also worth of notice the contents of vendor/composer/autoload_classmap.php:
'App\\Models\\Customer' => $baseDir . '/app/Models/Customer.php',
'App\\Models\\Test\\Test' => $baseDir . '/app/Models/Test.php',
My problem is that whenever I execute the url: http://127.0.0.1:8000/customer I will encounter the following error output:
(1/1) FatalThrowableError
Class 'App\Models\Cutomer' not found
Would you please help me understand where of my work has been incorrect, and how to fix it? Thank you very much in advance.
The namespace in the model should be namespace App\Model; (hence why you call the class as \App\Models\Cutomer)
When you use php artisan make:model Models/Customer it should have set the namespace correctly then.
Also, you don't need to edit your composer.json to do this. Remove the additions you've made to your composer.json file for the autoloading and then run composer dumpautoload from the command line.
Hope this helps!
First, you have an error in your PSR-4 setup.
"App\\Models\\": "App/Models"
This does not map to a valid directory. Secondly, and more importantly, there is no need to autoload a nested namespace of one that is already declared. By autoloading App you will already autoload any nested namespaces as long as they conform to PSR-4 standards i.e namespace as directory name and filename as class name.
Composer setup only needs to be the following:
"psr-4": {
"App\\": "app/"
}

Symfony3 ClassNotFoundException after bundle creation

I wanted to start a new 3.3 project in Symfony and started as usual:
1.) Creating the new project: symfony new ArtProject
2.) Creating a new Bundle: php app/console generate:bundle (Paul/ArtBundle, yml, src/)
Then I run the local server and when I open 127.0.0.1:8000 I get this beautiful message:
(1/1) ClassNotFoundException
Attempted to load class "PaulArtBundle" from namespace
"Paul\ArtBundle". Did you forget a "use" statement for another
namespace? in AppKernel.php (line 19)
Which is strange and I haven't figured out why this happen so far. Before creating the Bundle, there was no error; I saw the typical startpage of symfony.
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
......
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
new Paul\ArtBundle\PaulArtBundle(),
];
}
<?php
namespace Paul\ArtBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class PaulArtBundle extends Bundle
{
}
Any idea whats going on there? I did not change a thing, I only ran these commands.
I just installed a fresh copy of S3.3.4 (latest version as of this writing) using:
composer create-project symfony/framework-standard-edition s334 "3.3.4"
bin/console generate:bundle
Share across multiple apps: yes
namespace: Paul\ArtBundle
bundle name: PaulArtBundle
Target Directory: src/
Refreshed the browser and sure enough I got the class not found message.
The generate:bundle command is not updating the autload section of composer.json when a new namespace is introduced. Edit composer.json and:
# composer.json
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle",
"Paul\\": "src/Paul"
},
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
},
Then run
composer dumpautoload
And restart the server(maybe). That should fix the bundle class not found problem.
I have not used the generate:bundle command is quite some time ever since the standard was to put everything under AppBundle so I don't know how long this has been "broken". But at least three questions in the last week or so indicates it was something recent.
And by the way, when I refreshed the browser I got "Hello World" which threw me for a bit. Turns out the new bundle overrides the / route which is also sort of special.
And in case anybody is wondering why this started happening, Symfony 3.2 changed from
#composer.json
"psr-4": { "": "src/" },
To
"psr-4": { "AppBundle\\": "src/AppBundle" },
You could always just change it back though I think spelling out individual namespaces might be "better". Not sure.
And here is an issue with more details: https://github.com/symfony/symfony-standard/issues/1098
Looks like the maintainer favored a tiny speed improvement over breaking an existing command. Oh well. Symfony Flex is supposed to make everything great again.
If you generate a bundle for usage in multiple projects (with own namespace) you need to add it in the composer.json as follwed:
Lets assume your bundle name is CompanyFooBundle with namespace Company\Bundle\FooBundle then the composer autoload section should look like:
...
"autoload": {
"psr-4": {
"Company\\Bundle\\FooBundle\\": "src/Company/Bundle/FooBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
...
This works for me in:
Generate your Bundle with
./console generate:bundle
And follow the steps as always, now, do what you want in your composer.json file with the line
"AppBundle\\": "src/AppBundle"
Replace with "": "src/" or add your bundle, for example: "BackendBundle\\": "src/BackendBundle"
Here's the new part:
Install composer in your bin directory, copy and paste the steps from https://getcomposer.org/download/
Up a level in your project directory, and in your root folder (of your project) run the next command
php ./bin/composer.phar update
Removing vendor dir and again running composer install helped me with same problem.

Why won't my Composer package autoload?

I've been testing getting my packages up to Packagist with a simple class I made. Whenever I require it in a different project, it says the class cannot be found. Is something wrong with my composer.json autoload block?
Here's my project repo file structure:
- src
- prodikl
- View.php
- .gitignore
- composer.json
And here's my composer.json:
{
"name":"prodikl/simple-view",
"description":"A simple to use, basic View object.",
"require" : {
"php" : ">=5.3.0"
},
"autoload": {
"psr-4": {"prodikl": "src/"}
}
}
And finally, in my View.php:
<?php
namespace prodikl;
class View
{
...
}
But whenever I require it into a project and do require "vendor/autoload.php" and use use prodikl\View; it it keeps saying not found
You just need to point your autoloader down one more directory:
"autoload": {
"psr-4": {"prodikl": "src/prodikl/"}
}
This means "classes that belong to the \prodikl namespace can be found in the src/prodikl/ directory."
You might need trailing backslashes on the namespace name too, not sure how picky Composer is about it:
"psr-4": {"prodikl\\": "src/prodikl/"}

Composer plugin autoload depedency

So I'm working on a composer plugin that adds a custom command that can be run after an install or update.
I understand the autoloading configuration, and composer is autoloading all classes but it's also missing a file that just contains namespaced functions.
In my plugin composer.json I have the following:
{
"name": "myco/composer-s3-downloader",
"type": "composer-plugin",
"version": "0.1",
"require": {
"composer-plugin-api": "1.1.*",
"aws/aws-sdk-php": "3.20.*"
},
"autoload": {
"psr-4": {"MyCo\\Composer\\": "MyCo/"}
},
"extra": {
"class": "MyCo\\Composer\\S3Downloader"
}
}
My plugin classes load without a problem. All of the classes for my dependencies also load without a problem. So my plugin command code starts off just fine using the AWS SDK.
The problems comes here, when I try to instantiate an S3Client:
private function initClient() {
if (is_null($this->_s3Client)) {
$this->_s3Client = new \Aws\S3\S3Client([
"version" => "latest",
"region" => 'us-west-2',
"credentials" => [
"key" => $this->_creds['key'],
"secret" => $this->_creds['secret'],
]]);
}
}
I get the following error:
PHP Fatal error: Call to undefined function Aws\manifest()
in .../test/vendor/aws/aws-sdk-php/src/AwsClient.php on line 143
I can see the autoload config in the AWS composer.json and it's correct:
"autoload": {
"psr-4": {
"Aws\\": "src/"
},
"files": ["src/functions.php"]
}
The Aws\manifest function is declared in functions.php. And functions.php is then specified in vendor/composer/autoload_files.php. But near as I can tell that file isn't being loaded. So not all of my dependencies are actually available.
What step am I missing that forces the inclusion of autoload_files.php? I'm not doing a single include for anything in the vendor folder. I'm assuming that composer will handle that for me. But I guess I'm wrong.
So after posting an issue at the Composer Github repo, I did learn that the autoloader that runs during composer execution only includes classes. So if you do need to include loose functions, you'll have to manually run the full autoloader.
I added the following method to my Command class that is loaded by composer and defined in the extra section of the plugin's composer.json.
private function getIncludes() {
$vendorDir = $this->composerInstance->getConfig()->get('vendor-dir');
require $vendorDir . '/autoload.php';
}
I just call it in my plugin constructor and everything I need becomes available.

How to autoload classes without namespaces with Composer without reinstalling?

I just need to autoload some classes, and I don't like the psr-0 namespace insanity (no offense).
This used to work just fine in my project:
"psr-0": {
"": [
"app/controller/",
"app/model/"
]
}
For some reason it doesn't work anymore, even though I'm using the same Composer version. I need it for a new project that is also using Silex. Could this be a conflict with Silex?
I know about the "classmap" option, but it's kind of useless because it requires that I run "composer install" every time I add a new class.
Any ideas?
Try to use "primitive" JSON properties; not an array (like in your example).
This works for me with psr-4 like you say, with "": "app/":
{
"autoload": {
"psr-4": {
"Robbie\\": "core/",
"": "app/"
}
},
"require": {
"monolog/monolog": "1.2.*"
}
}
This gives me the Robbie namespace under the directory core, as an example of sources not controlled by composer, the 3rd party (vendor) Monolog namespace and my default or non-namespace for sources underneath the app directory.
After a composer update, all of them are available when including the generated autoload.php:
<?php
require_once 'vendor/autoload.php';
// ...
?>
Use classmap in instead of psr-4:
"autoload": {
"classmap": ["models/"]
}
If you just want to regenerate the autoload file use composer dump-autoload.

Categories