PHP: Composer auto-load not working - php

Actually Iam new to PHP. I am running this from a nearly empty folder (actually following along a Lara-casts tutorial: Design a Fluent API with TDD).
My directory structure looks like
src
Expression.php
tests
ExpressionTest.php
vendor
composer.json
composer.lock
Inside composer.json:
{
"require-dev": {
"phpunit/phpunit": "^5.2"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}
Inside ExpressionTest.php:
class ExpressionTest extends PHPUnit_Framework_TestCase
{
/** #test */
public function it_finds_a_string()
{
$regex = Expression::make()->find('www');
$this->assertRegExp($regex, 'www');
}
}
Inside Expression.php
<?php
class Expression
{
}
I then run composer dump-autoload and run phpunit but I still get:
"Fatal error: Class 'Expression' not found in
C:\Users\nobis\code\testing2\tests\ExpressionTest.php on line 8"
Is there something wrong with my syntax? My understanding of Composer is very basic. Thanks in advance.

PHPUnit does not know about Composer natively, therefore without configuring PHPUnit, it will not know about your autoloader setup.
try running PHPunit with --bootstrap vendor/autoload.php to tell it to load with your autoload file.
If that does not work, check your namespace value in your Composer configuration (i.e. "": "src/" might need to change.)

You need to include the autoloader at the top of your test. It is typically at
require __DIR__ . '/vendor/autoload.php';
You can also add a phpunit.xml file to your tell it where the autoloader is then it will run it before every test:
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
bootstrap="/path/to/bootstrap.php"
</phpunit>

Related

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 phpunit psr-4 autoload class not found

I am giving composer autoload a try with some phpunit testing classes, and I can't seem to get it to work. When I run phpunit from the command line, I get the following error : "PHP Fatal Error: Class ... not found".
I will give all the structure and file information.
I can, so hopefully someone will spot where I went wrong.
Structure (cut down to relevant files):
composer.json
composer.lock
phpunit.xml
vendor/
tests/
functional/
BaseTestCase.php
HomepageTest.php
composer.json
{
"require": {
"php": ">=5.5.0",
"slim/slim": "^3.1",
"slim/php-view": "^2.0",
"monolog/monolog": "^1.17"
},
"require-dev": {
"phpunit/phpunit": ">=4.8 < 6.0"
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
phpunit.xml
<?xml version="1.0" encoding="utf-8" ?>
<phpunit colors="true" bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Initial tests">
<directory>tests/</directory>
</testsuite>
</testsuites>
</phpunit>
test/functional/BaseTestCase.php
<?php
namespace Tests\Functional;
use Slim\App;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\Environment;
class BaseTestCase extends \PHPUnit_Framework_TestCase
{
...
test/functional/HomepageTest.php
<?php
namespace Tests\Functional;
class HomepageTest extends BaseTestCase
{
...
I then ran an update to refresh the autoload files
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Writing lock file
Generating autoload files
I then tried running phpunit and got a class not found error:
$ vendor/bin/phpunit
PHP Fatal error: Class 'Tests\Functional\BaseTestCase' not found in <project-root>/tests/functional/HomepageTest.php on line 6
Just to be thorough I tried refreshing the autoload files another way, just in case:
$ composer dump-autoload
Generating autoload files
sfbagency#sfb1:~/clients/ctest/dev$
I also checked vendor/composer/autoload_psr4.php to make sure the Test reference is being set, and it is.
...
Tests\\' => array($baseDir . '/tests'),
...
I have Googled like crazy, but have no idea where I am going wrong.
Namespace directories are case sensitive. You have to rename the folder to Functional
As said in the PSR-4 documentation:
The subdirectory name MUST match the case of the sub-namespace names.
I had a similar problem but without syntax problem.
As soon as I added a second ClassTest (ModelTwoTest.php below), the Fixtures.php class was autoloaded. If I remove 1 modelTest, only the remaining ModelTest is autoloaded without Fixtures. Weird behavior.
src/
tests/
Models/
ModelOneTest.php
ModelTwoTest.php <---
Fixtures/
Fixtures.php

Psr-4 composer autoload own class - no found

I have structure directory
autoload composer:
"autoload": {
"psr-4": {
"model\\": "src/"
}
},
my class
namespace model;
class ClientAgent
{
private $pdo;
public function __construct(\PDO $pdo)
{
$this->pdo = $pdo;
}
public function sentAgent()
{
}
}
in index.php i tried add
use model\ClientAgent; but it throw error, not found class? why?
Edit after answer
"autoload": {
"psr-4": {
"model\\": "src/model/"
}
},
my index.php
use model\ClientAgent;
$loader=require_once __DIR__ . '/../vendor/autoload.php';
$clientAgent =new ClientAgent($pdo);
error
Uncaught Error: Class 'model\ClientAgent' not found in C:\xampp\htdocs\Wieloagenty\index.php:15
My suggestion is to introduce a vendor prefix. That might be your developer name, the name of your company or the name of the application.
composer.json
"autoload": {
"psr-4": {
"YourApplication\\": "src/"
}
},
Now, every class inside the src folder and below needs this vendor prefix on it's namespace.
Let's take src\model\ClientAgent.php as example:
namespace YourApplication\Model;
class ClientAgent
{
Now, the FQCN (full qualified class name) is YourApplication\Model\ClientAgent and you might use it as part of a use statment.
// first require the Composer autoloader
require_once __DIR__ . '/../vendor/autoload.php';
// declare which other classes you are using
use YourApplication\Model\ClientAgent;
$clientAgent = new ClientAgent($pdo);
Important!
After the modifications (to classes and the composer.json file) please regenerate the Composer autoloader with php composer.phar dumpautoload -o.
Composer will scan the complete src folder including subfolders for classes (so you'll have all classes from src\models\ and src\views autoloading ready).
"model\\": "src/" will give you the folder src/ as the base for the model-namespace. So this would give you model\model\Classname.
Change it to:
"psr-4": {
"model\\": "src/model/"
}
When defining psr-4 autoloader in composer, you associate a folder with a specific namespace.
Any sub folders will be a sub-namespace. So if you create a folder in your "model"-folder, the namespace would be: model\new-foldername\Classname and so on.
Note: When ever you update your composer.json file, you always need to run the command: composer dump-autoload to make composer regenerate all it's cached files.

Symfony2 Composer Bundle Namespace

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.

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