I have a FeatureContext class, whose methods implement step definitions for my feature scenarios.
Is it possible to obtain information about current scenario or feature within FeatureContext class? To be specific, I need the path of the feature file, so I can create directory paths relative to dirname('file.feature').
The context class resides somewhere in vendor directory structure, i.e. far away from the actual feature file, so getting the path using __DIR__ would not work.
Any ideas?
Thanks, Sascha
I did find an answer to my question: "hooks"
class MyContext implements Context
{
// ...
/**
* #BeforeScenario
*/
public function beforeScenario(BeforeScenarioScope $scope)
{
var_dump($scope->getFeature()->getFile());
}
}
Related
I was just going through the laravel documentation HERE and came across the following peice of code ::
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
$this->app->singleton('Riak\Contracts\Connection', function ($app) {
return new Connection(config('riak'));
});
}
}
I am new to use in php , just learnt how it functions a few days ago , now does use , when used with a framework like laravel, where one class can be in a directory totally different from another , need to specify the directory structure too ?
I.E. can directory structure impact the way use is used ?
The use statement in PHP (when used outside of a class) is used to import a class from another namespace. Namespaces and folder structure do not necessarily correspond, but it is generally pretty close.
The autoloader used by Laravel, and most other modern PHP applications is part of the Composer package manager. Composer in turn supports multiple namespace standards, most notably PSR-0 and its successor, PSR-4.
In a composer.json file, you'll generally specify a namespace to autoload, and a base directory like so:
{
"autoload": {
"psr-4": {
"My\\Namespace\\": "src"
}
}
}
Any classes in the src/ directory should be in the My\Namespace directory. Classes in src/Model should have the namespace My\Namespace\Model and so on.
What a lot of PHP libraries use nowadays is called an autoloader which may mirror the directory structure, but does not necessarily have to.
I have a Symfony project to which I added some non-symfony php files containing various classes. But for some reason the classes are not loaded when loading the website, even though the IDE sees them properly.
So, I have a class that needs other classes:
namespace rootspace\FrontBundle\Controller;
use rootspace\FrontBundle\Networks\TwitterOAuth;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class TwitterController extends Controller
{
public function connectAction(){
// The TwitterOAuth instance
$connection = new TwitterOAuth('abc', '123');
}
}
And then the class which fails to load (that needs yet another file)
namespace rootspace\FrontBundle\Networks;
/* Load OAuth lib. You can find it at http://oauth.net */
//require_once('OAuth.php'); -- should this be commented out?
/**
* Twitter OAuth class
*/
class TwitterOAuth {
/* Contains the last HTTP status code returned. */
}
Lastly, the third file
namespace rootspace\FrontBundle\Networks;
use Symfony\Component\Config\Definition\Exception\Exception;
class OAuthConsumer
{
public $key;
public $secret;
}
(...)
I assume the actual filenames don't matter, right? Nor their structure? PhpStorm sees all the classes properly, I can right-click through them, but it fails when deployed.
Thanks for help
Edit - the whole error message says
Attempted to load class "TwitterOAuth" from namespace "rootspace\FrontBundle\Networks" in D:\Dropbox\project\src\rootspace\FrontBundle\Controller\TwitterController.php line 15. Do you need to "use" it from another namespace?
This is because Symfony's autoloader follows PSR standards (PSR-0, PSR-4) which says that fully qualified (with namespace) class name translates to file location and name. So in fact file names does matter.
So in your case rootspace\FrontBundle\Networks\TwitterOAuth class should be located in rootspace/FrontBundle/Networks directory in file called TwitterOAuth.php
If classes you are using does not follow PSR standards you can also register them manually in app/autoloader.php file
Check these for more info:
How can I add a namespace to Symfony 2.1?:
How to autoload class
And check this answer
I forgot to add a .php extension to my filename
I am using a framework that allows adding new components to the framework's base class. Is there any way to document these new methods without changing the frameworks files so I can click through to the method in my IDE.
I highly recommend against trying to inject a subclass. If the framework instantiates the class you're extending directly, you'll need to find a way to get it to use your subclass instead.
NetBeans and PhpStorm (and probably many others) will combine elements from multiple definitions of the same class/interface. This allows you to add properties and methods to any existing class without modifying the original source.
/**
* Framework controller base class.
* Provides helpers via __call().
*/
class Framework_Controller { ... }
Now create a file in your code base that you never require containing the same class definition. Your IDE should still parse it and merge its elements with the class above:
if (false) { // Safety first!
/**
* ACME Co. controller base class.
*
* #method ACME_Model_User getUser Load user via authentication helper
*/
class Framework_Controller { /* nothing to add */ }
}
You can try using an interface and declaring the methods normally instead of with #method. That is what we did with Zend_View since it's already an interface. I haven't tried mixing class with interface to see if PhpStorm likes it.
It depends mainly on IDE you are using. I think you should extend base class and add there some new methods/properties with phpdoc comments. Of course changing framework's files is no solution as you already mentioned
You could extend the original class, redefine the function, with new doc, and call the parent function.
e.g.
class newClass extends originalClass
{
/**
* New PHPDoc
*/
function functionName($a)
{
return parent::functionName($a);
}
}
Try to use #see or inline #link directives.
I am using a custom scheme in naming my files. Any pointers on how to autoload them with Zend's autoloader?
Thanks!
You can write your own autoloader class and register it with the ZF autoloader. There is a brief bit about this in the manual: http://framework.zend.com/manual/en/zend.loader.autoloader.html#zend.loader.autoloader.interface
Basically it's just a class defining one method which takes the class name as the parameter. So for you it would be something like:
class My_Autoloader implements Zend_Loader_Autoloader_Interface
{
public function autoload($class)
{
$filename = $class.'.obj.php';
require $filename;
}
}
the above assumes the classes are on the include path, if not, just stick the full path in front of $filename. Add any other mapping/checking you need in here and then register it as per the example in the manual. Normally you would do this in your bootstrap.
The ZF Docs reference 'Subclassing the Action Controller' (bottom of the page), but don't reference a standard place to put the new Action_Controller class.
Application_Module_Autoloader sets up pats for a bunch of things, but never controllers. I guess putting it on library/APPNAMESAPCE/Action/Contoller would work. But that seems a bit odd since every other application specific file is stored under application/.
The class gets autoloaded like any other class, there isn't a 'standard' place for it as such. So the question becomes, where do you want it to live?
The convention I usually follow in modular applications is to have most stuff in the modules, but register an app namespace and use application/models for 'core' type classes. So in your case, say your app namespace was Wordpress, you'd have:
class Wordpress_Controller_Action extends Zend_Controller_Action
{
}
and the file would live in application/models/Wordpress/Controller/Action.php.
To make this work you'll need application/models on your include path, and you'll want to init the standard autoloader with something like this (in your bootstrap class):
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Wordpress_');
return $autoloader;
}
alternatively you could setup the above in application.ini.