V
V
Vladimir Korovin2013-10-24 10:11:57
PHP
Vladimir Korovin, 2013-10-24 10:11:57

The second question is for smart web developers who are familiar with patterns

After the previous question , new ones arose. I thought about it for 2 days, everything that you answered me, thank you very much. I can't say that everything has cleared up. Therefore, using a specific example, I ask you to show the vector along which to move further. Yes, I looked at yii and symfony, and even have a little experience with them. But. I don’t have the task of building a framework, all I need is to achieve readable code, achieve independence from data storage and not build queries in the controller.

I ask you to delve into what I will describe below.

Let's say there is a controller class userController. It has the following action methods:

search — called by default;
view - subscriber card;
create - adding a subscriber to billing;
remove — subscriber removal;
etc. (about 10 actions, it's not about them).

There is a user model class that implements the ArrayAccess interface (I wrote in the last question, but I repeat - to access the Subscriber object as an array).
Methods are defined in this class:
__construct(), which accepts an array, in which either id or login of the subscriber is passed. Both are unique, but sometimes you need to get a subscriber by login (for payments). I have already been told that it can be implemented differently than I did:

$user = new user(array(
'id'=>$id
));

and

$user=user->find_by('id', $id);

I like this approach. But. Analyzing further refactoring along the chain, I stumble upon some kind of misunderstanding. It is connected with this. Trying to unload the controller, I load the model. And if initially the model was just a description of the object, now there is validation, logging, static methods for processing database tables that store these objects. It seems to be not bad. The result of this approach was that I received many models, from the initial 5-6 there were several dozen of them. And although there are more of them, the code has become simpler and I don’t think about checks before updating some entity in different parts of the system - the model itself checks (although not everywhere yet, but that’s not the point), and that’s great. Now I understand that it is necessary to unload the model, separating the very receipt of data from the Storage (it does not matter whether it is a database or a configuration file). With your comments you pushed me to the mapper. I'm reading it, but there is no final understanding at what point he enters the work and whether he creates an object or not. Those. if I want to get a user object, does the model (in my case) create itself, or does the mapper take parameters, get an entry from the Store, and return an object of the user class? Or does the user model process incoming conditions and, based on them, a request is made to the mapper, which returns a result and, based on this response, the model creates an object? I look at examples on the Internet, but I don’t understand how to apply this in my case. or does the mapper take parameters, get an entry from the Store, and return an object of the user class? Or does the user model process incoming conditions and, based on them, a request is made to the mapper, which returns a result and, based on this response, the model creates an object? I look at examples on the Internet, but I don’t understand how to apply this in my case. or does the mapper take parameters, get an entry from the Store, and return an object of the user class? Or does the user model process incoming conditions and, based on them, a request is made to the mapper, which returns a result and, based on this response, the model creates an object? I look at examples on the Internet, but I don’t understand how to apply this in my case.

And the next moment. As I wrote above, there is a search action in the userController controller. There are questions about his work.
Now the search for subscribers in this action is as follows:

$params=array();

$tariff=get_param('tariff', 'int', 0);
if ($tariff>0) $params[]="tariff=$tariff";

$cities=get_param('city', 'int_array', array());
if (!empty($cities)) $params[]=”city IN (”.implode(', ', $cities).”)”;

$users=user::search($params);

This is where the static method of the model is called, which looks for subscribers that match the specified parameters. As you can see, not even in the model, but in the controller, I form part of the sql query. But apparently, even the model should not see this, somehow transferring mixed conditions to the mapper.

Thank you for reading this stream of consciousness)) I'm looking forward to your answers.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
N
Nikolai Vasilchuk, 2013-10-24
@Anonym

1. Use DBAL, at least PDO.
2. Create a UserCollection model for the user collection. It would be more logical something like this

$users = new UserCollection();
$users->findByParams(array(
  'tariff' => $tariff,
  'city' => $cities,
));

or
$users = UserCollection::findByParams(array(
  'tariff' => $tariff,
  'city' => $cities,
));

S
Sergey Cherepanov, 2013-10-24
@fear86

Everything in our engine is implemented through mappers, by default we have two types, Collections and Model Resources, the first implements work with a set of entities, the second with one specific one.
So, the collection is engaged in sampling and searching, and filtering is implemented there through a separate method to which the conditions for filtering are passed in a special format, and the collection already forms an sql query and screens the parameters. If this is not enough for me, I will add my own method that implements some specific request.
ps: the use of static methods and singletons is bad manners.

C
cawakharkov, 2013-10-29
@cawakharkov

try to read about the Service Layer, this approach unloads both the model and the controller

C
cawakharkov, 2013-10-29
@cawakharkov

unless of course I understand you correctly, implement the UserService class that operates with models of the User type and performs all manipulations

M
Masterme, 2013-10-29
@Masterme

here I already wrote my thoughts on the topic, so I’ll just add:
you need to correctly handle the situation with an empty $cities array, otherwise we will get an SQL error, if it has 0 elements, then do not include the condition

class SomeController extends BaseController {
  function search($params){
    $where = array();
    if ($params['tariff']) $where['tariff'] = $params['tariff'];
    if (is_array($params['cities']) and count($params['cities'])) $where['cities'] = $params['cities'];
    $uses = $this->Users->find($where); // массив cities будет автоматически сджойнен
    return compact('users');
  }
}

it is better to make $params an object with the ArrayAccess interface, and return null for all non-existent parameters.
What you are writing now is an injection for injections, it is enough to pass something like ROBIN DROP TABLE `users` to tariff ...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question