Reputation: 424
After instantiating a model class that extends Laravel's Eloquent Model class, is there a way to determine if the property/attribute maps to the table, and therefore can be saved to the table?
For example, I have a table announcements
with columns id
, text
and "created_by".
How can I know created_by
is an attribute and will be saved if set?
$announcement = new Announcement();
isset($announcement->created_by)
understandably returns false if I haven't explicitly set the value yet. I have tried various functions inherited from the Eloquent model class, but so far none have worked. I'm looking for something like:
$announcement->doesThisMapToMyTable('created_by')
that returns true whether or not $announcement->created_by
has been set.
Upvotes: 22
Views: 77137
Reputation: 378
I realise this is very old but there is an even simpler answer that doesn't require querying the columns of the table on which the model is based.
If you are using standard timestamp columns in the models where you use them, you can use the following to determine if the 'created_at' column exists:
$model->usesTimestamps();
If you are using a non-standard name for the created column, you would need to additionally get the name of that column using:
$model->getCreatedAtColumn();
Upvotes: 0
Reputation: 3299
Rather than writing your own lookup into the database internals, you can just use the Schema
facade to look up the columns:
use Illuminate\Support\Facades\Schema;
$announcement = new Announcement();
$column_names = Schema::getColumnListing($announcement->getTable());
if (in_array('created_by', $column_names)) {
// whatever you need
}
Alternatively, as early as Laravel 4 there's the hasColumn()
check:
use Illuminate\Support\Facades\Schema;
$announcement = new Announcement();
if (Schema::hasColumn($announcement->getTable(), 'created_by')) {
// whatever you need
}
Upvotes: 14
Reputation: 1151
Laravel 5.4
I used Leiths answer to create generic helper method, which automatically maps JS-object to Laravel model (and basically ignores those properties which are not part of model, thus avoiding QueryBuilder error messages for undefined columns). Additionally contains simple createOrEdit -approach (even though doesn't have "does ID exist?" -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;
}
Upvotes: 0
Reputation: 488
For Laravel 5.4:
$hasCreatedAt = \Schema::hasColumn(app(Model::class)->getTable(), 'created_at');
if($hasCreatedAt == true) {
...
}
Upvotes: 7
Reputation: 87789
If your model is filled with data, you can:
$announcement = Announcement::find(1);
$attributes = $announcement->getAttributes();
isset($attributes['created_by']);
For empty models (new Models), unfortunately you will have to get the columns using a small hack. Add this method to your 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;
}
}
Extend your model from it:
class Announcement extends BaseModel {
}
Then you will be able to:
$columns = $announcement->getAllColumnsNames();
isset($columns['created_by']);
Upvotes: 37
Reputation: 90
I used to !empty($announcement->created_by)
and it's work great for my
Upvotes: -2