PHP Good First Issues

Leonid Bugaev
|
(Updated August 31, 2026)
|
8 min read
php beginners good-first-issue contributing

PHP labels the same string on three jobs that are not the same sitting. A composer.json whose README never composer installs. One PHPUnit next to the method. A WordPress hook that boots a plugin, not a library. This URL is the PHP filter. The list is the hub.

Generic hunting: how to find good first issues. Multi-language picking: best open source projects for beginners. Merge checks: how to pick an issue that will get merged. This URL is the PHP filter.

Open the PHP hub

PHP hub

Labeled good-first and help-wanted issues on active GitHub repos whose language is PHP. On 2026-08-31: about 788 labeled issues at 10+ stars. Snapshot. It moves.

Not writing PHP? The homepage is the language switch.

Read the body. Skip stale, claimed, and repos that have not merged lately. I am not listing famous projects. A leftover label on a well-known name is still leftover. The feed is the hub, ticket by ticket.

Composer: a README that actually composer install-s

In PHP the real first sitting is often composer install. The README still shows composer require vendor/pkg against a name that never shipped. composer.json still lists a require Packagist dropped. The issue already named that hole.

Shapes that merge:

Done is: a newcomer can follow that page, composer install, and get the same packages the project ships. Done is not a souvenir version bump, a composer.lock rewrite you were not asked for, or migrating the autoloader because you like PSR-4 a different way.

Do not bump package versions “while you are here.” Do not bump the PHP constraint, a replace/provide, or a related package as a drive-by. Version bumps review as policy and stall the install fix.

CONTRIBUTING will name composer install and the test command. Run them on the default branch first. If install cannot boot on your machine, pick another ticket. Debugging their platform is two projects.

A green composer install on main is the gate. The code change comes after.

PHPUnit: one test next to the method

The mergeable first PHP PR is usually one PHPUnit test beside the method the issue named. Same suite. Same tests/ (or whatever phpunit.xml already points at) they already use. PHPUnit 9, 10, or 11 — whichever the xml and require-dev already pulled.

That is the job. It is not:

FooTest next to Foo. One method. Assert the behavior the issue described. Run that test class, not the universe, unless CONTRIBUTING says otherwise.

If the project tests with PHPUnit, you test with PHPUnit. Do not “improve” the harness on issue one. Pest or PHPSpec only if the issue named that runner.

WordPress vs modern: they are different first evenings

Be honest about this. A labeled WordPress ticket is not a labeled ticket in a small Composer library. The badge is the same string. The evening is not.

WordPress-shaped. A hook, a template, a plugin readme. Those look tiny. They are not library-sized. You boot WordPress, a plugin layout, maybe a theme. Review is WP conventions: hooks, plugin headers, template parts. If you have never run this WP stack locally, it is not issue one. I am not listing famous plugins. Judge the surface, not the brand.

Laravel / Symfony-ish. A console command, a config key, a service the ticket named can be a first PR — until it is framework core. Container internals, routing guts, ORM internals: those review like architecture. A good first issue badge on core is a request for help, not a size.

Small Composer library. composer.json, src/, PHPUnit. A handful of classes. Prefer that surface for issue one. The test you want runs with vendor/bin/phpunit. You do not stand up WordPress. You do not boot a framework kernel.

Do not pick WordPress because you “know PHP” if you cannot boot WP tonight. Do not pick a framework-core ticket because the brand is familiar. Prefer the smaller Composer-library surface for issue one.

I am not listing famous WordPress plugins or Laravel packages. Filter the PHP hub and judge the repo surface, not the logo.

After a merge in a small lib, issue two can be a WP leaf or a framework leaf. Not before.

php-cs-fixer and phpcs: the hunk

php-cs-fixer will always have opinions. phpcs will too. That is not an invitation.

A first-time fixer run on the tree rewrites files nobody asked you to touch. Maintainers read it as a style crusade. They close it, or they make you revert 90% of the diff, which is the same delay.

Rules:

A formatted test is hygiene. A tree-wide reformat is a closed PR.

Not framework core, not WP core

Skip Laravel/Symfony core and WordPress core on purpose. wp-includes, wp-admin internals, container and routing guts, ORM internals — those review like architecture. A good first issue badge on them is a request for help, not a size.

Your first merge should be a leaf: the Composer install snippet, one PHPUnit next to the method, a small library — not framework core, not WP core.

After you have a merge in that repo and have watched how they review internals, issue two can move inward. Not before.

I am not listing famous core or plugin repos. Filter the PHP hub and judge the file, not the brand.

Ship one ticket

  1. Filter on the PHP hub. Drop stale and claimed threads. Confirm recent merged PRs. Prefer a small Composer library over a WordPress or framework-core surface.
  2. Read CONTRIBUTING.md for composer install / PHPUnit and php-cs-fixer or phpcs. Get install green on the default branch.
  3. Comment on one issue. Do not reserve five.
  4. Keep the diff on the ticket. One PHPUnit next to the method (Pest/PHPSpec only if the issue asked). php-cs-fixer / phpcs only what you touched. No package-version bump. Link Fixes #123. Say which test command you ran. Stay for review.

Git mechanics: first pull request guide. Week-1 map: how to contribute to open source.

FAQ

Is a composer.json or README that actually composer install-s a real first PR?

Yes. Install metadata and a snippet that composer install can follow is a real merge. Bumping package versions or the PHP constraint as a souvenir is not.

Should I add PHPSpec or Pest if the project already uses PHPUnit?

No. One test next to the method, in the suite they already have. If that is PHPUnit, write PHPUnit. Pest or PHPSpec only if the issue asked. Do not add a second runner as a side quest.

Can my first issue be a WordPress ticket? What about Laravel or Symfony?

Prefer a smaller Composer library. A labeled WP ticket (hook, template, plugin readme) is not the same size as a labeled ticket in a small library. Laravel/Symfony-ish core is a different evening. Do not pick by brand. Judge the surface. Framework core and WP core wait for issue two.

Should I run php-cs-fixer or phpcs on the whole tree?

No. Format the hunk you touched. A whole-tree php-cs-fixer or phpcs rewrite of files you did not need is a style PR. Leave .php-cs-fixer.php and phpcs.xml alone unless that file is the ticket. If CI formats the tree, let CI.

Where do I find live PHP good first issues?

On the PHP hub. Filter, skip stale and claimed threads. Read CONTRIBUTING for composer install, PHPUnit, and the formatter. Other languages: the homepage.

Start here

Open the PHP hub. Pick one unclaimed ticket that is a Composer snippet that actually composer installs, one PHPUnit (or the runner the issue named) next to the method, or a small library — not WordPress core, not framework core, not a whole-tree php-cs-fixer. Comment once, format only what you touched, keep the diff on that job, and stay for review. Not writing PHP tonight? The homepage is the language switch.

Back to all articles Find projects that need your help