Adding a custom Artisan command with Behat - php

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.

Related

Localization in a custom Laravel Package

My service provider of my custom package has the following lines in the boot() method:
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'name');
$this->publishes([
__DIR__.'/../resources/lang' => resource_path('lang/vendor/name'),
], 'lang');
I ran the php artisan vendor:publish command and the packages/vendorname/packagename/resources/lang/de.json file was successfully copied to the project.
The translation is not working. I tried copying to the /lang/vendor/name/ folder as well.
When I move my de.json file manually to /lang then the translation is working. To there is no issue with the file itself.
I tried to clear all caches already.
I am not sure why, But, it seems that Laravel just loads only the JSON translation files of the main project and the first package in the Vendor folder.
My solution is:
for loading the JSON translation files from your package, you have to
use loadJsonTranslationsFrom in your package's service provider:
class CustomeServiceProvider extends ServiceProvider
{
/**
* Bootstrap the package services.
*
* #return void
*/
public function boot()
{
$this->loadJsonTranslationsFrom(__DIR__.'/../resources/lang');
}
}
In your JSON file you can use your package name as a prefix for every key. for example, if your package name is MyPackage, your en.json file
looks like:
{
"MyPackage::email": "Email",
"MyPackage::username": "Username",
...
}
You can use some helper functions of Laravel to load your translation keys:
trans('MyPackage::email'); // returns "Email"
OR
__('MyPackage::username'); // returns "Username"
You can follow the links below for more information:
https://laracasts.com/discuss/channels/laravel/loadjsontranslationsfrom-does-not-load-all-json-translation-files
https://github.com/laravel/framework/issues/17923
Laravel 5 loadJsonTranslationsFrom method does not load all JSON translation files from packages
https://github.com/nWidart/laravel-modules/pull/412
https://github.com/laravel/framework/pull/20599

PHPUnit does not find a class

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.

Class 'Vendor\PackageName\ClassName' not found for newly created Laravel package

I've a problem running my newly created Laravel package which please check out https://github.com/Younesi/laravel-aparat
I can download it via Composer with no problem and it's auto-discovered via Laravel but when I try to use it, It gives me the following error of not finding class.
Class 'Younesi\LaravelAparat\Aparat' not found
My service Provider code is like:
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->bind('aparat', function ($app) {
return new Aparat;
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return array('aparat');
}
Any help would be appreciated.
Looking at the package it's working fine, in composer.json of that package there is:
"autoload": {
"psr-4": {
"Younesi\\laravelAparat\\": "src"
}
},
Notice that laravel is not with capital letter here, so in your code you should import rather this way:
use Younesi\laravelAparat\Aparat;
instead of:
use Younesi\LaravelAparat\Aparat;
I also see that you are author of this package, so I would recommend using standard conversion (namespace starting with capital letter) instead of current namespace.
Looking further at package code, I also see that in service provider there is:
namespace Younesi\LaravelAparat;
namespace so it's nothing weird it won't work if you autoload it with lower-case letter and have namespace with upper-case letter
There were some cases with registration problem, cache issues, etc. Try one of these solutions:
register your provider (in main composer.json, then in config/app.php [provider & alias] ), then run composer dump-autoload
make sure you have initiated your package : go to the folder, then composer init
try php artisan config:cache or delete everything in bootstrap/cache/

Class 'AWeberAPI' not found

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';

Testing a Laravel package

So, I'm writing a basic Laravel package and I seem to have stumbled upon yet another problem, this time with testing.
The package in development is currently in a packages folder in the root of the project. I have modified the composer.json file of the package to include the dependencies I need
"require-dev": {
"phpunit/phpunit": "~4.0",
"laravel/laravel": "dev-develop"
}
However , whenever I try running phpunit tests in the package folder (which contains a folder named tests along with a sample test), I get the following error:
PHP Fatal error: Class 'Illuminate\Foundation\Testing\TestCase' not found in /workspace/laravel/packages/sample/http-request/tests/HttpRequestTest.php on line 8
The test file is just the auto-generated stub:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HttpRequestTest extends Illuminate\Foundation\Testing\TestCase
{
/**
* A basic test example.
*
* #return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
Any idea why this isn't working? The app tests run without a hitch, but the app itself doesn't have dependencies other than what's in the box.
SOLUTION
Managed to make it work independently by extending the PHPUnit_Framework_TestCase:
class HttpRequestTest extends PHPUnit_Framework_TestCase
However , running it like:
vendor/bin/phpunit packages/yourname/package-name/
Works as well, so I picked it as an answer.
This works for me:
class HttpRequestTest extends TestCase
And running test with:
vendor/bin/phpunit packages/yourname/package-name/
(Posted on behalf of the OP as an answer).
Managed to make it work independently by extending the PHPUnit_Framework_TestCase:
class HttpRequestTest extends PHPUnit_Framework_TestCase
However , running it like:
vendor/bin/phpunit packages/yourname/package-name/
Works as well, so I picked it as an answer.
For Windows environments you need to use backslashes!
vendor\bin\phpunit packages\yourname\package-name
Create a directory named tests in your root of the package and write various test classes inside it. You can have all functioning of your package inside various methods in a single class or you can use multiple classes.
Move to your project's root and run following commands,
vendor/bin/phpunit packages/YOUR_DIRECTORY_NAME/PACKAGE_NAME
Wait a little and you will get the response for your test cases. No. of positive and negative tests will be shown.

Categories