packages/sql-fixture/src/FileFixtureProvider.php
1<?php
2
3declare(strict_types=1);
4
5namespace SqlFixture;
6
7use Faker\Generator;
8use Faker\Provider\Base;
9use RuntimeException;
10use SqlFixture\Hydrator\HydratorInterface;
11use SqlFixture\Platform\PlatformFactory;
12use SqlFixture\Schema\TableSchema;
13use SqlFixture\TypeMapper\TypeMapperInterface;
14
15/**
16 * Faker provider that generates fixtures from local DDL files.
17 */
18class FileFixtureProvider extends Base
19{
20 private FixtureGenerator $fixtureGenerator;
21
22 /**
23 * @var array<string, TableSchema> Table name → parsed schema cache
24 */
25 private array $schemas = [];
26
27 /**
28 * @param string $dialect SQL dialect ('mysql' or 'sqlite')
29 */
30 public function __construct(
31 Generator $faker,
32 string $ddlPath,
33 ?TypeMapperInterface $typeMapper = null,
34 ?HydratorInterface $hydrator = null,
35 string $dialect = PlatformFactory::DRIVER_MYSQL,
36 ) {
37 parent::__construct($faker);
38
39 $typeMapper ??= PlatformFactory::createTypeMapper($dialect);
40 $schemaParser = PlatformFactory::createSchemaParser($dialect);
41
42 $this->fixtureGenerator = new FixtureGenerator($faker, $typeMapper, $hydrator, $schemaParser);
43 $this->schemas = (new Provider\DdlDirectory())->loadSchemas($ddlPath, $schemaParser);
44 }
45
46 /**
47 * Generate a fixture from a DDL file.
48 *
49 * @template T of object
50 * @param string $tableName Table name (e.g., "users")
51 * @param array<string, mixed> $overrides Override values
52 * @param class-string<T>|null $className Deserialization target class
53 * @return ($className is null ? array<string, mixed> : T)
54 * @throws RuntimeException
55 */
56 public function fixture(
57 string $tableName,
58 array $overrides = [],
59 ?string $className = null,
60 ): array|object {
61 $normalizedName = strtolower($tableName);
62
63 if (!isset($this->schemas[$normalizedName])) {
64 throw new RuntimeException("Schema not found for table: {$tableName}");
65 }
66
67 return $this->fixtureGenerator->generate($this->schemas[$normalizedName], $overrides, $className);
68 }
69
70 /**
71 * Check if a table schema is loaded.
72 */
73 public function hasTable(string $tableName): bool
74 {
75 return isset($this->schemas[strtolower($tableName)]);
76 }
77
78 /**
79 * Get list of available table names.
80 *
81 * @return list<string>
82 */
83 public function getTableNames(): array
84 {
85 return array_keys($this->schemas);
86 }
87
88 /**
89 * Manually register a schema.
90 */
91 public function registerSchema(string $createTableSql): void
92 {
93 $schema = $this->fixtureGenerator->getSchemaParser()->parse($createTableSql);
94 $this->schemas[strtolower($schema->tableName)] = $schema;
95 }
96
97 /**
98 * Get the underlying fixture generator.
99 */
100 public function getFixtureGenerator(): FixtureGenerator
101 {
102 return $this->fixtureGenerator;
103 }
104}
105