Skip to content

Commit

Permalink
Improvements (#1)
Browse files Browse the repository at this point in the history
* remove inaccurate description of process method from docblock and fix return type

* remove unnecessary resource related parts from gii template

* preload correct model namespace

* rename AbstractDomain to AbstractService because it is more relevant naming

* update readme for new classes and naming convention

* update crud templates

* rename test methods in templates

* allow to configure test path in crud template

* mark deprecated classes

* rename domains to services in test templates

* update module name default placeholder in ns property of model generator
  • Loading branch information
albertborsos authored Sep 26, 2018
1 parent 194ded2 commit 580ef17
Show file tree
Hide file tree
Showing 36 changed files with 459 additions and 590 deletions.
148 changes: 30 additions & 118 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
DDD Classes for Yii 2.0
=======================
Classes for Domain-Driven Development with Yii 2.0 Framework
Classes for a Domain-Driven Design inspired workflow with Yii 2.0 Framework

Installation
------------

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run
Run

```
php composer.phar require --prefer-dist albertborsos/yii2-ddd
```

or add

```
"albertborsos/yii2-ddd": "~0.1"
```

to the require section of your `composer.json` file.

Usage
Expand All @@ -28,14 +22,14 @@ Lets see an example with a standard `App` model which is an implementation of `\
I recommend to do not make any modification with this class, but make it `abstract` to prevent direct usages.

Then create a business model which extends our abstract active record class and implements `BusinessObject` interface.
Every business logic will be implemented into this class.
Every business logic will be implemented in this class.

```php
<?php

namespace albertborsos\resources\app\business;
namespace application\domains\app\business;

use albertborsos\resources\app\activerecords\App as AbstractApp;
use application\domains\app\activerecords\AbstractApp;
use albertborsos\ddd\interfaces\BusinessObject;

class App extends AbstractApp implements BusinessObject
Expand All @@ -44,102 +38,18 @@ class App extends AbstractApp implements BusinessObject
}
```

Then create a resource class which will be responsible to manage CRUD operations.


```php
<?php

namespace albertborsos\resources\app;

use albertborsos\ddd\models\AbstractResource;
use albertborsos\resources\app\business\App;
use Yii;

class AppResource extends AbstractResource
{
/**
* Business logic to insert data.
*
* @return bool
*/
protected function insert()
{
$model = $this->getModel() ?? new App();
$model->load($this->getForm()->attributes, '');

$model = $this->generateApiKey($model);

if ($model->save()) {
$this->setId($model->id);
return true;
}

$this->getForm()->addErrors($model->getErrors());
return false;
}

/**
* Business logic to update data.
*
* @return bool
*/
protected function update()
{
$model = $this->getModel();
$model->load($this->getForm()->attributes, '');

if ($model->save()) {
$this->setId($model->id);
return true;
}

$this->getForm()->addErrors($model->getErrors());
return false;
}

/**
* Business logic to delete data.
*
* @return bool
*/
public function delete()
{
/** @var App $model */
$model = $this->getModel();
$model->delete();
return true;
}

private function generateApiKey(App $model)
{
$apiKey = Yii::$app->security->generateRandomString(32);

if (App::findOne(['api_key' => $apiKey]) === null) {
$newModel = clone $model;
$newModel->api_key = $apiKey;

return $newModel;
}

return $this->generateApiKey($model);
}
}

```

#### Lets create a new record!

We will need a new `FormObject` which will be responsible for the data validation.
And we will need a `domain` model, which handles the business logic with the related models too.
And we will need a `service` model, which handles the business logic with the related models too.


A simple example to a `FormObject`:
A simple example for a `FormObject`:

```php
<?php

namespace albertborsos\domains\app\forms;
namespace application\services\app\forms;

use yii\base\Model;
use albertborsos\ddd\interfaces\FormObject;
Expand All @@ -160,34 +70,36 @@ class CreateAppForm extends Model implements FormObject

```

And a simple example to a `domain`. Domains are expecting that the values in the `FormObject` are valid values.
And a simple example for a `service`. Services are expecting that the values in the `FormObject` are valid values.
That is why it is just store the values. The validation will be handled in the controller.

```php
<?php

namespace albertborsos\domains\app;
namespace application\services\app;

use albertborsos\ddd\models\AbstractDomain;
use albertborsos\domains\app\forms\CreateAppLanguageForm;
use albertborsos\resources\app\AppResource;
use albertborsos\ddd\models\AbstractService;
use application\services\app\forms\CreateAppLanguageForm;
use application\domains\app\business\App;
use yii\base\Exception;

class CreateAppDomain extends AbstractDomain
class CreateAppService extends AbstractService
{
/**
* Business logic to store data for multiple resources.
*
* @return mixed
*/
public function process()
public function execute()
{
try {
$resource = new AppResource($this->getForm());
if ($resource->save()) {
$this->assignLanguages($resource->getId(), $this->getForm()->languages);
$this->setId($resource->getId());

$model = new App();
$model->load($this->getForm()->attributes, '');

if ($model->save()) {
$this->assignLanguages($model->getId(), $this->getForm()->languages);
$this->setId($model->getId());

return true;
}
} catch(\yii\db\Exception $e) {
Expand All @@ -208,8 +120,8 @@ class CreateAppDomain extends AbstractDomain
throw new Exception('Unable to validate language for this app');
}

$domain = new CreateAppLanguageDomain($form);
if ($domain->process() === false) {
$service = new CreateAppLanguageService($form);
if ($service->execute() === false) {
throw new Exception('Unable to save language for this app');
}
}
Expand All @@ -223,11 +135,11 @@ And this is how you can use it in the controller
```php
<?php

namespace albertborsos\controllers;
namespace application\controllers;

use Yii;
use albertborsos\domains\app\forms\CreateAppForm;
use albertborsos\domains\app\CreateAppDomain;
use application\services\app\forms\CreateAppForm;
use application\services\app\CreateAppService;

class AppController extends \yii\web\Controller
{
Expand All @@ -236,10 +148,10 @@ class AppController extends \yii\web\Controller
$form = new CreateAppForm();

if ($form->load(Yii::$app->request->post()) && $form->validate()) {
$domain = new CreateAppDomain($form);
if ($domain->process()) {
$service = new CreateAppService($form);
if ($service->execute()) {
AlertWidget::addSuccess('App created successfully!');
return $this->redirect(['view', 'id' => $domain->getId()]);
return $this->redirect(['view', 'id' => $service->getId()]);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/data/ResourceDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

/**
* Class ResourceDataProvider
* @deprecated since 0.3.0, will be removed in 1.0.0.
* @package albertborsos\ddd\data
*/
class ResourceDataProvider extends ActiveDataProvider
Expand Down
Loading

0 comments on commit 580ef17

Please sign in to comment.