diff --git a/README.md b/README.md
index 110f147..d6aa2e3 100644
--- a/README.md
+++ b/README.md
@@ -111,9 +111,16 @@ to your `doctrine.php` configuration file:
```
+### Naming Strategy
+
+The default naming strategy uses the Inflector's `urlize()` method to change 'associationName' into 'association-name'.
+If this is not the way you want to name your relationsihps or routes then create your own naming strategy and assign
+it in the config file.
+
+
## Route naming
-When using the `routeNamePatterns` to create a route name, the entity name becomes `$inflector->urlize(shortName)`
+When using the `routeNamePatterns` to create a route name, the entity name becomes `$namingStrategy->route($entityName)`
such as `api.short-name::fetch` according to the example configuration.
diff --git a/config/hal-doctrine.php b/config/hal-doctrine.php
index 396f8ad..3341f12 100644
--- a/config/hal-doctrine.php
+++ b/config/hal-doctrine.php
@@ -3,6 +3,7 @@
return [
'default' => [
'entityManager' => \Doctrine\ORM\EntityManager::class,
+ 'namingStrategy' => \ApiSkeletons\Laravel\HAL\Doctrine\NamingStrategy\DefaultNamingStrategy::class,
'routeNamePatterns' => [
'entity' => 'api.{entityName}::fetch',
'collection' => 'api.{entityName}::fetchAll',
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 9a1fad5..3aa8af8 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -13,5 +13,7 @@
src
-
+
+
+
diff --git a/src/DoctrineHydrator.php b/src/DoctrineHydrator.php
index 004b111..1d9239c 100644
--- a/src/DoctrineHydrator.php
+++ b/src/DoctrineHydrator.php
@@ -4,16 +4,14 @@
namespace ApiSkeletons\Laravel\HAL\Doctrine;
+use ApiSkeletons\Laravel\HAL\Doctrine\NamingStrategy\NamingStrategyInterface;
use ApiSkeletons\Laravel\HAL\Hydrator;
use ApiSkeletons\Laravel\HAL\Resource;
use DateTime;
-use Doctrine\Inflector\Inflector;
-use Doctrine\Inflector\InflectorFactory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\MappingException;
use Exception;
use Illuminate\Foundation\Application;
-use ReflectionClass;
use function array_diff_key;
use function array_flip;
@@ -28,7 +26,7 @@ class DoctrineHydrator extends Hydrator
protected array $config = [];
protected string $configurationSection = 'default';
protected EntityManager $entityManager;
- protected Inflector $inflector;
+ protected NamingStrategyInterface $namingStrategy;
public function __construct(Application $application)
{
@@ -50,8 +48,8 @@ public function __construct(Application $application)
// @codeCoverageIgnoreEnd
- $this->entityManager = $application->get($this->config['entityManager']);
- $this->inflector = InflectorFactory::create()->build();
+ $this->entityManager = $application->get($this->config['entityManager']);
+ $this->namingStrategy = $application->get($this->config['namingStrategy']);
}
public function extract(mixed $entity): Resource
@@ -108,14 +106,14 @@ public function extract(mixed $entity): Resource
if ($entityMetadata->isAssociationInverseSide($associationName)) {
$resource->addLink(
- $associationName,
+ $this->namingStrategy->association($associationName),
route($associationRouteName, [
'filter' => [$associationMapping['mappedBy'] => $identifier],
])
);
} else {
$resource->addLink(
- $associationName,
+ $this->namingStrategy->association($associationName),
route($associationRouteName, [
'filter' => [$associationMapping['inversedBy'] => $identifier],
])
@@ -128,13 +126,13 @@ public function extract(mixed $entity): Resource
$associationRouteName = $this->getRouteName($associationMapping['targetEntity'], 'entity');
$resource->addLink(
- $associationName,
+ $this->namingStrategy->association($associationName),
route($associationRouteName, $identifier)
);
} else {
// For 1:1 relationships, only embed the owning side
$resource->addEmbeddedResource(
- $associationName,
+ $this->namingStrategy->association($associationName),
$data[$associationName]
);
}
@@ -149,7 +147,7 @@ protected function getRouteName(string $entityName, string $routeType): string
return $this->config['entities'][$entityName]['routeNames'][$routeType] ??
str_replace(
'{entityName}',
- $this->inflector->urlize((new ReflectionClass($entityName))->getShortName()),
+ $this->namingStrategy->route($entityName),
$this->config['routeNamePatterns'][$routeType]
);
}
diff --git a/src/NamingStrategy/DefaultNamingStrategy.php b/src/NamingStrategy/DefaultNamingStrategy.php
new file mode 100644
index 0000000..6b93786
--- /dev/null
+++ b/src/NamingStrategy/DefaultNamingStrategy.php
@@ -0,0 +1,30 @@
+inflector = InflectorFactory::create()->build();
+ }
+
+ public function route(string $entityName): string
+ {
+ return $this->inflector
+ ->urlize((new ReflectionClass($entityName))->getShortName());
+ }
+
+ public function association(string $associationName): string
+ {
+ return $this->inflector->urlize($associationName);
+ }
+}
diff --git a/src/NamingStrategy/NamingStrategyInterface.php b/src/NamingStrategy/NamingStrategyInterface.php
new file mode 100644
index 0000000..18c165a
--- /dev/null
+++ b/src/NamingStrategy/NamingStrategyInterface.php
@@ -0,0 +1,12 @@
+ [
'entityManager' => \Doctrine\ORM\EntityManager::class,
+ 'namingStrategy' => \ApiSkeletons\Laravel\HAL\Doctrine\NamingStrategy\DefaultNamingStrategy::class,
'routeNamePatterns' => [
'entity' => 'api.{entityName}::fetch',
'collection' => 'api.{entityName}::fetchAll',