marcin110987
marcin110987

Reputation: 182

MVC Class between controller and Model

I'm building application in Phalcon PHP where I have database with access from website and API.

In normal website I would create MVC like here:

- app
-- controllers
-- models
-- views
- public

but I have problem with duplicate code for API and Web.

Sample code:

class Users extends Model {
    // ...
    protected $id;
    protected $username;
    protected $email;
    // setters and getters, validation
}

class UserController extends ControllerBase {
    // ...
    public function loginAction() {
        if ($this->request->isPost()) {
            // ... get post
            // check login is correct
            // create session
            // redirect
        }
        $this->view->var = $var;
    }
}

class ApiController extends ControllerBase {
    // ...
    public function loginAction() {
        if ($this->request->isPost() //or put) {
            $json = $this->request->getJsonRawBody();
            // ... get json
            // check login is correct
            // create session
        }
        $response->setStatusCode('2xx/4xx', 'msg');
        $response->setJsonContent([
            'status' => 'OK / ERROR',
            'message' => '$msg / $ex->getMessage()'
        ]);
    }
}

Now I would create class with logic for check is user data correct. I think about class like this:

class MyClass extends ParentClass {
    public function login($username, $password) {
        $user = Users::findFirstByEmail($email);
        if ($user->password === hash($password)) {
            $successLogin = new UserSuccessLogins();
            $successLogin ->setId('id');
            $successLogin ->setIpAddress('ip');
            $successLogin ->save();
        } else {
            $failedLogin = new UserFailedLogins();
            $failedLogin->setId('id');
            $failedLogin->setIpAddress('ip');
            $failedLogin->save();
        }
    }
}

And now I could use it in controllers like here:

class UserController extends ControllerBase {
    public function loginAction() {
        if ($this->request->isPost()) {
            $c = new MyClass();
            if ($c->login($username, $password)) {
                // redirect
            } 
        }
        $this->view->var = $var;
    }
}

class ApiController extends ControllerBase {
    public function loginAction() {
        if ($this->request->isPost() //or put) {
            $c = new MyClass();
            if ($c->login($username, $password)) {
                // send json OK
            } else {
                // send json Error
            }
        }
    }
}

What is best way for this? I don't want logic in model class. I have read about Plugin and Component, but I don't know how create good self commented code.

Upvotes: 1

Views: 973

Answers (3)

Radolan
Radolan

Reputation: 129

Your suggestion is a good option, however if you want to decouple and segregate responsibilities in a better way, you can try to use a service layer like in this example https://github.com/phalcon/mvc/tree/master/multiple-service-layer-model. Where you will have:

  • entities ( the models generated by phalcon)
  • repositories ( all the operations that requires fetching, updating or persisting data)
  • services (where the business logic is).

Whit this the call graph can be summarised as follow:

controllers -> services -> repositories -> entities

Note that the dependencies go in a single direction, nonetheless for simple tasks you can use a repo inside the controller directly o a entity inside the service, is up to you how hard or flexible your architecture will be.

I hope It is clear regards.

Upvotes: 0

a_byte_late
a_byte_late

Reputation: 131

You might be looking for Phalcon Multimodule, have a look at this example. Besides "Front-End" and "Back-End" modules, you can add "API" module.

Upvotes: 1

marcin110987
marcin110987

Reputation: 182

OK, I'm going to extend my project with components like here:

-app
--components
--controllers
--models
--views
-public

Now, my code may looks like below:

use Phalcon\Mvc\Model;
class Users extends Model {
    // ...
    protected $id;
    protected $username;
    protected $email;
    // setters and getters, validation
}

use Phalcon\Mvc\User\Component;
class UserComponent extends Component {
    // class with access to dependecy injector
    public login ($email, $password) {
        $user = Users::findFirstByEmail($email);
        // logic with setting session in $di
    }
}

class UserController extends ControllerBase {
    public function loginAction() {
        if ($this->request->isPost()) {
            $userComponent = new UserComponent();
            if ($userComponent ->login($username, $password)) {
                return $this->response->redirect($this->url->getBaseUri(), false, 301);
            } else {
                $this->flash->error('message');
            }
        }
        // setting view variables if not post or login filed
        $this->view->var = $var;
    }
}


class ApiController extends ControllerBase {
    public function loginAction() {
        if ($this->request->isPost()) {
            $userComponent = new UserComponent();
            if ($userComponent ->login($username, $password)) {
                //json OK
            } else {
                //json Error
            }
        }
    }
}

If no one have better proposition I'll close this topic as solved in few days.

Upvotes: 0

Related Questions