@Alk90
php, mysql, jquery, css, html, api

Что такое модель в ООП в веб?

Всем привет! Я постоянно возвращаюсь к этому вопросу от задачи к задаче и в зависимости от необходимой задачи, модель у меня плавает из стороны в сторону. Поясните пожалуйста на моем примере что нужно считать моделью и как с ней работать. А я пока опишу свои размышления по этому поводу. Прошу учесть их при ответе, потому как это важно...
На всех ресурсах и во всех мануалах, да и я сам, в принципе разобрались с контроллером и видом (есть конечно неточности, но я начу).
Контроллер получает данные от пользователя и просто отправляет данные в модель, которая может их обработать, тут вроде все понятно.
Модель что-то сделав возвращает данные контроллеру, который отправляет эти данные в некий класс, который знает как обработать. На примере вывода страницы со списком пользователей, это получается так: модель возвращает "массив" (коллекцию),в которой содержатся объекты пользователей (объект пользователя это отдельный класс) который содержит в себе поля name, address, avatar и т.д. Вид, это класс, который знает, что он получил именно массив объектов пользователей и знает их методы. Значит класс вида вклинивает в шаблон (HTML) готовые данные. т.е. для вывода имени и фамилии, объект UserEntity содержит метод который возвращает $this->getName().' '.$this->getLastName()
Но теперь модель... И тут непонятки...
Я представлял себе модель как класс, который работает с БД. Например, в контроллере SearchUsers мы вызываем методы модели и указываем какие данные нам нужны. $this->model->setFields('name, last_name,photo');. и потом вызывает метод $this->model->searchUsers(). Модель строит на основе полученных данных запрос к БД. т.е. внутри модели прописано, что если контроллер запросил поля где есть photo, то модель включает в SELECT запрос поле, скажем, avatar. Да, они не совпадают, но я вижу в этом преимущество. Контроллер не знает названия полей в БД но может указать просто то, что ему нужно, а модель понимает и подставляет реальное имя поля или нескольких полей (например если контроллер указал, что нужно address, то модель запросит в БД поля country, state, city). Дальше, получив данные из БД модель выполняет внутренний метод $this->createObject(), который создает из полученных данных из БД объект UserEntity и вставляет в него те поля, которые у нее есть (все остальные указаны по умолчанию в объекте UserEntity). Ну вот собственно и вся ее работа. НО во многих комментариях я вижу сообщения по типу: "модель не должна лезть в БД". Но тогда кто в нее должен лезть? Опять же. Где-то модель представляют как мой объект UserEntity который и получает сам себя из БД с помощью ORM, но как он получает целый список пользователей (самого себя), я не могу понять.
Поэтому и возник такой вопрос...
Но в моем методе я так же вижу проблемы... Если для одного контроллера я хочу получить мой UserEntity, а для другого контроллера, другой объект UserEntity который содержит не только те данные которые нужны для вывода пользователям, но и те, которые нужны в админке, уже не получается. Потому что мне из контроллера как-то нужно будет передавать объект User в модель, чтобы та создала объект на основе другого класса, но как ей дать понять, какие поля там есть а каких нету - уже не понятно....
  • Вопрос задан
  • 511 просмотров
Пригласить эксперта
Ответы на вопрос 2
@Vitsliputsli
Контроллер, представление, модель - это элементы MVC, к ООП отношения не имеют.
Контроллер получает от пользователя запрос в определенном виде (запрос браузера, обращение к API, команда, все это разные группы контроллеров). Распарсив запрос передает его в модель для обработки.
Модель содержит бизнес-логику, т.е. по-сути то, что должно делать ваше приложение, без привязки к способам обращения пользователей и способам вывода. Возможно будут вызываться модели работающие с БД, а может и не будут, это неважно, не превозносите БД как сверхсущность, это обычный инструмент, один из множества.
Далее модель передает подготовленные для вывода данные в контроллер (в классической MVC сразу в представление), и контроллер передает их в нужное представление.
Вот и все, простая схема, которая позволит отделить мух от котлет, создавать API, видоизменять вывод, не трогая основную логику. А работа с БД, совсем другой вопрос.
Ответ написан
Комментировать
IgorPI
@IgorPI
Как то всё запутанно у вас, перемешались кони и люди.

Вот что мне известно.

Вы в вопросе пишете

Дальше, получив данные из БД модель выполняет внутренний метод $this->createObject(), который создает из полученных данных из БД объект UserEntity и вставляет в него те поля, которые у нее есть (все остальные указаны по умолчанию в объекте UserEntity). Ну вот собственно и вся ее работа. НО во многих комментариях я вижу сообщения по типу: "модель не должна лезть в БД". Но тогда кто в нее должен лезть?


Вы ни разу не упомянули про репозиторий, его так не хватает в вашем монологе.

Терминология.

Модель - это некоторый объект, имеющий поля, геттеры и сеттеры - то, это место куда мы помещаем данные и только их.

Сущность - Entity и имеет особые отношения с вашей базой данных - обычно каждый экземпляр сущности соответствует отдельной строке. В doctrine orm модель может быть описана в аннотации.

Репозиторий - класс, соответствующий классу Entity и содержащий методы типа getById, getMyHome, ...

Теперь имея некое представление
Если модель, э всего лишь объект, которые хранит некоторые значения, а сущность может быть классом, или аннотацией, которая описывает отношения и типы полей. Модель это всего лишь класс с геттерами и сеттерами

То репозиторий над моделью и сущностью, да простит меня всевышний.

Именно в репозитории вы описываете, то как вы будите тянуть ваши данные из базы и в итоге вы получите данные которые будут в расположены в модели.

Вот некоторые примеры:

Метод в репозитории
/**
     * @param int $id
     * @return mixed
     * @throws NonUniqueResultException
     * @throws NoResultException
     */
    public function getById(int $id) {
        return  $this->createQueryBuilder("org")
            ->leftJoin("org.category", "cat")
            ->leftJoin("org.region", "region")->addSelect("region")
            ->leftJoin("org.country", "country")->addSelect("country")
            ->leftJoin("org.city", "city")->addSelect("city")
            ->leftJoin("org.street", "street")->addSelect("street")
            ->leftJoin("org.gps", "gps")->addSelect("gps")
            ->leftJoin("org.services", "services")->addSelect("services")
            ->leftJoin("services.group", "grp")->addSelect("grp")
            ->leftJoin("org.images", "images", "", "")->addSelect("images")
            ->leftJoin("org.reviews", "reviews", Join::WITH, "reviews.status = 1")->addSelect("reviews")
            ->where("org = :id")->setParameter("id", $id)
            ->getQuery()
            ->getSingleResult();
    }


Из примера выше, мы может определить, какие модели буду заполнены.

А вот пример, то как я тяну данные в контроллере, используя репозиторий

/**
     * @Rest\Route(
     *     path="/organization.getById",
     *     name="organization_get_by_id",
     *     requirements={ "id"="\d+" }
     * )
     *
     * @param Request $request
     * @return object|JsonResponse
     * @throws ExceptionInterface
     * @throws NonUniqueResultException
     * @throws NoResultException
     */
    public function getById(Request $request)
    {
        $organization_repository = $this->getDoctrine()->getManager()->getRepository("App:Organization");

        $rs = new ResponseSchemaData();
        $rs->setData($organization_repository->getById($request->get("id")));

        $serializer = $this->get('serializer');
        $response_object = $serializer->normalize($rs, "json", ["attributes" => [
            "code",
            "data" => [
                "id",
                "name",
                "images",
                "description",
                "postCode",
                "phone",
                "email",
                "home",
                "site",
                "schedule",
                "images",
                "rating",
                "gps" => [
                    "latitude",
                    "longitude",
                ],
                "category" => [
                    "id",
                    "name",
                ],
                "reviews" => [
                    "id",
                    "author",
                    "text",
                    "likes",
                    "dislike",
                    "rating",
                    "createAt",
                ],
                "services" => [
                    "id",
                    "name",
                    "types" => [
                        "id",
                        "name"
                    ]
                ],
                "country" => [
                    "id",
                    "name"
                ],
                "region" => [
                    "id",
                    "name"
                ],
                "city" => [
                    "id",
                    "name"
                ],
                "street" => [
                    "id",
                    "name",
                    "streetType"
                ],
            ]
        ]]);

        return new JsonResponse($response_object);
    }


В итоге, если я сериальную объект в json, то у меня получится нечто
{
    "data": {
        "name": "Здравстолет",
        "home": "51",
        "phone": "8 (800) 350-29-32",
        "site": "https://zdravstolet.ru/",
        "schedule": "пн–пт 08:00–17:00",
        "id": "641659",
        "category": [],
        "city": {
            "id": 3170,
            "name": "Бийск"
        },
        "street": {
            "name": "Петра Мерлина",
            "id": 19583,
            "street_type": "улица"
        },
        "country": {
            "name": "Россия",
            "id": 3159
        },
        "reviews": [
            {
                "author": "пиаипиапи",
                "text": "иапипиаиапипаипаиапи",
                "likes": 0,
                "dislike": 0,
                "id": "41",
                "rating": 0,
                "create_at": "2019-09-22T20:03:42+00:00"
            }
        ],
        "description": null,
        "email": null,
        "rating": "3.7",
        "services": [],
        "images": [],
        "post_code": 659303,
        "region": null,
        "gps": {
            "latitude": 52.529974,
            "longitude": 85.173845
        }
    },
    "code": 0
}


Каждый объект в JSON это 1 таблица в базе данных.
Или скажем так:

1 объект = 1 таблица = 1 модель
Сущность = таблица

Да простит меня господь за грехи мои.
ORM
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы