Symfony - Autoloader can't find class / composer error - php

When I tried adding a new dependency to my project with composer require xyz I got the following error:
The autoloader expected class "PackageVersions\Versions" to be defined in file ".../vendor/ocramius/package-versions/src/PackageVersions/Versions.php".
The file was found but the class was not in it, the class name or namespace probably has a typo.
I dug into that file, to see that the Versionsclass is there, in the right file, but with a the following name:
Versions_composer_tmp0
The namespace declarations seem to be good in the entire project, as well as php opening tags (I read that might cause such problems).
Additionally, I remarked that all the use statements in the Installer class file, which is the one that creates the Versions class are marked by phpstorm as Undefined Classes. They all should be found in the namespace Composer\xyz.
I tried the following without succes:
clearing the symfony cache
clearing composer cache
composer self-update
deleting the ocramius vendor folder so that composer would download it again
renaming the class, which is pointless since the entire purpose of this Versions class is to be rewritten with each composer install or composer update
edit:
I'm trying to install 1up-lab/OneupUploaderBundle, the Ocramius/PackageVersionsis already there as a dependency probably (I did not require it manually)
edit 2:
I just saw that server:run won't work either. So the problem is definitely not related to the bundle I'm trying to install. I managed to make the server run by renaming the class from Versions_composer_tmp0 to Versions.

It turns out that this is a composer issue:
composer/composer#5237
Ocramius released a fix/workaround for this:
Ocramius/PackageVersions - Release 1.0.4

Related

Composer - Setup autoload in new package

I'm trying to make a composer package, but I'm struggling to setup the autoload to work in the project where I'm developing it.
I have two projects:
Project Foo (where I'm developing the package).
Project Bar (where I've installed the package: composer require myhandle/mypackage).
In Project Foo I (obviously) have to be able to use the package as well. But setting up the autoload in my own package is not working.
However... When I commit the changes to Github, update the package at Packagist and run composer update in Project Bar, then it works(?!).
And wierdly enough... If I do composer update from Project Foo (the project where it isn't working). So updating the package to it's current version (?), makes it start working.
So it must somehow be related to how I've setup the autoload.
A note:
I started the package by making a new (empty) folder in the vendor directory, and then build the package there. I figured it was smart, since it then would mirror how it would look had I composer required the package.
I don't know if this is bad practice, since Composer no longer 'are in control' of all files in the vendor directory.
There are tons of guides on how to make a composer package out there, - but non of them explains about a good way to structure the files in the project where the package is being developed.
Here's what I do to 'get the error' (in Project Foo):
Create new class file, such as: myhandle/mypackage/src/Test.php
Then I instantiate it like this: $test = new MyNamespace\MyPackageName\Test();
And then I get the error:
Fatal error: Uncaught Error: Class 'MyNamespace\MyPackageName\Test' not found
And this is what works in Project Bar (the very same code).
I can't find a guide on how to correctly setup autoload in the package I'm developing. I'm using this autoload file, that I found in another composer project. I've put it in the root of my project. It looks like this:
<?php
namespace MyNamespace\MyPackageName;
spl_autoload_register(function($cls) {
$cls = ltrim($cls, '\\');
if (strpos($cls, __NAMESPACE__) !== 0) {
return;
}
$classWithoutBaseNamespace = str_replace(__NAMESPACE__, '', $cls);
// Load files from 'src' directory based on their class name without
// the StoutLogic\AcfBuilder namespace.
$path = dirname(__FILE__).
DIRECTORY_SEPARATOR.
'src'.
str_replace('\\', DIRECTORY_SEPARATOR, $classWithoutBaseNamespace).
'.php';
require_once($path);
});
I can't find it in the Composer Documentation, how to set it up in a new project/package. However I can find a bazillions guides on how to use autoload.
As yivi and Daniel Protopopov pointed out:
Check the documentation at getcomposer.org regarding autoloading
Delete your custom autoloader definition, register your namespace in composer.json (hoping you follow PSR-4 already), run composer dump-autoload.
Last but not least, when- and wherever you need to use it, just include the
require __DIR__ . '/vendor/autoload.php';

Symfony3 - creating a vendor-based bundle

We'd like to create a bundle which can deployed via composer/packagist for others to use. It'll wrap the logic created by the owners of MessageBird. Basically a kind of Service which will indeed be called with the container via ourvendor.messagebird.messaging.
Since it's a type of bundle (as per the docs of Sf3), we created a bundle while following the documentation:
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_bundle.html
As the directory /src we used /vendor instead. That's when it all went wrong. Our namespace could not be located, loaded or even when we manually added it to the autoloading classes of Composer it failed all the same.
The question is, what is the best practice to go about this? We got it working right now and what we did was the following:
We created a bundle wit the following cmd:
bin/console generate:bundle --shared --namespace=OurVendor/MessageBird/MessageBirdBundle --bundle-name=MessageBirdBundle --format=yml
We moved the /src/OurVendor directory to /vendor/OurVendor as the only way to get a perfect generation was to use the default /src folder.
We manually updated the AppKernel.php
We did some debugging with namespaces for Composer but eventually we added "OurVendor\\":"vendor/" to the "autoload/psr-4" directive in root composer.json
We ran composer dumpautoload && bin/console cache:clear -e dev which resulted in an error.
We ran composer -o update which checked all dependencies and updated accordingly, including autogenerated autoload files
Strangely enough we had to add the Bundle to the AppKernel.php class and cleaned the cache again.
After all this it worked but the documentation said no such thing about developing a 3rd party vendor bundle.
http://symfony.com/doc/current/bundles/best_practices.html
So long story short, did we go about it the wrong way or what?
/vendor directory is managed by composer. Do not copy/move anything there. Don't even edit anything there, unless you understand all consequences.
When you create a shared bundle, you need to push it to a VCS of your choice, and add it as a dependency in composer.json of the project which uses it.
When you run composer update it will check-out your bundle into /vendor directory and generate correct autoload file.
Please read more how to use private repositories with composer.

Reference .phar classes installed globally with composer

I've created a small command line tool in PHP and I've also packed that as a PHAR archive.
Next thing I did was publish my archive to packagist.org aka composer.
I can now install my PHAR package through composer like so:
composer global require acme/mypackage
This installs my package fine. And I'm able to run it through command as well.
So far so good, but here comes the problem I´m currently facing.
I have another project should use acme/mypackage. I want that project to reference a class that is packed into that PHAR. Something like this:
<?php
class SomeClass extends AcmeClass {
}
The problem is that the PHP code doesn't recognize the AcmeClass class. Makes sense, because it´s obviously "globally" installed somewhere on the system.
How do other libraries solve this issue? If I'm not mistaken then PHPUnit does something similar right?
How can I solve this issue?
You'll need to add a composer.json file to the root of your project:
The first (and often only) thing you specify in composer.json is the require key. You're simply telling Composer which packages your project depends on.
{
"require": {
"monolog/monolog": "1.0.*"
}
}
Next, you'll need to autoload your dependencies.
For libraries that specify autoload information, Composer generates a vendor/autoload.php file. You can simply include this file and you will get autoloading for free.
require 'vendor/autoload.php';
https://getcomposer.org/doc/01-basic-usage.md

cannot find class, numerous libraries, composer php5.5

I am trying different libraries via composer and on all of them I hit a similar error:
Fatal error: Class 'MyRestApi\Admin' not found in /usr/home/www/tmp/index.php on line 6
I have tried short and long path names:
set_include_path('/usr/home/www/vendor/marcj/php-rest-service/RestService');
require_once('/usr/home/www/vendor/marcj/php-rest-service/RestService/Server.php');
I have tried require, include, require_once, set_include_path.
Also I have tried
require "../vendor/autoload.php";
and
require "/home/www/vendor/autoload.php";
Always the same error trying to find the first class.
This particular library https://github.com/marcj/php-rest-service it the one I am trying.
How do you get a composer library to work without an autoload? (I am assuming this has something to do with my issue)
You don't. Using the autoloader of Composer is one of the central contracts that every package that gets installed with Composer relies on.
In theory you could try to invent your own autoloading. In practice: Why?
Your code is missing a require "vendor/autoload.php"; - the path to vendor depends on where your file is that wants to include the autoloader.
Note that if you add your own package and install it via Composer, it must not include the autoloader by itself - the code that uses this package is supposed to do it.

PHP Zend library results in Fatal Error: class 'Zend\[whatever]' not found

I'm hoping someone can spot what I've forgotten to do. Here are my steps:
Downloaded and unpacked the ZendFramework-2.3.5 into /usr/share.
Updated include_path in my php.ini file to include '/usr/share/ZendFramework-2.3.5/library' per the INSTALL.md, and restarted Apache to confirm the path is set (now ".:/usr/share/php:/usr/share/ZendFramework-2.3.5/library").
Created a test script in my web document root (using the class 'CamelCaseToUnderscore' as an example):
use Zend\Filter\Word\CamelCaseToUnderscore;
$filter = new CamelCaseToUnderscore();
echo $filter->filter('BigsAndLittles');
...and I get the fatal error "class 'zend\filter\word\camelcasetoseparator' not found".
In order to do use Zend classes like this, do I need to do some additional configuration or create an autoloader or something to find them? Seems like this should have worked. If I include the CamelCaseToUnderscore.php file in a require_once statement, then I get a fatal error that it's parent class doesn't exist (CamelCaseToSeparator.php). What am I missing?
You can use require 'Zend/Mvc/Application.php' to test if your include path is correct, but you will need an autoloader:
http://framework.zend.com/manual/current/en/modules/zend.loader.standard-autoloader.html.
You can find an example here (lines 18-20):
https://github.com/zendframework/zf2/blob/master/demos/Zend/Feeds/consume-feed.php
I strongly suggest using composer as it will save you a lot of time troubleshooting your include paths, but it also allows you manage version better. It makes it easier for other developers and to deploy your code.
Starting with composer is very easy, just install it and create composer.json:
https://getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup
Run:
composer require zendframework/zendframework
Composer will download all libraries to vendor folder and will generate an autoloader, all you have to do is to include
require 'vendor/autoload.php';
https://getcomposer.org/doc/01-basic-usage.md#autoloading
Most popular PHP frameworks use composer for managing dependencies:
https://github.com/zendframework/zf2/blob/master/composer.json
https://github.com/symfony/symfony/blob/2.7/composer.json

Categories