IDE
PHPStorm, of course. In fact, this monopoly already scares me, because many buns are tied to him alone, and when switching to something else, a lot of time will be spent not on retraining, but simply on re-creating the functional. Of the ryushechek that are used less frequently:
- File Watcher + Codeception + intermediate shell script (if there are tests / Unit / $ $ Test.php file - run it) = auto-tests that will fail with an error if something happens. Not to say that saved me at least once, but the mind pleasantly excites
- The run configurations stack is almost ci-jobe. You can set up all the testing and analysis with one stack and run one hour before the end of the working day.
- Running the same configurations in debug mode allows you to climb right into the test and see what fell. In a good way, it is impossible to do this, in an amicable way, such reports should be made for tests so that they can establish the root cause of the fall, but we never have time.
- Connection coverage.xml and highlighting not yet covered rows.
- Refactoring is an absolutely divine thing.
- Code generation (alt + insert) - as a rule, I use it only for getters / setters and still parve PHPDoc, but a very nice thing
- I don’t know how in other IDEs, but PHPStorm has a pretty nice namespace support.
- Integration of PHPMD / PHPCS right at the level of backlighting sour lines.
- Checking files before a commit is a very useful thing, even though I can normally use it only in my projects (time, unfortunately, is not enough at work).
Web server
nginx. Until now, I’m not freely guided in configs, but it’s somehow easier with him than with Apache (burn in hell, .htaccess) + in 99% of cases on production it will be him. PHP-FPM is configured for three configurations - dev, test, prod, but it never gave a serious boost. I am configuring with my hands what’s wrong about 100% - I still don’t know how it should be ideally (vagrant? Docker? Virtualbox + chef / puppet / saltstack?), But you can't do this with your hands. At one time, there was an idea to write a simple console web server configurator, but the project successfully stalled - in order to implement it completely, I first need to add a couple more libs that safely stand still.
OS
Linux Mint / KDE. Just personal preference. Well, in fact, on a home hospital, for several reasons, Windows 8, but in a virtual machine - Linux Mint. By the way - you should also organize your own environment through some puppet, because it is very painful to roll everything for the fifth time manually.
Source location
In my own way, I’m dumb, so I keep this structure:
- / srv / http / src - real sore web projects
- / srv / http / hosts - symlinks to sorts according to host names (for example, the playground project can roll in sorts, and playground.dev, admin.playground.dev, special.playground.dev can roll in the hosts)
- / srv / http / apps - all sorts of pma, which I stopped using
- / home / etki / Workspace - folders with symlinks on sorts + own projects that do not require a web server (library)
- / usr / local / bin / composer - composer
- / usr / local / composer - global composer folder
- / var / cache / composer - cache composer. Together with the last but one folder, they turn the global visibility of the user-wide composite into system-wide
- / usr / local / composer / vendor / bin - added to PATH
For normal people, instead of / srv / http, use / var / www
I will organize hosts with the help of dnsmasq (I just added a resolver to 127.0.0.1 for tld loc, local, dev, prod, test)
Libraries, frameworks and utilities
During the last months the following was established:
For PHP, there are pretty cool tools for testing and analyzing code - the phpcs and phpmd, phpcpd, phpdcd, php docblock checker (this is for such as I), parallel lint, pdepend, phploc, which can say a lot about code, are already mentioned. php-cs-fixer will also fix the code for you. Specifically for testing - athletic, codeception, the first, for obvious reasons, is rarely used, but when I manage to use it, I am happy as a child.
Opencart, Yii, Yii2, CI, Kohana, Wordpress, Joomla - fierce, impenetrable, which can never be used. Yii2 - the disappointment of the year, it would seem, all the crutches are already known, but still there is a rake at every step.
Right now there is a project to which to unscrew Yii and substitute symfony. This is no longer possible, but if I did migrate to Phinx (and I can do a pancake) and initially wrote a more portable code, I would still be able to jump between iterations over these New Year holidays.
Any apishka should be written through guzzle. It tritely repels in time. In addition, a mock plugin allows you to invade the course of execution once and twice and slip your answer, which allows you to develop an apish client without touching the apish itself. Another nail in the current project.
On packagist there are several virtual file system packages. It will take time to understand them, but with this thing you can test directly takes off to a new level.
Mock (no matter from which library, PHPUnit, Mockery, Codeception / Stub) is the best invention of mankind. This again comes up against my favorite testing, but when I finally began to use the whole bunch of these magical practices, I finally understood how and why the disconnected code is written (and why nothing could be more disgusting than a Yii tax object).
Wherever there is no template engine or there is a choice, it is better to use Twig. He and his hands screwed lines for five code, and removes most of the headache - you want, inherit the patterns, you want, implement the usual layout-system.
Code Writing Practices
Static methods really cannot be used. Because if a specific object can still be replaced, then a static call always depends on the name of the class, which tightly drives the dependency into the code. This is not to test, and not to refactor in a short time. You can, of course, use $className::method() , but personally I have such an eye on my forehead. Any simple container will allow you to initialize objects once and be confident in the performance of the code.
ALWAYS, ALWAYS implement support for the dev / prod / test environment, even if it is not in the framework. When the project is blown up to a dozen apishki, it’s already late to implement this thing, because all the surplus goes to fast (and therefore bad) refactoring.
Whenever possible, support for feature flags and dev traits should be introduced (by and large, it’s the same thing, dev traits I invented for myself). Feature flags are simply a set of flags (booleans) in a configuration that controls whether certain features are turned on or off. This allows you to turn features on and off by hand, and in a dev, a feature may be unstable, but it can work and it can be turned off altogether. Or work stably, but expect a review from the testing department. Dev traits is also a set of flags that works only in the dev-environment and controls the additional behavior of the application that facilitates development: it fills out forms, hides elements, etc. In my current project, this thing saved me when I had to translate a giant landing page - I taught the translation component to tint the tokens with different colors depending on whether they were translated or not, and instead of empty calls to put a red stub about the absence of a token. Another flag allows you to hide the translation at all to hell, which allows me to see only the untranslated text.
Not a single config in the world should be written in PHP (hello again, Yii!). This is simply disgusting, such a config is impossible to write to the file again. Even if you restore the structure of the array, all expressions and inclusions will be lost. One of my side projects waiting for free time is a yaml-based configurator that supports simple expressionals like !include file.yaml / !realpath src / !instantiate \Vendor\Lib\Class , which finally allows me to work comfortably with Yii (well, what else).
I already wrote above about migrations - on any project that does not use the database structure that is deployed out of the box, they should be used; any step to the side is punished through a shot through foot. I once asked how atomic migrations should be - well, well, they should be as atomic as possible, one change - one migration. When a table is created in one migration, and then the subsequent creation of a foreign key fails, it shoots the second leg as well. Plus, in general, all migrations should be written with the expectation of the presence of data - you cannot make a column unique if there are already non-unique values hanging there.
Interfaces first: where implementation is intended, everything should depend on the interfaces. This is a rather subtle point, for which I will not have enough abilities to verbalize, but if in brief with an example: the client of the apish should process not HttpResponse , but HttpResponseInterface . In this case, changing the library that implements network requests turns from digging up all levels of written code into writing a trivial wrapper that will meet the requirements of HttpResponseInterface . As far as I understand, this is exactly D in SOLID. Well, according to I - no interface should incorporate a million methods. Until I found out about the mozzle plugin for guzzle, I was going to write a similar functionality that would bypass the guzzle entirely and return the ResponseInterface object (a simple moka would clearly not be enough here). When I saw that there I would have to implement about fifteen methods, about 70% of which I have no idea - I felt sad about the order.
As a rule, any project practically makes you write your exceptions. In this case, there is a very useful hack, which allows you to set an exception handler only for the exceptions of this library, while maintaining the traditional chain of inheritance. This is done like this:
The empty interface is written.
interface MahSuperLibExceptionInterfce {}
All standard SPL exceptions with inclusion of this interface are inherited.
namespace Vendor\MahSuperLib\Exception; use LogicException as SplLogicException; class LogicException extends SplLogicException implements MahSuperLibExceptionInterface {}
Non-standard exceptions are inherited from those created in the previous paragraph.
After that, it is enough for any handler to catch the interface in order to catch only the exceptions of this project / project only:
try { // ... } catch (MahSuperLibExceptionInterface $e) { // hehe }
And the link to a pretty cool, albeit concise pdf http://www.planetgeek.ch/wp-content/uploads/2014/11/Clean-Code-V2.4.pdf
And a bit more
I don’t know how (I almost have everything at the minimum until the end of January), but in the near future I’ll pick myself a stack of jenkins + agents on docker + selenium + phantom + sonarqube. All previous simply fades after this chain is configured. Jenkins will allow you to run out any application tests, and Sonarqube is such a divine server of statanalysis of a code that itself calculates a technical debt and will tell you how much to refactor. It's easier to show once, see, this is an incredible creation, it can work with all major languages.
So far I have been sitting on travis and codeship, I plan to try shippable too. Well, there are still a billion useful services (scrutinizer, versioneye, codeclimate), to which just hands do not reach.
Sorry for the muddled presentation, later a couple more edits may be added.