{"id":87085,"date":"2022-01-17T12:00:20","date_gmt":"2022-01-17T17:00:20","guid":{"rendered":"https:\/\/blog.logrocket.com\/?p=87085"},"modified":"2024-06-04T17:12:36","modified_gmt":"2024-06-04T21:12:36","slug":"modern-tools-php-developers","status":"publish","type":"post","link":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/","title":{"rendered":"Modern tools for PHP developers"},"content":{"rendered":"<!DOCTYPE html>\n<html><p>When discussing PHP, there\u2019s no point in avoiding the elephant in the room; PHP used to be a really mediocre tool, and that\u2019s probably an understatement. In fact, I saw an article recently that addressed the issue of <a href=\"https:\/\/blog.logrocket.com\/why-dont-people-like-php\/\">why people don\u2019t like PHP<\/a>. However, in my personal experience, developers often confuse what they think PHP is with what it actually is.<\/p><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"487\" src=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png\" class=\"attachment-full size-full wp-post-image\" alt=\"Modern PHP Best Practices\" srcset=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png 730w, https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices-300x200.png 300w\" sizes=\"auto, (max-width: 730px) 100vw, 730px\">\n<p>The fact is that PHP got its reputation from somewhere. But the old, dark days of PHP v4 and earlier are way behind us. If you hadn\u2019t run off screaming in horror, you\u2019d have seen PHP evolve, and did it evolve.<\/p>\n<p>In this article, I\u2019ll cover what a modern PHP development environment looks like, reviewing the tools that are available both within the language itself and as complements. With the complexities involved in web development nowadays, you can\u2019t judge the language in isolation. You need to be aware of all the satellite technologies that help you create high-quality software.<\/p>\n<p>By the end of the article, you\u2019ll hopefully have second thoughts about your certainty of how PHP sucks. However, if you\u2019re a fan of PHP, you\u2019ll have more reasons to defend your choice. Let\u2019s get started!<\/p>\n<h2>What is modern PHP?<\/h2>\n<p>Before we jump into the details of what makes PHP great, let\u2019s first establish a definition for modern PHP. At the time of writing, PHP v8.1.0 has just seen the light of day, <a href=\"https:\/\/opencollective.com\/phpfoundation\">the PHP Foundation is about to become a reality<\/a>, and PHP v5.6 is reaching its end-of-life. So, when I refer to modern PHP, I\u2019m referring to v7 and later versions.<\/p>\n<p>Since being rewritten in v5.0, the evolution of the language and its tools has been impressive. PHP v5.0 marked an inflection point in PHP\u2019s history, bringing it to the realm of actual object-oriented languages.<\/p>\n<p>Another discrete leap was the introduction of <a href=\"https:\/\/getcomposer.org\/\">Composer<\/a>, a PHP dependency manager, which certainly drew the line between amateur and professional development. But, I\u2019m getting a little ahead of myself, we\u2019ll cover this in-depth later. Let\u2019s review some major improvements made to PHP within the last few versions.<\/p>\n<h2>PHP language improvements from \u2265v7.x<\/h2>\n<p>Since <a href=\"https:\/\/www.php.net\/releases\/index.php\">PHP v7.0<\/a>, which was released on December 3, 2015, several exciting new features have been introduced, like type declarations, built-in cryptography, support for complex data structures, named arguments, and attributes.<\/p>\n<p>The syntax also experienced some powerful improvements, like <a href=\"https:\/\/www.php.net\/manual\/en\/functions.arrow.php\">arrow functions<\/a>, the spaceship operator, and null coalescing. Each new release came packed with major performance improvements over the previous one.<\/p>\n<p>Each of these new features might be pretty shocking to someone who left PHP three or four versions ago. To get the most of these great features, you\u2019d probably have to be a heavy PHP user, however, for those of us who use PHP more casually, PHP has introduced additional new features tailored towards everyday use cases.<\/p>\n<p>Now that we have a grasp on the features the latest PHP versions have introduced, let\u2019s build our toolbox. In the following sections, I\u2019ll discuss some tools I consider to be indispensable when it comes to professional software development in PHP. They are presented in incremental order, meaning I believe this will be the&nbsp;easiest path to adoption.<\/p>\n<h2>Debuggers<\/h2>\n<p>Before the introduction of debuggers like <a href=\"https:\/\/xdebug.org\/\">XDebug<\/a> and <a href=\"https:\/\/www.zend.com\/downloads\/zend-studio-web-debugger\">ZendDebugger<\/a>, developers were forced to spend excessive time understanding the root cause of an application\u2019s misbehavior.<\/p>\n<p>In practice, debugging involves looking at the contents of variables during a program\u2019s execution.<br>\nIn general, PHP is used in batch mode, meaning that the output is only visible once the script has run to completion, making it hard for developers to guess what the context was when the error occurred.<\/p>\n<p>Additionally, the tools available for this task like <code><a href=\"https:\/\/www.php.net\/manual\/en\/function.var-dump.php\">var_dump<\/a><\/code>, <a href=\"https:\/\/www.php.net\/manual\/en\/function.echo.php\"><code>echo<\/code><\/a>, and <a href=\"https:\/\/www.php.net\/manual\/es\/function.print-r.php\"><code>print_r<\/code> <\/a>pose a high risk of leaving traces behind, potentially exposing sensitive information and lowering the bar for malicious attackers.<\/p>\n<p>Both XDebug and ZendDebugger work well with modern IDEs like PhpStorm and VS Code to solve the issues mentioned above. If you prefer to go straight through the command line, <code><a href=\"https:\/\/www.php.net\/manual\/en\/book.phpdbg.php\">phpdbg<\/a><\/code> comes bundled with PHP since v5.6.<\/p>\n<h2>Dependency management<\/h2>\n<p>Importing external libraries as dependencies used to be a real pain in PHP. However, one of the most prominent changes in PHP\u2019s maturity came with the release of <a href=\"https:\/\/getcomposer.org\/\">Composer<\/a>. Before Composer, PHP used <a href=\"https:\/\/pear.php.net\">PEAR<\/a>, which solved the same problem in a more primitive way.<\/p>\n<p>For example, it\u2019s complex to have individual project dependencies using PEAR. Dependency management with PEAR is an all-or-nothing situation, so running several projects on the same server is difficult, especially if each depends on a different or conflicting set of dependencies.<\/p>\n<p>On the other hand, dependency management is much simpler with Composer. Every project has its own <code>composer.json<\/code> and <code>vendor<\/code> folders, keeping everything self-contained.<\/p>\n<p>Another great advantage of Composer is its versioning system, which has built-in intelligence to determine the best fit for a dependency tree; think of dependencies that have dependencies of their own. PEAR, on the other hand, does a very poor job in this area.<\/p>\n<p>Nowadays, PHP best practice requires familiarity with Composer. Most of the tools we\u2019ll cover require its availability in your working environment.<\/p>\n<h2>MVC frameworks<\/h2>\n<p>If you\u2019re building any non-trivial application, chances are you\u2019ll have to create a lot of boilerplate code before you can actually solve your client\u2019s problem. Think of issues like authentication, routing, and database management.<\/p>\n<p>In the older days of PHP, these were a real challenge. Nowadays, there are many MVC frameworks available, most notably <a href=\"http:\/\/symfony.com\/\">Symfony<\/a> and <a href=\"https:\/\/laravel.com\/\">Laravel<\/a>, which you can use as a basis for your task. Symfony and Laravel both boast of large community support and widespread usage.<\/p>\n<h2>Automated testing<\/h2>\n<p>Automated testing tools have become a standard throughout the software development industry. Every language has its own tools, and the biggest player for PHP is definitely <a href=\"https:\/\/phpunit.de\/\">phpUnit<\/a>.<\/p>\n<p>phpUnit was originally designed as a unit testing framework, but other tools have helped expand it to provide other types of testing like end-to-end and integration testing.<\/p>\n<p>Using phpUnit is pretty simple. Say you have a class like the following:<\/p>\n<pre class=\"language-php hljs\">&amp;lt;?php\n\nnamespace LeewayAcademy;\n\nclass Calculator\n{\n    public function add(int $a, int $b): int\n    {\n        return $a + $b;\n    }\n}\n<\/pre>\n<p>Reading the code, you probably assume it will work.&nbsp;But with phpUnit, you can define a set of repeatable tests that will help you build and justify your confidence level. For example, a test case will look like the following:<\/p>\n<pre class=\"language-php hljs\">&lt;?php\n\nuse PHPUnit\\Framework\\TestCase;\nuse LeewayAcademy\\Calculator;\n\nclass CalculatorTest extends TestCase\n{\n    public function testAdd()\n    {\n        $sut = new Calculator();\n        $this-&gt;assertEquals(3, $sut-&gt;add(1, 2));\n        $this-&gt;assertEquals(10, $sut-&gt;add(5, 5));\n        $this-&gt;assertEquals(10, $sut-&gt;add(0, $sut-&gt;add(4, 6)));\n    }\n}\n<\/pre>\n<p>The code above runs the <code>add<\/code> method with different sets of inputs, then validates that the output matches what was expected. You can run tests with phpUnit using the following command:<\/p>\n<pre class=\"language-php hljs\">php vendor\/phpunit\/phpunit\/phpunit --no-configuration --filter CalculatorTest --test\n<\/pre>\n<p>The code above will produce an output like the following:<\/p>\n<pre class=\"language-php hljs\">Testing started at 10:07 ...\nPHPUnit 9.5.11 by Sebastian Bergmann and contributors.\nTime: 00:00.006, Memory: 4.00 MB\nOK (1 test, 3 assertions)\n<\/pre>\n<p>You can run this kind of test as many times as you want. If all of them pass, you\u2019ll have some actual proof that your application is doing what it\u2019s supposed to do. Of course, these tools are <a href=\"https:\/\/blog.logrocket.com\/hosting-all-your-php-packages-together-in-a-monorepo\/\">only as good as the tests you write<\/a>, but that\u2019s another discussion altogether.<\/p>\n<p>Other tools worth mentioning include <a href=\"https:\/\/codeception.com\/\">Codeception<\/a>&nbsp;and <a href=\"https:\/\/behat.org\/\">behat<\/a>. Both use phpUnit underneath, but have different approaches to writing tests.<\/p>\n<h2>Static analysis tools<\/h2>\n<p>A lack of static analysis used to be a big drawback&nbsp;for PHP and other non-compiled languages. Some bugs were so well-hidden in obscure execution paths, it was very hard to find them under normal testing situations. We now have phpstan, Psalm, and Exakat, just to name a few. For example, consider the following bug:<\/p>\n<pre class=\"language-php hljs\">&lt;?php\n\nfunction f(int $p): int\n{\n        return $p * 2;\n}\n\n$a = 'M';\n\necho f($a);\n<\/pre>\n<p>With static analysis tools, a <code>type<\/code> mismatch bug like the one above can be detected without running the code, simply by issuing a command like the one below:<\/p>\n<pre class=\"language-php hljs\">vendor\/bin\/phpstan analyse test.php --level 5\n<\/pre>\n<p>The code above will produce the following output:<\/p>\n<pre class=\"language-php hljs\"> 1\/1 [\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593\u2593] 100%\n\n ------ ---------------------------------------------------------- \n  Line   test.php                                                  \n ------ ---------------------------------------------------------- \n  10     Parameter #1 $p of function f expects int, string given.  \n ------ ----------------------------------------------------------                                                                                \n [ERROR] Found 1 error \n<\/pre>\n<p>Now, you have very precise information on errors that might have otherwise been overlooked. By including these tools in a continuous integration pipeline or running them as part of Git Hooks, you can more easily improve the quality of your codebase.<\/p>\n<h2>Deployment tools<\/h2>\n<p>A developer\u2019s job doesn\u2019t end once they\u2019ve written their last line of code. To reach an audience, your application must first reach a production server.<\/p>\n<p>With older versions of PHP, deploying your application required pushing the new files to a remote location. However, nowadays, it\u2019s a bit more complicated. You\u2019ll probably have to handle database updates, directory permissions, and an abundance of other small tasks to get everything up and running. Oftentimes, missing one of these actions or running them in a different order makes the whole deployment fail.<\/p>\n<p>Just like automated testing tools, the PHP ecosystem provides fantastic tools for taking your application to production and keeping it updated as needed, preventing tremendous headaches. Some of these include Deployer, Rocketeer, Pomander, and easydeploy. As an example, here\u2019s a configuration for Deployer I used for a client\u2019s project:<\/p>\n<pre class=\"language-php hljs\">&amp;lt;?php\nnamespace Deployer;\n\nrequire 'recipe\/codeigniter.php';\n\n\/\/ Project name\nset('application', 'APP');\n\n\/\/ Project repository\nset('repository', 'git@bitbucket.org:maurochojrin\/REPO.git');\nset('branch', 'master');\n\nset('default_stage', 'prod');\n\n\/\/ [Optional] Allocate tty for git clone. Default value is false.\nset('git_tty', true); \n\n\/\/ Shared files\/dirs between deploys \nadd('shared_files', [\n    'application\/config\/database.php',\n    'app_env.php',\n]);\nadd('shared_dirs', [\n    'application\/sessions',\n    'application\/logs',\n    'assets\/uploads\/excel',\n    'logs',\n]);\n\n\/\/ Writable dirs by web server \nadd('writable_dirs', [\n    'application\/sessions',\n    'assets\/uploads',\n    'application\/logs',\n]);\n\n\/\/ Hosts\n\nhost('THE_HOST')\n    -&gt;stage('prod')\n    -&gt;identityFile('~\/.ssh\/MauroChojrin.pem')\n    -&gt;set('user', 'ubuntu')\n    -&gt;set('deploy_path', '~\/{{application}}');\n\n\/\/ Tasks\n\ntask('build', function () {\n    run('cd {{release_path}} &amp;&amp; build');\n});\n\ntask('pwd', function () {\n    $result = run('pwd');\n    writeln(\"Current dir: $result\");\n});\n\n\/\/ [Optional] if deploy fails automatically unlock.\nafter('deploy:failed', 'deploy:unlock');\n<\/pre>\n<p>With this configuration in place, whenever I push a new version to production, I just have to run the command below:<\/p>\n<pre class=\"language-php hljs\">dep deploy\n<\/pre>\n<p>The script will remotely run every task required to make the app available for users. If you\u2019re still pushing files over FTP, you probably want to check these tools out.<\/p>\n<h2>Asynchronous execution<\/h2>\n<p>Another common complaint when it comes to PHP is its lack of asynchronous execution support. There are a couple of projects aimed in that direction like <a href=\"https:\/\/www.swoole.co.uk\/\">Swoole<\/a> and <a href=\"https:\/\/reactphp.org\/\">ReactPHP<\/a>. Take a look at the following code pulled from the <a href=\"https:\/\/github.com\/deminy\/swoole-by-examples\">Swoole By Examples repository<\/a>:<\/p>\n<pre class=\"language-php hljs\">#!\/usr\/bin\/env php\n&lt;?php\n\ndeclare(strict_types=1);\n\n\/**\n * How to run this script:\n *     docker exec -t $(docker ps -qf \"name=client\") bash -c \"time .\/io\/blocking-io.php\"\n *\n * This script takes about 3 seconds to finish, and prints out \"12\".\n *\n * Here the PHP function sleep() is used to simulate blocking I\/O. The non-blocking version takes about 2 seconds to\n * finish, as you can see in script \"non-blocking-io.php\".\n *\/\n(function () {\n    sleep(2);\n    echo '1';\n})();\n\n(function () {\n    sleep(1);\n    echo '2';\n})();\n<\/pre>\n<p>Compare it to its non-blocking counterpart:<\/p>\n<pre>#!\/usr\/bin\/env php\n&lt;?php\n\ndeclare(strict_types=1);\n\n\/**\n * How to run this script:\n *     docker exec -t $(docker ps -qf \"name=client\") bash -c \"time .\/io\/non-blocking-io.php\"\n *\n * This script takes about 2 seconds to finish, and prints out \"21\".\n *\n * Here the Swoole function co:sleep() is used to simulate non-blocking I\/O. If we update the code to make it work in\n * blocking mode, it takes about 3 seconds to finish, as you can see in script \"blocking-io.php\".\n *\n * To see how the code is executed in order, please check script \"non-blocking-io-debug.php\".\n *\/\ngo(function () {\n    co::sleep(2);\n    echo '1';\n});\n\ngo(function () {\n    co::sleep(1);\n    echo '2';\n});\n<\/pre>\n<p>Syntactically, they look pretty similar, but underneath, the second version is leveraging Swoole\u2019s power for parallel processing, decreasing the time required to achieve the end result.<\/p>\n<p>In PHP v8.1, <a href=\"https:\/\/php.watch\/versions\/8.1\/fibers\">Fibers<\/a> were introduced as an out-of-the-box feature, so if async is your goal, there\u2019s nothing stopping you from achieving it without leaving PHP.<\/p>\n<h2>Conclusion<\/h2>\n<p>PHP has come a long way. Sadly, not every PHP developer has followed along with these best practices, so you can still find a lot of spaghetti code out there. However, this reflects more of an individual\u2019s responsibility rather than a tool\u2019s shortcomings.<\/p>\n<p>On the bright side, there are <a href=\"https:\/\/blog.logrocket.com\/?post_type=post&amp;s=PHP&amp;orderby=relevance&amp;order=DESC&amp;post_type=post\">many excellent resources to level up with PHP<\/a> if you want to. I hope you enjoyed this article. If you weren\u2019t already, I hope you\u2019re now a fan of PHP, or at least willing to give it a shot. Let\u2019s turn PHP\u2019s reputation around.<\/p>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>PHP got its reputation from somewhere. But the old, dark days of PHP v4 and earlier are way behind us.<\/p>\n","protected":false},"author":156415891,"featured_media":87094,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2147999,1],"tags":[2109825],"class_list":["post-87085","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-uncategorized","tag-php"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Modern tools for PHP developers - LogRocket Blog<\/title>\n<meta name=\"description\" content=\"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Modern tools for PHP developers - LogRocket Blog\" \/>\n<meta property=\"og:description\" content=\"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/\" \/>\n<meta property=\"og:site_name\" content=\"LogRocket Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-01-17T17:00:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-04T21:12:36+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png\" \/>\n\t<meta property=\"og:image:width\" content=\"730\" \/>\n\t<meta property=\"og:image:height\" content=\"487\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mauro Chojrin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/mchojrin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mauro Chojrin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/\",\"url\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/\",\"name\":\"Modern tools for PHP developers - LogRocket Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.logrocket.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png\",\"datePublished\":\"2022-01-17T17:00:20+00:00\",\"dateModified\":\"2024-06-04T21:12:36+00:00\",\"author\":{\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/b220413c087982b746f6dda7a7405dc9\"},\"description\":\"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage\",\"url\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png\",\"contentUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png\",\"width\":730,\"height\":487,\"caption\":\"Modern PHP Best Practices\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.logrocket.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Modern tools for PHP developers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.logrocket.com\/#website\",\"url\":\"https:\/\/blog.logrocket.com\/\",\"name\":\"LogRocket Blog\",\"description\":\"Resources to Help Product Teams Ship Amazing Digital Experiences\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.logrocket.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/b220413c087982b746f6dda7a7405dc9\",\"name\":\"Mauro Chojrin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/97fba1466065746a1cc32cd22fb2e525b85c6d5395c4cf1e47de01089aeaba99?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/97fba1466065746a1cc32cd22fb2e525b85c6d5395c4cf1e47de01089aeaba99?s=96&d=mm&r=g\",\"caption\":\"Mauro Chojrin\"},\"description\":\"I'm a PHP trainer and consultant who has been involved with the IT industry since 1997 in a wide array of positions, including technical support, development, team leadership, IT management, and teaching.\",\"sameAs\":[\"https:\/\/academy.leewayweb.com\",\"https:\/\/www.linkedin.com\/in\/maurochojrin\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/mchojrin\"],\"url\":\"https:\/\/blog.logrocket.com\/author\/mauro-chojrin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Modern tools for PHP developers - LogRocket Blog","description":"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/","og_locale":"en_US","og_type":"article","og_title":"Modern tools for PHP developers - LogRocket Blog","og_description":"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.","og_url":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/","og_site_name":"LogRocket Blog","article_published_time":"2022-01-17T17:00:20+00:00","article_modified_time":"2024-06-04T21:12:36+00:00","og_image":[{"width":730,"height":487,"url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png","type":"image\/png"}],"author":"Mauro Chojrin","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/mchojrin","twitter_misc":{"Written by":"Mauro Chojrin","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/","url":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/","name":"Modern tools for PHP developers - LogRocket Blog","isPartOf":{"@id":"https:\/\/blog.logrocket.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage"},"image":{"@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png","datePublished":"2022-01-17T17:00:20+00:00","dateModified":"2024-06-04T21:12:36+00:00","author":{"@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/b220413c087982b746f6dda7a7405dc9"},"description":"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.","breadcrumb":{"@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.logrocket.com\/modern-tools-php-developers\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#primaryimage","url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png","contentUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2022\/01\/modern-php-best-practices.png","width":730,"height":487,"caption":"Modern PHP Best Practices"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.logrocket.com\/modern-tools-php-developers\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.logrocket.com\/"},{"@type":"ListItem","position":2,"name":"Modern tools for PHP developers"}]},{"@type":"WebSite","@id":"https:\/\/blog.logrocket.com\/#website","url":"https:\/\/blog.logrocket.com\/","name":"LogRocket Blog","description":"Resources to Help Product Teams Ship Amazing Digital Experiences","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.logrocket.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/b220413c087982b746f6dda7a7405dc9","name":"Mauro Chojrin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/97fba1466065746a1cc32cd22fb2e525b85c6d5395c4cf1e47de01089aeaba99?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/97fba1466065746a1cc32cd22fb2e525b85c6d5395c4cf1e47de01089aeaba99?s=96&d=mm&r=g","caption":"Mauro Chojrin"},"description":"I'm a PHP trainer and consultant who has been involved with the IT industry since 1997 in a wide array of positions, including technical support, development, team leadership, IT management, and teaching.","sameAs":["https:\/\/academy.leewayweb.com","https:\/\/www.linkedin.com\/in\/maurochojrin\/","https:\/\/x.com\/https:\/\/twitter.com\/mchojrin"],"url":"https:\/\/blog.logrocket.com\/author\/mauro-chojrin\/"}]}},"yoast_description":"Cover what a modern PHP development environment looks like, reviewing available tools both within the language itself and as complements.","_links":{"self":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/87085","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/users\/156415891"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/comments?post=87085"}],"version-history":[{"count":11,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/87085\/revisions"}],"predecessor-version":[{"id":87201,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/87085\/revisions\/87201"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media\/87094"}],"wp:attachment":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media?parent=87085"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/categories?post=87085"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/tags?post=87085"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}