Intereting Posts
При использовании PHP включить странный верхний край Как установить флажок, если это значение находится в БАЗЕ ДАННЫХ. PHP Как отправить содержимое внешнего файла на принтер? Как проверить, что аукцион закончен – Обработка Triggered PHP Удалить дубликаты данных в текстовом файле с помощью php Как идентификатор поля ввода может быть прочитан PHP? Модель Codeigniter Неопределенное свойство Обновить DOM с помощью jquery после вызова AJAX Порядок запросов MySQL по «наиболее заполненным полям» PHPMailer, сохранить 1 SMTP-соединение с другим получателем по контенту электронной почты Вставка данных в таблицу (вставка mysqli) Как я могу взорвать массив, пропуская пустые элементы массива? Как избежать строки из PHP для javascript? Отредактировано все записи в базе данных Длительный фоновый скрипт PHP блокирует другие страницы PHP до тех пор, пока он не будет завершен

Как отличить красноречивые параметры?

У меня есть следующие Eloquent Models с отношениями:

class Lead extends Model { public function contacts() { return $this->belongsToMany('App\Contact') ->withPivot('is_primary'); } } class Contact extends Model { public function leads() { return $this->belongsToMany('App\Lead') ->withPivot('is_primary'); } } 

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

 { "id": 565, "leads": [ { "id": 349, "pivot": { "contact_id": "565", "lead_id": "349", "is_primary": "0" } } ] } 

Есть ли способ is_primary к этому логическому? Я попытался добавить его в массив $casts обеих моделей, но это ничего не изменило.

Related of "Как отличить красноречивые параметры?"

Поскольку это атрибут в сводной таблице, использование атрибута $casts не будет работать ни в модели Lead ни в Contact .

Однако одна вещь, которую вы можете попробовать, – использовать пользовательскую модель Pivot с определенным атрибутом $casts . Здесь представлена ​​документация по пользовательским моделям. В принципе, вы создаете новую модель Pivot с настройками, а затем обновляете модели Lead и Contact чтобы использовать эту настраиваемую модель Pivot вместо базовой.

Во-первых, создайте свою собственную модель Pivot которая расширяет базовую модель Pivot :

 <?php namespace App; use Illuminate\Database\Eloquent\Relations\Pivot; class PrimaryPivot extends Pivot { protected $casts = ['is_primary' => 'boolean']; } 

Теперь переопределите метод newPivot() в моделях Lead и Contact :

 class Lead extends Model { public function newPivot(Model $parent, array $attributes, $table, $exists) { return new \App\PrimaryPivot($parent, $attributes, $table, $exists); } } class Contact extends Model { public function newPivot(Model $parent, array $attributes, $table, $exists) { return new \App\PrimaryPivot($parent, $attributes, $table, $exists); } } 

В Laravel 5.4.14 этот вопрос был решен. Вы можете определить настраиваемую сводную модель и сообщить своим отношениям использовать эту настраиваемую модель, когда они определены. См. Документацию в разделе « Определение пользовательских моделей промежуточных таблиц» .

Для этого вам нужно создать класс для представления сводной таблицы и расширить класс Illuminate\Database\Eloquent\Relations\Pivot . В этом классе вы можете определить свойство $casts .

 <?php namespace App; use Illuminate\Database\Eloquent\Relations\Pivot; class CustomPivot extends Pivot { protected $casts = [ 'is_primary' => 'boolean' ]; } 

Затем вы можете использовать метод using в отношении BelongsToMany чтобы сообщить Laravel, что вы хотите, чтобы ваш стержень использовал указанную настраиваемую сводную модель.

 <?php namespace App; use Illuminate\Database\Eloquent\Model; class Lead extends Model { public function contacts() { return $this->belongsToMany('App\Contact')->using('App\CustomPivot'); } } 

Теперь, всякий раз, когда вы получаете доступ к своей оси с помощью ->pivot , вы должны обнаружить, что это экземпляр вашего настраиваемого класса pivot, и свойство $casts должно быть выполнено.


Обновление 1 июня 2017 года

Вопрос, поднятый в комментариях @cdwyer относительно обновления сводной таблицы с использованием обычных методов sync / attach / save как ожидается, будет зафиксирован в Laravel 5.5, который должен быть выпущен в следующем месяце (июль 2017 года).

См. Комментарий Тейлора в нижней части этого отчета об ошибке и его фиксации, исправляя проблему здесь .

Хорошие новости! Tylor уже исправил эту ошибку:

https://github.com/laravel/framework/issues/10533

В Laravel 5.1 или выше вы можете использовать точечную нотацию для поворота:

 protected $casts = [ 'id' => 'integer', 'courses.pivot.course_id' => 'integer', 'courses.pivot.active' => 'boolean' ] 

Ответ, предоставленный @patricus выше, является абсолютно правильным, однако, если вы , как я, вы также хотите извлечь из JSON-закодированных строк внутри сводной таблицы, тогда прочитайте дальше.

Проблема

Я считаю, что на этом этапе в Laravel есть ошибка. Проблема заключается в том, что при создании экземпляра модели поворота, он использует родной Осветите-модель setAttributes метод «скопировать» значения сводной таблицы звукозаписывающей к модели поворота.

Это отлично подходит для большинства атрибутов, но становится липким, когда он видит, что массив $casts содержит приведение в стиле JSON – он фактически выполняет двойное кодирование данных.

Решение

То, как я преодолел это, выглядит следующим образом:

1. Настройте свой собственный базовый класс Pivot, из которого можно расширить свои подклассы (подробнее об этом немного)

2. В новом базовом классе Pivot переопределите метод setAttribute , setAttribute строки, которые обрабатывают атрибуты JSON-castable

 class MyPivot extends Pivot { public function setAttribute($key, $value) { if ($this->hasSetMutator($key)) { $method = 'set'.studly_case($key).'Attribute'; return $this->{$method}($value); } elseif (in_array($key, $this->getDates()) && $value) { $value = $this->fromDateTime($value); } /* if ($this->isJsonCastable($key)) { $value = json_encode($value); } */ $this->attributes[$key] = $value; } } 

Это подчеркивает удаление isJsonCastable метода isJsonCastable , который вернет true для любых атрибутов, которые вы выбрали как json , array , object или collection в ваших подклассах свиста.

3. Создайте сводные подклассы, используя какое-то полезное соглашение об именах (я использую {PivotTable}Pivot например FeatureProductPivot)

4. В базовом классе модели измените / создайте свой метод newPivot переопределив что-то более полезное

Моя выглядит так:

 public function newPivot(Model $parent, array $attributes, $table, $exists) { $class = 'App\Models\\' . studly_case($table) . 'Pivot'; if ( class_exists( $class ) ) { return new $class($parent, $attributes, $table, $exists); } else { return parent::newPivot($parent, $attributes, $table, $exists); } } 

Затем просто убедитесь, что модели расширяются от базовой модели, и вы создаете «модели» сводной таблицы в соответствии с вашим соглашением об именах, и вы будете работать с JSON на столбцах сводной таблицы на выходе из БД!

NB: Это не было тщательно протестировано и может возникнуть проблемы с возвратом в БД.

Мне пришлось добавить дополнительные проверки, чтобы функции сохранения и загрузки работали правильно в Laravel 5.

 class BasePivot extends Pivot { private $loading = false; public function __construct(Model $parent, array $attributes, $table, $exists) { $this->loading = true; parent::__construct($parent, $attributes, $table, $exists); $this->loading = false; } public function setAttribute($key, $value) { // First we will check for the presence of a mutator for the set operation // which simply lets the developers tweak the attribute as it is set on // the model, such as "json_encoding" an listing of data for storage. if ($this->hasSetMutator($key)) { $method = 'set'.Str::studly($key).'Attribute'; return $this->{$method}($value); } // If an attribute is listed as a "date", we'll convert it from a DateTime // instance into a form proper for storage on the database tables using // the connection grammar's date format. We will auto set the values. elseif ($value && (in_array($key, $this->getDates()) || $this->isDateCastable($key))) { $value = $this->fromDateTime($value); } /** * @bug * BUG, double casting */ if (!$this->loading && $this->isJsonCastable($key) && ! is_null($value)) { $value = $this->asJson($value); } $this->attributes[$key] = $value; return $this; } }