boldsinas101
boldsinas101

Reputation: 330

Putting a Where query condition in controller or model in CakePHP 3.5

I'm new in CakePHP 3.5. Please answer me nicely because I really need help in solving this problem or at least give an idea on how to solve this. I've read almost the same question but most of the answers they provide are already deprecated.

My problem is I want to display in index the transactions that are reserves. I try this query in client transaction controller

public function index()
{
    $this->paginate = [
        'contain' => ['Clients']
    ];

    $clientTransaction = $this->paginate($this->ClientTransaction);
    $clientTransaction = $this->ClientTransaction->find()
    ->where(['status' => 0]);
    $this->set(compact('clientTransaction'));
}

This the screenshot of the error in index.ctp

It is right that I code it in a controller or it is better to place that query code in model?

Upvotes: 0

Views: 715

Answers (2)

floriank
floriank

Reputation: 25698

The answer is pretty clear: Model.

The manual also tells you "Fat models, skinny controllers". The reason is simply the separation of concerns in different parts of the application. A controller doesn't need to know anything about the model and it's logic.

A controller just needs to deal with the request and use it to delegate its data to some other object that implements the actual business logic. This makes it easier to change and test and exchange or share parts of an application.

If you want to go a step further and do proper SoC it would be actually Controller, Service, Model/Table.

For example custom finders should go into a table, any DB (or whatever kind of repository the model implements) should happen in the model.

So in your case implement whatever find conditions you need in your model as custom finder then call it in the controller:

$query = $this->MyTable->find('customFinder');
$this->set('results', $this->paginate($query));

In the case you need to pass args to the query I usually implement a separate method (findIndex & getIndexQuery($queryParams)) that takes the arguments, for example the URLs query params and calls the custom find and returns the query object. If you use a service layer, this method would go into your service layer because it implements the business logic.

The service class, a custom made class, not part of the CakePHP framework, would implement the real business logic and do any kind of calculations or whatever else logic operations need to be done and pass the result back to the controller which would then pass that result to the view.

This ensures that each part of the code is easy to test and exchange. For example the service is as well useable in a shell app because it doesn't depend on the controller.

Upvotes: 1

Greg Schmidt
Greg Schmidt

Reputation: 5098

The result of your paginate call is being thrown away and overwritten with the result of find call, because you're using the same variable name. There's an example in the manual of passing a query object to the paginator. In your case, it would look something like this:

$clientTransaction = $this->ClientTransaction->find()
    ->where(['status' => 0]);
$clientTransaction = $this->paginate($clientTransaction);

Upvotes: 2

Related Questions