Après avoir instancié une classe de modèle qui étend la classe de modèle Eloquent de Laravel, existe-t-il un moyen de déterminer si la propriété/l'attribut est mappé sur la table et peut donc être enregistré dans la table?
Par exemple, j'ai une table announcements
avec les colonnes id
, text
et "created_by".
Comment savoir que created_by
est un attribut et sera sauvegardé s'il est défini?
$announcement = new Announcement();
isset($announcement->created_by)
renvoie naturellement false si je n'ai pas encore explicitement défini la valeur. J'ai essayé diverses fonctions héritées de la classe de modèles Eloquent, mais aucune n'a fonctionné jusqu'à présent. Je cherche quelque chose comme:
$announcement->doesThisMapToMyTable('created_by')
qui renvoie true, que $announcement->created_by
ait été défini ou non.
Pour Laravel 5.4:
$hasCreatedAt = \Schema::hasColumn(app(Model::class)->getTable(), 'created_at');
if($hasCreatedAt == true) {
...
}
Si votre modèle est rempli de données, vous pouvez:
$announcement = Announcement::find(1);
$attributes = $announcement->getAttributes();
isset($attributes['created_by']);
Pour les modèles vides (nouveaux modèles), vous devrez malheureusement obtenir les colonnes avec un petit hack. Ajoutez cette méthode à votre modèle de base:
<?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;
}
}
Étendez votre modèle à partir de celui-ci:
class Announcement extends BaseModel {
}
Ensuite, vous pourrez:
$columns = $announcement->getAllColumnsNames();
isset($columns['created_by']);
Plutôt que d'écrire votre propre recherche dans les éléments internes de la base de données, vous pouvez simplement utiliser la façade Schema
pour rechercher les colonnes:
use Illuminate\Support\Facades\Schema;
$announcement = new Announcement();
$column_names = Schema::getColumnListing($announcement->getTable());
if (isset($column_names['created_by'])) {
// whatever you need
}
Laravel 5.4
J'ai utilisé Leiths answer pour créer une méthode d'assistance générique, qui mappe automatiquement l'objet JS au modèle de Laravel (et ignore essentiellement les propriétés qui ne font pas partie du modèle, évitant ainsi les messages d'erreur QueryBuilder pour les colonnes non définies). Contient en outre une méthode simple createOrEdit (même si elle n'a pas la valeur "l'ID existe-t-il?"):
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;
}
!empty($announcement->created_by)
et j’ai travaillé très bien pour mon