{"id":21252670,"url":"https://github.com/atomicptr/php-functional","last_synced_at":"2026-02-27T00:31:22.430Z","repository":{"id":251530761,"uuid":"837604155","full_name":"atomicptr/php-functional","owner":"atomicptr","description":"A set of tools to enable a more functional style of programming in PHP, inspired by OCaml","archived":false,"fork":false,"pushed_at":"2026-02-05T15:34:45.000Z","size":592,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-06T01:50:36.017Z","etag":null,"topics":["functional-programming","php","php-library"],"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/atomicptr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"atomicptr","buy_me_a_coffee":"atomicptr"}},"created_at":"2024-08-03T13:12:05.000Z","updated_at":"2026-02-05T15:43:24.000Z","dependencies_parsed_at":"2024-08-03T19:03:47.826Z","dependency_job_id":"cc8bb550-5c62-4c3c-b244-fd84997c8dc0","html_url":"https://github.com/atomicptr/php-functional","commit_stats":null,"previous_names":["atomicptr/php-functional"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/atomicptr/php-functional","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicptr%2Fphp-functional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicptr%2Fphp-functional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicptr%2Fphp-functional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicptr%2Fphp-functional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomicptr","download_url":"https://codeload.github.com/atomicptr/php-functional/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomicptr%2Fphp-functional/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29878966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T23:51:21.483Z","status":"ssl_error","status_checked_at":"2026-02-26T23:50:46.793Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["functional-programming","php","php-library"],"created_at":"2024-11-21T03:48:24.159Z","updated_at":"2026-02-27T00:31:22.396Z","avatar_url":"https://github.com/atomicptr.png","language":"PHP","readme":"# php-functional\n\nA set of tools to enable a more functional style of programming in PHP, inspired by [OCaml](https://ocaml.org/).\n\n\u003cimg src=\"https://cdn.jsdelivr.net/gh/atomicptr/php-functional/.github/logo.png\" height=\"150\" /\u003e\n\n```php\n\u003c?php\n\n// lots of list utility functions\nlist($even, $odd) = Lst::partition(fn (int $num) =\u003e $num % 2 === 0, [1, 2, 3, 4, 5, 6]);\n//     $even is [2, 4, 6]\n//     $odd is  [1, 3, 5]\n\n// pipe a bunch of operations\nCollection::from(Lst::init(fn (int $index) =\u003e $index * $index, 100))\n    -\u003efilter(fn (int $num) =\u003e $num % 2 === 0)\n    -\u003efilter(fn (int $num) =\u003e $num \u003e 50)\n    -\u003emap(fn (int $num, int $index) =\u003e $num * $index)\n    -\u003efoldl(fn (int $acc, int $val) =\u003e $acc + $val, 0);\n\n// better error handling with Result\nfunction safeDivision(int $a, int $b): Result\n{\n    if ($b === 0) {\n        return Result::error(\"cant divide by 0\");\n    }\n\n    return Result::ok($a / $b);\n}\n\n$res = safeDivision(10, 2);\n\nif ($res-\u003ehasError()) {\n    print($res-\u003evalue());\n    exit(1);\n}\n\n// use bind for Result or Option to only continue as long as there is a value\n// lets assume we have a function fetch(string $url): Result that just returns\n// the response as a string wrapped into Result\n$title = fetch(\"https://atomicptr.dev/api/blog/post/1337\")\n    -\u003ebind(fn (string $response) =\u003e Result::capture(fn () =\u003e json_decode($resp, true, flags: JSON_THROW_ON_ERROR)))\n    -\u003ebind(function (array $data) {\n        assert(BlogPostSchema::isValid($data)); // A ficticious json schema validator\n        return BlogPostResource::createFrom($data); // This converts the json data into a structure\n    })-\u003ebind(fn (BlogPost $post) =\u003e $post-\u003etitle());\n\nif ($title-\u003ehasError()) {\n    // something went wrong along the chain, so just panic\n    $title-\u003epanic();\n    exit(1);\n}\n\n// express \"nothing\" without using null\nfunction findOneById(int $id): Option\n{\n    $rows = DB::find(\"table_name\", [\"id\" =\u003e $id]);\n\n    if (empty($rows)) {\n        return Option::none();\n    }\n\n    return Option::some($rows[0]);\n}\n\n$row = findOneById(1337);\n\nif ($row-\u003eisNone()) {\n    print(\"Can not find object 1337\");\n    exit(1);\n}\n\n// ...\n\n// maps\n$incrementer = fn (Option $value) =\u003e $value-\u003eisSome() ? Option::some($value-\u003evalue() + 1 : 1;\n$map = Map::empty()\n    -\u003eupdate(\"a\", $incrementer)\n    -\u003eupdate(\"a\", $incrementer)\n    -\u003eupdate(\"b\", $incrementer)\n    -\u003eset(\"c\", 5);\n\n$map-\u003eget(\"a\"); // 3\n$map-\u003eget(\"b\"); // 1\n\n// group products by type\n$productsByType = Lst::groupBy(fn (Product $product) =\u003e $product-\u003egetType()-\u003etoString(), Product::all());\n$productsByType-\u003eget(\"electronics\") // [Product, Product]\n\n// memoize functions\n$f = Memo::make(fn (int $a, int $b) =\u003e doSomethingHeavy($a, $b));\n$res = $f(1337, 8080); // this will call \"doSomethingHeavy\" which might take a while\n// ...\n$res = $f(1337, 8080); // now we call it again but it will now instantly return the result because we already called it with 1 and 2\n````\n\n## Install\n\nThe package is available on [packagist](https://packagist.org/packages/atomicptr/functional)\n\nInstall via:\n\n```bash\n$ composer req atomicptr/functional\n````\n\n## Docs\n\n### Atomicptr\\Functional\n\n* [Lst](./docs/Lst.md)\n* [Collection](./docs/Collection.md)\n* [Option](./docs/Option.md)\n* [Result](./docs/Result.md)\n* [Map](./docs/Map.md)\n\n### Atomicptr\\Functional\\Traits\n\n* [EnumCollectionTrait](./docs/Traits/EnumCollectionTrait.md)\n\n### Atomicptr\\Functional\\Exceptions\n\n* [ResultError](./docs/Exceptions/ResultError.md)\n* [ImmutableException](./docs/Exceptions/ImmutableException.md)\n\n## License\n\nMIT\n","funding_links":["https://github.com/sponsors/atomicptr","https://buymeacoffee.com/atomicptr"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomicptr%2Fphp-functional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomicptr%2Fphp-functional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomicptr%2Fphp-functional/lists"}