mattcrowe mattcrowe - 3 months ago 22
PHP Question

Laravel Eloquent Model Attributes

After instantiating a model class that extends Laravel's Eloquent Model class, is there 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 a attribute and will save 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.

Answer

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']);