Расширение аксессуаров и мутаторов в Laravel

Я пытаюсь разработать небольшое приложение на Laravel 5.5, где я сделал abstract model, который расширяет Laravel eloquent model примерно так:

<?php

use Illuminate\Database\Eloquent\Model;

class AbstractModel extends Model
{


}

Теперь просто для общего соглашения я устанавливаю соединение с базой данных для этой модели:

<?php

use Illuminate\Database\Eloquent\Model;

class AbstractModel extends Model
{
    /**
     *  Defining connection for database
     *
     * @var string
     **/
    protected $connection='mysql';

}

И я создал свою собственную модель, которая расширяет этот abstract class:

<?php

use Illuminate\Database\Eloquent\SoftDeletes;

class Posts extends AbstractModel
{
    use SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'unique_id', 'title', 'contents'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'id'
    ];

}

Определив это по умолчанию, мы узнаем, что он будет иметь соединение с базой данных mysql, аналогично fillable определены для массового назначения. Аналогичным образом я хочу создать одну переменную encrypt, которая будет encrypt и decrypt данными из базы данных, поэтому для этого я добавил accessor и mutator в свой encrypt variable внутри моей модели:

<?php

use Illuminate\Database\Eloquent\SoftDeletes;

class Posts extends AbstractModel
{
    use SoftDeletes;

    /**
     * The attributes that will have encryption.
     *
     * @var array
     */
    protected $encryption = ['unique_id', 'title', 'contents'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'unique_id', 'title', 'contents'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'id'
    ];

}

и настроил его обратно в моем abstract model:

<?php

use Illuminate\Database\Eloquent\Model;

class AbstractModel extends Model
{
    /**
     *  Defining connection for database
     *
     * @var string
     **/
    protected $connection='mysql';

    /**
     *  Defining encryption
     *
     * @var array
     **/
    protected $encryption = [];

    public function setAttributes()
    {
        foreach ($this->encryption as $attributes)
        {
            $this->attributes[$attributes] = Crypt::encryptString($this->attributes[$attributes]);
        }
    }

    public function getAttributes()
    {
        foreach ($this->encryption as $attributes)
        {
            $this->attributes[$attributes] = Crypt::decryptString($this->attributes[$attributes]);
        }
    }
}

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

Более того, я хотел бы иметь случай использования, когда я шифрую эти поля, также их метод доступа к атрибутам или мутатор вызывается внутри их собственной модели, например:

<?php

use Illuminate\Database\Eloquent\SoftDeletes;

class Posts extends AbstractModel
{
    use SoftDeletes;

    /**
     * The attributes that will have encryption.
     *
     * @var array
     */
    protected $encryption = ['unique_id', 'title', 'contents'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'unique_id', 'title', 'contents'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'id'
    ];

    public function setTitleAttributes($value)
    {
        return ucfirst($value);
    }

    public function getTitleAttributes($value)
    {
        return ucfirst($value)
    }

}

Любые отзывы и комментарии приветствуются. Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
1 151
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, модель Eloquent имеет методы setAttribute() и getAttribute(), а не setAttributes() и getAttributes().

Во-вторых, для такой ситуации. Я бы предпочел Мероприятие Eloquent. Потому что методы setAttribute() или getAttribute() будут активированы только при динамическом доступе к атрибуту, например: $post->title.

Вы можете зашифровать атрибуты события saving. И расшифруйте его обратно с помощью события retrieved.

<?php

namespace App;

use Illuminate\Support\Facades\Crypt;
use Illuminate\Database\Eloquent\Model;

abstract class AbstractModel extends Model
{
    protected $connection = 'mysql';

    protected $encryption = [];

    protected static function boot()
    {
        parent::boot();

        // When being retrieved, decrypt the attributes.
        static::retrieved(function ($instance) {
            foreach ($instance->encryption as $encryptedKey) {
                $instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
            }
        });

        // When saving (could be create or update) the modal, encrypt the attributes.
        static::saving(function ($instance) {
            foreach ($instance->encryption as $encryptedKey) {
                $instance->attributes[$encryptedKey] = Crypt::encryptString($instance->attributes[$encryptedKey]);
            }
        });

        // Once it's saved, decrypt it back so it's still readble.
        static::saved(function ($instance) {
            foreach ($instance->encryption as $encryptedKey) {
                $instance->attributes[$encryptedKey] = Crypt::decryptString($instance->attributes[$encryptedKey]);
            }
        });
    }
}

Когда вы решили использовать этот подход, не отменяйте оба метода setAttribute() и getAttribute(). Поскольку он, скорее всего, дважды зашифрует / расшифрует атрибуты.

Кроме того, это должны быть setTitleAttribute() и getTitleAttribute() - в единственном числе. А на setTitleAttribute() вы должны изменить атрибут title; не возвращает предполагаемое значение. Я также не вижу смысла использовать title с заглавной буквы, поскольку он все равно будет зашифрован.

<?php

namespace App;

class Post extends Model
{
    protected $encryption = ['unique_id', 'title', 'contents'];

    protected $fillable = ['unique_id', 'title', 'contents'];

    // Expected to mutate the title attribute.
    public function setTitleAttribute($value)
    {
        $this->attributes['title'] = ucfirst($value);
    }

    public function getTitleAttribute($value)
    {
        return ucfirst($value);
    }
}

Надеюсь, это даст вам некоторые идеи.

Привет, спасибо за обновление, я вижу, что все мои значения шифруются, но я получаю ошибку при получении данных Illuminate\Contracts\Encryption\DecryptException with message 'The payload is invalid.'

Nitish Kumar 11.03.2018 05:08

Но когда я делаю $posts = App\Posts::find(3); Illuminate\Support\Facades\Crypt::decryptString($posts->name‌​); в tinker, я получаю соответствующие результаты.

Nitish Kumar 11.03.2018 05:22

Я не могу точно сказать, что происходит. Необходимо видеть ваш код как в классах AbstractModel, так и в Post.

Risan Bagja Pradana 11.03.2018 06:28

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

Nitish Kumar 11.03.2018 08:07

@NitishKumar Я решил попробовать это самостоятельно, используя Laravel 5.5 с базой данных sqlite. На моей машине все работает нормально. Проверьте код здесь: gist.github.com/risan/99d1cf2b71c0fa754d01ad45227b4697

Risan Bagja Pradana 11.03.2018 12:15

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

Nitish Kumar 11.03.2018 14:04

Другие вопросы по теме