I am working on a new tokenizer class for PHP_CodeSniffer. This also requires making a new Standard since the valid tokenizers are specified within each standard.
My new classes are using the same namespaces as the “sibling” classes from the original codebase.
If I use composer to install my project, and run phpcs, the auto loader seems to pick up my new classes just fine. PHP_CodeSniffer will load my tokenizer by calling:
$className = ‘PHP_CodeSniffer\\Tokenizers\\’ . $type;
$class = new $className(<stuff>);
Similarly, my custom standard has a use statement for a class in the original codebase. When running phpcs, no error are thrown.
When I try to run a test file through phpcs in a unit test, I get an error that my custom sniff file is unable to find the class in the use statement. My guess is this is auto-loading related. The bootstrap.php file for phpunit requires __DIR__ . ‘/../vendor/autoload.php’.My project composer.json has:
“autoload”: {
“psr-4”: { “PHP_CodeSniffer\\”: “src\” }
},
“autoload-dev”: {
“psr-4”: { “PHP_CodeSniffer\\Tests\\”: “tests\” }
}
Is there an issue with using the same namespace as the original code? With registering the same namespace to a different location in composer? Why does it work in runtime but not in testing?
It turns out PHPUnit has its own custom bootloader. When I added a require_once() for that in my PHPUnit bootloader, it loaded successfully. Thanks to a user on the PHP subreddit.
Related
all. I've installed HybridAuth 3.0 and went step-by-step through the Install instructions using composer. I've used the example code and am able to get an initial HybridAuth class instantiated. However, when I continue on to the example with using the Facebook provider class, I'm getting the error, "Class 'Hybridauth\Hybridauth\Provider\Facebook' not found". I'm also using this in a Drupal 7 environment but have other classes like this that autoload just fine so I'm hopeful that little extra detail has no bearing on the problem.
I tried this both with the composer autoloader and the basic autoloader included with the library (as described in the Installation instructions). They both have the same error when attempting to find the Facebook class which is down in the /src/Provider directory. It does this for other classes as well.
That said, using the Hybridauth\Hybridauth "unified interface" works fine and is my current workaround as it allows one to work with multiple providers at one time. But I'm wondering what I'm doing wrong to not be able to load a specific provider as shown in their Introduction documentation.
This works:
// Include Composer's autoloader
include 'vendor/autoload.php';
// Import Hybridauth's namespace
use Hybridauth\Hybridauth;
// Now we may proceed and instantiate Hybridauth's classes
$instance = new Hybridauth([ /* ... */ ]);
This gives an error:
// Include Composer's autoloader
include 'vendor/autoload.php';
// Import Hybridauth's namespace
use Hybridauth\Hybridauth;
$adapter = new Hybridauth\Provider\Facebook([ /* ... */ ]);
I got no clue why AWeberAPI is not found. Any help is appreciated.
php code:
require('vendor/autoload.php');
new PHPExcel;
new AWeberAPI;
composer.json:
{
"require": {
"aweber/aweber": "^1.1",
"phpoffice/phpexcel": "^1.8"
}
}
The problem
The module doesn't appear to be properly configured for use/autoloading with composer. They may have just added the composer configuration to allow you to easily install it, but not to use it within the composer autoloader.
The generic convention for it is that AWeberAPI should match the package's PSR-4 autoloader format, which says "look in aweber_api", then it will look for a class named AWeberAPI.php. You can test this behaviour is correct by adding this file:
<?php
// File: vendor/aweber/aweber/aweber_api/AWeberAPI.php
class AWeberAPI {
public function __construct() {
die('yeah, it works now...');
}
}
Then try your script again, the class will exist now.
What can I do?
Well - you could submit a pull request to their repository to fix it, but it looks like it would involve renaming the classes and filenames which would be a breaking change so I probably wouldn't bother.
You can get it to work by requiring the actual source of the API library instead of the composer autoloader in this case:
require_once 'vendor/aweber/aweber/aweber_api/aweber_api.php';
I want to write tests for MySQL Database. When I try to extend the database extension, it gives me the above error in title:
class FixtureTestCase extends PHPUnit_Extensions_Database_TestCase
Note: I have installed PHPUnit globally and I can access it through phpunit in cmd. I have latest PHPUnit 4.5.1.
I also installed Dbunit globally through composer:
composer global require phpunit/dbunit
Any help will be much appreciated. I've used PHP 5.4.
For referring to classes that are located within the global namespace, you can simply prefix them with a backward ( \ ) slash.
Try with this:
class FixtureTestCase extends \PHPUnit_Extensions_Database_TestCase
With the leading backward ( \ ) slash, PHP knows that we are referring to the PHPUnit_Extensions_Database_TestCase class in the global namespace, and located that one.
More info here
Hope this help.
It just might be the version of DBUnit. For example I'm using PHPUnit 4.8 and it works with DBUnit 1.4.
I had the above error when I was using composer with "phpunit/dbunit": ">=1.2" and I ended up with DBUnit 2.0.
Test your DB how? Through an API you created or direct accesses to DB? i would recommend you to write an API to access your DB and then write the tests to the API.
for exemple if you want to insert a user you call your web-server address (localhost:3000) or something you have and then call /users through POST to insert and make the routes to that.
I would suggest using LARAVEL for that.
I've registered a custom Artisan command:
Artisan::add(new MigrateAll);
The class resides in app/commands (default location)
However when I run Behat I get the error:
Class 'MigrateAll' not found
Artisan is called in Behat for setting up the DB:
/**
* #static
* #beforeSuite
*/
public static function setUpDb()
{
Artisan::call('migrate:install');
//...
}
Do I need to give it a namespace? (I could not find the correct way to call the Artisan::add command with a namespaced class)
This is somewhat related to your earlier question. Your Behat test suite runs in a separate process independently of your app and knows nothing about the configuration. This also applies to the autoloading in your bootstrap and the autoloading would be the most likely reason why classes don't get found. This should be easily fixed by using Composer to autoload your own sources and vendor packages (both in your app and in your test suite).
# composer.json
{
"require": {
"…": "…"
},
"autoload": {
"psr-0": {
"": "../src"
}
}
}
// Include composer's autoloader in your `setUp()` / bootstrap / index.php.
include __DIR__ . '../vendor/autoload.php';
Take that process separation as a rule and keep in mind that Laravel like any other framework requires a whole bunch of other configuration. Since you are trying to use the database component, your next issue will be with that, because it won't be configured in your test suite.
The best approach is to create separate bootstrap file for Behat, which would inherit most lines from your normal bootstrap, where you need to pass the necessary configuration and do this:
/**
* #static
* #beforeSuite
*/
public static function setUp()
{
include_once('bootstrap.php');
}
If you configured your behat environment with this tut (Laravel, BDD And You: Let’s Get Started), after you added a new command, you need to $ composer dump-autoload to make behat to know the command.
We have existing stuff in our code base that uses dompdf (version 0.5.1)... which has no namespace.
When I include the the aws.phar, using something like
require '/path/to/aws.phar';
all of sudden, I get fatal errors
Class 'DOMPDF' not found in XXXX on line 1193
The code that is causing the error is simply a new instantiating of the class:
$dompdf = new \DOMPDF();
I am guessing this is a namespace problem, but I have no idea how to go about fixing it, since I already put the global escape in front of DOMPDF... If I comment out the require line for the phar, then everything goes back to working.
I also did open up the AWS.phar to see what is going on inside. From the code that is not obfuscated, I see that they are using the symfony class loder.
$classLoader = new Symfony\Component\ClassLoader\UniversalClassLoader();
$classLoader->registerNamespaces(array(
'Aws' => 'phar://aws.phar/src',
'Guzzle' => 'phar://aws.phar/vendor/guzzle/guzzle/src',
'Symfony\\Component\\EventDispatcher' => 'phar://aws.phar/vendor/symfony/event-dispatcher',
'Doctrine\\Common' => 'phar://aws.phar/vendor/doctrine/common/lib',
'Psr\\Log' => 'phar://aws.phar/vendor/psr/log',
'Monolog' => 'phar://aws.phar/vendor/monolog/monolog/src'
));
I tried a couple of different things also to register the dompdf with the class loader, but they all threw errors. I am guessing bc it if written without namespaces.
I have also tried loading the dompdf include config file before and after loading the phar, it seem to make no difference.
Anyone have any suggestions??
v0.5.1 of dompdf did not yet implement SPL autoloading, it registered __autoload(). This outdated method of autoloading didn't work very well because it was difficult to register more than one autoload function at a time. Plus, when using writing PHP that does use SPL autoloading the v0.5.1 autoloader will not be called. PHP SPL autoloading disables calling __autoload() (spl_autoload_register).
v0.6.0 (just released) uses SPL autoloading and should be compatible with AWS.phar. v0.6.0 is (for the most part) a drop-in replacement for v0.5.1 so you might want to try upgrading your copy of dompdf.
If that's not possible for whatever reason you could register the dompdf autoloader manually using SPL after including dompdf_config.inc.php. At a minimum you could try the following:
<?php
require_once('dompdf/dompdf_config.inc.php');
spl_autoload_register('DOMDPF_autoload');
// ...
?>
See the dompdf v0.6.0 autoload include for a more complete example.