ProgrammingPiotrN / ProjectNewWork

0 stars 0 forks source link

Anemiczny obiekt encji #2

Open szymjab opened 6 months ago

szymjab commented 6 months ago

https://github.com/ProgrammingPiotrN/ProjectNewWork/blob/907a705ab417ca83ee2a85d00276f19b4765db8f/Blog/app/Models/Post.php#L8

Laravel narzuca pewną konwencję - zachęca do tworzenia relacji poprzez wbudowane mechanizmy oraz zachęca do tworzenia nowych encji z użyciem istniejących metod create lub save.

Nie jest to dobre jeśli tworzymy obiekt odzwierciedlający naszą dziedzinę (DDD). Powoduje to, że nasz obiekt jest tylko gołym nośnikiem danych o relacjach.

W związku z tym zaleca się stosowanie statycznych metod wytwórczych, które pozwolą na tworzenie prawidłowego obiektu, zgodnego z naszymi założeniami biznesowymi.

Dla przykładu, obiekt Geolocation mógłby zostać utworzony na różne sposoby:

Wówczas przydatne mogą być metody:

Konkretne informacje zawarte są w książce, którą podesłałem na maila :)

ProgrammingPiotrN commented 5 months ago
  1. Aktualizacja modelu:
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content'];

    public static function createFromString(string $post): self
    {
        $postArray = json_decode($post, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \InvalidArgumentException('Invalid JSON string');
        }

        return new self([
            'title' => $postArray['title'] ?? '',
            'content' => $postArray['content'] ?? ''
        ]);
    }

    public static function createEmpty(): self
    {
        return new self([
            'title' => '',
            'content' => ''
        ]);
    }
}
  1. Aktualizacja kontrolera:
namespace App\Http\Controllers;

use App\Http\Requests\CreatePostFromStringRequest;
use App\Http\Requests\CreateEmptyPostRequest;
use App\Models\Post;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function storeFromString(CreatePostFromStringRequest $request): JsonResponse
    {
        try {
            $post = Post::createFromString($request->input('post_data'));
            $post->save();

            return response()->json(['message' => 'Post created successfully', 'post' => $post], 201);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function storeEmpty(CreateEmptyPostRequest $request): JsonResponse
    {
        try {
            $post = Post::createEmpty();
            $post->save();

            return response()->json(['message' => 'Empty post created successfully', 'post' => $post], 201);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }
}
  1. Żądania HTTP:
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreatePostFromStringRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'post_data' => 'required|string',
        ];
    }
}

....

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreateEmptyPostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [];
    }
}
  1. Routing:

Route::resource('posts', PostController::class);