{"id":34017249,"url":"https://github.com/waxim/vouchers","last_synced_at":"2026-04-08T19:32:41.487Z","repository":{"id":56943632,"uuid":"78642763","full_name":"waxim/vouchers","owner":"waxim","description":"A voucher lib","archived":false,"fork":false,"pushed_at":"2023-04-19T11:59:34.000Z","size":30,"stargazers_count":97,"open_issues_count":3,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-03-11T13:37:26.239Z","etag":null,"topics":["composer-packages","ecommerce","php","php-library","voucher"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/waxim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2017-01-11T13:42:31.000Z","updated_at":"2024-11-29T07:33:41.000Z","dependencies_parsed_at":"2022-08-21T07:50:49.820Z","dependency_job_id":null,"html_url":"https://github.com/waxim/vouchers","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/waxim/vouchers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waxim%2Fvouchers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waxim%2Fvouchers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waxim%2Fvouchers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waxim%2Fvouchers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/waxim","download_url":"https://codeload.github.com/waxim/vouchers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/waxim%2Fvouchers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31571600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"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":["composer-packages","ecommerce","php","php-library","voucher"],"created_at":"2025-12-13T14:29:31.619Z","updated_at":"2026-04-08T19:32:41.458Z","avatar_url":"https://github.com/waxim.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![StyleCI](https://styleci.io/repos/78642763/shield?branch=master)](https://styleci.io/repos/78642763) [![Build Status](https://travis-ci.org/waxim/vouchers.svg?branch=master)](https://travis-ci.org/waxim/vouchers)\n\n# Vouchers Lib\nA PHP library for generating and validating vouchers. We make no assumptions about storage and instead offer the concept of `Bags` which can take any number of `Vouchers`. These bags can validate vouchers, generate new vouchers and apply validation \nrules across the whole set.\n\n## Install\n```\ncomposer require alancole/vouchers\n```\n\n## Example\n```php\n\n$model = new Vouchers\\Voucher\\Model([\n    'owner' =\u003e [\n        'required'  =\u003e true,\n        'immutable' =\u003e true,\n    ],\n    'claimed_by' =\u003e [\n        'required' =\u003e true,\n    ]\n]);\n\n$collection = new Vouchers\\Bag($model);\n$collection-\u003efill(1000);\n\n$voucher = $collection-\u003epick();\n\nprint $voucher; // FHUW-JSUJ-KSIQ-JDUI\n```\n\n## Vouchers\nVouchers can take on almost any form, however you can use `Vouchers\\Voucher\\Model` to enforce validation and structure. The only required attribute is `code` which by default is immutable.\n\n```php\n$voucher = new Vouchers\\Voucher();\nprint $voucher; // ABCD-EFGH-IJKL\n```\n\nYou may also pass an array to the voucher to set pre existing values to the voucher. Matching fields (including `code`) will be validated.\n\n```php\n$voucher = new Voucher(['code' =\u003e 'ALAN-COLE-CODE', 'claimed_by' =\u003e '', 'claimed_on' =\u003e '']);\nprint $voucher; // \"ALAN-COLE-CODE\"\n```\n\nAny value passed on voucher creation can be get and set using `get()` and `set()` on the voucher.\n\n```php\n$voucher-\u003eset('owner', 'Alan');\necho $voucher-\u003eget('owner'); // Alan\n```\n\n### Model\nBy creating a model you can set default values and validation on vouchers created or loaded. Models are passed as an array to `Vouchers\\Voucher\\Model`\n\n```php\n$model = new Vouchers\\Voucher\\Model([\n    'owner' =\u003e [\n        'required'  =\u003e true,\n        'immutable' =\u003e true,\n    ],\n    'claimed_by' =\u003e [\n        'required' =\u003e true,\n    ]\n]);\n```\n\nIf you set a voucher attribute as `immutable` then `Voucher` will throw the `ImmutableData` exception.\n\n### Code\nYou can change the way the code is generated by settings generator on a model. A generator must implement `Vouchers\\Voucher\\Code\\GeneratorInterface`\n\n```php\nnamespace My\\Voucher\\Generator;\n\nuse Vouchers\\Voucher\\Code\\Interface as Generator;\n\nclass MyCode implements Generator\n{\n    public function part()\n    {\n        return bin2hex(openssl_random_pseudo_bytes(2));\n    }\n\n    public function generate()\n    {\n        return strtoupper(sprintf(\"%s-%s-%s\", $this-\u003epart(), $this-\u003epart(), $this-\u003epart()));\n    }\n\n    public function validate()\n    {\n        return true;\n    }\n}\n\n```\n\nThen tell the model to use this generator.\n\n```php\n$model = new Vouchers\\Voucher\\Model([\n    'code' =\u003e [\n        'generator' =\u003e \\My\\Voucher\\Generator\\MyCode::class\n    ]\n]);\n```\n\n## Bags\nBags act as collections for vouchers and allow you to enforce validations on a whole set. Bags can also act as a selector for vouchers, allowing to you pick a voucher at random and enforce rules on that selection. Bags are also `Iterable` so they can be used in loops.\n\n```php\n$collection = new Vouchers\\Bag();\n$collection-\u003efill(1000);\n\nforeach($collection as $voucher) {\n    print $voucher;\n}\n```\n\nYou can use `Vouchers\\Voucher\\Model` to enfore a model on all items in a bag by passing a model as the first attribute on construction.\n\n```php\n$collection = new Vouchers\\Bag($model);\n```\n\nYou can fill a model with existing vouchers by using `add()` add will only accept an instance of `Vouchers\\Voucher`\n\n```php\n$vouchers = [$voucher1...$voucher100];\nforeach ($vouchers as $voucher) {\n    $collection-\u003eadd(new Vouchers\\Voucher($voucher));\n}\n```\n\nYou can also run a map on any array, mapping the return as new vouchers within the bag. This is handy if you need to transform data to fit a model.\n\n```php\n$collection-\u003emap($vouchers, function ($voucher) {\n    return new Vouchers\\Voucher($voucher);\n});\n```\n\nYou can get a voucher by code, which can be used to see if a voucher exists.\n\n```php\n$collection = new Vouchers\\Bag();\n$voucher = new Vouchers\\Voucher(['code' =\u003e 'special-voucher']);\n$collection-\u003eadd($voucher);\n\n$v = $collection-\u003efind(\"special-voucher\");\n\nif ($v) {\n    print (string)$v;\n} else {\n    print \"Voucher does not exist.\";\n}\n```\n\n### Pick\nYou can have the bag pick you a voucher at random by using `pick()` on any bag.\n\n```php\n$collection = new Vouchers\\Bag();\n$collection-\u003efill(1000);\n\n$collection-\u003epick();\n```\n\nIf you wish to validate the selection you can pass a callback to pick which will run until it returns a `true` or throw an `Vouchers\\Exceptions\\NoValidVouchers` exception.\n\n```php\n$collection-\u003epick(function ($voucher) {\n    return (bool)$voucher-\u003eowner == \"Alan\";\n});\n```\n\n```php\ntry {\n    $collection-\u003epick(function ($voucher) {\n        return 2 == 1;\n    });\n} catch (Exception $e) {\n    print $e-\u003egetMessage();\n}\n```\n\nYou may also ask `pick()` to check all validators this bag might have (see Validate) and only return a voucher that is valid. Again this will throw `Vouchers\\Exceptions\\NoValidVouchers` is it doesn't find a voucher.\n\n```php\n$collection-\u003epickValid();\n```\n\n### Validate\nYou can add validators to a bag, these validators can be used to validate requirements of a voucher using `validate()` on a bag and passing the voucher code as a parameter.\n\n```php\n$collection-\u003evalidate(\"ALAN-COLE-CODE\");\n```\n\nValidators can be added as callbacks to the validator function, or as a class that implements `Vouchers\\Voucher\\Validator` here is an example that assumes a voucher has an `expire_date` and checks it has not passed.\n\n```php\n$collection-\u003evalidator(function ($voucher) {\n    return $voucher-\u003eexpire_date \u003e new DateTime();\n}, \"Sorry, this voucher is expired\");\n\ntry {\n    $collection-\u003evalidate(\"ALAN-COLE-CODE\");\n} catch (\\Vouchers\\Exceptions\\VoucherNotValid $e) {\n    return $e-\u003egetMessage(); // \"Sorry, this voucher is expired\";\n}\n```\n\n### Kitchen Sink\nThis shows how to get vouchers from the subscriptions api, take a requested voucher, validate it and the claim it on the API.\n\n```php\n$api = new Discovery\\Subscriptions\\Api();\n$api-\u003esetApiKey(getenv(\"SUBS_API_KEY\"));\n$api-\u003esetAppId(getenv(\"SUBS_APP_ID\"));\n\n$vouchers = $api-\u003egetAllVouchers();\n\n$bag = new Vouchers\\Bag();\n$bag-\u003emap($vouchers, function($voucher) {\n    return new Vouchers\\Voucher($voucher);\n});\n\n# Add some validators\n$bag-\u003evalidator(function ($voucher) {\n    return $voucher-\u003eowner == \"Eurosport\";\n}, \"Sorry, this voucher was not valid.\");\n\n$bag-\u003evalidator(function ($voucher) {\n    return !$voucher-\u003eused;\n}, \"Sorry, this voucher has been used.\");\n\n$bag-\u003evalidator(function ($voucher) {\n    return new DateTime($voucher-\u003evalid_till) \u003c new DateTime();\n}, \"Sorry, this voucher is expired.\");\n\ntry {\n    $voucher = $collection-\u003evalidate(filter_val(INPUT_POST, \"voucher_code\", FILTER_SANITIZE_STRING));\n    $voucher-\u003eset(\"used\", true // not really needed.\n    $api-\u003eputVoucherClaim($voucher); // because this takes care of it.\n} catch (\\Vouchers\\Exceptions\\VoucherNotValid $e) {\n    echo $e-\u003egetMessage();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaxim%2Fvouchers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwaxim%2Fvouchers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwaxim%2Fvouchers/lists"}