Переделка проекта: я должен использовать первичные составные ключи и json для переводов с Laravel? - PullRequest
4 голосов
/ 04 мая 2020

Контекст

Я полностью переделываю веб-сайт (код и базу данных), используя Laravel 7 и Mysql.
Цель состоит в том, чтобы перестроить весь проект, максимально используя лучшие практики. .
В этом проекте у меня много таблиц базы данных и связей между ними, и я также работаю с большим количеством пользовательского содержимого.

Задача 1

В реляционной базе данных При разработке дизайна рекомендуется использовать composite primary keys, если вы точно знаете, что id бесполезен (например, сводные таблицы).
Но я знаю, что Laravel не обрабатывает composite primary keys для моделей и отношения, вы должны установить некоторые внешние пакеты или сделать это самостоятельно с наследованием Trait / Class.

Итак, мне интересно, стоит ли мне использовать composite primary keys, или мне следует придерживаться автоинкремента по умолчанию id вместе с composite unique key?

Чтобы показать пример что я имею в виду, мне нужно выбирать между идеей 1 или идеей 2, или, может быть, чем-то другим?

Идея 1: со стандартным первичным ключом

Schema::create('user_documents', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
    $table->foreignId('document_id')->constrained();
    $table->string('file_name', 50);
    $table->json('comments')->nullable();
    // [...] Maybe some more columns
    $table->timestamps();

    $table->unique(['user_id', 'document_id']);
});

Идея 2: со сложным первичным ключом

Schema::create('user_documents', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
    $table->foreignId('document_id')->constrained();
    $table->string('file_name', 50);
    $table->json('comments')->nullable();
    // [...] Maybe some more columns
    $table->timestamps();

    $table->primary(['user_id', 'document_id']);
});

Задача 2

Возможно, вы заметили, что я использовал тип json для столбца comments.
Это потому, что пользователь мог написать комментарий на одном или нескольких языках. когда он загружает файл.

Значения для этого столбца выглядят так:

{
    "en": "a comment in english",
    "fr": "a comment in french",
    "*": "the comment for all other languages"
}

Если он хочет, чтобы все видели один и тот же текст на любом языке, у нас могло бы быть это:

{
    "*": "the comment for all languages"
}

У меня много вещей, которые работают подобным образом для пользовательского многоязычного контента, и я подумал, что этот подход будет лучше, чем указание c таблиц для переводов.

Но я не уверен, что это хорошая практика использовать столько столбцов json, есть ли что лучше сделать для переводов?

1 Ответ

1 голос
/ 06 мая 2020

Вы поднимаете много хороших вопросов, на которые также нужно ответить. У нас нет точного контекста ваших «проблем», но вы дали нам немного информации, которая может быть полезна для понимания того, о чем вы просите.

Итак, вот мои два цента:

Задача 1

Вы указываете как на понятия composite primary keys, так и composite unique keys SQL, которые отлично подходят для работы с комбинированными клавишами, которые относятся к модели вашего приложения. Как указывалось вначале 4 года go (столько!) На это топи c, сегодня действительно нет никакого способа получить эту естественную работу от Eloquent. Но есть обходной путь, чтобы это работало замечательно.

Я бы предпочел использовать composite primary keys, чтобы убедиться, что база действительно равна solid и избежать ошибок при перемещении строк в базе данных. Я бы сказал, что это зависит от вас, с какой-то степенью терпимости в отношении потенциальных ошибок или пробелов, которые вы, возможно, забыли при разработке своего приложения.

Мне не очень нравится идея № 1, потому что в моем мнение, что нет чудесной и прагматичной причины иметь автоинкрементный ключ здесь. Я всегда держу в уме принцип "KISS" ("Делай это глупо просто"). SQL предлагает способ комбинирования ключей изначально (и он работает очень хорошо в общих целях), "зачем мне go с еще одним ключом, если он не подходит для действительно полезной функции моего приложения?"

Laravel сильно вырос, но постоянно обновляется и совершенствуется каждый месяц. Мне очень нравится этот фреймворк, но в нем всегда отсутствуют ценные вещи, и поэтому открытый исходный код так важен. Он предлагает какой-то способ создания Traits, Interface, Helpers для извлечения, обновления и поиска строк с помощью пары первичных ключей, как вы, возможно, знаете, поэтому не тратьте слишком много времени; просто убедитесь, что он соответствует вашим потребностям, и вы можете легко манипулировать вашей моделью через него. Создайте свою собственную черту HasCompositePrimaryKey, для которой вы можете определить новое свойство первичного ключа: protected $primaryKey = array('key1', 'key2'); (пожалуйста, отметьте этот ответ ).

Задача 2

Действительно я также подумайте, что json - лучший тип поля для обработки многоязыковых строковых значений. Последняя версия MySQL (8.0) внесла множество улучшений в поиск контента в JSON объектах , на которые вы, возможно, захотите взглянуть. Я бы тоже сохранил все строки в одной строке для нескольких языков, как вы делали это для своей таблицы comments. Это позволит вам легко извлекать, отображать и легко манипулировать контентом в соответствии с выбором языка вашего пользователя или посетителя. Вы можете сохранить двухбуквенный код iso lang в пользовательском сеансе cook ie и использовать его в своем шаблоне Blade, где его будет гораздо проще использовать: $comment[$user_lang_key], где $user_lang_key может быть получено из некоторого вида из Session::get('settings_lang_key').

Я действительно не знаю, какова цель отображения другого комментария ко «всем другим языкам», которые недоступны. Я бы предпочел использовать существующий язык в качестве запасного для моего приложения, например, engli sh, который часто используется и отображается для многих значений по умолчанию. Вам нужно просто отменить ключ lang сеанса до en, чтобы это работало везде. Использование какого-либо «псевдонима», такого как '*', может сделать это немного запутанным, и, возможно, вам потребуется предварительная проверка, чтобы правильно его использовать. Если вы хотите дать своему пользователю возможность отображать комментарии в том виде, в каком он хочет, как вы сказали в комментариях, я бы предпочел сохранить это значение настроек где-нибудь в вашей базе данных и использовать его для указания на выбранный язык.

Кроме того, в случае, если вам это нужно (поскольку пользователь вашего приложения может настроить некоторые варианты поведения вашего приложения), вот как я могу обработать многоязычный параметр, который он может создать в моем приложении для электронной коммерции:

{
    "fr": {
        "title": "Choix d'un T-Shirt",
        "fields": [
            {
                "label": "Taille de T-Shirt",
                "type": "single-choice",
                "choices": [
                    { "name": "S", "price": 10 },
                    { "name": "M", "price": 15 }
                ]
            },
            {
                "label": "Couleur",
                [...]
            }
        ]
    }, 
    "en": {
        "title": "T-Shirt Selection",
        "fields": [
            {
                "label": "T-Shirt Size",
                "type": "single-choice",
                "choices": [
                    { "name": "S", "price": 10 },
                    { "name": "M", "price": 15 }
                ]
            },
            {
                "label": "Color",
                [...]
            }
        ]
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...