Связи таблиц, точнее функционал ORM для работы с БД

12 3
ArbNet
На сайте с 27.10.2019
Offline
124
189

Начал было делать сайт на своём инструменте, всё хорошо, но при работе с базой данных нужно в классах узлов прописывать SQL запросы. Раньше думал сделаю пока так, а потом продумаю и ORM. Но настроив узел для категорий с автосохранением изменений решил, что это замечательный подход, который надо применить в ORM. Не откладывая это дело в долгий ящик решил всё же сначала разработать ORM для своего фреймворка, далее продолжить настройку сайта проекта и тд.

Итак, как у меня сейчас работает ORM.
Есть класс данных(Data), через него задаются параметры отбора и загрузка данных: $Data->Where('otdel=2')->Limit(10)->Load('user');
Далее получаем сущность данных $users=$Data->user; Переменная $users становится объектом у которого есть поля, которые можно менять, удалять, добавлять. Потом система в зависимости какие были изменения делает запрос в базу и там производится удаление, обновление и вставка данных. Всё прекрасно.

Теперь мне надо настроить работу с связями таблиц. При получении данных сущности формируется массив в котором:

['user']=>[
		'source'=>'MySql', // источник данных в данном случае MySql, может быть другая база или удалённый сервер и тд.
		'fields'=>$fields,// поля и типы данных этих полей вида 'поле'=>'тип данных','pole'=>'STRING'
		'attain'=>$attain,// связи ['table'='otdel','field'='id','delete'=>'RESTRICT','update'=>'RESTRICT']
		'values'>=$values // значения [0]=>['pole1'=>'значение1','pole2'=>'значение2'], [1]=>[...] - где [0],[1] записи строк
	   ]

Хочу посоветоваться с форумчанами как лучше и удобнее сделать. Можно подгружать в начале просто значения id строк других таблиц, потом при необходимости делать выборку, можно сразу, а можно сделать по желанию и так и так. Так же варианты связей один к одному, один к многим и многие к многим. Пока смутно представляю как это сделаю, надеюсь натолкнёте на интересные мысли.

Обсуждение разработки на моём фреймворке https://discord.gg/23N4s9x2kp
W1
На сайте с 22.01.2021
Offline
284
#1
ArbNet :
Пока смутно представляю как это сделаю, надеюсь натолкнёте на интересные мысли.

Осмелюсь предположить, что у форумчан ещё более смутное представление. Лично я вообще не понял, что Вы хотите сделать.

Мой форум - https://webinfo.guru –Там я всегда на связи
ArbNet
На сайте с 27.10.2019
Offline
124
#2
webinfo1 #:

Осмелюсь предположить, что у форумчан ещё более смутное представление. Лично я вообще не понял, что Вы хотите сделать.

Как бы да, вопрос не такой простой. Вот сижу и думаю...

К примеру:

table1

id pole  _table2
1   value1 3
2   value2 2
3   value3 1

table2

id valA valB
1 aaa1 bbb1
2 aaa2 bbb2
3 aaa3 bbb3

Первая таблица table1 имеет поле _table2 которое указывает на вторую таблицу table2, связь 1 к 1. Если сделаем запрос c JOIN, то получим сущность с следующими данными

id pole valA valB
1 value1 aaa3 bbb3
2 value2 aaa2 bbb2
3 value3 aaa1 bbb1

в PHP коде это будет

$Data->Load('table1');
$table1=$Data->table1;

foreach
($table1 as $num=>$val){
        echo $num.' - '.$val->pole.' '.$val->valA.' '.$val->valB.CRLF;
}
/* в результате получим

1 - value1 aaa3 bbb3 2 - value2 aaa2 bbb2 3 - value3 aaa1 bbb1

*/

Соответственно можем менять значения  $val->pole, $val->valA, $val->valB изменения будут так же произведены и в базе данных

Так же и с другими видами связей. Вот и кумекаю, будет ли так удобно и как другие связи сделать, так же как регламентировать по ON DELETE, ON UPDATE и тд.

Sly32
На сайте с 29.03.2012
Offline
302
#3

Не надоело тебе изобретать то, что давно есть? Как пример:

// src/Repository/ProductRepository.php

// ...
class ProductRepository extends ServiceEntityRepository
{
    public function findAllGreaterThanPrice(int $price, bool $includeUnavailableProducts = false): array
    {
        // automatically knows to select Products
        // the "p" is an alias you'll use in the rest of the query
        $qb = $this->createQueryBuilder('p')
            ->where('p.price > :price')
            ->setParameter('price', $price)
            ->orderBy('p.price', 'ASC');

        if (!$includeUnavailableProducts) {
            $qb->andWhere('p.available = TRUE');
        }

        $query = $qb->getQuery();

        return $query->execute();

        // to get just one result:
        // $product = $query->setMaxResults(1)->getOneOrNullResult();
    }
}
ArbNet
На сайте с 27.10.2019
Offline
124
#4
Sly32 #:

Не надоело тебе изобретать то, что давно есть? Как пример:

Говно пример. Я насмотрелся уже на разные ORMки всё сделано через задний проход..

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

Sly32
На сайте с 29.03.2012
Offline
302
#5
ArbNet #:
Мне же нужен свежий взгляд тех кто понимает, что такое связи в БД

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

Ну и опять же о голословности. Я тебе пример пример ормки из симфони - ты в состоянии это переписать понятнее? Челлендж? Я даже не буду арбитром, мне лень разбираться в пхп коде, форумчане рассудят.

По факту ты бы мог прикрутить эту ОРМ и пойти дальше к к готовому продукту, а ты опять придумываешь квадратные колеса.

ArbNet
На сайте с 27.10.2019
Offline
124
#6
Sly32 #:

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

Ну и опять же о голословности. Я тебе пример пример ормки из симфони - ты в состоянии это переписать понятнее? Челлендж? Я даже не буду арбитром, мне лень разбираться в пхп коде, форумчане рассудят.

По факту ты бы мог прикрутить эту ОРМ и пойти дальше к к готовому продукту, а ты опять придумываешь квадратные колеса.

Завязывай уже меня смешить 😀

lutskboy
На сайте с 22.11.2013
Offline
171
#7

зачем самому себе усложнять жизнь?

$rows = DB::query( "SELECT id, date, comment FROM table WHERE id=? AND date>?", [$id, $date] );
ArbNet
На сайте с 27.10.2019
Offline
124
#8
lutskboy #:

зачем самому себе усложнять жизнь?

Я не себе усложняю, а другим облегчаю.

К примеру: посмотрите видео как в RedBean можно работать с БД не написав ни одного SQL запроса https://www.youtube.com/watch?v=iU8zlbkpwyo

Для кодеров которые не знают SQL это замечательная штука. Но для нормальных прогеров это куча ~500кб с каждой обработки формирования страницы и ненужных\лишних запросов и тд. Проще как вы прописать нужный запрос и всё.

НО, сама задумка ORM не плохая(людям не надо изучать SQL), вот только реализация как обычно.. хотели как лучше, а получилось как всегда.. Поэтому я разработал свой фреймворк, и для облегчения работы с БД я написал свою ORM,  которая быстрая, всего 3 класса, в которых ~ по 100-200 строк кода, в отличии от того же редбин, в котором 17к строк. Человеку не нужно будет ничего изобретать, прикручивать редбин, доктрин или ещё что то. Легко получать,  изменять, удалять, добавлять данные и просто с ними работать не составляя никаких SQL запросов,  с любой базой данных или удалённым xml, json, yaml, др. файлом и тд.

Sly32
На сайте с 29.03.2012
Offline
302
#9
ArbNet #:
Легко получать,  изменять, удалять, добавлять данные и просто с ними работать не составляя никаких SQL запросов

Как обычно - ты перепутал форум и разглагольствуешь для  домохозяек, забывая, что тут так есть программисты/кодеры. Приведи пример своего класса, покажи что именно он упрощает и так уж совсем ли не надо знать SQL?

Вот к примеру тебе простенький запрос из реальной жизни - покажи как он будет выглядеть в твоей ОРМке?

        query = db.text("""
                WITH related_audio_and_subtitles AS
                (
                   SELECT
                      cms_media.media_type as media_type,
                      avail_item.id as media_id
                   FROM
                      cms_media
                      INNER JOIN
                         cms_item media_item
                         ON (cms_media.item_ptr_id = media_item.id)
                      INNER JOIN
                         catalog_avails avails
                         ON avails.item_id = media_item.parent_id
                      INNER JOIN
                         cms_item avail_item
                         ON avails.item_id = avail_item.id
                      INNER JOIN
                         cms_item episode_item
                         ON (avail_item.parent_id = episode_item.id)
                      INNER JOIN
                         cms_item season_item
                         ON (episode_item.parent_id = season_item.id)
                      INNER JOIN
                         cms_territory AS territory
                         ON avails.territory_id = territory.id
                         AND territory.code = ANY (ARRAY [:territory_code, 'all_terr'])
                      LEFT JOIN
                         catalog_avails_devices AS many_devices
                         ON many_devices.avails_id = avail_item.id
                      LEFT JOIN
                         cms_device device
                         ON many_devices.device_id = device.id
                   WHERE
                      (
                         cms_media.media_type = 'audio'
                         OR cms_media.media_type = 'subtitle'
                      )
                      AND season_item.parent_id = :item_id
                      AND avails.start_timestamp::int8 < extract(epoch from now())::int8
                      AND avails.end_timestamp::int8 > extract(epoch from now())::int8
                      AND
                      (
                         LOWER(device.title) = ANY (ARRAY [LOWER(:device_type), 'all'])
                         OR device.title isnull
                      )
                )
                SELECT DISTINCT
                   cms_language.id,
                   cms_language."LanguageName" as language_name,
                   cms_language."LanguageCode" as language_code,
                   related_audio_and_subtitles.media_type as media_type
                FROM
                   cms_media_languages
                   INNER JOIN
                      cms_language
                      ON ( cms_media_languages.language_id = cms_language.id )
                   INNER JOIN
                      related_audio_and_subtitles
                      ON cms_media_languages.media_id = related_audio_and_subtitles.media_id
            """)
ArbNet
На сайте с 27.10.2019
Offline
124
#10
Sly32 #:
покажи как он будет выглядеть в твоей ОРМке

Включи мозг. Запрос к базе ничем не будет отличатся, также будут джониться таблицы.

Кроме того запросы могут быть и через таблицу и через ту таблицу которая через и тд. намного сложнее чем простое добавление(JOIN LEFT|RIGHT|FULL). И все запросы будет составлять ORMка в зависимости от связей таблиц, а в коде зная связи можно получать данные например зная только id из одной таблицы которая имеет связь с второй, вторая с третьей и четвёртой из которых получить доступ к пятой по определённому отбору. Тебе с твоим ущербным мозгом никогда такой запрос не составить, а моя ORMка легко это сделает.

12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий