{"id":47868680,"url":"https://github.com/linkorb/hatter","last_synced_at":"2026-04-04T00:41:55.724Z","repository":{"id":239952435,"uuid":"800175101","full_name":"linkorb/hatter","owner":"linkorb","description":"Database fixture loading tool","archived":false,"fork":false,"pushed_at":"2025-12-17T18:03:23.000Z","size":77,"stargazers_count":7,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-12-21T06:33:05.335Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/linkorb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2024-05-13T21:00:46.000Z","updated_at":"2025-12-11T22:19:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"47a98945-df4a-417b-956c-e402c31dc629","html_url":"https://github.com/linkorb/hatter","commit_stats":null,"previous_names":["linkorb/hatter"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/linkorb/hatter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkorb%2Fhatter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkorb%2Fhatter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkorb%2Fhatter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkorb%2Fhatter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linkorb","download_url":"https://codeload.github.com/linkorb/hatter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linkorb%2Fhatter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31383634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T23:20:52.058Z","status":"ssl_error","status_checked_at":"2026-04-03T23:20:51.675Z","response_time":107,"last_error":"SSL_read: 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":[],"created_at":"2026-04-04T00:41:55.075Z","updated_at":"2026-04-04T00:41:55.709Z","avatar_url":"https://github.com/linkorb.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hatter\n\n\u003cimg src=\"https://i.pinimg.com/originals/cd/d5/55/cdd5551862180e0a321dd78b69a08f35.gif\" style=\"width: 100%\" /\u003e\n\nA database fixture tool inspired by [Alice](https://github.com/nelmio/alice) and [Haigha](https://github.com/linkorb/haigha), but better suited for non-symfony or third-party application written in other programming languages.\n\n**Hatter allows you to write human-friendly YAML files containing the data you want to load into your database for testing and initialization.**\n\nHave a look at the [example/](example/) directory to get a feel for how to write your own database fixtures.\n\n## Hatter vs Alice\n\nAlice is a great tool, but it depends on Doctrine Entities.\nThis restricts the usage because it can only work for apps that use Doctrine as their ORM\n\nHatter on the other hand writes to databases directly. This way you can use it for *any* app, even if it's written in another language, or if you don't have access to the source-code.\n\nAlice is more feature rich, but Hatter supports most common use-cases and features, making it a great alternative.\n\n## Quick start\n\n**Installation**\n\n```shell\ncomposer require --dev linkorb/hatter\n```\n\n**Database connection**\n\nHatter reads the connection string from the environment variable `HATTER_DSN`. symfony/dotenv is used to load the \nenvironment variables in standalone mode, which means all the `.env*` precedence rules apply.\n\n```shell\n# .env.local\nHATTER_DSN=mysql://username:password@somehost/mydatabase\n```\n```shell\n# or within symfony when doctrine is used\nHATTER_DSN=$DATABASE_URL\n```\n\n**Running hatter**\n\n```shell\n./vendor/bin/hatter load /path/to/hatter/fixtures\n```\n\n## Writing database fixtures as YAML files\n\nHave a look at the [example/](example/) directory for some example hatter files.\n\nThe general outline of a hatter file:\n\n```yaml\n# my-cms-data.hatter.yaml\ntables:\n  user:\n    columns:\n      id:\n        type: int\n        generator: autoIncrement\n    rows:\n      bob:\n        firstname: Bob\n        lastname: \"{{ faker.lastName() }}\"\n        age: \"{{ faker.numberBetween(18, 60) }}\"\n      claire:\n        firstname: Claire\n        lastname: \"{{ faker.lastName() }}\"\n        age: \"{{ faker.numberBetween(18, 60) }}\"\n\n  post:\n    columns:\n      id:\n        type: int\n        generator: autoIncrement\n    rows:\n      bob-first-post:\n        headline: Hello world!\n        author_id: @user.bob.id\n        content: |\n          This is my first beautiful post      \n```\n\nLoading this file through hatter will:\n\n1. create two records in the `user` table (for bob and for claire)\n2. create a record in the `post` table\n3. link the post to user bob (by it's auto generated id)\n4. tell hatter to auto generate id values for both tables\n5. create random lastnames for bob and claire using the faker library, and assign random ages (note: the random seed is fixed, so the values will be the same on each run)\n\n## Features:\n\n* Use an `includes` key to include one or more external `.hatter.yaml` files to nicely structure your fixture data (wildcard includes supported!)\n* Use the [Faker PHP](https://fakerphp.github.io/) library to generate random values\n* Use the Symfony Expression language to generate complex values based on referenced fields in other columns, custom functions and many more\n* Support generated fields with generators `autoIncrement`, `uuid.v4` and `xuid`\n\n## FAQ and Best Practices\n\n##### Q: Where do I store my hatter files?\n\nA: It's recommended to store your `.hatter.yaml` files in a `hatter/` sub-directory in your application's repository. This way your application, database schema and database fixtures can evolve together. \nFor special cases, i.e. dedicated testing projects, it could make sense to store your hatter files in an external dedicated repository for that project and app combination. This also makes sense if you're writing hatter files for a third-party application.\n\n##### Q: How do I name a dedicated Hatter repository?\n\nA: It's recommended to name your repository like `{{ project_name }}-hatter`, i.e. `wordpress-hatter`. The `project_name` generally matches the repository name of the application. For dedicated testing projects a dedicated project name could make more sense (i.e. `wordpress-customer-x-hatter` for a dedicated customer project).\n\n##### Q: What database backends are supported?\n\nA: Database connection strings (DSN) are parsed using the [linkorb/connector](https://github.com/linkorb/connector) library. This library currently supports mysql, pgsql, sqlite and sqlsrv drivers.\n\n##### Q: How do I deal with UUIDs (or XUIDs)\n\nA: Hatter supports auto-generating UUIDs and XUIDs for your database rows. But they will always be random, and different on every run of Hatter. This may not always be desirable.\n\nSome applications / database schemas heavily rely on UUID or similar identifiers. Having these change between Hatter runs can complicate testing.. i.e. it's helpful to have stable IDs to keep testing and itterating on business objects. For this reason it's recommended to generate those IDs externally i.e. using [uuidgenerator.net](https://www.uuidgenerator.net/version4), and paste these values into your YAML file. This way you are sure that the data is restored in the same way on each Hatter run.\n\nTo better recognize UUIDs in your test projects, you can consider setting up a format for your UUIDs that aid humans (developers, testers) in recognizing them. For example, your app can use `xxxxxxxx-xxxx-xxxx-xxxx-` as the prefix of all your UUIDs (assuming the underlying database column accepts regular strings). This way you recognize that these are test UUIDs. You can further scope your UUIDs by including test-case names or user names into your UUIDs so you can quickly recognize where given records belong to.\n\n\n## License\n\nMIT (see [LICENSE.md](LICENSE.md))\n\n## Brought to you by the LinkORB Engineering team\n\n\u003cimg src=\"http://www.linkorb.com/d/meta/tier1/images/linkorbengineering-logo.png\" width=\"200px\" /\u003e\u003cbr /\u003e\nCheck out our other projects at [linkorb.com/engineering](http://www.linkorb.com/engineering).\n\nBtw, we're hiring!\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinkorb%2Fhatter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinkorb%2Fhatter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinkorb%2Fhatter/lists"}