Open-source project
thecodingmachine/safe avatar
thecodingmachine/safe

thecodingmachine/safe: PHP core functions that throw instead of returning false

All PHP functions, rewritten to throw exceptions instead of returning false

2,496 stars170 forksPHPMIT

At a glance

What is it?
Safe-PHP redeclares PHP's core functions in the Safe namespace so that errors raise exceptions. This article covers what it replaces, how the PHPStan rule keeps you from forgetting the import, and where the approach breaks down.
Who is it for?
Adopt thecodingmachine/safe if your codebase relies on core functions that return false on error and you want failures to surface as exceptions, especially if you already run PHPStan, since the bundled rule flags every unsafe call.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 44 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The false-return problem Safe-PHP was built to remove

PHP's core function library predates exception handling in the language. The README states the consequence plainly: most core functions do not throw, they return false on error. That leaves two bad options. Check every return value by hand, which the README calls out as something most developers are too lazy to do, or skip the check and let a false propagate through the program as if it were real data.

The README's own example shows how quickly this compounds. `file_get_contents` returns false when the file is missing, and `json_decode` returns false when the input is not valid JSON. Chain the two without checks and a missing file silently becomes a decoding failure, or the other way around, depending on what you pass in. The correct version of that snippet needs an explicit comparison against false plus a `json_last_error()` check before it can be trusted. Safe-PHP exists for teams that want the short version to be the correct version.

The target audience is PHP application developers with existing code that calls core functions directly, and it skews toward codebases with legacy error handling rather than greenfield projects where a framework already wraps I/O in exceptions.

How the Safe namespace redeclares core PHP functions

Safe-PHP redeclares core PHP functions inside the `Safe` namespace. The signature and behaviour match the original, with one change: on error the function throws instead of returning false. Because the functions live in a namespace, you opt in per function with a `use function` statement, and the unqualified call in your file then resolves to the Safe variant.

php
use function Safe\file_get_contents;
use function Safe\json_decode;

$content = file_get_contents('foobar.json');
$foobar = json_decode($content);

The README says every PHP function that can return false on error is covered, and that the library also ships two classes, `Safe\DateTime` and `Safe\DateTimeImmutable`, whose methods throw instead of returning false. The repository layout is consistent with the scale: the `generated/` directory holds the function files, `generator/` holds the tooling that produces them, and the README notes the functions are auto-generated from the PHP documentation, with `CONTRIBUTING.md` describing how to regenerate them. The README also states that Safe loads 1000+ functions from roughly 85 files on each request.

That per-request loading is the design trade-off at the centre of the library. You get exception semantics without a framework, and you pay for it with autoloading work on every request. The README quantifies the cost at about 700 microseconds and points to a `performance/` directory in the repository for the methodology.

Installing Safe-PHP with Composer and the PHPStan safe rule

Installation is a single Composer command. The README gives it as:

bash
composer require thecodingmachine/safe

After that, calls to `Safe\`-namespaced functions resolve through Composer's autoloader. The README strongly recommends adding the PHPStan rule as a dev dependency, because nothing stops you from forgetting a `use function` statement and silently falling back to the unsafe core function.

bash
composer require --dev thecodingmachine/phpstan-safe-rule

The rule is wired in through your `phpstan.neon` file. The README shows this include:

yml
includes:
    - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon

With the rule active, PHPStan reports a call like `$content = file_get_contents('foobar.json');` with a message naming the function as unsafe to use because it can return FALSE instead of throwing, and telling you to add `use function Safe\file_get_contents;` at the top of the file. That message is the first real output a new user sees, and it is the mechanism that makes the library practical on a large codebase: you do not have to remember the imports, the analyser does.

Rector migration rewrites calls but not your error handling

For a large legacy codebase, changing function imports one at a time is tedious. Safe bundles a Rector configuration, `rector-migrate.php`, that rewrites call sites in bulk. The README's steps are to install Rector and then run it against your source directory with the bundled config:

bash
composer require --dev rector/rector
bash
vendor/bin/rector process src/ --config vendor/thecodingmachine/safe/rector-migrate.php

The README is explicit that this is a dumb replacement. It changes the function being called and nothing else. If your code already handled the false return, that handling is now dead or wrong, and the README says so directly, showing that an existing guard like `if (!mkdir($dirPath))` becomes `if (!\Safe\mkdir($dirPath))`, which can never be true once the function throws. The manual rewrite it suggests is a try/catch around the call, catching `\Safe\FilesystemException`.

This is the sharpest limitation in the whole library, and it is worth stating as a rule rather than a caveat: the Rector pass is a starting point for a migration, not the migration. Budget review time proportional to the number of existing false checks in your code, because every one of them is a place the automated pass can leave behind code that no longer means what it says.

The PHPStan rule is the real adoption mechanism

The namespace design has an obvious failure mode: a developer adds a new file, calls `file_get_contents` without the import, and gets the old false-returning behaviour with no signal at all. The library's answer is to make that mistake visible in static analysis rather than at runtime.

What makes this worth calling out is the direction of the dependency. The PHPStan rule is a separate Composer package, `thecodingmachine/phpstan-safe-rule`, and it is the piece that enforces the convention across a team. Without it, Safe-PHP is a library you must remember to use. With it, any call to an unsafe core function becomes a reported error in the same pipeline that already checks your types.

The README's framing of the rule is a direct response to the objection that developers will forget the imports. That framing is honest about where the burden sits. Safe-PHP does not change PHP's behaviour or intercept calls to core functions; it offers replacements and a lint rule that points at the places you have not replaced yet. If your project does not run PHPStan, you are adopting the functions without the enforcement, and the value drops accordingly.

Where Safe-PHP is the wrong tool

The library only helps where the failure mode is a false return. Code that already checks return values correctly gains little, and code that deliberately uses false as a sentinel value, for example a lookup function where a missing key is a normal outcome rather than an error, will fight the library rather than benefit from it. Converting such a call to the Safe variant turns an expected branch into an exception path.

The per-request loading cost is the second boundary. The README puts it at about 700 microseconds, attributed to loading 1000+ functions from roughly 85 files. For a web request that does real work, that is noise. For a tight loop, a CLI tool that boots thousands of short-lived processes, or a latency-sensitive endpoint, it is a fixed tax on every execution, and the README itself frames the number as a reassurance rather than a claim of zero cost.

The third boundary is scope. Safe-PHP covers core PHP functions that return false on error, plus the two DateTime classes. It does not wrap PDO, it does not wrap extension functions outside that set, and it does not change how you handle the exceptions once they are thrown. Teams looking for a general error-handling framework will find this is narrower than the name suggests.

A real alternative in the same space is PHPStan's own strict rules and the `declare(strict_types=1)` culture around it, which push you toward checking return values explicitly rather than replacing the functions. The difference in approach is where the work lands: Safe-PHP keeps the short call syntax and moves the check into the function, while strict analysis leaves the call as-is and forces the check into your code. The first reads better and costs an autoload per request; the second reads worse and costs nothing at runtime. A third option is a framework's filesystem and HTTP abstractions, which throw by design but only cover the operations the framework chose to wrap.

Maintenance, licensing and what a version bump costs

The repository is not archived, and the last push was on 2026-08-17. Releases are infrequent rather than constant: v3.4.0 landed on 2026-02-15, preceded by v3.3.0 on 2025-05-14 and v3.2.0 on 2025-05-13. That cadence fits the project's nature. The functions are generated from PHP's documentation, so the library changes when PHP's core function set or documentation changes, not on a product roadmap.

The upgrade cost follows from the same fact. Because the Safe variants mirror core signatures, a PHP minor upgrade that alters a core function's behaviour is the event that pulls a new Safe release in behind it. The practical check before upgrading PHP is whether a Safe release exists that covers the new version, and whether the PHPStan rule package has moved with it, since the two are separate Composer packages with separate version numbers.

Licensing is MIT, per the repository's LICENSE file and the Packagist badge in the README. That permits commercial use and modification with the usual attribution requirement. This is a statement of what the licence is, not legal advice; if your organisation has specific obligations around bundled generated code, check the LICENSE file and your own policy.

One thing the README does not document is a rollback path. If you migrate a codebase with the Rector config and then want to revert, there is no described inverse operation, which is an argument for running the migration on a branch and reviewing the diff before merging.

Editorial conclusion

Adopt thecodingmachine/safe if your codebase relies on core functions that return false on error and you want failures to surface as exceptions, especially if you already run PHPStan, since the bundled rule flags every unsafe call. Do not adopt it if you need a guarantee that existing false-checking branches keep working: the Rector config only rewrites call sites, and the README states it will not modify how false return values are handled, so error handling must be reworked by hand. Before committing, verify three things: that your PHP version is supported by the release you pin, that the PHPStan rule's warning output matches your current baseline, and that the roughly 700 microseconds per request the README attributes to loading 1000+ functions is acceptable for your traffic profile.

Frequently asked questions

What does thecodingmachine/safe actually change about PHP functions?

It redeclares core PHP functions inside the Safe namespace. The Safe variant behaves like the original except that it throws an exception on error instead of returning false.

How do I install thecodingmachine/safe?

Run composer require thecodingmachine/safe. The README also recommends installing thecodingmachine/phpstan-safe-rule as a dev dependency and including vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon in your phpstan.neon file.

Will the Rector migration fix my existing false checks?

No. The README states the refactoring performs a dumb replacement of functions and will not modify the way false return values are handled, so existing error handling has to be dealt with manually.

Does using thecodingmachine/safe slow down my application?

The README states Safe loads 1000+ functions from roughly 85 files on each request and puts the cost at about 700 microseconds, with more detail in the performance section of the repository.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. thecodingmachine/safe on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/thecodingmachine-safe.svg)](https://hysenlabs.com/projects/thecodingmachine-safe)