Атрибуты модели Laravel Eloquent

После создания экземпляра класса модели, который расширяет класс Laravel Eloquent Model, существует ли способ определить, сопоставляется ли свойство/атрибут с таблицей и, следовательно, может быть сохранено в таблице?

Например, у меня есть табличные announcements с id столбцов, text и "created_by".

Как я могу узнать, что created_by является атрибутом и будет сохранен, если он установлен?

$announcement = new Announcement();

isset($announcement->created_by) понятно возвращает false, если я еще не задал значение еще раз. Я пробовал различные функции, унаследованные от класса модели Eloquent, но пока никто не работал. Я ищу что-то вроде:

$announcement->doesThisMapToMyTable('created_by') который возвращает true, был ли установлен $announcement->created_by.

Ответы

Ответ 1

Для Laravel 5.4:

$hasCreatedAt = \Schema::hasColumn(app(Model::class)->getTable(), 'created_at');

    if($hasCreatedAt == true) {
       ...
    }

Ответ 2

Если ваша модель заполнена данными, вы можете:

$announcement = Announcement::find(1);

$attributes = $announcement->getAttributes();

isset($attributes['created_by']);

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

<?php

class BaseModel extends Eloquent {

    public function getAllColumnsNames()
    {
        switch (DB::connection()->getConfig('driver')) {
            case 'pgsql':
                $query = "SELECT column_name FROM information_schema.columns WHERE table_name = '".$this->getTable()."'";
                $column_name = 'column_name';
                $reverse = true;
                break;

            case 'mysql':
                $query = 'SHOW COLUMNS FROM '.$this->getTable();
                $column_name = 'Field';
                $reverse = false;
                break;

            case 'sqlsrv':
                $parts = explode('.', $this->getTable());
                $num = (count($parts) - 1);
                $table = $parts[$num];
                $query = "SELECT column_name FROM ".DB::connection()->getConfig('database').".INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = N'".$table."'";
                $column_name = 'column_name';
                $reverse = false;
                break;

            default: 
                $error = 'Database driver not supported: '.DB::connection()->getConfig('driver');
                throw new Exception($error);
                break;
        }

        $columns = array();

        foreach(DB::select($query) as $column)
        {
            $columns[$column->$column_name] = $column->$column_name; // setting the column name as key too
        }

        if($reverse)
        {
            $columns = array_reverse($columns);
        }

        return $columns;
    }

}

Расширьте свою модель:

class Announcement extends BaseModel {

}

Тогда вы сможете:

$columns = $announcement->getAllColumnsNames();

isset($columns['created_by']);

Ответ 3

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

use Illuminate\Support\Facades\Schema;

$announcement = new Announcement();
$column_names = Schema::getColumnListing($announcement->getTable());
if (isset($column_names['created_by'])) {
  // whatever you need
}

Ответ 4

Ларавел 5.4

Я использовал Leiths для создания универсального вспомогательного метода, который автоматически сопоставляет JS-объект с моделью Laravel (и в основном игнорирует те свойства, которые не являются частью модели, что позволяет избежать сообщений об ошибках QueryBuilder для неопределенных столбцов). Дополнительно содержит простой createOrEdit -approach (хотя у него нет "существует ли идентификатор?" -validation):

    public function store(Request $request) {
        if($request->input("club")) {
            $club = \App\Club::find($request->input("club")["id"]);
        } else {
            $club = new \App\Club;
        }
        $club = self::mapModel($request->input("club"), $club);
        $club->save();
    }
    
    public function mapModel($input,$model) {
        $columns = Schema::getColumnListing($model->getTable());
        foreach ($columns as $i => $key) {
            if($input[$key]) {
                $model->{$key} = $input[$key];
            }
        }
        return $model;
    }

Ответ 5

Я использовал для !empty($announcement->created_by) и он отлично работает для моего