Behat and PHPUnit installed globally with composer on Mac OS X

I am using PhpStorm 8 and Php 5.5.13. Composer and other packages are at the latest versions.

I have installed behat and PHPUnit globally using compioser. They are installed int $HOME/.composer/vendor/bin and the sources in $HOME/.composer/vendor/behat and $HOME/.composer/vendor/phpunit. Although they both run without problems, PhpStorm doesn't seem to be able to find the behat namespaces in the editor or the PHPUnit classes. I have tried a number of paths based on the $HOME/.composer/vendor path but none seem to correct the problem. This is frustrating because I don't get the code completion hints that I would expect when coding step definitions and unit tests.

I also notice that PhpStorm in the Preferences is saying that Behat is not installed regardless of the path that I put in.

10 comments
Comment actions Permalink

Hi there,

Please show some screenshots with your settings where I can see which path and where you have put for PHPUnit (cannot advise anything on Behat -- have not used it myself).

0
Comment actions Permalink

I have Phpunit selected as loading from the include path. The include paths are as shown in the attached screenshoot.

Running PhpUnit works fine. It is simply the editor that can't find the classes.



Attachment(s):
Screen Shot 2014-10-24 at 12.59.41.png
Screen Shot 2014-10-24 at 12.54.06.png
0
Comment actions Permalink

If PHPUnit files are located in "/Users/kiwi-et/.composer/vendor" folder (which sounds right) then it SHOULD work.

Those paths should be listed under "External Libraries" branch in the Project View -- can you see them there?
If you do -- what happens if you naviage trough that tree and open one of those files, for example the one that contains PHPUnit_Framework_TestCase class?

I'm using PHPUnit but PHAR option and it seems to work OK for me. Include paths also work .. but "normal" libraries (like, ZF1, SwiftMailer and similar)

Also: what is your PhpStorm version exactly, including build number (Help | About)? PHPUnit version?

0
Comment actions Permalink

Thanks. This last response gave me the clue. I am more used to working with IntelliJ IDEA and Java. In IntelliJ IDEA, there is are two menu entries. One defines the global context and the other the current projects settings. In PhpStorm, the File menu has a default settings but there is no project or module settings.

What I was doing was adjusting the default settings and I wasn't seeing these reflected in the project. Since the default settings reflected the way I had PHP setup to run from the terminal, I could run behat and phpunit but PhpStorm wasn't finding the libraries. The external libraries was empty. By putting the same paths in there as I had in the default settings, PhpStorm was able to find the BehatContext and phpUnit libraries. It looks like it is almost working fine.

There is only a small problem now. The require_once 'PHPUnit/Framework/Assert/Functions.php'; doesn't seem to find Framework within PhpStorm but does when I run behat. Since the PhpUnit asserts are still found for syntax checking, this is really a minor issue.

0
Comment actions Permalink

The require_once 'PHPUnit/Framework/Assert/Functions.php'; doesn't seem to find Framework within PhpStorm but does when I run behat.

What do you mean by that? IDE complains that it cannot resolve the included file?

PHP can find it because it checks all include paths during runtime + possible autoloading.

PhpStorm, on another hand, cannot see what paths are used during actual runtime -- it can only judge based on how you configure it:

1) PhpStorm searches for references relative to: the current file; the project root; the library roots

2) You are using "/Users/kiwi-et/.composer/vendor" as one of the include paths .. so it searches for that file as "/Users/kiwi-et/.composer/vendor/PHPUnit/Framework/Assert/Functions.php". Is this the right full path? I think no.
If I'm correct, you better include each vendor/package separately instead of one entry for everything (obviously, it has positive and negative sides: e.g. more paths to configure if few packages are used). On positive side: if you only need one packeg out of (lets say) 10 installed, IDE has less to index/less to remember and working with when showing you code completion etc.

0
Comment actions Permalink

2) You are using "/Users/kiwi-et/.composer/vendor" as one of the include paths .. so it searches for that file as "/Users/kiwi-et/.composer/vendor/PHPUnit/Framework/Assert/Functions.php". Is this the right full path? I think no.
If I'm correct, you better include each vendor/package separately instead of one entry for everything (obviously, it has positive and negative sides: e.g. more paths to configure if few packages are used). On positive side: if you only need one packeg out of (lets say) 10 installed, IDE has less to index/less to remember and working with when showing you code completion etc.

The Behat package is found fine by PhpStorm with the "/Users/kiwi-et/.composer/vendor" path. It also finds the PHPUnit_Framework_TestCase class in a PhpUnit but it will not find the require_once for "PHPUnit/Framework/Assert/Functions.php". If I try to add a sub path such as "/Users/kiwi-et/.composer/vendor/phpunit/phpunit", PhpStorm seems to ignore it as a duplicate of the higher level path. It makes no difference to whether PhpStorm finds the PHPUnit directory.

If I change the require-once to 'phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php'. PhpStorm reports finding the file but the run of behat then crashes. I would like some consistency in the configuration between the PhpStorm environment and the run environment. Is that too much to ask for?

0
Comment actions Permalink

include/require and just a class reference are two different things.

IDE can find your class by name even if it will be 10 folders deep with wrong folder names and PHP itself will return "unknown class" during run time. You can grab your entire PHPUnit installation and put into PROJECT_ROOT/secret_place/bla-bla-bla/ folder .. and IDE will find those classes (because it matches by class names). But your require/include will remain not resolved.

If I try to add a sub path such as "/Users/kiwi-et/.composer/vendor/phpunit/phpunit", PhpStorm seems to ignore it as a duplicate of the higher level path.


I did not said "add another one" -- I've said "replace".

It makes no difference to whether PhpStorm finds the PHPUnit directory.


PhpStorm resolves class references by class names not by file paths/names.

If I change the require-once to 'phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php'.

Why would you do that?

PhpStorm reports finding the file but the run of behat then crashes.


I'm pretty sure it will -- PHP will not be able to find that file during runtime.

I would like some consistency in the configuration between the PhpStorm environment and the run environment. Is that too much to ask for?


Sure thing. That's why I've suggested to configure PROPER include paths in PhpStorm (that would match the logic of how resolving of include/require works) if you want to see include/require statements not marked as warnings (or .. just disable corresponding inspection).

0
Comment actions Permalink

I'm beginning to think PHP is crap. The autoload in the vendor directory sets up the paths for execution and from what I have read that is the PROPER way to configure PHP. Now you are telling me the PROPER way is to spend hours configuring each project with individual package paths. What seems strange to me is that the way Behat is written, it works fine with the vendor path but I suspect this is because it uses namespaces rather than require_once as PHPUnit does. I look at the number of packages that I am having to put paths in for and I shudder. There has to be an easier way to configure this environment.

The thing is I generally like JetBrain products but in this case, it is easier to configure NetBeans for PHP development than PhpStorm but I have a real dislike for NetBeans and its generally unstable environment.

At this point, I am just going to ignore that PhpStorm says it can't find the file as it makes no difference to anything while writign the code.

0
Comment actions Permalink
I'm beginning to think PHP is crap.

Possibly. Especially compared to more established / better designed languages. But I'm not into this, at all.

The autoload in the vendor directory sets up the paths for execution and from what I have read that is the PROPER way to configure PHP.

Yes. Autoload is preferred over manually specifying required files (include/require statements).

But you are forgetting that actual PHP and IDE for PHP is not the same thing: IDE can perform static analysis and cannot see details/changes that you will have when php script will be executed by PHP interpreter.

You possibly forgetting one thing: autoloader also needs to be configred in order to know where to search for missing classes. When you installing package via Composer, it (Composer) does it automatically for you. But nothig is get done for IDE...

Now you are telling me the PROPER way is to spend hours configuring each project with individual package paths.

No need to over-react -- it does not take hours -- max minute or two. Plus other nuances, like the one above: autoload is not the same as include/require statements.

What seems strange to me is that the way Behat is written, it works fine with the vendor path but I suspect this is because it uses namespaces rather than require_once as PHPUnit does.

Not really.

PHPUnit still uses PEAR style naming where Behat uses more modern namespaces. They both can use autoloading: from autoloader point of view the difference between "\Vendor\Package\Class" and "Vendor_Package_Class" is very minimal.

The "problem" here (why we do have this discussion) is that the include/require statement is used when it could possibly be done without it (it actually depends on the content of that included file -- autoloading works/gets triggered for classes .. but not individual functions/files).

At this point, I am just going to ignore that PhpStorm says it can't find the file as it makes no difference to anything while writign the code.

That's the point that I was trying to explain to you: either configure IDE providing correct paths (so that include/require inspection can work with those paths) .. or just disable that inspection altogether -- it's pretty useless, especially nowadays with autoloading in use and especially when your code actually works fine when executed.

If the classes/packages/libraries you are using support autoloading, then you should not use include/require to load those classes (classes, not indivuidual functions), because "$someVar = new Some_Class()" is enough (if all configured, the autoloader will know where to look for "Some_Class" and will "magically" issue include/require statement for you with correct path).

----

To sum it up.

You have:
"/Users/kiwi-et/.composer/vendor" as one of the include paths configured in IDE.

For require_once 'PHPUnit/Framework/Assert/Functions.php'; statement the corresponding inspection in IDE will check at least these paths:

  • CURRENT_FILE/PHPUnit/Framework/Assert/Functions.php
  • CONTENT_ROOT/PHPUnit/Framework/Assert/Functions.php (in most projects only one CONTENT_ROOT is present, so it's basically equal to PROJECT_ROOT)

  • /Users/kiwi-et/.composer/vendor/PHPUnit/Framework/Assert/Functions.php

If it will not find such file in those paths .. it will mark that require_once statement with warning label.

IDE will NOT check for you if that file is POSSIBLY located in /Users/kiwi-et/.composer/vendor/SOME/SUB-FOLDER/PHPUnit/Framework/Assert/Functions.php

Therefore:

  • If you need that inspection to show "green" for that statement -- please configure your include paths *in IDE* accordingly.
  • If you do not care about those statements (becuse it's working anyway) -- just as I do -- just disable that inspection altogether .. or just ignore those warnings.
0
Comment actions Permalink

Thanks. I do understand.

It is clearly part of the issues with the development of a language. As it matures, it introduces features to make programming easier and as a consequence easier for an IDE. PHP at present has an old include/require structure and the newer namespace. From my perspective the namespace seems to be the prefered direction.

0

Please sign in to leave a comment.