PHP - BlogFlock All things PHP 2026-07-23T07:45:06.836Z BlogFlock PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog, Exakat, Rob Allen, Blog entries :: mwop.net PhpStorm 2026.2 is Now Out - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=720098 2026-07-17T09:18:17.000Z <p>Welcome to the PhpStorm 2026.2 release overview. This version advances PhpStorm as a platform for your preferred coding agents, models, and AI subscriptions, improves PHP and Laravel support, and delivers productivity gains for working with Git repositories, databases, and the built-in terminal.</p> <p class="has-text-align-center"><a class="jb-download-button" href="https://www.jetbrains.com/phpstorm/download/" target="_blank" rel="noopener">Download PhpStorm 2026.2</a></p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" fetchpriority="high" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/PS-releases-BlogFeatured-1280x720-1-2.png" alt="" class="wp-image-723845"/></figure> <h2 class="wp-block-heading">AI in PhpStorm</h2> <p>PhpStorm 2026.2 adds native support for more third-party AI providers and gives coding agents even greater access to the IDE&#8217;s deterministic features.</p> <h3 class="wp-block-heading">Agents skills manager </h3> <p>AI agents are only as useful as the context they have. When they don’t have knowledge of your frameworks, conventions, and tooling, you end up re-explaining the same setup in every new chat window.</p> <p>Agent skills fix that. Install them once in PhpStorm, and your agents carry that domain knowledge across every project and session – automatically. Browse and manage skills directly from the IDE, expand the built-in library with external registries like public GitHub repositories, or let PhpStorm import skills you&#8217;ve already set up for Claude Code or Codex.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/agent-skills.png" alt="" class="wp-image-720206"/></figure> <p>Learn more in <a href="https://blog.jetbrains.com/ai/2026/04/skill-manager-and-skill-repository/#skills-manager-one-place-to-install-manage-and-reuse-skills">our blogpost</a>.</p> <h3 class="wp-block-heading">Support for third-party providers in AI-based code completion</h3> <p>AI сompletion is an in-editor code suggestion experience that combines inline completion and next edit suggestions that go beyond the cursor. Available to all JetBrains AI users out of the box, it&#8217;s powered by JetBrains-trained models and doesn’t use up your AI credits.&nbsp;</p> <p>With the latest update, you can now connect your own OpenAI-compatible model providers for AI completion.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/third-party-providers-in-ai-completion.png" alt="" class="wp-image-721710"/></figure> <h3 class="wp-block-heading">GitHub Copilot in PhpStorm</h3> <p>Built through a direct partnership between JetBrains and Microsoft, GitHub Copilot is now a natively integrated agent in JetBrains IDEs. Unlike in the previous <a href="https://blog.jetbrains.com/ai/2026/01/acp-agent-registry/" target="_blank" rel="noreferrer noopener">ACP Registry setup</a>, Copilot is available out of the box and provides a more cohesive experience.</p> <p>You can access Copilot directly from the agent picker in the AI chat. Authentication is handled through OAuth with your GitHub account, and an active GitHub Copilot subscription is required.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/github_copilot.png" alt="" class="wp-image-720217"/></figure> <h3 class="wp-block-heading">Faster PhpStorm MCP server setup for terminal AI sessions</h3> <p>To help you get more out of AI agent workflows in the terminal, the IDE can now prompt you to configure the PhpStorm MCP server when starting a new session with your preferred coding agent. If no MCP server is configured, a notification appears automatically and takes you directly to the relevant settings.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/faster-phpstorm-mcp-server-setup.png" alt="" class="wp-image-721721"/></figure> <h2 class="wp-block-heading">PHP</h2> <h3 class="wp-block-heading"><code>#[FileReference]</code> attribute for persistent file references</h3> <p>PhpStorm now lets you mark string literals as file or directory paths using the #<code>[FileReference]</code> attribute on parameters in functions, methods, and constructors. When a path is passed as a string to such a parameter, it gets first-class PhpStorm support for navigation and refactoring.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/persistent_reference1_upd-1.png" alt="" class="wp-image-721961"/></figure> <figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/07/persistent_reference2_upd-2.mp4"></video></figure> <p>Annotated file references apply project-wide and persist across IDE restarts, making them a better alternative to manual reference injections. In addition to simple references, PhpStorm supports relative paths defined with <code>basePath</code>, as well as paths constructed dynamically or using variables and constants.</p> <h3 class="wp-block-heading">Trigger options for code quality tools&nbsp;<strong>&nbsp;</strong></h3> <p>To further optimize the IDE’s performance, PhpStorm now allows you to configure how often third-party code quality tools like PHPStan or Laravel Pint are triggered: on the fly as you type, on idle, or on file save. You can set the <em>Run mode</em> setting in <em>Settings | PHP | Quality Tools | {quality_tool_name}</em>.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/run_mode_qulity_tool-1.png" alt="" class="wp-image-721938"/></figure> <p>Additional language support improvements include: <strong>&nbsp;</strong></p> <ul class="wp-block-list"> <li>Support for <a href="https://www.php-fig.org/per/coding-style/" target="_blank" rel="noreferrer noopener">PER Coding Style 3.0</a>. To configure PhpStorm’s built-in PHP formatter to use the PER Coding Style 3.0 specification on <a href="https://www.jetbrains.com/help/phpstorm/reformat-and-rearrange-code.html" target="_blank" rel="noreferrer noopener">code reformatting actions</a>, go to <em>Settings | Editor | Code Style | PHP | Set from… </em>and select <em>PER-CS 3.0.0</em> from the list.<br><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/per-cs-3-0-0.png" alt=""></li> </ul> <ul class="wp-block-list"> <li>Arrow autocompletion after object variables. The new setting is enabled by default. To disable it, go to <em>Settings | Editor | General | Smart Keys | PHP</em>.<br><video controls="" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/arrow_completion.mp4"></video></li> </ul> <ul class="wp-block-list"> <li>Code completion for nested arrays without explicit keys in<code> #[ArrayShape]</code>.<br><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/nested_arrays_without_keys.png" alt=""></li> </ul> <h2 class="wp-block-heading">Laravel</h2> <h3 class="wp-block-heading"><em>Laravel</em> tool window</h3> <p>The new<em> Laravel</em> tool window lets you manage Laravel projects without leaving PhpStorm. Use the <em>Dashboard</em> tab for general project information and quick access to Artisan commands, the <em>Errors</em> tab to browse local or Sentry-hosted log files and explore or fix errors with AI without copy-pasting logs, and the <em>Laravel Cloud</em> tab to manage deployments and env variables.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/laravelLogViewer.gif" alt="" class="wp-image-720327"/></figure> <p>Other improvements for Laravel developers include:</p> <ul class="wp-block-list"> <li>Support for <code>laravel/passport and stancl/tenancy </code>packages.</li> <li>Support for PHP 8.5’s pipe operator.</li> <li><code>ide.json</code> options for pointing to database schema files, explicit mapping of Eloquent model classes to database tables, custom paths to Laravel Livewire locations, and new <code>viteAsset, passportScopeId, and staticStrings</code> (with file links) completion types.</li> </ul> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/laravel_updates.png" alt="" class="wp-image-720338"/></figure> <p>For the full list of updates, see <a href="https://laravel-idea.com/docs/changelog" target="_blank" rel="noreferrer noopener">Laravel Idea&#8217;s changelog</a>.<br></p> <h2 class="wp-block-heading">Web</h2> <h3 class="wp-block-heading">IDE support for TypeScript 7</h3> <p>If your TypeScript project has grown to the point where completion lags and refactorings feel sluggish, TypeScript 7 is the fix. Microsoft rewrote the compiler and language server in Go, making type-checking up to 4x faster while delivering more responsive code completion and snappier refactorings even in the large codebases.</p> <p>PhpStorm 2026.2 supports TypeScript 7 as the default for projects already using it, with an opt-in upgrade path for those still on earlier versions. You get the full speed benefit immediately – no full project migration required on day one.</p> <h2 class="wp-block-heading">Version control</h2> <h3 class="wp-block-heading">Enhanced Git worktree support</h3> <p>Version 2026.2 simplifies the management of Git worktrees in various development environments, such as WSL. Additionally, you can easily remove and clean up worktrees directly from the IDE.</p> <p>These updates help streamline day-to-day worktree management while reducing the need to switch to external Git tooling.</p> <figure class="wp-block-image size-full"><img loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/worktree_prunable.png" alt="" class="wp-image-720349" style="object-fit:cover; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <h3 class="wp-block-heading">Streamlined Git conflict resolution flow</h3> <p>In large projects, merges often result in dozens of file conflicts, many of which are simple import mismatches or formatting differences. PhpStorm 2026.2 improves the conflict resolution flow, allowing you to invoke the <em>Resolve All Simple Conflicts</em> action, which automatically resolves standard conflicts across the entire changeset instantly, instead of having to open each file one by one. With the new flow, you can also see a complete overview of resolved and unresolved files, reopen files at any time, and revert and reapply conflict chunks in any order.</p> <div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/conflicts_resolution.png" alt="" class="wp-image-720360"/></figure> </div> </div> <h3 class="wp-block-heading">Username autocompletion in code reviews</h3> <p>Mentioning teammates in code review comments is now easier. Simply type <em>@</em> in a comment to open a list of users from the current GitHub or GitLab repository and select the person you want to mention.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/Github_mentions.png" alt="" class="wp-image-720371"/></figure> <h2 class="wp-block-heading">Terminal</h2> <h3 class="wp-block-heading">Easier file and image sharing in terminal sessions</h3> <p>No more copying and pasting paths from your project or external applications when working in the terminal or with CLI agents. You can now drag and drop a file or folder directly into the terminal to insert its path into the current command.</p> <p>To quickly start working from a specific location, drop a file or folder onto the terminal tab area to open a new tab with its root path already set.</p> <p>You can now also paste images directly from the clipboard into supported CLI agent sessions, which makes it easier to share visual information with your agent.</p> <figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/07/drag-and-drop-to-terminal.mp4"></video></figure> <h2 class="wp-block-heading">UI</h2> <h3 class="wp-block-heading">Non-modal <em>Settings</em> dialog</h3> <p>When the <em>Settings</em> dialog is open, you no longer have to close it to interact with the IDE window. This makes it easy to copy project paths to set up scopes, insert values from configuration files into the settings, view code appearance adjustments immediately, or even switch to another project in the middle of the configuration process.</p> <p>By default, the <em>Settings </em>window stays visible above the project where it was invoked. Unpin it to send it to the background.</p> <div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-2 wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/07/non-modal-settings-dialog.mp4"></video></figure> </div> </div> <h2 class="wp-block-heading">Databases</h2> <h3 class="wp-block-heading">Redesigned empty state: A faster way to begin projects<strong>&nbsp;</strong></h3> <p>To streamline your initial setup and provide a ready-to-code experience right from the start, we’ve redesigned the empty state in the <em>Database Explorer</em> tool window. When you open a new project, the tool window now displays quick actions for creating data sources.</p> <p>Additionally, to help you familiarize yourself with basic database features without the distraction of configuration steps, the empty state provides one-click access to PostgreSQL, MySQL, and SQLite demo databases from our <a href="https://www.jetbrains.com/help/datagrip/2026.2/quick-start-guide.html" target="_blank" rel="noreferrer noopener">Quick Start Guide</a>.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/dg_20262_db_explorer_empty_state-1.png" alt="" class="wp-image-720876"/></figure> <h3 class="wp-block-heading">Custom query console names: More context at a glance&nbsp;</h3> <p>You can now customize how query console names are displayed in editor tab headers, making it easier to identify open consoles and files.</p> <p>Previously, only the data source name was displayed next to the file name. Now, you can use variables to include additional details such as the attached data source, database, schema, or search path. To configure the template, go to <em>Settings | Database | Query Files</em> <em>and Consoles</em>, place the caret in the <em>Template</em> field, and insert the variables you need.</p> <p>You can also apply the same template to query files by enabling <em>Use this template for query files</em>.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/ps_20262_query_customs_names_for_query_consoles.png" alt="" class="wp-image-721949"/></figure> <h3 class="wp-block-heading">Database colors: v2.0</h3> <p>The database color system offers a refreshed, more consistent user experience and several usability improvements. This release introduces an adaptive color engine alongside several structural usability improvements:</p> <ul class="wp-block-list"> <li><strong>Theme-aware custom colors. </strong>Previously, static <code>#RRGGBB</code> hex codes remained identical across light and dark themes, ofte1n destroying visual contrast when you switched. Now you only need to choose a hue, and the IDE automatically adjusts the shades for the active theme.</li> <li><strong>Folder color support. </strong>You can now apply custom colors to folders as well as individual database objects.</li> <li><strong>Easier access to color settings. </strong>The color submenu has been moved up a level to make it easier to find, and all color settings are now available directly in the main <em>Settings</em> window instead of a separate dialog.</li> </ul> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/dg_20262_db_explorer_colors.png" alt="" class="wp-image-720898"/></figure> <p><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/dg_20262_db_explorer_colors_themes.png" alt=""></p> <h2 class="wp-block-heading">Performance</h2> <p>As announced in the <a href="https://blog.jetbrains.com/phpstorm/2026/05/phpstorm-2026-2-early-access-program-has-started/" target="_blank" rel="noreferrer noopener">2026.2 EAP blog post</a>, PhpStorm 2026.2 focuses heavily on the overall IDE stability and performance. While not yet showing immediate results beyond an up to 10%* faster project indexing time, the latest changes lay the foundation for reduced startup time, indexing time, and freezes for both local and remote development scenarios in upcoming releases.&nbsp;</p> <p>Share your feedback about performance in PhpStorm by taking this <a href="https://forms.gle/hRM2k4B5aoJS2edc6" target="_blank" rel="noreferrer noopener">survey.</a></p> <p><em>*Benchmarked on a pool of projects representing different PHP frameworks&nbsp;</em>&nbsp;</p> <h2 class="wp-block-heading">Cloud</h2> <h3 class="wp-block-heading">Docker Compose statuses right in the editor&nbsp;</h3> <p>Docker Compose files are now more informative and interactive. You can view the status of running containers directly inside your Docker Compose file and quickly access common actions without leaving the editor.</p> <p>With the ability to jump straight to logs for a specific service, create a database connection, or open a service in your browser directly from the corresponding entry in the Compose file, it is easier to monitor and work with your application stack.</p> <h3 class="wp-block-heading">Faster Docker Compose setup with service templates<strong>&nbsp;</strong></h3> <p>Creating dependent services in Docker Compose is now easier with ready-to-use templates for popular technologies such as PostgreSQL and Kafka.</p> <p>Simply start typing the name of a service or select one from the completion list, and the IDE will generate the corresponding Docker Compose configuration for you. This helps you get common services up and running faster while reducing manual configuration work.</p> <h3 class="wp-block-heading">Terraform testing framework support</h3> <p>Version 2026.2 extends the IDE’s&nbsp; support for Terraform infrastructure-as-code capabilities by introducing native support for the Terraform test framework. This integration rounds out the IDE&#8217;s ecosystem support, allowing you to validate module behavior and enforce configuration policies early in the development lifecycle.</p> <p>These additions build on out-of-the-box infrastructure tooling, ensuring your deployment configurations remain highly maintainable, predictable, and clean.</p> Key Takeaways From PHPverse 2026 - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=722457 2026-07-17T07:57:46.000Z <p>On June 9, PHPverse 2026 brought together PHP developers from different backgrounds to watch talks by domain experts, exchange opinions, and even try to <a href="https://discord.com/channels/1376821413599510648/1511305383916994651" target="_blank" rel="noopener">catch a running elePHPant</a>. The <a href="https://www.youtube.com/live/NR9L0zwXJq4?si=bYUlcL7_UFhU8BG2" target="_blank" rel="noopener">five-hour live stream</a> has been viewed 15,000 times in total and received 10,206 live chat comments, with over 2,600 people watching concurrently at peak hours.&nbsp;</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" fetchpriority="high" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image.jpeg" alt="" class="wp-image-722458"/></figure> <p>Our goal was to give a stage to voices from different parts of the PHP ecosystem. And despite the diversity of perspectives, the main challenges and action points across the talks were the same: living with AI agents, countering new security threats, encouraging contributions and community involvement, and building on the foundation of modern PHP.</p> <p>Below is a quick recap of the talks and key insights.</p> <h2 class="wp-block-heading">Fabien Potencier on maintaining the Symfony project&nbsp;</h2> <p>As someone who has been maintaining Symfony’s open-source GitHub project of over 320 &#8220;subtree split&#8221; repositories for the last 20 years, Fabien attributes its longevity to a handful of deliberate choices: a stable core team of maintainers, staying opinionated, strict predictability, and non-negotiable backward compatibility. Together with the long-established practices, agents and LLMs are introducing new trends to OSS project maintenance too. </p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>From human with scripts to human with agent skills.</p> </blockquote> <p>Fabien shared how he uses his own AI agent (written in PHP!) with continuously refined agent skills to further automate the handling of pull requests, Git conflict resolution, and release delivery.</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>A good GitHub issue is a good prompt. We don&#8217;t need the pull request anymore.</p> </blockquote> <p>Fabien also brought up how AI is shifting the notion of a good open-source contribution, from a PR with ready-made fixes toward a detailed, reproducible issue with clear context, the steps to reproduce it, and discussion threads. If the ticket is thorough enough, it is basically a well-formed prompt. The agent can take it and generate the fix itself.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-1.jpeg" alt="" class="wp-image-722469"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>We are using Terraform in an interesting way: We are not managing servers. This is all about ensuring consistency across all GitHub repositories.</p> </blockquote> <p>Symfony’s use of Terraform deserves special attention. With Terraform, Symfony treats the monorepos as the single source of truth and keeps the descriptions, tags, and team permissions of its over 320 GitHub repositories consistent.</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe title="Running a Large Open-Source Project Like Symfony | Fabien Potencier | PHPverse 2026" src="https://www.youtube.com/embed/uBuP1jERR20?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Ashley Hindle on infrastructure for shipping agent-generated code</h2> <p>After more than 20 years of writing PHP and over half a trillion tokens spent across every major AI provider, Ashley Hindle now has agents writing roughly 99% of his code. In his talk, he argued that AI can now reliably produce production-ready PHP, but that capability only shows up if you do the work to make your systems &#8220;agent-ready&#8221;.</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>The gap between what agents can produce and what you actually get is the developer&#8217;s new job to close.</p> </blockquote> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-2.jpeg" alt="" class="wp-image-722578"/></figure> <p>Ashley framed agent readiness as a set of pillars resting on the foundation of reproducible, parallelizable development environments<strong> </strong>that have everything the agent needs.</p> <p>Another major consideration, in his experience, is ensuring a fast feedback loop for agents through enforced quality gates. Those comprise three tiers of checks: pre-commit checks on changed files only, pre-push checks on the whole codebase, and an agent-coordinated full quality gate running smoke tests and headless browser tests.</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>Your AGENTS.md guidelines file should have pointers to rules and references, but the fixing and enforcement should be automated with traditional tooling.</p> </blockquote> <p>Crucially, rules should live in tooling (Rector, PHPStan, Laravel Pint, Pest), not in a bloated instructions file, and the agents should come into play only after programmatic automatic fixes have been run.</p> <p>The guidelines file for Ashley’s current project is just 124 lines. It opens with the project&#8217;s goal and references &#8220;golden examples&#8221; of a test or a feature. He supplements this with skills (his favorites being <a href="https://github.com/anthropics/skills/tree/main/skills/frontend-design" target="_blank" rel="noopener">Antropic’s front-end design skill</a>, as well as skills for SVG animations, browser automation, and releases), along with cloned documentation repos as references.&nbsp;</p> <p>As for the prompt, Ashley recommends starting your work in <em>Plan</em> mode and having the agent interview you about what you want to achieve. He also recommends making sure to always tag the relevant files.</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="My AI Writes Perfect* PHP | Ashley Hindle | PHPverse 2026" src="https://www.youtube.com/embed/957MaDK4sG0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Jonathan Bossenger on present-day WordPress</h2> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>My goal today is not to ask you to always consider WordPress. I believe in the right tool for the job. But don&#8217;t overlook it due to possibly outdated beliefs.</p> </blockquote> <p>In his talk, Jonathan Bossenger busts the 10 most common myths about WordPress. Starting with the misconception that modern WordPress is an outdated codebase with poor usage of the OOP principles, he highlighted that the project now recommends PHP 8.3 for new installs, and the Gutenberg editor and newer core code (like Interactivity API, AI client, and the MCP adapter) make extensive use of modern PHP practices, including type declarations, namespaces, and stricter patterns.&nbsp;</p> <p>Block editor has also evolved. Block themes now use WordPress&#8217;s own declarative templating language, replacing the old PHP tags-littered templates.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-7.png" alt="" class="wp-image-722589"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>WordPress 6.9 had a 2.8 to 5.8 speed gain over WordPress 6.8, and every release continues to speed up like that.</p> </blockquote> <p>Jonathan also tackled the performance stigma. WordPress now has a dedicated team maintaining a performance lab plugin, delivering steady, measurable gains release over release in contrast to the sluggishness of years past.</p> <p>Other misconceptions about WordPress that Jonathan thoroughly cleared up include the beliefs that it has a heavy reliance on global state, overreliance on plugins to support custom fields, incongruent paradigms, security vulnerabilities, and lack of proper dependency management, as well as usage of <code>WP_Error</code> instead of exceptions.&nbsp;</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="WordPress is dead, long live WordPress! | Jonathan Bossenger | PHPverse 2026" src="https://www.youtube.com/embed/Ri-Ph-Sy1CM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Nils Adermann on the security of Composer dependencies in 2026</h2> <p>Two recent security incidents – a <a href="https://socket.dev/blog/mini-shai-hulud-packagist-malicious-intercom-php-package-compromise" target="_blank" rel="noopener">compromised Intercom PHP SDK</a> and an <a href="https://www.aikido.dev/blog/supply-chain-attack-targets-laravel-lang-packages-with-credential-stealer" target="_blank" rel="noopener">attack on the Laravel-Lang project</a> – showed that the threat models for developers have changed and PHP packages are now a direct target.</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>One compromised GitHub account, or one poorly secured GitHub Action, is now enough to hit a widely used PHP package.</p> </blockquote> <p>In his talk, Nils Adermann, co-creator of Composer and Packagist, thoroughly walked us through what Composer and Packagist already protect against, what shipped recently, and what’s coming next.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-3.jpeg" alt="" class="wp-image-722600"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>We&#8217;re trying to now focus a bit more on prevention rather than just reaction.</p> </blockquote> <p>Among the security measures that have already shipped, Nils mentioned an <a href="https://www.aikido.dev/blog/launching-aikido-malware---open-source-threat-feed" target="_blank" rel="noopener">Aikido Malware</a> feed ingested into Packagist, static analysis of GitHub Actions via <a href="https://github.com/zizmorcore/zizmor" target="_blank" rel="noopener">zizmor</a>, immutable stable versions, a dependency-policy framework, and the deprecation of the source-fallback mechanism that could circumvent malware blocks.</p> <p>Besides that, a number of measures are still on their way. Those include a minimum release-age &#8220;cooldown&#8221;, organizational package ownership, staged release publishing with multi-factor authentication (MFA) approvals, client-side provenance policies, and many more.</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="Composer and Packagist Supply Chain Security in 2026 | Nils Adermann | PHPverse 2026" src="https://www.youtube.com/embed/ACxuzGsomv0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Jeffrey Way on how AI is changing the programmer world</h2> <p>What does AI actually mean for web developers? Depending on which social media thread you are currently reading, you are about to be either unstoppable or unemployed. In his talk, Jeffrey Way covered three worries, three wins, and three realities he thinks we, as software developers, have to contend with nowadays.&nbsp;</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-8.png" alt="" class="wp-image-722611"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>Are we all months away from losing our jobs? That&#8217;s the big question. The answer is maybe. But almost certainly not. Surely not.</p> </blockquote> <p>The wins center around ambition and enjoyment. AI allows you to build the things you&#8217;d never have made time for, build the things you weren&#8217;t capable of, and eliminate the work you&#8217;ve always hated.</p> <p>Jeffrey also called for rethinking our current principles and systems – for example, what a commit or a six-week sprint means now, or whether human-optimized best practices still hold – and suggested viewing reusable skills as &#8220;almost like Wikipedia for programming best practices&#8221;.</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="How AI Is Changing the Programmer World | Jeffrey Way | PHPverse 2026" src="https://www.youtube.com/embed/nZPtLigTLmM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Mike Herchel on modern Drupal</h2> <p>Longtime Drupal core contributor Mike Herchel challenged misconceptions about Drupal and showed how much both Drupal CMS and the Drupal Core framework have changed.&nbsp;</p> <p>Under the hood, modern PHP is making Drupal faster. Since adopting object-oriented PHP and Symfony components around 2015, Drupal has leaned on Composer, dependency injection, PHP fibers, and what Mike called the best caching system he&#8217;s ever seen. A recent release cut database queries by up to 33%, and HTMX is replacing the legacy jQuery Ajax system.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-4.jpeg" alt="" class="wp-image-722622"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>It&#8217;s built for agents.</p> </blockquote> <p>Finally, Mike noted how much Drupal&#8217;s architecture is AI-ready. Its strict, object-oriented APIs and structured content give agents the unambiguous feedback they need. Drupal&#8217;s AI initiative provides base modules for secure provider connections, as well as over 20 bolt-on modules, and agents can now generate JSX code components, Tailwind classes, CSS, and even ECA workflows.</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="This Isn&#039;t the Drupal You Remember | Mike Herchel | PHPverse 2026" src="https://www.youtube.com/embed/dkxZSQLKlYQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Larry Garfield on the internals of the PHP RFC process</h2> <p>Larry Garfield&#8217;s talk was about the machinery behind new PHP language releases – and how anyone using PHP can get involved. Larry explained the mailing list, what makes good language features, the RFC lifecycle, and the voting system, making the case that contributing to a language that &#8220;runs the internet&#8221; means helping millions of developers.&nbsp;</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-5.jpeg" alt="" class="wp-image-722634"/></figure> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>You do not need to have ever looked at a line of C code to be able to get involved in the discussion and say, “I would totally use this” – or “I will never use this”.</p> </blockquote> <p>In addition to becoming RFC authors, Larry encouraged everyone who uses PHP to get involved in the discussions around submitted RFCs, provide feedback, and help shape what makes it to the voting stage.</p> <p>The conversation also touched on RFCs that have already become PHP features. Larry&#8217;s own pick for the best PHP feature of the last decade is constructor property promotion. Looking ahead, he&#8217;d welcome generics, but argues that, from an ecosystem perspective, <a href="https://frankenphp.dev/" target="_blank" rel="noopener">FrankenPHP</a> is &#8220;the most important thing happening right now&#8221;.&nbsp;</p> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="PHP RFCs | Larry Garfield | PHPverse 2026" src="https://www.youtube.com/embed/n3Nhy3g5MHU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Elizabeth Barron on The PHP Foundation</h2> <p>Elizabeth Barron, <a href="https://thephp.foundation/blog/2026/02/27/welcoming-elizabeth-barron-new-executive-director/" target="_blank" rel="noopener">the new executive director of The PHP Foundation</a>, shed light on why this organization exists. The goal is to keep PHP sustainable and viable for the long term, funding people to work on the language while explicitly keeping out of its governance.</p> <p>For 2026, the plan is to show up more and build with the community through a series of special interest groups: an ecosystem security team, a PHP ambassador program, an onboarding initiative, a cryptography SIG, a community events coalition, and an accessibility and inclusion group.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" loading="lazy" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/07/image-9.png" alt="" class="wp-image-722645"/></figure> <p>Elizabeth also focused on changing the perception of modern PHP:</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>Am I worried about PHP? Not at all. And there are two reasons for that: the community and the language itself. It&#8217;s great, it’s stable, it does exactly what you want it to do. The language is not the problem – that&#8217;s the perception. So that&#8217;s an absolutely solvable problem – just telling stories and changing perception.</p> </blockquote> <p>When asked how the foundation would spend a hypothetical sponsorship of 100 million dollars, Elizabeth’s immediate answer was: on the backlog of open issues and PRs in the PHP source.</p> <blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"> <p>Getting rid of the technical debt would make things so much easier to move forward. I think one of the reasons it takes a while for things to get merged is that the process is not easy. Tweaking our processes, cleaning stuff up – all of that takes time and money and energy to do, and there&#8217;s so many other fun things to work on.</p> </blockquote> <p>Watch the full talk:</p> <figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <iframe loading="lazy" title="Getting to Know The PHP Foundation | Elizabeth Barron | PHPverse 2026" src="https://www.youtube.com/embed/ltoPWEzPqEQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div></figure> <h2 class="wp-block-heading">Don&#8217;t miss next year&#8217;s PHPverse</h2> <p>We are looking forward to seeing you at PHPverse next year. <a href="https://lp.jetbrains.com/phpverse-2026/#dont-miss-the-next-phpverse" target="_blank" rel="noopener">Subscribe to the email list</a> to be among the first to get notified about the date and lineup for next year’s event.</p> <p>Want to come as a speaker? Submit your talk proposal <a href="https://docs.google.com/forms/d/e/1FAIpQLSfp-_MYwaeVcDYZuPcL-YHHHikuoyB9hM7FUkpP2nUggba8hQ/viewform" target="_blank" rel="noopener">here</a>.</p> <p>And don’t forget to follow <a href="https://x.com/phpstorm">PhpStorm on X</a> for all the latest news.</p> <p></p> Nextcloud SSRF rules and internal address ranges - Blog entries :: mwop.net https://mwop.net/blog/2026-07-07-nextcloud-ssrf-and-internal-address-ranges.html 2026-07-07T15:12:23.000Z <p>I use <a href="https://nextcloud.com">Nextcloud</a>, and have used the <a href="https://apps.nextcloud.com/apps/news">Nextcloud News</a> app as my feed reader for a number of years.</p> <p>Since moving all my hosting to a home lab, I noticed that Nextcloud News was unable to retrieve feeds from my own website, which was weird. Looking at the logs, I saw notes about &quot;host violates local access rules&quot;.</p> <p>This was a DNS issue (it's always DNS), right? Well, kind of.</p> <p>In order to help prevent <a href="https://owasp.org/www-community/attacks/Server_Side_Request_Forgery">SSRF attacks</a>, Nextcloud, by default, has protections against domains that resolve to internal IP address ranges. When I moved my sites to my homelab, I also setup DNS such that when on the local network, the services resolve to the local address range instead of the public external IP. This was the root of the problem.</p> <p>Fortunately, there's a configuration setting for that:</p> <pre><code class="language-php hljs php" data-lang="php"><span class="hljs-comment">// in the Nextcloud config.php:</span> [ <span class="hljs-string">'allow_local_remote_servers'</span> =&gt; <span class="hljs-keyword">true</span> ] </code></pre> <p>After making that change and restarting Nextcloud, I was able to get it to resolve and access my feeds.</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-07-07-nextcloud-ssrf-and-internal-address-ranges.html">Nextcloud SSRF rules and internal address ranges</a> was originally published <time class="dt-published" datetime="2026-07-07T10:12:23-05:00">7 July 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> Musings on GenAI - Blog entries :: mwop.net https://mwop.net/blog/2026-07-06-musings-on-gen-ai.html 2026-07-06T21:00:00.000Z <p><img src="https://mwop.net/images/art/thumbnails/1f177c9e-8c03-6e3e-8080-62f485bac900.png" alt="My AI web weight" title="My intheweights ranking" /></p> <p>Evidently, the AI models trained on my internet activity, and I have thoughts.</p> <hr /> <p>I recently saw some folks posting images like the above, linking to <a href="https://intheweights.com">intheweights.com</a>; the site allows you to put in a name, and then it analyzes the various models to see how much they have used that person's work to train them.</p> <p>I evidently fall in the top 2% of sources on which they trained.</p> <p>Now, this is not entirely surprising. I have done <em>a lot</em> of open source software development over the past couple decades, and have hundreds of thousands of lines of code up in GitHub that have been downloaded many 10s and 100s of millions of times. I've participated in newsgroups, mailing lists, forums, and standards bodies. I've written a lot of documentation, published a ton of blog articles, and co-authored books.</p> <p>So, how do I feel about AI companies slurping it all up to train their models?</p> <blockquote> <p>There's <em>so much more</em> I could cover in this post. I know I'm not even touching on the environmental impacts, or the inability of AI companies to optimize code and models to consume fewer resources. That doesn't mean those topics are not important; they just weren't the ones top of mind as I wrote this. My apologies if I missed something you find important.</p> </blockquote> <h2>The copyright and attribution problem</h2> <p>Most of my OSS work has used either a BSD, MIT, ASF, or Creative Commons license. The thing about these licenses is that they are permissive; they basically allow anybody to use them in any way, without restriction.</p> <p>Well, I should say <em>almost</em> no restriction.</p> <p>Most of these have an <em>attribution</em> clause: the work can be re-used and remixed, so long as <em>attribution</em> is given. This is generally something as simple as including copyright information when you redistribute code.</p> <p>But here's the thing with generative AI: it doesn't do that. It simply spits out some code. It doesn't tell you where it came from, who wrote it, etc. In fact, it will tell you that the <em>generative AI tool</em> wrote it... and recent court rulings indicate that such code <em>cannot be copyrighted</em>.</p> <p>This is not great from an ethical or legal point of view. Using generative AI means you're not attributing the work that informed and powered it.</p> <h2>The reality of work in IT today</h2> <p>All that said, I work for a software company, and, like basically all software companies today, there's a push to use AI to accelerate outcomes. And like many in the software industry, I have bills to pay, and can't just walk away.</p> <p>So, I've been learning the ins-and-outs of generative AI, both for managing processes as well for doing development.</p> <p>Unsurprisingly, I can point generative AI at a code base of mine, and it will generate code that is structurally similar to what I would have done by hand. And it will do it in a fraction of the time. It's fairly uncanny to prompt Claude Code with a change I want to implement, and have it generate tests, code, and templates that look pretty much how I would have written them. And to be honest, a lot of this is stuff I don't have time for: yes, they may be tools I maintain for doing my work or coordinating with my teams, but as a PM for two different brands, I simply don't have time for coding. Being able to write a specification of what I want to do, tell Claude Code to do it, and then go off to do the strategy and planning work that my employer expects of me is huge.</p> <p>We're also using it as part of our process workflow within the various PM teams. We have MCP servers setup with access to a ton of our internal tools, which gives the agents we use for our PM processes a huge amount of data. And this data turns into signals that were really, really hard to get at before. Developing a business proposal in the past required that I do weeks and weeks worth of competitive research, pricing research, reporting out of our CRM, scouring support and engineering tickets, and more — oftentimes to ultimately decide to table the idea. Today, I can fire off an agent to do some discovery, and take that work to develop a hypothesis for a product or support feature, and then agents will fire off to do more research, collating the information, raising questions for me to follow-up on with peers, and helping me identify if an idea has value we should follow-up on — often in hours or days.</p> <p>With web search having gone to shit, and so many enterprise tools being opaque and requiring expert knowledge to use effectively, what AI agents and tools enable for me is tremendous.</p> <h2>The workforce problem</h2> <p>When it comes to coding, one thing that sticks out: I have been programming for literal decades. I know how to write a specification. Between that, and the fact that generative AI models trained on my literal code, I'm an ideal target for these tools, as what I write is perfectly tailored for them.</p> <p>But here's the thing: how do <em>new</em>, <em>junior</em> developers get to that same stage?</p> <p>In the past, we'd toss those specifications their way, give them tools to help them conform to coding standards guidelines, and do peer review of their work. These activities helped them <em>learn</em>. This was how we got a pipeline from junior to senior developers, by mentoring and training. If we cut out that stage, what will happen to the software industry once the senior developers of today retire?</p> <h2>GenAI as an accessibility aide</h2> <p>I mentioned the process changes where we're using GenAI. There's something I didn't talk about though, and it's pretty important.</p> <p>I'm Autistic and have ADHD. One trait I have is that I see <em>all the steps</em> that need to happen to accomplish something, and quite often, that will overwhelm me. Business plans? One of the worst. I have to do web research, and that often leads into rabbit holes. I have to ask other people to run reports for me, or prepare estimates for me, and that means — ugh! — waiting on somebody else, and the uncertainty of when I'll get the information I need pushes my anxiety up. Then there's trying to understand what information is relevant to the executive team. It's a lot of work. I can do it, I'm even good at it, but knowing what I have to do can lead me to freeze, until it becomes urgent, and then I'm panicking as I scramble to get it all done.</p> <p>Even doing the weekly reports — sure, I've developed systems to capture that information in my Obsidian vault, but I still have to collate download statistics and make sense of them, and then locate the Confluence page for this week's report, edit it, and paste my material in. And even with all that, I have to also think about if the information is even useful, and if I'm communicating it correctly, because Autism and masking. And this happens every. Single. Week.</p> <p>What does this have to do with AI?</p> <p>Surprisingly, AI has acted as an <em>accessibility tool</em> for me.</p> <p>I can task GenAI with doing something, and then go off and do <em>other</em> things. It allows me to let go of the plan from my head, because it's already written down, and the agents are doing the squirreling for me. Being able to free up this cognitive space means I'm less tired, and I'm more able to focus on what matters.</p> <p>Those recurring tasks? As Larry Wall said, one sign of a good programmer is that they're <em>lazy</em>; the counterpoint is we'll spend hours and hours automating something that takes just a few minutes every now and then. But GenAI changes that; I can walk it through a process, and have it capture it as a repeatable skill.</p> <p>Being able to focus on what matters, and still have energy at the end of the day? This makes a huge difference to my quality of life.</p> <p>(I've rediscovered the joy of cooking, because I still have the ability to make decisions at the end of the day!)</p> <h2>The GenAI paywall</h2> <p>But for all of that, it's also creating an accessibility <em>issue</em>.</p> <p>I got into open source in part because I did not need to pay for licenses in order to code software. I was able to download runtimes for free, and access manuals for free.</p> <p>This may not seem like a big deal today, but back in the late 90s and early 00s, it was huge. I didn't need to fork out for ColdFusion, or Frontpage, or Dreamweaver. I didn't need a Microsoft NT license or IIS license. I could spin up Apache with mod_php on my computer, along with MySQL, and just start coding.</p> <p>Here's the issue: GenAI tools <em>cost money</em>.</p> <p>Sure, the plans seem cheap, and sure, there's even free thresholds. But the bills are coming in for the data centers used to train LLMs, and investors are starting to wonder when they'll see money back, and this is already leading to pricing changes; just this past month, Microsoft and Github changed from flat pricing plans to usage-based models, and many people discovered that using them was no longer tenable when bills went from $200 to sometimes tens of thousands.</p> <p>Which leaves me in an interesting spot: GenAI tooling can make my work more accessible to my neurodivergent brain — but I have to <em>pay</em> for that, even though I have no control over how my brain works.</p> <h2>The new build-vs-buy equation, and the death of OSS</h2> <p>I mentioned above that I got into OSS in part due to the fact I didn't have to purchase licenses. I stayed because of community, and because I believe strongly that we all build things better when we do them together. You may be the most brilliant coder in your domain, but when you step out of it — implementing a message queue, working with encryption, adopting DevOps processes — you'll benefit from reaching out to somebody with that experience to review.</p> <p>Open Source Software commoditizes that. We all share our software, and we can all contribute to other people's software. We can stop reinventing the wheel, knowing somebody else, or some group of people, has done it already, and knows the domain better than we do.</p> <p>For a company that consumes OSS, this can be critical. Your teams do not need to be experts of every technology they touch or implement; they can rely on OSS packages or frameworks or libraries to do the hard work.</p> <p>The downside is that when a &quot;supply chain&quot; attack occurs on an OSS project, every piece of software in the world that depends on the project, whether or not it's OSS or commercial, now is vulnerable. I put &quot;supply chain&quot; in quotes deliberately: OSS is not a vendor, not a supplier, but <em>businesses treat it as such</em>. And that puts a lot of pressure on OSS developers, who are often unfunded or underfunded, and getting pressure from companies who depend on them, but will never pay them a dime.</p> <p>But one benefit of OSS is the oft-cited parable of &quot;many eyes makes all bugs shallow.&quot; <em>Because</em> the source is openly available, and because the patching happens within a community, an OSS project is also often uniquely suited to rapid patching of security vulnerabilities.</p> <p>AI turns all of this on its head.</p> <p>Because LLMs are trained on OSS, it also means they are very good at generating code to solve the problems that OSS addresses. And because GenAI is currently relatively cheap compared to developers (I expect this to change, and we're already seeing it change!), the &quot;build vs buy&quot; equation has changed.</p> <p>&quot;Buy&quot; in the &quot;build-vs-buy&quot; equation doesn't need to literally mean &quot;buy&quot;; it can also mean &quot;we're going to add this OSS dependency&quot;. When you add a dependency, you now have to monitor it for security vulnerabilities, and have processes in place to mitigate those. The more dependencies, the larger your security surface area.</p> <p>And that means a lot of companies do a lot of review before they adopt an upstream dependency.</p> <p>But now you can tell GenAI, &quot;please develop the functionality <em>X</em>; it should act like OSS project <em>Y</em> and give us the same public API to consume. Provide tests so we can maintain this going forward, and hook it into our static code and security analysis tooling.&quot; And GenAI will happily go and do that, you'll have a one-time token cost, and a small amount of ongoing token costs for periodic maintenance, and have eliminated an upstream dependency for yourself. Sounds like a win, right?</p> <p>Except it comes at the expense of the OSS ecosystem.</p> <p>Over time, we'll get more proprietary software that's created using GenAI, and the models won't have a growing corpus of OSS to work against.</p> <p>And developers will increasingly need to rely on GenAI tooling to do basic programming, because there's nothing in the commons anymore to use. And that will depend on having privilege and money, excluding a whole class of potential upcoming software engineers from ever entering the workforce.</p> <h2>So, what do you really think?</h2> <p>I'm incredibly torn on the entire subject.</p> <p>I hate the hype cycle behind GenAI, and the hand-waving at environmental, ethical, and societal concerns.</p> <p>At the same time, the tooling has truly freed up time and literal energy for me, and helped me combat some of my worst executive dysfunction, and I see it as being a huge enabler for people.</p> <p>In other words... it's like everything I've ever observed after decades in technology fields. And I wish it wasn't.</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-07-06-musings-on-gen-ai.html">Musings on GenAI</a> was originally published <time class="dt-published" datetime="2026-07-06T16:00:00-05:00">6 July 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> Opening Sublime Text from the command line - Rob Allen https://akrabat.com/?p=7569 2026-06-30T10:00:00.000Z <p>I nearly always open <a href="https://www.sublimetext.com">Sublime Text</a> from the command line using <tt><a href="https://www.sublimetext.com/docs/command_line.html">subl</a></tt> and have specific requirements for when it should open a new window or re-use one. </p> <p>If I'm opening a directory, then I would like it to re-use the same window if I have previously opened that directory. However if I open a random file, I never want that file in the last directory window as it's unrelated.</p> <p>To do this I wrote a simple bash function:</p> <pre lang="bash"> # subl: wrapper that opens files in a new window, and reuses the window # for directories subl() { local args=() opts=() for a in "$@"; do if [[ "$a" == -* ]]; then opts+=("$a") else args+=("$a") fi done # No path argument means the current directory [[ ${#args[@]} -eq 0 ]] && args=(.) if [[ ${#args[@]} -eq 1 && -d "${args[0]}" ]]; then # Single directory: open in same window command subl "${opts[@]}" "${args[0]}" else # File(s): so open in a new window command subl -n "${opts[@]}" "${args[@]}" fi } </pre> <p>Firstly we determine which parameters on the command line are arguments and which are options. Options start with a dash and arguments are either file or directory names.</p> <p>After that, we inspect the arguments.</p> <ul> <li>If there's no arguments, or if there's one argument that is a directory, then we open Sublime Text with the arguments and options we collected and a new directory window opens, unless the directory is already open, in which case it is reused.</li> <li>Otherwise we open Sublime Text with the <tt>-n</tt> option in addition to those passed in. This has the effect of forcing a new window to open.</li> </ul> <h2>Remembering which files were last open</h2> <p>This works really well, but if I close a directory window and then open it again, it has forgotten which files I had open. To get Sublime Text to remember, we need a <em>project</em> file. This is a JSON file with the extension <tt>.sublime-project</tt> file and a minimal one would be:</p> <pre lang="json"> { "folders": [ { "path": "." } ] } </pre> <p>We then open a directory with <tt>subl foo.sublime-project</tt> and then the open files are persisted across sessions.</p> <p>Obviously, I'm not going to manually create this file or remember to use it as argument, so I extended my <tt>subl()</tt> function to manage the project file for me:</p> <pre lang="bash"> # subl: wrapper that opens files in a new window, and directories in the same # window as a Sublime project, reusing an existing .sublime-project, creating # one if opening a dir. subl() { local args=() opts=() for a in "$@"; do if [[ "$a" == -* ]]; then opts+=("$a") else args+=("$a") fi done # No path argument means the current directory [[ ${#args[@]} -eq 0 ]] && args=(.) if [[ ${#args[@]} -eq 1 && -d "${args[0]}" ]]; then # Single directory: use existing project or create one, then open in same window local proj proj=$(find "${args[0]}" -maxdepth 1 -name '*.sublime-project' -print -quit) if [[ -z "$proj" ]]; then local name name=$(basename "$(cd "${args[0]}" && pwd)") proj="${args[0]}/${name}.sublime-project" cat > "$proj" <<EOF { "folders": [ { "path": ".", "file_exclude_patterns": [".*.sublime-project", ".*.sublime-workspace"] } ] } EOF fi command subl "${opts[@]}" "$proj" else # File(s): open in a new window command subl -n "${opts[@]}" "${args[@]}" fi } </pre> <p>The comment covers what happens. Firstly we check for a <tt>sublime-project</tt> file. If one doesn't exist, then we create a default one called <tt>{directory name}.sublime-project</tt>. I'm not particularly interested in this project file, so I exclude it from the Sublime Text side bar using the <tt>file_exclude_patterns</tt> option within the project file itself. Then we open the project with the options that were provided on the command line.</p> <p>Now <tt>subl .</tt> in a fresh directory creates a hidden project file and opens it, and every <tt>subl</tt> after that picks the project back up with my files open exactly where I left them.</p> Your JetBrains IDE Expertise, Now on LinkedIn - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=blog&p=711459 2026-06-17T13:11:02.000Z <p>Every developer has tools they rely on daily. The workflows they&#8217;ve built around them, the ways they&#8217;ve learned to move faster, debug smarter, and write better code – that kind of hands-on experience can be hard to put into words.</p> <p>We’re collaborating with LinkedIn to make it easier for you to showcase your expertise with JetBrains IDEs on the world’s largest professional network. You can now connect your IDE to LinkedIn and let your real tool usage speak for itself.</p> <p align="center"><a class="jb-download-button" href="https://plugins.jetbrains.com/plugin/32011-linkedin-connected-apps" target="_blank" rel="noopener" data-test="blog-article-cta"><i class="download-icon"></i>Connect your IDE</a></p> <p>IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, Rider, GoLand, CLion, RustRover, and RubyMine are already supported via a free plugin, while support for DataGrip is coming soon.</p> <p>In this blog post, we’ll explain what LinkedIn connected apps are, what they mean for your profile, and how to get started.</p> <h2 class="wp-block-heading">What this is about</h2> <p>Building on early <a href="https://www.linkedin.com/pulse/title-newways-stand-out-verify-skills-unlock-new-hari-srinivasan-zhtvc/" target="_blank" rel="noopener">collaboration</a> with Descript, Duolingo, Lovable, Relay.app, and Replit, LinkedIn is expanding the range of apps you can feature on your LinkedIn profile, turning real-world product usage into a credible, visible signal of practical tool experience. We’re glad to join forces with them to bring this to JetBrains IDE users.</p> <blockquote class="wp-block-quote"> <p></p> <cite>“We&#8217;re building new ways for members to show real, credible proof of what they&#8217;re capable of, right on their LinkedIn profile. And for the brands behind these tools, there&#8217;s no better endorsement than a customer who&#8217;s actively using and loving your product.”<br>– Dan Shapero, CEO of LinkedIn</cite></blockquote> <p>Connected apps let you link the tools you use in your daily work directly to your LinkedIn profile, where they appear prominently, helping you stand out to your professional network. Once connected, each app generates a simple statement based on how you actually use it. Unlike manually added skills, this is based on real usage and updates automatically as your experience evolves.</p> <figure class="wp-block-image size-full is-style-default"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/06/In-LinkedIn-4.png" alt="" class="wp-image-713887"/></figure> <h2 class="wp-block-heading">How to get started</h2> <p>Open your JetBrains IDE, go to <em>Settings | Plugins</em>, search for the <em>LinkedIn Connected Apps</em> plugin under the <em>Marketplace</em> tab, and install it.&nbsp;</p> <p>Once installed, the plugin starts collecting data locally about how you use your IDE. Depending on your usage history, you may receive an initial statement right away, which will then be updated once the plugin has collected enough data to better reflect your real IDE expertise.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/06/LinkedIn-integration-in-JetBrains-IDEs-example-1.png" alt="LinkedIn-integration-in-JetBrains-IDEs-example " class="wp-image-713131"/></figure> <p><strong>Your IDE usage data stays on your machine</strong>. When you are ready, you can connect your LinkedIn account and share your IDE expertise badge there. If you keep the plugin installed, your badge will update automatically as your IDE usage evolves.</p> <p>The plugin is free for all JetBrains IDE users.</p> <h2 class="wp-block-heading">What’s included in this release</h2> <p>This is the first version of the integration, delivered as a standalone plugin rather than being built directly into the IDE. It covers IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine; DataGrip is not yet supported.&nbsp;</p> <p>Usage is detected within the IDE itself, so if you use AI features via an external tool or terminal, those won&#8217;t be reflected yet.</p> <h2 class="wp-block-heading">How your IDE expertise is determined</h2> <p>The model is intentionally simple for now. It is designed to represent your practical use of JetBrains tools, <em>not </em>to rank developers or certify skill levels. Our goal was to provide a solid starting point, but we know there&#8217;s more to capture about how developers work with their IDEs.</p> <p>Statements map to different levels of experience and are generated based on how you interact with your IDE – from writing and editing code using basic features to working with debugging tools, version control, and AI-assisted workflows. For more information, see <a href="https://www.jetbrains.com/help/idea/linkedin-connected-apps.html" target="_blank" rel="noopener">our documentation</a>.</p> <h2 class="wp-block-heading">What’s coming next</h2> <p>We’re already working on the next version, planned for later this year. We’ll focus on improving how IDE usage, including AI feature usage, is represented, expanding support to DataGrip, and making the overall experience feel more integrated.</p> <h2 class="wp-block-heading">FAQ</h2> <h3 class="wp-block-heading">Which JetBrains IDEs are supported?</h3> <p>IntelliJ IDEA, PyCharm, WebStorm, GoLand, PhpStorm, Rider, CLion, RustRover, and RubyMine. Support for DataGrip is coming soon.</p> <h3 class="wp-block-heading">Why isn’t DataGrip supported yet?</h3> <p>DataGrip is designed for working with databases and includes workflows that differ from our other IDEs. We plan to support it soon.</p> <h3 class="wp-block-heading">Can I connect multiple IDEs?</h3> <p>Yes, if you use multiple supported JetBrains IDEs, you can connect each of them. You’ll get a badge for all connected IDEs.</p> <p><strong>Note</strong>: If you use multiple JetBrains accounts across different IDE instances but link them all to the same LinkedIn profile, IDE usage statements from each account will be displayed on that LinkedIn profile.</p> <h3 class="wp-block-heading">Do I need to keep the plugin installed after connecting?&nbsp;</h3> <p>You can share your IDE usage statement once and then remove the plugin, but note that it must remain installed if you want to track your ongoing progress and have any changes reflected on LinkedIn.</p> <h3 class="wp-block-heading">Is this feature free?</h3> <p>Yes, it’s available to all JetBrains IDE users at no cost.</p> <h3 class="wp-block-heading">Is this a certification?</h3> <p>Connected apps reflect real IDE usage and are designed to showcase applied experience, not to act as a formal certification or skill ranking. Certifications, degrees, and licenses remain important markers of professional achievement. Connected apps on LinkedIn add a different kind of signal: partner-validated tool usage that reflects practical work and can update over time.</p> <h3 class="wp-block-heading">What data is shared with LinkedIn and JetBrains?</h3> <p>Only the information required to represent your connected account and IDE usage statement.&nbsp;</p> <h3 class="wp-block-heading">Will this help me get hired?</h3> <p>Having connected apps on your LinkedIn profile is extra proof of your practical experience with leading tools. While connected apps make your expertise visible, they are just one part of your profile. Think of it as a way to let your tooling speak for itself.</p> <p>Give it a try and let us know what you think in the comments below. We&#8217;re continuing to develop this integration, and your feedback will help shape what comes next.</p> Contribute to the State of PHP Survey - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=710104 2026-06-11T10:38:57.000Z <p>Together with <a href="https://thephp.foundation/" target="_blank" rel="noopener">The PHP Foundation</a>, we’re embarking on an exciting expedition – the first annual State of PHP census that aims to tally the elePHPant population across the world. Come join us!</p> <div class="buttons"> <div class="buttons__row"> <a href="https://surveys.jetbrains.com/s3/b-state-of-php-2026" class="btn" target="_blank" rel="noopener">Take the survey</a> </div> </div> <p>With the <a href="https://thephp.foundation/blog/2026/04/22/announcing-plans-for-a-php-ecosystem-survey/" target="_blank" rel="noopener">help of the community</a>, we’ve designed a comprehensive survey that aims to unearth the PHP developer trends – from years of experience and favorite frameworks to AI preferences and beyond. Our goal is to draw the most representative picture of the PHP ecosystem and the developers behind it, and share insights that will benefit the community and help shape the future direction of PHP.</p> <figure class="wp-block-image size-full"><a href="https://surveys.jetbrains.com/s3/b-state-of-php-2026" target="_blank" rel="noopener"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/06/Directus-1200x200-2x.png" alt="" class="wp-image-711709"/></a></figure> <p>For this to be a success, we need your help. Our survey will only be truly representative if PHP developers of all backgrounds participate, regardless of where you live, how long you’ve been developing in PHP, what frameworks you prefer, or the tools you use. So take part in the State of PHP survey now and help us map the herd!</p> <p>Survey participants can enter a drawing to win one of five EUR 500 (or equivalent in local currency) vouchers, which they can redeem for any prize they want via Tremendous (subject to <a href="https://surveygizmolibrary.s3.amazonaws.com/library/321629/TermsandConditionsoftheStateofthePHPSurveyContest_20260529.pdf" target="_blank" rel="noopener">the applicable terms and conditions</a>).</p> <h2 class="wp-block-heading">State of PHP report</h2> <p>You can expect to read the travel logs from this journey in October 2026. We will publish the aggregated results in the State of PHP 2026 report, so be sure to follow <a href="https://x.com/ThePHPF" target="_blank">The PHP Foundation</a> and <a href="https://x.com/phpstorm" target="_blank">PhpStorm</a> on X or sign up for our newsletter below to be among the first to see the results.</p> <p>Thank you for being part of the first edition of the State of PHP!</p> <p>The PHP Foundation and PhpStorm teams</p> Fixing two minor git irritations in my OSS fork workflow - Rob Allen https://akrabat.com/?p=7566 2026-05-26T10:00:00.000Z <p>For OSS work, I work with two git remotes:</p> <ul> <li><tt>upstream</tt>: the canonical OSS project repository, where <tt>main</tt> is the default branch and is what gets released.</li> <li><tt>origin</tt>: a personal fork. All my feature branches live here.</li> </ul> <p>I set up locally like this:</p> <ol> <li>Fork the project repo to my account.</li> <li>Clone my fork locally, so the <tt>origin</tt> remote is my fork.</li> <li>Set an <tt>upstream</tt> remote using <tt>git remote add upstream &lt;ssh-url&gt;</tt>.</li> </ol> <p>and then when working on something, I tend to do these steps:</p> <ol> <li>Switch to the main branch with <tt>git switch main</tt>.</li> <li><tt>git pull</tt> from <tt>upstream</tt> to pick up the latest code.</li> <li>Create a new feature branch from <tt>main</tt> using <tt>git switch -c &lt;branch&gt;</tt>.</li> <li>Do work, then commit and push the feature branch to <tt>origin</tt>.</li> <li>Open a PR from <tt>origin/&lt;branch&gt;</tt> against <tt>upstream/main</tt> (usually using <tt>gh</tt>).</li> <li>Once merged upstream, pull from <tt>upstream</tt> back into my local <tt>main</tt> branch and delete my feature branch.</li> </ol> <h2>The problems</h2> <p>I have a couple of little irritations with this workflow that I finally sat down to solve.</p> <ul> <li>Firstly, when I <tt>git pull</tt> on main, it pulls from <tt>origin</tt> by default unless I remember to use <tt>git pull upstream main</tt>. If I don't catch it, I don't have the latest code when I branch for my new work.</li> <li>Secondly, when I push my new branch, I get an error message <em>fatal: The current branch foo has no upstream branch</em> which is just irritating as I then sigh and re-run the <tt>push</tt> with <tt>-u origin</tt>.</li> </ul> <h2>The solutions</h2> <p>To remove these minor irritations, I discovered that I can run these useful git commands:</p> <p>Firstly, set <tt>main</tt> to track <tt>upstream/main</tt>:</p> <pre lang="bash"> git branch --set-upstream-to upstream/main main </pre> <p>Usually I set which repo's branch to track using <tt>git push -u</tt>, but that doesn't make sense for the <tt>main</tt> branch as I never push it to the upstream repo. Using <tt>--set-upstream-to</tt> on the <tt>branch</tt> command does the same thing, without a push.</p> <p>Secondly, to make the first <tt>git push</tt> automatically create the <tt>origin/&lt;branch&gt;</tt> and track it:</p> <pre lang="bash"> git config push.autoSetupRemote true </pre> <p> Now <tt>git pull</tt> on <tt>main</tt> always pulls from upstream, and git push on a new branch just works.</p> Improving Accessibility in JetBrains IDEs: What’s New and What’s Next in 2026 - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=platform&p=707397 2026-05-21T06:45:13.000Z <p>Making software accessible often comes down to removing small but repeated points of friction in everyday workflows. Today, on <a href="https://accessibility.day/" target="_blank" rel="noopener">Global Accessibility Awareness Day</a>, we’re sharing recent improvements in JetBrains IDEs across several areas: compatibility with assistive technologies on various platforms, keyboard navigation, and non-visual feedback. Some of these improvements are already available, and some are coming later this year.</p> <p><em>You can use the audio player below to listen to this blog post.</em></p> <audio class="article-audio" preload="metadata" style="width: 100%;" controls> <source type="audio/mp4" src="https://blog.jetbrains.com/wp-content/uploads/2026/05/Accessibility-Blog-Post-Audio.mp4"> <a href="https://blog.jetbrains.com/wp-content/uploads/2026/05/Accessibility-Blog-Post-Audio.mp4"> Accessibility Blog Post Audio </a> </audio> <h2 class="wp-block-heading">Better compatibility with assistive technologies</h2> <p>One of the key areas we’ve been working on is improving how JetBrains IDEs interact with OS-level accessibility tools.</p> <h3 class="wp-block-heading">Improved Magnifier support on Windows</h3> <p>Screen magnifiers are among the most commonly used assistive technologies in JetBrains IDEs. Until recently, the built-in Windows Magnifier didn’t reliably follow the text cursor in the editor, making navigation and editing more difficult for low-vision users. We’ve implemented support for cursor tracking so Magnifier follows text as you type, just as it does in other applications.</p> <figure class="wp-block-video" alt="Video demonstrating how Windows Magnifier follows the text caret while typing in a code editor"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/05/MAgnifier_output.mp4"></video></figure> <p>This builds on earlier work on macOS, where we addressed text cursor tracking with macOS Zoom. Now, the same support is being extended to Windows.</p> <h3 class="wp-block-heading">Orca and GNOME Magnifier support on Linux</h3> <p>With version 2026.2, coming this summer, JetBrains IDEs will allow you to use the Orca screen reader and GNOME Magnifier in <a href="https://www.jetbrains.com/help/idea/2026.1/installation-guide.html#operating-systems" target="_blank" rel="noopener">supported Linux environments</a>.&nbsp;</p> <p>This is an active area of work, with multiple related tasks already underway. Accessibility shouldn’t depend on your operating system, and we’re continuing to improve support across platforms.</p> <h2 class="wp-block-heading">More predictable keyboard navigation</h2> <p>We’ve also been making it easier to move through the IDE without relying on a mouse.</p> <h3 class="wp-block-heading">Main menu access with <em>Alt </em>on Windows</h3> <p>In native Windows applications, pressing <em>Alt</em> moves the focus to the main menu, allowing you to navigate it with the keyboard. This behavior was previously missing from JetBrains IDEs, and screen readers, such as NVDA, would sometimes announce the system menu instead.</p> <p>Now, the main menu behaves in a way that feels familiar and predictable for keyboard-only and screen-reader users, and the bright focus indicator helps low-vision users identify the selected item.&nbsp;&nbsp;</p> <figure class="wp-block-video" alt="Video demonstrating how the IDE main menu receives focus and is highlighted with a blue frame when pressing the Alt key"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/05/AltF_output.mp4"></video></figure> <h3 class="wp-block-heading">Navigating between major parts of the IDE</h3> <p>Another focus area is the experience of moving between different parts of the IDE interface, such as toolbars, panels, and the editor. We’re working on a more structured model for navigating through the big component groups:</p> <ul> <li><em>Tab</em> and <em>Shift+Tab</em> move the focus within the current area.</li> <li>A dedicated shortcut lets you jump between larger sections of the IDE.</li> </ul> <p>This reduces the effort required to reach essential controls and makes the overall layout easier to navigate. For the current iteration, we made it possible to bring the main toolbar and status bar into focus, and we fixed the <em>Project</em><strong> </strong>and <em>Git</em> toolbar widgets, which were not selectable by screen readers, even though other elements already were.&nbsp;</p> <figure class="wp-block-video" alt="Video demonstrating how the IDE main toolbar receives focus and is highlighted with a blue frame when the Alt+PgUp shortcut is pressed"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/05/AltPgUp_output.mp4"></video></figure> <p>As the next step, we’ll polish specific controls and include tool window bars on both sides of the IDE frame in the navigation flow.</p> <h2 class="wp-block-heading">Exploring richer non-visual feedback with audio cues</h2> <p>Accessibility is not only about reaching controls, but also about understanding what’s happening while you work. We’re exploring ways to provide richer audio feedback in the IDE. Two directions we’re currently investigating:</p> <ul> <li>Contextual signals when the caret lands on lines with errors, warnings, breakpoints, or version control changes. We want the IDE to provide immediate, non-visual feedback in context.</li> <li>More general audio notifications for IDE actions and state changes.</li> </ul> <p>The goal is to reduce the need to rely on visual indicators or switch contexts just to understand what changed. Instead, we want the IDE to provide that information more directly.</p> <h2 class="wp-block-heading">Accessibility as an ongoing effort</h2> <p>We’re improving accessibility in JetBrains IDEs across multiple areas at once, including by providing compatibility with assistive technologies like screen readers and magnifiers, as well as by offering more consistent keyboard navigation and clearer feedback for events that are otherwise mostly visual.</p> <p>These improvements build on earlier updates, such as support for VoiceOver and NVDA, a high-contrast UI theme, and color schemes for red-green vision deficiency. There’s still more to do, and we’ll continue working in this direction.</p> <h2 class="wp-block-heading">We’d love to hear from you</h2> <p>We’re eager to hear from developers who rely on accessibility features, as well as from anyone interested in improving the experience of using them.</p> <p>If you have ideas or feedback about accessibility in JetBrains IDEs, you can reach us directly at <strong>accessibility@jetbrains.com</strong>. You can also report issues through <a href="https://youtrack.jetbrains.com/newIssue?project=IJPL" target="_blank" rel="noopener">YouTrack</a> or the <a href="https://www.jetbrains.com/support/" target="_blank" rel="noopener">support request form</a>.</p> <p>If you’d like to stay informed about accessibility improvements, you can subscribe to updates <a href="https://lp.jetbrains.com/ij-accessibility/" target="_blank" rel="noopener">here</a>.</p> PhpStorm 2026.2 Early Access Program Has Started - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=706754 2026-05-12T13:36:37.000Z <p>The Early Access Program (EAP) for the next major&nbsp;PhpStorm 2026.2 release is now open!</p> <p>PhpStorm&#8217;s <a href="https://www.jetbrains.com/resources/eap/" data-type="link" data-id="https://www.jetbrains.com/resources/eap/" target="_blank" rel="noopener">EAP builds</a> are a great opportunity to try upcoming features for free in your real workflows and share feedback with the PhpStorm team. Your input directly influences what makes it into the final release. </p> <p>This release, our main areas of focus are:</p> <ul> <li>Native mode for remote development scenarios, as we aim to significantly improve interaction with the projects located on WSL 2 and in Dev Containers.</li> <li>Ongoing enhancements in PhpStorm&#8217;s understanding of PHPDoc-based generics.</li> <li>Overall performance and stability improvements, including reduced startup time, indexing time, and freezes. </li> </ul> <div class="buttons"> <div class="buttons__row"> <a href="https://www.jetbrains.com/phpstorm/nextversion/" class="btn" target="_blank" rel="noopener">Download PhpStorm 2026.2 EAP</a> </div> </div> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Getting started with the EAP</h2> <p>If you&#8217;re not familiar with how our Early Access Program (EAP) works, here&#8217;s a quick overview:</p> <ol> <li>We release new EAP builds weekly, giving you a sneak peek at upcoming features.</li> <li>EAP builds are completely free to use and do not require a license.</li> <li>You can install the EAP version alongside your stable PhpStorm installation, so there&#8217;s no need to uninstall your current version.</li> <li>The most convenient way to access EAP builds and keep both your stable and EAP versions up-to-date is by using <a href="https://www.jetbrains.com/toolbox-app/" target="_blank" rel="noopener">our Toolbox App</a>.</li> <li>Alternatively, you can download EAP builds from the <a href="https://www.jetbrains.com/phpstorm/nextversion/" target="_blank" rel="noopener">EAP page</a> or set up your IDE to automatically receive updates by selecting <em>Check IDE Updates for the Early Access Program</em> under <em>Settings/Preferences | Appearance &amp; Behavior | System Settings | Updates</em>.</li> </ol> Determining if a reboot is required on Linux - Blog entries :: mwop.net https://mwop.net/blog/2026-05-04-reboot-required.html 2026-05-04T13:35:08.000Z <p>I've been using the construct <code>sudo run-parts /etc/update-motd.d/</code> to determine if recent system updates required a reboot.</p> <p>Today I learned I can simply check for the existence of the file <code>/var/run/reboot-required</code>.</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-05-04-reboot-required.html">Determining if a reboot is required on Linux</a> was originally published <time class="dt-published" datetime="2026-05-04T08:35:08-05:00">4 May 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> Join Us for PHPverse 2026 on June 9 - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=704430 2026-04-30T15:10:32.000Z <p>JetBrains PHPverse – a community-inspired professional event for PHP developers – returns once more on June 9, 2026. This year, we’re gathering some of the most influential voices in the PHP ecosystem to share their insights on shaping the modern PHP language, the internals of ecosystem tools and frameworks, and the adoption of agentic workflows for shipping PHP code.</p> <div class="buttons"> <div class="buttons__row"> <a href="https://lp.jetbrains.com/phpverse-2026/#register-for-phpverse-2026" class="btn" target="_blank" rel="noopener">Register now</a> </div> </div> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/Featured-blog-1.png" alt="" class="wp-image-704458"/></figure> <h1 class="wp-block-heading">About PHPverse 2026</h1> <p>Expect a one-day event of curated talks, live Q&amp;As with the speakers, several special announcements, and even a few surprises (after all, it’s PHP’s 31st birthday).</p> <p><strong>When: </strong>11:00 am – 3:50 pm UTC on June 9, 2026.</p> <p><strong>Where:</strong> Streamed live on the <a href="https://youtube.com/live/NR9L0zwXJq4" target="_blank" rel="noopener">PHP Annotated YouTube channel</a>.</p> <p><strong>Hosted by:</strong> <strong>Brent Roose</strong>, JetBrains Developer Advocate for PhpStorm and creator of the <a href="https://www.youtube.com/@phpannotated" target="_blank" rel="noopener">PHP Annotated</a> YouTube channel, and <a href="https://nunomaduro.com/" target="_blank" rel="noopener"><strong>Nuno Maduro</strong></a>, creator of <a href="https://pestphp.com/" target="_blank" rel="noopener">Pest</a>, <a href="https://github.com/larastan/larastan" target="_blank" rel="noopener">Larastan</a>, and <a href="https://github.com/laravel/pint" target="_blank" rel="noopener">Laravel Pint</a>, and staff software engineer at <a href="https://laravel.com/" target="_blank" rel="noopener">Laravel</a>.</p> <h1 class="wp-block-heading">This year’s lineup</h1> <ul> <li><em>PHP Foundation Keynote</em> by <a href="https://github.com/ElizabethN" data-type="link" data-id="https://www.linkedin.com/in/elizabethn/" target="_blank" rel="noopener">Elizabeth Barron</a>, Executive Director at the PHP Foundation.</li> <li><em>My AI Writes Perfect* PHP</em> by <a href="https://x.com/ashleyhindle" data-type="link" data-id="https://x.com/ashleyhindle" target="_blank">Ashley Hindle</a>, Founder of Fuel and creator of Laravel Boost.</li> <li><em>WordPress Is Dead, Long Live WordPress!</em> by <a href="https://x.com/jon_bossenger" data-type="link" data-id="https://x.com/jon_bossenger" target="_blank">Jonathan Bossenger</a>, Developer Advocate at Automattic.</li> <li><em>Packagist Internals</em> by <a href="https://x.com/naderman" data-type="link" data-id="https://x.com/naderman" target="_blank">Nils Adermann</a>, Co-Founder at Packagist.</li> <li><em>Running a Large Open-Source Project Like Symfony</em> by <a href="https://x.com/fabpot" data-type="link" data-id="https://x.com/fabpot" target="_blank">Fabien Potencier</a>, Founder and Project Lead at Symfony.</li> <li><em>PHP RFCs</em> by <a href="https://github.com/crell" data-type="link" data-id="https://github.com/crell" target="_blank" rel="noopener">Larry Garfield</a>, Functional Programming Enthusiast.</li> <li><em>How AI Is Changing the Programmer World</em> by <a href="https://x.com/jeffrey_way" data-type="link" data-id="https://x.com/jeffrey_way" target="_blank">Jeffrey Way</a>, Founder at Laracasts.</li> </ul> <p></p> <p>For more information about the speakers and their talks, see the <a href="https://lp.jetbrains.com/phpverse-2026/#program" target="_blank" rel="noopener">PHPverse 2026 page</a>.</p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/00_Main_PHP_Verse_20260.png" alt="" class="wp-image-704434"/></figure> <h1 class="wp-block-heading">PHPverse 2025 recap</h1> <p>PHPverse took off last year as a celebration of PHP’s 30th anniversary, with over 15,000 viewers worldwide tuning in to the livestream. The event outreach and feedback showed how big and vibrant the PHP community is and why we should keep gathering every year to connect and learn from the people behind the major frameworks and tools.</p> <p>You can catch up with recordings of last year’s talks:&nbsp;</p> <ul> <li><a href="https://www.youtube.com/watch?v=k-UwH91XnAo" target="_blank" rel="noopener"><em>FrankenPHP: The Future of PHP?</em></a> by <a href="https://x.com/dunglas" target="_blank">Kévin Dunglas</a></li> <li><a href="https://youtu.be/7IVDUnvvhmc?si=b4B7g00WZwdbhqEl" target="_blank" rel="noopener"><em>20 Years of Symfony</em></a> by <a href="https://x.com/nicolasgrekas" target="_blank">Nicolas Grekas</a></li> <li><a href="https://youtu.be/T22_rXew72M?si=me2oD0gFpUpBKTGY" target="_blank" rel="noopener"><em>MCP in PHP</em></a> by <a href="https://x.com/marcelpociot" target="_blank">Marcel Pociot</a></li> <li><a href="https://youtu.be/lwf7nAuZQHY?si=Zdk-6BXBS0N_0Luh" target="_blank" rel="noopener"><em>Q&amp;A With Taylor Otwell</em></a></li> <li><a href="https://youtu.be/zxTMzygBt7s?si=3w5hMZC9irsei07B" target="_blank" rel="noopener"><em>Growing PHP for the Future</em></a> by <a href="https://x.com/pronskiy" target="_blank">Roman Pronsky</a> and <a href="https://gpb.moe/" target="_blank" rel="noopener">Gina Banyard</a></li> <li><a href="https://youtu.be/Jraf2E2QPBI?si=qPj1DoLKRdXT5Mdk" target="_blank" rel="noopener"><em>The Future of PHP Education</em></a> by&nbsp;<a href="https://x.com/jeffrey_way" target="_blank" rel="noreferrer noopener">Jeffrey Way</a>,&nbsp;<a href="https://twitter.com/PovilasKorop" target="_blank" rel="noreferrer noopener">Povilas Korop</a>, and&nbsp;<a href="https://x.com/zenstruck" target="_blank" rel="noreferrer noopener">Kevin Bond</a></li> </ul> <blockquote class="twitter-tweet"><p lang="en" dir="ltr">I gotta say <a href="https://twitter.com/hashtag/PHPverse?src=hash&amp;ref_src=twsrc%5Etfw" target="_blank" rel="noopener">#PHPverse</a> was awesome today! Well done to everyone who spoke for building so many awesome things! <a href="https://t.co/lJttpMlxvG" target="_blank">pic.twitter.com/lJttpMlxvG</a></p>&mdash; Liam Hammett (@LiamHammett) <a href="https://twitter.com/LiamHammett/status/1935008846495232367?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">June 17, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/PHPverse?src=hash&amp;ref_src=twsrc%5Etfw" target="_blank" rel="noopener">#PHPverse</a> 2025 was such a valuable experience! We got practical advice from dope developers like <a href="https://twitter.com/naderman?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@naderman</a> (who happened to be co-host), also <a href="https://twitter.com/jeffrey_way?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@jeffrey_way</a> and <a href="https://twitter.com/PovilasKorop?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@PovilasKorop</a>.<br><br>My favourite session was: Laravel Q&amp;A With <a href="https://twitter.com/taylorotwell?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@taylorotwell</a>.<br><br>I feel super inspired to level up 💪<a href="https://twitter.com/hashtag/PHP30?src=hash&amp;ref_src=twsrc%5Etfw" target="_blank" rel="noopener">#PHP30</a> <a href="https://t.co/IT1vAksITr" target="_blank">pic.twitter.com/IT1vAksITr</a></p>&mdash; Timothy Samuel (@tsshekwogaza) <a href="https://twitter.com/tsshekwogaza/status/1935065344793788570?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">June 17, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <h1 class="wp-block-heading">Stay tuned&nbsp;</h1> <p>JetBrains PHPverse 2026 is free, online, and open to everyone. <a href="https://lp.jetbrains.com/phpverse-2026/#register-for-phpverse-2026" target="_blank" rel="noopener">Register now</a>, and we&#8217;ll send you a reminder email before the event. You can tune in for the whole day or drop in for the talks that interest you most.&nbsp;</p> <p>Can’t make it on June 9? Register anyway, and you’ll receive the link with the talk recordings via email after the event.</p> <p>In the meantime, join the <a href="https://discord.gg/uEUkSNhdd8" target="_blank" rel="noopener">event’s Discord server</a> to receive the latest updates or drop your questions for the speakers – the event hosts will make sure to ask them during the Q&amp;A sessions.</p> <p>PHPverse grows as its community reach grows. Spread the word among your colleagues, use the #PHPverse hashtag in your social media posts, and help us bring more people into the conversation about the present and future of PHP.&nbsp;</p> <p>See you at PHPverse!</p> PHP DateTimeImmutable::createFromFormat Reset Character - Blog entries :: mwop.net https://mwop.net/blog/2026-04-16-php-create-from-format-reset.html 2026-04-16T15:30:00.000Z <p>I was recently building something that was taking date input from an HTML form field, and casting it to a PHP <code>DateTimeImmutable</code>. I was then comparing that to another date, and got thrown off during testing when I compared the resulting instance to <code>new DateTimeImmutable('today')</code>; the instances were not considered equal.</p> <p>To recreate the conditions, you can try the following:</p> <pre><code class="language-php hljs php" data-lang="php">$date = <span class="hljs-string">'2016-06-16'</span>; $fromForm = DateTimeImmutable::createFromFormat(<span class="hljs-string">'Y-m-d'</span>, $date); $today = <span class="hljs-keyword">new</span> DateTimeImmutable(<span class="hljs-string">'today'</span>); <span class="hljs-keyword">echo</span> $fromForm == $today ? <span class="hljs-string">'Equal'</span> : <span class="hljs-string">'Not equal'</span>; <span class="hljs-comment">// outputs "Not equal"</span> </code></pre> <p>What's happening? Well, if you were to echo the results of each of <code>$fromForm-&gt;format('c')</code> and <code>$today-&gt;format('c')</code>, the difference is clear: the <code>$fromForm</code> value includes the <em>time</em> when the instance was created, while <code>$today</code> has the time set to midnight.</p> <p>So, how do you zero out the time when using <code>createFromFormat()</code>?</p> <p>It turns out that one of the format characters you can use is the <code>|</code> operator. When you include this at the end of your format string, any fields not included in the format are zero'ed out:</p> <pre><code class="language-php hljs php" data-lang="php">$fromForm = DateTimeImmutable::createFromFormat(<span class="hljs-string">'Y-m-d|'</span>); </code></pre> <hr /> <h4>Reference</h4> <ul> <li><a href="https://www.php.net/manual/en/datetimeimmutable.createfromformat.php#datetimeimmutable.createfromformat.parameters">DateTimeImmutable::createFromFormat() Parameters</a></li> </ul> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-16-php-create-from-format-reset.html">PHP DateTimeImmutable::createFromFormat Reset Character</a> was originally published <time class="dt-published" datetime="2026-04-16T10:30:00-05:00">16 April 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> SQL ENUM Modification - Blog entries :: mwop.net https://mwop.net/blog/2026-04-08-sql-enum-modification.html 2026-04-08T20:34:00.000Z <p>I'm doing a little DB work recently, and needing to choose how to represent certain data in the database. For a few fields, ENUM would be the correct choice, but there's a possibility I would need to expand the ENUM later to add values.</p> <p>My question: is this safe?</p> <p>The short answer, in my research, is &quot;yes&quot;, but with caveats.</p> <p>For Postgres, it's trivial; you can easily add values to ENUM types:</p> <pre><code class="language-sql hljs sql" data-lang="sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TYPE</span> some_previously_defined_enum <span class="hljs-keyword">ADD</span> <span class="hljs-keyword">VALUE</span> <span class="hljs-string">'new-value'</span>; </code></pre> <p>For MySQL, it's a bit more complex. ENUMs are defined within the table schema, and to change them, you use an <code>ALTER TABLE</code> statement:</p> <pre><code class="language-sql hljs sql" data-lang="sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> some_table <span class="hljs-keyword">MODIFY</span> some_previously_defined_enum ENUM(<span class="hljs-string">'value-1'</span>,<span class="hljs-string">'value-2'</span>); </code></pre> <p>Essentially, you're <em>replacing</em> the definition. This is fine... so long as you don't change the order, or remove any previously defined value in the ENUM. In other words, <em>append</em> to the existing list if you want to safely change it.</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-08-sql-enum-modification.html">SQL ENUM Modification</a> was originally published <time class="dt-published" datetime="2026-04-08T15:34:00-05:00">8 April 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> CSS Grid Lanes - Blog entries :: mwop.net https://mwop.net/blog/2026-04-07-css-grid-lanes.html 2026-04-07T15:38:00.000Z <p>I've been using the experimental &quot;<code>display: masonry</code>&quot; CSS for my gallery and a few other areas of my website for over a year (with a fallback to standard grid columns). However, I noticed in the last few months that my browser was no longer honoring it, and finally researched what happened.</p> <p>It turns out it's been renamed to &quot;<code>display: grid-lanes</code>&quot; in the <a href="https://drafts.csswg.org/css-grid-3/#grid-lanes-layout">CSS Grid Level 3 specification</a>. Otherwise, everything else remains the same; continue using <code>grid-template-columns</code> and <code>grid-template-rows</code> as you did with the the masonry display.</p> <p>Safari has it in preview already, while Firefox and Chrome-based browsers have it behind a flag. (On Chrome-based browsers, visit <code>chrome://flags</code>, and enable the &quot;css-grid-lanes-layout&quot; flag.)</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-07-css-grid-lanes.html">CSS Grid Lanes</a> was originally published <time class="dt-published" datetime="2026-04-07T10:38:00-05:00">7 April 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div> PhpStorm 2026.1 is Now Out - PhpStorm : The IDE that empowers PHP developers | The JetBrains Blog https://blog.jetbrains.com/?post_type=phpstorm&p=687630 2026-03-26T13:58:03.000Z <p>Welcome to PhpStorm 2026.1! This release brings new PhpStorm MCP tools, new third-party agents inside your IDE, support for Git worktrees, and lots of other productivity-enhancing features for PHP and Laravel developers.</p> <p class="has-text-align-center"><a class="jb-download-button" href="https://www.jetbrains.com/phpstorm/download/" target="_blank" rel="noopener">Download PhpStorm 2026.1</a></p> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/PS-releases-BlogFeatured-1280x720-1.png" alt="" class="wp-image-688069"/></figure> <h2 class="wp-block-heading">PhpStorm MCP tools</h2> <p>In PhpStorm 2025.2, we added an <a href="https://plugins.jetbrains.com/plugin/26071-mcp-server" target="_blank" rel="noopener">integrated MCP server</a> for third-party coding agents like Claude Code, Windsurf, or Codex to access and use your IDE’s tools.&nbsp;</p> <p>In 2026.1, we are extending the MCP server toolset with more PhpStorm features, including:</p> <ul> <li><strong>Inspections and quick-fixes </strong>that enable agents to leverage PhpStorm’s powerful static analysis engine.</li> <li><strong>IDE search</strong> <strong>capabilities</strong>, including PhpStorm’s structural search and semantic search for code patterns.</li> <li><strong>Access to IDE actions</strong> so that you can delegate setup and customization of your IDE to your coding agent.</li> </ul> <figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/claude_code_plugin.png" alt="" class="wp-image-687633" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/claude_code_plugin2.png" alt="" class="wp-image-687644" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <p>Furthermore, the <a href="https://github.com/JetBrains/phpstorm-claude-marketplace" target="_blank" rel="noopener">PhpStorm plugin for Claude Code</a> provides Claude Code with context and instructions for using PhpStorm MCP server tools. To add the plugin’s skills and hooks to your project, go to PhpStorm’s <em>Settings</em> | <em>Tools</em> | <em>PHP Claude Skills</em>.</p> <p><strong><em>Note: </em></strong>PhpStorm’s MCP server is disabled by default. To enable the server and configure integration with your coding agent, go to <em>Settings</em> | <em>Tools</em> | <em>MCP Server</em>.</p> <h2 class="wp-block-heading">AI</h2> <h3 class="wp-block-heading">Third-party agents in PhpStorm</h3> <p>PhpStorm is evolving as an open platform that allows you to bring the AI tools of your choice into your professional development workflows.</p> <p>In addition to Junie, Claude Agent, and most recently <a href="https://blog.jetbrains.com/ai/2026/01/codex-in-jetbrains-ides/" data-type="link" data-id="https://blog.jetbrains.com/ai/2026/01/codex-in-jetbrains-ides/">Codex</a>, PhpStorm now lets you work with more AI agents directly in the AI chat. You can choose from agents such as GitHub Copilot, <a href="https://blog.jetbrains.com/ai/2026/03/cursor-joined-the-acp-registry-and-is-now-live-in-your-jetbrains-ide/" data-type="link" data-id="https://blog.jetbrains.com/ai/2026/03/cursor-joined-the-acp-registry-and-is-now-live-in-your-jetbrains-ide/">Cursor</a>, and many others supported through the <a href="https://www.jetbrains.com/acp/" data-type="link" data-id="https://www.jetbrains.com/acp/" target="_blank" rel="noopener">Agent Client Protocol</a>.</p> <figure class="wp-block-video"><video controls poster="https://blog.jetbrains.com/wp-content/uploads/2026/03/ACP_Registry_phpstorm.png" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/ACP_REGISTRY_phpstorm.mp4"></video></figure> <h3 class="wp-block-heading">Next edit suggestions</h3> <p><strong>Next edit suggestions </strong>are now available without consuming AI quota of your JetBrains AI Pro, Ultimate, and Enterprise subscriptions.<strong> </strong>These suggestions go beyond traditional code completion for PHP. Instead of updating only what’s at your cursor, they intelligently apply related changes across the entire file, helping you keep your code consistent and up to date with minimal effort.</p> <p>This natural evolution of code completion delivers a seamless <em>Tab Tab</em> experience that keeps you in the flow.</p> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/next_edit_suggestions_php-1.gif" alt="" class="wp-image-689064" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <h3 class="wp-block-heading">Junie CLI is now in Beta</h3> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/junie_cli_now_in_beta.webp" alt="" class="wp-image-687690" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <p><a href="https://junie.jetbrains.com/" target="_blank" rel="noopener">Junie CLI</a> is JetBrains’ LLM-agnostic coding agent you can use directly from the terminal, inside any IDE, in CI/CD, and on GitHub or GitLab. Junie CLI comes with:</p> <ul> <li><strong>Bring Your Own Key (<strong>BYOK</strong>)</strong> pricing, allowing you to use your own keys from model providers without additional charges.</li> <li><strong>One-click migration</strong> from other agents such as Claude Code or Codex.</li> <li><strong>Flexible customization</strong> through guidelines, custom agents and agent skills, commands, MCP, and more.</li> </ul> <p></p> <p>Read the full announcement <a href="https://blog.jetbrains.com/junie/2026/03/junie-cli-the-llm-agnostic-coding-agent-is-now-in-beta/">in our blog post</a>.</p> <h2 class="wp-block-heading">Project indexing optimization</h2> <p></p> <p>PhpStorm now automatically detects framework-specific directories that contain frequently changing generated, cached, or user-uploaded content and excludes such directories from project indexing.&nbsp;</p> <p>The IDE skips excluded folders during search, parsing, and other operations. Reducing indexing overhead helps optimize the CPU usage and performance of your IDE.&nbsp;</p> <p>If you want to re-enable indexing for any of the automatically excluded folders, you can do so in <em>Settings</em> | <em>Directories</em> by clicking <em>Exclude</em> and unselecting the checkboxes next to the directories you want to be indexed.</p> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/project_indexing_optimization.png" alt="" class="wp-image-687679" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <p></p> <h2 class="wp-block-heading">Generics support</h2> <p>The new release brings a number of improvements and bug fixes for PhpStorm’s type inference engine, including:&nbsp;</p> <ul> <li><strong>Improved type inference for callable generic types.</strong> Now the IDE can infer both the input parameter type from a <code>callable(T)</code> annotation and the callable template return type.<br><br><img decoding="async" loading="lazy" class="wp-image-687714" style="width: 600px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/callables-type-inference2-1.png" alt=""><br></li> <li><strong>Improved display for nested parameterized template types.</strong> PhpStorm 2026.1 displays parameter type (<em>Ctrl</em> + <em>Shift</em>+<em>P</em>) and quick documentation (<em>F1</em>) info with multiple layers of wrapping, such as <code>Wrapper&lt;Wrapper&lt;Wrapper&lt;stdClass&gt;&gt;&gt;</code>.<br><br><img decoding="async" loading="lazy" class="wp-image-687725" style="width: 600px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/callables-type-inference3.png" alt=""><br></li> </ul> <h2 class="wp-block-heading">More quality-of-life improvements</h2> <h3 class="wp-block-heading">Debugging non-PHP files</h3> <p>You can now set breakpoints in non-PHP files as soon as the file name pattern is <a href="https://www.jetbrains.com/help/phpstorm/creating-and-registering-file-types.html#change-extension" target="_blank" rel="noopener">associated with the PHP file type</a> in the IDE settings. Together with native path mapping between templates and compiled PHP files <a href="https://xdebug.org/funding/001-native-path-mapping" target="_blank" rel="noopener">introduced in Xdebug 3.5</a>, this feature allows you to debug source template files of any format, including niche extensions like <code>.ezt</code>.</p> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/non-php-breakpoints2.png" alt="" class="wp-image-687747" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <h3 class="wp-block-heading">Improved <em>Go to test</em> navigation</h3> <p>In PhpStorm 2026.1, we’ve improved <em>Go to Test</em> navigation for PHPUnit and Pest tests with the following enhancements:&nbsp;</p> <ul> <li>Navigation between PHPUnit tests that use a <code>#[UsesClass]</code> or <code>#[UsesMethod]</code> attribute and the related class/method.</li> <li>For Pest tests, you can now navigate from the <em>Test Runner</em> tab to the source test nested inside Pest describe blocks.&nbsp;</li> </ul> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-20.png" alt="" class="wp-image-687758" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <h3 class="wp-block-heading"><em>Convert to pipe operator</em> quick-fix</h3> <p>PhpStorm now detects code elements where the PHP 8.5 pipe operator syntax can be used and suggests a quick-fix to convert such code into easier-to-read pipe operator chains.</p> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-21.png" alt="" class="wp-image-687769" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <h2 class="wp-block-heading">Laravel</h2> <ul> <li><strong>Framework support:</strong> support for Laravel 13 and new versions of Livewire and Filament. Support for the new @hasStack and @includeIsolated Blade directives.</li> <li><strong>New package support</strong>: Laravel Wayfinder, PHP Native, staudenmeir/laravel-cte and staudenmeir/laravel-adjacency-list packages.</li> <li><strong>Eloquent enhancements: </strong>advanced #[Scope] methods support, optimized and more accurate <em>Find Usages</em> for scope, attribute and relation methods.</li> <li><strong>UI and navigation:</strong> Blade view usages UI, better controller inlays, new Route Search UI, and routes to the <em>Endpoints </em>tool window.</li> <li><strong>Productivity tweaks:</strong> a new <em>Add Application Database </em>action. Run Artisan commands in the <em>Terminal</em> tool window or via PHP interpreter.</li> <li><strong>Laravel Idea MCP server</strong> shipped with the PhpStorm MCP server.<br></li> </ul> <div class="wp-block-columns is-layout-flex wp-container-3 wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/laravel-1-1.png" alt="" class="wp-image-689707"/></figure> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/laravel-2-1.png" alt="" class="wp-image-689718"/></figure> </div> </div> <div class="wp-block-columns is-layout-flex wp-container-6 wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/laravel-3-1.png" alt="" class="wp-image-689729"/></figure> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/laravel-4-1.png" alt="" class="wp-image-689740"/></figure> </div> </div> <p>For the full list of updates, see <a href="https://laravel-idea.com/docs/changelog" target="_blank" rel="noopener">Laravel Idea’s changelog</a>.</p> <h2 class="wp-block-heading">Frontend</h2> <p>PhpStorm’s TypeScript support now uses the service-powered type engine (built on the TypeScript language service) by default, delivering more accurate type inference and lower CPU usage in large projects. The TypeScript support is further improved with better auto-import handling for path aliases and project references, as well as the integration of inlay hints from the TypeScript Go-based language server. JavaScript parsing now also correctly handles string-literal <code>import / export</code> specifiers.</p> <p>Framework and styling support have been refined across the board:&nbsp;</p> <ul> <li>The IDE now highlights React’s new <code>use memo</code> and <code>use no memo</code> directives.&nbsp;</li> <li>The Vue integration uses the updated 3.1.8 version of <code>@vue/typescript-plugin</code>.&nbsp;</li> <li>Astro settings accept JSON-based configuration for language server integration.&nbsp;</li> <li>Modern CSS <code>color()</code> functions and additional color spaces are supported in swatches and previews.&nbsp;</li> <li>Angular 21.x template syntax is supported.</li> </ul> <p></p> <h2 class="wp-block-heading">Databases</h2> <p>The AI chat integration for Codex and Claude Agent now offers full, native support for your connected databases. With that, you can now query, analyze, and modify your database state using natural language right from the IDE.</p> <p>The same functionality is available for external agents via an <a href="https://www.jetbrains.com/help/ai-assistant/mcp.html" target="_blank" rel="noopener">MCP server</a>.</p> <p>Data source settings can now be stored in your <a href="https://sales.jetbrains.com/hc/en-gb/articles/208459005-What-is-JetBrains-Account" target="_blank" rel="noopener">JetBrains Account</a> via data source templates. Especially nifty for All Products Pack users or anyone who uses multiple instances of JetBrains IDEs, this upgrade allows you to access data source templates and settings in every JetBrains IDE with database functionality.</p> <h2 class="wp-block-heading">Productivity-enhancing features</h2> <h3 class="wp-block-heading">Editor caret and selection updates</h3> <p>We’re continuing to modernize our IDEs, and in this update, we’ve refreshed something you interact with constantly – the editor. Smooth caret animation and updated selection behavior provide improved comfort, a cleaner look, and a more enjoyable coding experience. </p> <p><a href="https://blog.jetbrains.com/platform/2026/02/editor-improvements-smooth-caret-animation-and-new-selection-behavior/">Read more</a></p> <h3 class="wp-block-heading">Work on multiple branches at once with Git Worktrees</h3> <p>With the evolution of AI agents, running multiple tasks in parallel has become a major time-saver, and this is precisely where Git worktrees are extremely handy. To support cutting-edge workflows for AI-boosted software development, PhpStorm now provides first-class support for Git worktrees. Create a separate worktree for an urgent hotfix, hand off another one to an AI agent, and keep working in your main branch – all at the same time, without interruption.</p> <figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/several_worktrees_dark.png" alt="" class="wp-image-689752" style="width:706px; width:100% !important; height:auto !important; max-width:100% !important;"/></figure> <p>Even if you don’t use agents, worktrees will save you time on branch switching, especially in big projects.</p> <h3 class="wp-block-heading">Native Wayland support</h3> <p>IntelliJ-based IDEs now run natively on Wayland by default. This transition provides Linux professionals with ultimate comfort through sharper HiDPI and better input handling, and it paves the way for future enhancements like Vulkan support.</p> <p>While Wayland provides benefits and serves as a foundation for future improvements, we prioritize reliability: The IDE will automatically fall back to X11 in unsupported environments to keep your workflow uninterrupted. <a href="https://blog.jetbrains.com/platform/2026/02/wayland-by-default-in-2026-1-eap/">Learn more</a>.</p> <h3 class="wp-block-heading">Terminal completion</h3> <p>Stop memorizing commands. Start discovering them. In-terminal completion helps you instantly explore available subcommands and parameters as you type. Whether you&#8217;re working with complex CLI tools like Git, Docker, or kubectl or using your own custom scripts, this feature intelligently suggests valid options in real time.</p> <h2 class="wp-block-heading">Code With Me sunset</h2> <p>As we continue to evolve our IDEs and focus on the areas that deliver the most value to developers, we’ve decided to sunset Code With Me, our collaborative coding and pair programming service. Demand for this type of functionality has declined in recent years, and we’re prioritizing more modern workflows tailored to professional software development.</p> <p>As of version 2026.1, Code With Me will be unbundled from all JetBrains IDEs. Instead, it will be available on JetBrains Marketplace as a separate plugin. 2026.1 will be the last IDE version to officially support Code With Me, as we gradually sunset the service.</p> <p>Read the full announcement and sunset timeline in <a href="https://blog.jetbrains.com/platform/2026/03/sunsetting-code-with-me/">our blog post</a>.&nbsp;</p> Create an HTML version of an OpenAPI spec - Rob Allen https://akrabat.com/?p=7557 2026-03-17T11:00:00.000Z <p>I have a new project where we will be integrating with a third party API that is currently being written. Due to Conway's Law, we are being sent new versions of the OpenAPI spec as a set of JSON files via email.</p> <p>I quite like seeing the HTML rendering of an OpenAPI spec when reading it and understanding it, so I knocked up a simple shell script that takes an OpenAPI spec file and outputs an HTML doc. This is a trivial task thanks to <a href="https://scalar.com">Scalar</a>!</p> <p>This is the script:</p> <div><code>~/bin/create-openapi-spec-doc.sh:</code></div> <pre lang="bash"> #!/usr/bin/env bash set -eo pipefail if [[ $# -eq 0 ]]; then echo &quot;Usage: $(basename &quot;$0&quot;) &lt;spec-file&gt; [spec-file ...]&quot; echo &quot;Generates an HTML API reference document for each OpenAPI spec file provided.&quot; exit 1 fi for spec_file in &quot;$@&quot;; do base=&quot;${spec_file%.*}&quot; spec_name=&quot;$(basename &quot;$base&quot;)&quot; { cat &lt;&lt;EOF &lt;!doctype html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;${spec_name} API&lt;/title&gt; &lt;meta charset=&quot;utf-8&quot; /&gt; &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt; &lt;/head&gt; &lt;body&gt; &lt;div id=&quot;app&quot;&gt;&lt;/div&gt; &lt;script id=&quot;api-reference&quot; type=&quot;application/yaml&quot;&gt; EOF cat &quot;$spec_file&quot; cat &lt;&lt;'EOF' &lt;/script&gt; &lt;!-- Load the Script --&gt; &lt;script src=&quot;https://cdn.jsdelivr.net/npm/@scalar/api-reference&quot;&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt; EOF } &gt; &quot;$base&quot;.html echo &quot;Generated: $base.html&quot; done </pre Its very easy to use: <pre lang="bash"> $ create-openapi-spec-doc.sh *.json Generated: provided_svc.html Generated: required_svc.html </pre> <p>and now I have nicely formatted HTML files!</p> PHPStan custom rules - Rob Allen https://akrabat.com/?p=7552 2026-03-03T11:00:00.000Z <p>Recently I discovered that this code passed our PHPStan level 10 checks:</p> <pre> use http\Exception\InvalidArgumentException; // ... throw new InvalidArgumentException; </pre> <p>I was surprised as <tt>http\Exception\InvalidArgumentException</tt> is not a class in our system. While cooling, I discovered that there's an http PHP extension and it appears that PHPStan has a stub for this which means that it accepts it as existing even if it doesn't.</p> <p>What we think happened is that I wrote <tt>throw new InvalidArgumentException;</tt> and selected the wrong class from the dropdown in PHPStorm as I wanted to import the base <tt>InvalidArgumentExtension</tt></p> <p>I want PHPStan to fail in this case, so I wrote a PHPStan extension that calls <tt>class_exists()</tt> to ensure that the class really is available:</p> <pre> &lt;?php declare(strict_types=1); namespace Laminar\PHPStan\Rules; use PhpParser\Node; use PhpParser\Node\Stmt\Use_; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\ShouldNotHappenException; /** * Flags imported classes that PHPStan knows about via bundled extension stubs * but cannot be loaded in the current runtime environment. * * This rule checks using the xxx_exists() functions, so is only useful if run within * a context that matches deployment. * * @implements Rule&lt;Use_&gt; */ class ImportedClassExistsRule implements Rule { public function __construct(private readonly ReflectionProvider $reflectionProvider) { } public function getNodeType(): string { return Use_::class; } /** * @return list&lt;RuleError&gt; * @throws ShouldNotHappenException */ public function processNode(Node $node, Scope $scope): array { if ($node-&gt;type !== Use_::TYPE_NORMAL) { return []; } $errors = []; foreach ($node-&gt;uses as $use) { $className = $use-&gt;name-&gt;toString(); if (! $this-&gt;reflectionProvider-&gt;hasClass($className)) { continue; } if ( class_exists($className) || interface_exists($className) || trait_exists($className) || enum_exists($className) ) { continue; } $errors[] = RuleErrorBuilder::message( sprintf( 'Imported class %s does not exist at runtime. The required PHP extension may not be installed.', $className, ), )-&gt;identifier('akrabat.importedClassExists') -&gt;line($use-&gt;getLine()) -&gt;build(); } return $errors; } } </pre> <p>The only important thing you need to know about writing a custom PHPStan rule is that <tt>processNode()</tt> returns an array of errors and if that is empty, then the rule succeeded.</p> <p>This one isn't particularly complicated, but it solves the problem!</p> <p>As an aside, to prevent PhpStorm from providing autocomplete for extensions that don't exist in your application, go to Settings→PHP and select the PHP Runtime tab. You can then select the extensions you use and deselect those that you don't. There's even a "Sync Extensions with Interpreter" button which can be handy if you build your dev container from your prod one.</p> Feelings - Rob Allen https://akrabat.com/?p=7549 2026-02-27T22:16:58.000Z <p>Today has been a struggle entirely due to my own internal negative thoughts and feelings about impacting events that are outside my control. </p> <p>Navigating this to come out stronger rather than letting it consume my self-belief and confidence isn’t easy, especially at the time. I’m not worse at my job and my abilities haven’t diminished, but sometimes it’s hard to remember this. </p> <p>I need to give myself space to remember who I am and internalise that my emotions are valid, but not the whole truth. Introspection and understanding of the whole is important. </p> <p>Onwards and upwards.</p> Headless boot for Beelink EQ14 - Blog entries :: mwop.net https://mwop.net/blog/2026-02-24-headless-boot-beelink-eq14.html 2026-02-24T16:09:08.000Z <p>A few months back, I purchased a Beelink EQ14 mini server for my homelab. One thing that has frustrated me has been that rebooting or even powering on... has required I have either my keyboard or my monitor plugged in (I haven't been able to determine exactly which one yet). This has made me reluctant to reboot, as I then have to switch my keyboard from my workstation over to the server, and plug the HDMI from one of my monitors into it. I hate it.</p> <p>In browsing a number of forums, I saw one recommendation to switch the BIOS to use FastBoot.</p> <p>Can confirm, works!</p> <div class="h-entry"> <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew"> <a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-24-headless-boot-beelink-eq14.html">Headless boot for Beelink EQ14</a> was originally published <time class="dt-published" datetime="2026-02-24T10:09:08-06:00">24 February 2026</time> on <a href="https://mwop.net">https://mwop.net</a> by <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>. </div>