{"id":13518950,"url":"https://github.com/thecodingmachine/safe","last_synced_at":"2026-02-15T17:41:46.422Z","repository":{"id":37671779,"uuid":"147208524","full_name":"thecodingmachine/safe","owner":"thecodingmachine","description":"All PHP functions, rewritten to throw exceptions instead of returning false","archived":false,"fork":false,"pushed_at":"2025-04-28T09:21:57.000Z","size":2914,"stargazers_count":2431,"open_issues_count":28,"forks_count":161,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-06T16:12:46.681Z","etag":null,"topics":["exceptions","functions","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thecodingmachine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["staabm","shish","OskarStark"]}},"created_at":"2018-09-03T13:26:22.000Z","updated_at":"2025-05-06T08:30:59.000Z","dependencies_parsed_at":"2023-10-04T11:28:30.448Z","dependency_job_id":"9978717f-b192-40a6-8987-23c5be043b30","html_url":"https://github.com/thecodingmachine/safe","commit_stats":{"total_commits":347,"total_committers":51,"mean_commits":6.803921568627451,"dds":0.7031700288184438,"last_synced_commit":"3a6e43b4be3d3d65b272c2660300a50658ce168b"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thecodingmachine%2Fsafe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thecodingmachine%2Fsafe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thecodingmachine%2Fsafe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thecodingmachine%2Fsafe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thecodingmachine","download_url":"https://codeload.github.com/thecodingmachine/safe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253990455,"owners_count":21995773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exceptions","functions","php"],"created_at":"2024-08-01T05:01:51.197Z","updated_at":"2025-10-19T14:59:20.350Z","avatar_url":"https://github.com/thecodingmachine.png","language":"PHP","readme":"[![Latest Version](https://poser.pugx.org/thecodingmachine/safe/v/stable.svg)](https://packagist.org/packages/thecodingmachine/safe)\n[![Total Downloads](https://poser.pugx.org/thecodingmachine/safe/downloads.svg)](https://packagist.org/packages/thecodingmachine/safe)\n[![License](https://poser.pugx.org/thecodingmachine/safe/license.svg)](https://packagist.org/packages/thecodingmachine/safe)\n[![Tests](https://github.com/thecodingmachine/safe/workflows/Tests/badge.svg)](https://github.com/thecodingmachine/safe/actions)\n[![codecov](https://codecov.io/gh/thecodingmachine/safe/branch/master/graph/badge.svg)](https://codecov.io/gh/thecodingmachine/safe)\n\nSafe PHP\n========\n\nA set of core PHP functions rewritten to throw exceptions instead of returning `false` when an error is encountered.\n\n## The problem\n\nMost PHP core functions were written before exception handling was added to the language. Therefore, most PHP functions\ndo not throw exceptions. Instead, they return `false` in case of error.\n\nBut most of us are too lazy to check explicitly for every single return of every core PHP function.\n\n```php\n// This code is incorrect. Twice.\n// \"file_get_contents\" can return false if the file does not exist\n// \"json_decode\" can return false if the file content is not valid JSON\n$content = file_get_contents('foobar.json');\n$foobar = json_decode($content);\n```\n\nThe correct version of this code would be:\n\n```php\n$content = file_get_contents('foobar.json');\nif ($content === false) {\n    throw new FileLoadingException('Could not load file foobar.json');\n}\n$foobar = json_decode($content);\nif (json_last_error() !== JSON_ERROR_NONE) {\n    throw new FileLoadingException('foobar.json does not contain valid JSON: '.json_last_error_msg());\n}\n```\n\nObviously, while this snippet is correct, it is less easy to read.\n\n## The solution\n\nEnter *thecodingmachine/safe* aka Safe-PHP.\n\nSafe-PHP redeclares all core PHP functions. The new PHP functions act exactly as the old ones, except they\nthrow exceptions properly when an error is encountered. The \"safe\" functions have the same name as the core PHP\nfunctions, except they are in the `Safe` namespace.\n\n```php\nuse function Safe\\file_get_contents;\nuse function Safe\\json_decode;\n\n// This code is both safe and simple!\n$content = file_get_contents('foobar.json');\n$foobar = json_decode($content);\n```\n\nAll PHP functions that can return `false` on error are part of Safe.\nIn addition, Safe also provide 2 'Safe' classes: `Safe\\DateTime` and `Safe\\DateTimeImmutable` whose methods will throw exceptions instead of returning false.\n\n## PHPStan integration\n\n\u003e Yeah... but I must explicitly think about importing the \"safe\" variant of the function, for each and every file of my application.\n\u003e I'm sure I will forget some \"use function\" statements!\n\nFear not! thecodingmachine/safe comes with a PHPStan rule.\n\nNever heard of [PHPStan](https://github.com/phpstan/phpstan) before?\nCheck it out, it's an amazing code analyzer for PHP.\n\nSimply install the Safe rule in your PHPStan setup (explained in the \"Installation\" section) and PHPStan will let you know each time you are using an \"unsafe\" function.\n\nThe code below will trigger this warning:\n\n```php\n$content = file_get_contents('foobar.json');\n```\n\n\u003e Function file_get_contents is unsafe to use. It can return FALSE instead of throwing an exception. Please add 'use function Safe\\\\file_get_contents;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library.\n\n## Installation\n\nUse composer to install Safe-PHP:\n\n```bash\ncomposer require thecodingmachine/safe\n```\n\n*Highly recommended*: install PHPStan and PHPStan extension:\n\n```bash\ncomposer require --dev thecodingmachine/phpstan-safe-rule\n```\n\nNow, edit your `phpstan.neon` file and add these rules:\n\n```yml\nincludes:\n    - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon\n```\n\n## Automated refactoring\n\nYou have a large legacy codebase and want to use \"Safe-PHP\" functions throughout your project? PHPStan will help you\nfind these functions but changing the namespace of the functions one function at a time might be a tedious task.\n\nFortunately, Safe comes bundled with a \"Rector\" configuration file. [Rector](https://github.com/rectorphp/rector) is a command-line\ntool that performs instant refactoring of your application.\n\nRun\n\n```bash\ncomposer require --dev rector/rector\n```\n\nto install `rector/rector`.\n\nRun\n\n```bash\nvendor/bin/rector process src/ --config vendor/thecodingmachine/safe/rector-migrate.php\n```\n\nto run `rector/rector`.\n\n*Note:* do not forget to replace \"src/\" with the path to your source directory.\n\n**Important:** the refactoring only performs a \"dumb\" replacement of functions. It will not modify the way\n\"false\" return values are handled. So if your code was already performing error handling, you will have to deal\nwith it manually.\n\nEspecially, you should look for error handling that was already performed, like:\n\n```php\nif (!mkdir($dirPath)) {\n    // Do something on error\n}\n```\n\nThis code will be refactored by Rector to:\n\n```php\nif (!\\Safe\\mkdir($dirPath)) {\n    // Do something on error\n}\n```\n\nYou should then (manually) refactor it to:\n\n```php\ntry {\n    \\Safe\\mkdir($dirPath));\n} catch (\\Safe\\FilesystemException $e) {\n    // Do something on error\n}\n```\n\n## Performance impact\n\nSafe is loading 1000+ functions from ~85 files on each request. Yet, the performance impact of this loading is quite low.\n\nIn case you worry, using Safe will \"cost\" you ~700µs on each request. The [performance section](performance/README.md)\ncontains more information regarding the way we tested the performance impact of Safe.\n\n## Learn more\n\nRead [the release article on TheCodingMachine's blog](https://thecodingmachine.io/introducing-safe-php) if you want to\nlearn more about what triggered the development of Safe-PHP.\n\n## Contributing\n\nThe files that contain all the functions are auto-generated from the PHP doc.\nRead the [CONTRIBUTING.md](CONTRIBUTING.md) file to learn how to regenerate these files and to contribute to this library.\n","funding_links":["https://github.com/sponsors/staabm","https://github.com/sponsors/shish","https://github.com/sponsors/OskarStark"],"categories":["PHP","配置 Configuration","Configuration"],"sub_categories":["杂项 Miscellaneous","Miscellaneous"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodingmachine%2Fsafe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthecodingmachine%2Fsafe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodingmachine%2Fsafe/lists"}