Skip to content

Major refactor for v4 #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.0.0] - 2025-06-08

### Added

- Attribute `OpenSoutheners\LaravelDto\Attributes\Inject` to inject container stuff
- Attribute `OpenSoutheners\LaravelDto\Attributes\Authenticated` that uses base `Illuminate\Container\Attributes\Authenticated` to inject current authenticated user
- Ability to register custom mappers (extending package functionality)
- `OpenSoutheners\LaravelDto\Contracts\MapeableObject` interface to add custom mapping logic to your own objects classes
- ObjectMapper now extracts type info from generics inside collections typed properties [#1]

### Changed

- Package renamed to `open-southeners/laravel-data-mapper`
- Config file changed and renamed to `config/data-mapper.php` (publish the new one using `php artisan vendor:publish --tag="laravel-data-mapper"`)
- Full refactor [#7]

### Removed

- Abstract class `OpenSoutheners\LaravelDto\DataTransferObject` (using POPO which means _Plain Old Php Objects_)
- Attribute `OpenSoutheners\LaravelDto\Attributes\WithDefaultValue` (when using with `Illuminate\Contracts\Auth\Authenticatable` can be replaced by `OpenSoutheners\LaravelDto\Attributes\Authenticated`)
- Artisan commands: `make:dto`, `dto:typescript`

## [3.7.0] - 2025-03-04

### Added
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
Laravel DTO [![required php version](https://img.shields.io/packagist/php-v/open-southeners/laravel-dto)](https://www.php.net/supported-versions.php) [![run-tests](https://github.com/open-southeners/laravel-dto/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/open-southeners/laravel-dto/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/open-southeners/laravel-dto/branch/main/graph/badge.svg?token=LjNbU4Sp2Z)](https://codecov.io/gh/open-southeners/laravel-dto) [![Edit on VSCode online](https://img.shields.io/badge/vscode-edit%20online-blue?logo=visualstudiocode)](https://vscode.dev/github/open-southeners/laravel-dto)
Laravel Data Mapper [![required php version](https://img.shields.io/packagist/php-v/open-southeners/laravel-data-mapper)](https://www.php.net/supported-versions.php) [![run-tests](https://github.com/open-southeners/laravel-data-mapper/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/open-southeners/laravel-data-mapper/actions/workflows/tests.yml) [![codecov](https://codecov.io/gh/open-southeners/laravel-data-mapper/branch/main/graph/badge.svg?token=LjNbU4Sp2Z)](https://codecov.io/gh/open-southeners/laravel-data-mapper) [![Edit on VSCode online](https://img.shields.io/badge/vscode-edit%20online-blue?logo=visualstudiocode)](https://vscode.dev/github/open-southeners/laravel-data-mapper)
===

Integrate data transfer objects into Laravel, the easiest way
Extensible data mapper to objects, DTOs, enums, collections, Eloquent models, etc

## Getting started

```
composer require open-southeners/laravel-dto
composer require open-southeners/laravel-data-mapper
```

## Documentation

[Official documentation](https://docs.opensoutheners.com/laravel-dto/)
[Official documentation](https://docs.opensoutheners.com/laravel-data-mapper/)

## Partners

Expand Down
20 changes: 13 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
{
"name": "open-southeners/laravel-dto",
"description": "Integrate data transfer objects into Laravel, the easiest way",
"name": "open-southeners/laravel-data-mapper",
"description": "Extensible data mapper to objects, DTOs, enums, collections, Eloquent models, etc",
"license": "MIT",
"keywords": [
"open-southeners",
"laravel",
"laravel-package",
"data",
"data-transfer-objects",
"data-mapper",
"object-mapper",
"requests",
"http"
],
Expand All @@ -30,10 +32,11 @@
"illuminate/support": "^11.0 || ^12.0",
"open-southeners/extended-laravel": "~0.4",
"phpdocumentor/reflection-docblock": "^5.3",
"symfony/property-info": "^6.0 || ^7.0"
"symfony/property-info": "^7.3"
},
"require-dev": {
"larastan/larastan": "^3.0",
"laravel/pint": "^1.22",
"orchestra/testbench": "^9.0 || ^10.0",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^11.0"
Expand All @@ -42,12 +45,15 @@
"prefer-stable": true,
"autoload": {
"psr-4": {
"OpenSoutheners\\LaravelDto\\": "src"
}
"OpenSoutheners\\LaravelDataMapper\\": "src"
},
"files": [
"src/functions.php"
]
},
"autoload-dev": {
"psr-4": {
"OpenSoutheners\\LaravelDto\\Tests\\": "tests",
"OpenSoutheners\\LaravelDataMapper\\Tests\\": "tests",
"Workbench\\App\\": "workbench/app/",
"Workbench\\Database\\Factories\\": "workbench/database/factories/",
"Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
Expand All @@ -59,7 +65,7 @@
"extra": {
"laravel": {
"providers": [
"OpenSoutheners\\LaravelDto\\ServiceProvider"
"OpenSoutheners\\LaravelDataMapper\\ServiceProvider"
]
}
},
Expand Down
8 changes: 4 additions & 4 deletions config/data-transfer-objects.php → config/data-mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/**
* Normalise data transfer objects property names.
*
*
* For example: user_id (sent) => user (DTO) or is_published (sent) => isPublished (DTO)
*/
'normalise_properties' => true,
Expand All @@ -14,13 +14,13 @@
* are passed to the command.
*/
'types_generation' => [

'output' => null,

'source' => null,

'filename' => null,

'declarations' => false,

],
Expand Down
6 changes: 3 additions & 3 deletions src/Attributes/AsType.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace OpenSoutheners\LaravelDto\Attributes;
namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;

Expand All @@ -9,6 +9,6 @@ class AsType
{
public function __construct(public string $typeName)
{
//
//
}
}
}
12 changes: 12 additions & 0 deletions src/Attributes/Authenticated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;
use Illuminate\Container\Attributes\Authenticated as BaseAttribute;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)]
class Authenticated extends BaseAttribute
{
//
}
26 changes: 26 additions & 0 deletions src/Attributes/Inject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Container\ContextualAttribute;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)]
class Inject implements ContextualAttribute
{
public function __construct(public string $value)
{
//
}

/**
* Resolve the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public static function resolve(self $attribute, Container $container)
{
return $container->make($attribute->value);
}
}
14 changes: 14 additions & 0 deletions src/Attributes/ModelWith.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
class ModelWith
{
public function __construct(public string|array $relations, public ?string $type = null)
{
//
}
}
2 changes: 1 addition & 1 deletion src/Attributes/NormaliseProperties.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace OpenSoutheners\LaravelDto\Attributes;
namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;

Expand Down
36 changes: 12 additions & 24 deletions src/Attributes/BindModel.php → src/Attributes/ResolveModel.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace OpenSoutheners\LaravelDto\Attributes;
namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;
use Exception;
Expand All @@ -9,12 +9,11 @@
use Illuminate\Support\Str;

#[Attribute(Attribute::TARGET_PROPERTY)]
class BindModel
final class ResolveModel
{
public function __construct(
public string|array|null $using = null,
public string|array $with = [],
public string|null $morphTypeKey = null
public string|array|null $keyFromRouteParam = null,
public ?string $morphTypeFrom = null
) {
//
}
Expand All @@ -26,12 +25,12 @@ public static function getDefaultMorphKeyFrom(string $key): string

public function getBindingAttribute(string $key, string $type, array $with)
{
$usingAttribute = $this->using;
$usingAttribute = $this->keyFromRouteParam;

if (is_array($usingAttribute)) {
$typeModel = array_flip(Relation::morphMap())[$type];

$usingAttribute = $this->using[$typeModel] ?? null;
$usingAttribute = $this->keyFromRouteParam[$typeModel] ?? null;
}

/** @var \Illuminate\Http\Request|null $request */
Expand All @@ -55,28 +54,19 @@ public function getBindingAttribute(string $key, string $type, array $with)

protected function resolveBinding(string $model, mixed $value, mixed $field = null, array $with = [])
{
$modelInstance = new $model();
$modelInstance = new $model;

return $modelInstance->resolveRouteBindingQuery($modelInstance, $value, $field)
->with($with);
}

public function getRelationshipsFor(string $type): array
{
$withRelations = (array) $this->with;

$withRelations = $withRelations[$type] ?? $withRelations;

return (array) $withRelations;
}

public function getMorphPropertyTypeKey(string $fromPropertyKey): string
{
if ($this->morphTypeKey) {
return Str::snake($this->morphTypeKey);
if ($this->morphTypeFrom) {
return Str::snake($this->morphTypeFrom);
}

return static::getDefaultMorphKeyFrom($fromPropertyKey);
return self::getDefaultMorphKeyFrom($fromPropertyKey);
}

public function getMorphModel(string $fromPropertyKey, array $properties, array $propertyTypeClasses = []): array
Expand All @@ -90,6 +80,7 @@ public function getMorphModel(string $fromPropertyKey, array $properties, array
}

$morphMap = Relation::morphMap();

$modelModelClass = array_filter(
array_map(
fn (string $morphType) => $morphMap[$morphType] ?? null,
Expand All @@ -98,12 +89,9 @@ public function getMorphModel(string $fromPropertyKey, array $properties, array
);

if (count($modelModelClass) === 0 && count($propertyTypeClasses) > 0) {
var_dump($propertyTypeClasses);
var_dump($morphMap);
var_dump($types);
$modelModelClass = array_filter(
$propertyTypeClasses,
fn (string $class) => in_array((new $class())->getMorphClass(), $types)
fn (string $class) => in_array((new $class)->getMorphClass(), $types)
);

$modelModelClass = reset($modelModelClass);
Expand Down
14 changes: 14 additions & 0 deletions src/Attributes/Validate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace OpenSoutheners\LaravelDataMapper\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_CLASS)]
class Validate
{
public function __construct(public string $value)
{
//
}
}
14 changes: 0 additions & 14 deletions src/Attributes/WithDefaultValue.php

This file was deleted.

Loading
Loading