{"id":15525061,"url":"https://github.com/staabm/side-effects-detector","last_synced_at":"2025-05-16T03:02:29.861Z","repository":{"id":257803936,"uuid":"864464748","full_name":"staabm/side-effects-detector","owner":"staabm","description":"Analyzes php-code for side-effects.","archived":false,"fork":false,"pushed_at":"2025-01-01T14:17:23.000Z","size":543,"stargazers_count":89,"open_issues_count":6,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-12T09:10:03.076Z","etag":null,"topics":[],"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/staabm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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},"funding":{"github":["staabm"]}},"created_at":"2024-09-28T09:40:22.000Z","updated_at":"2025-05-06T08:31:33.000Z","dependencies_parsed_at":"2024-12-09T12:20:40.439Z","dependency_job_id":"47b2a770-6a93-41e2-9b04-bffcbc26a8df","html_url":"https://github.com/staabm/side-effects-detector","commit_stats":{"total_commits":53,"total_committers":3,"mean_commits":"17.666666666666668","dds":0.09433962264150941,"last_synced_commit":"a9a74fd9e8313d5345a879bf6f70639fa6184675"},"previous_names":["staabm/side-effects-detector"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/staabm%2Fside-effects-detector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/staabm%2Fside-effects-detector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/staabm%2Fside-effects-detector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/staabm%2Fside-effects-detector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/staabm","download_url":"https://codeload.github.com/staabm/side-effects-detector/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254459081,"owners_count":22074604,"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":[],"created_at":"2024-10-02T10:54:27.978Z","updated_at":"2025-05-16T03:02:29.841Z","avatar_url":"https://github.com/staabm.png","language":"PHP","funding_links":["https://github.com/sponsors/staabm"],"categories":["PHP"],"sub_categories":[],"readme":"Analyzes php-code for side-effects.\n\nWhen code has no side-effects it can e.g. be used with `eval($code)` in the same process without interfering.\n[Side-effects are classified](https://github.com/staabm/side-effects-detector/blob/main/lib/SideEffect.php) into categories to filter them more easily depending on your use-case.\n\nThis library is used e.g. in PHPUnit to [improve performance of PHPT test-cases](https://staabm.github.io/2024/10/19/phpunit-codesprint-munich.html).\n\n## Install\n\n`composer require staabm/side-effects-detector`\n\n## Usage\n\nExample:\n\n```php\nuse staabm\\SideEffectsDetector\\SideEffectsDetector;\n\n$code = '\u003c?php version_compare(PHP_VERSION, \"8.0\", \"\u003e=\") or echo(\"skip because attributes are only available since PHP 8.0\");';\n\n$detector = new SideEffectsDetector();\n// [SideEffect::STANDARD_OUTPUT]\nvar_dump($detector-\u003egetSideEffects($code));\n```\n\nIn case functions are called which are not known to have side-effects - e.g. userland functions - `null` is returned.\n\n```php\nuse staabm\\SideEffectsDetector\\SideEffectsDetector;\n\n$code = '\u003c?php userlandFunction();';\n\n$detector = new SideEffectsDetector();\n// [SideEffect::MAYBE]\nvar_dump($detector-\u003egetSideEffects($code));\n```\n\nCode might have multiple side-effects:\n\n```php\nuse staabm\\SideEffectsDetector\\SideEffectsDetector;\n\n$code = '\u003c?php include \"some-file.php\"; echo \"hello world\"; exit(1);';\n\n$detector = new SideEffectsDetector();\n// [SideEffect::SCOPE_POLLUTION, SideEffect::STANDARD_OUTPUT, SideEffect::PROCESS_EXIT]\nvar_dump($detector-\u003egetSideEffects($code));\n```\n\n## Compensate some side-effects\n\nIt might be useful to compensate some side-effects, so evaluation of code in the current process is still acceptable:\n\n```php\nuse staabm\\SideEffectsDetector\\SideEffectsDetector;\n\nfunction runCodeInLocalSandbox(string $code): string\n{\n    $code = preg_replace('/^\u003c\\?(?:php)?|\\?\u003e\\s*+$/', '', $code);\n    $code = preg_replace('/declare\\S?\\([^)]+\\)\\S?;/', '', $code);\n\n    // wrap in immediately invoked function to isolate local-side-effects\n    // of $code from our own process\n    $code = '(function() {' . $code . '})();';\n    \n    // wrap in output buffer to isolate stdout side-effects\n    ob_start();\n    @eval($code);\n\n    return ob_get_clean();\n}\n\nfunction shouldRunInSubprocess(string $code): bool\n{\n    $detector    = new SideEffectsDetector;\n    $sideEffects = $detector-\u003egetSideEffects($code);\n\n    if ($sideEffects === []) {\n        return false; // no side-effects\n    }\n\n    foreach ($sideEffects as $sideEffect) {\n        // stdout is fine, we will catch it using output-buffering\n        if ($sideEffect === SideEffect::STANDARD_OUTPUT) {\n            continue;\n        }\n\n        return true;\n    }\n\n    return false;\n}\n\nfunction runCode(string $code) {\n    if (!shouldRunInSubprocess($code)) {\n        return runCodeInLocalSandbox($code);\n    }\n    \n    // run $code in isolation, e.g. in a subprocess\n    // ...\n}\n```\n\n\n## Disclaimer\n\nNon goals are:\n- find the best possible answer for all cases\n- add runtime dependencies\n- inspect additional metadata like attributes or phpdoc tags\n\nIf you are in need of a fully fledged side-effect analysis, use more advanced tools like PHPStan.\n\nLook at the test-suite to get an idea of [supported use-cases](https://github.com/staabm/side-effects-detector/blob/main/tests/SideEffectsDetectorTest.php).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstaabm%2Fside-effects-detector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstaabm%2Fside-effects-detector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstaabm%2Fside-effects-detector/lists"}