25

How can I get column names of a table in an array or object in Laravel 4, using Schema, DB, or Eloquent?

It seems that I can't find a ready to use function, maybe you have some custom implementations.

miken32
  • 42,008
  • 16
  • 111
  • 154
Centurion
  • 5,169
  • 6
  • 28
  • 47
  • You might have to do a [raw query](http://stackoverflow.com/questions/4165195/mysql-query-to-get-column-names) – UltraInstinct Nov 13 '13 at 11:20
  • Note that solutions below may change when Laravel hits 4.1, as it removed Doctrine (and thus Doctrine's Schema classes) as a dependency – fideloper Nov 13 '13 at 13:55
  • Can't believe Laravel does not already provides this feature, CodeIgniter have it. Where I can submit a request for this functionality in Laravel ? – digfish May 20 '14 at 11:01

8 Answers8

51

New Answer

At the time I gave this answer Laravel hadn't a way to do this directly, but now you can just:

$columns = Schema::getColumnListing('users');

Old Answer

Using attributes won't work because if you do

$model = new ModelName;

You have no attributes set to that model and you'll get nothing.

Then there is still no real option for that, so I had to go down to the database level and this is my 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->table."'";
                $column_name = 'column_name';
                $reverse = true;
                break;

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

            case 'sqlsrv':
                $parts = explode('.', $this->table);
                $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;
        }

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

        return $columns;
    }

}

Use it doing:

$model = User::find(1);

dd( $model->getAllColumnsNames() );
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
18

You may try Schema::getColumnListing('tablename'):

$columns = Schema::getColumnListing('users'); // users table
dd($columns); // dump the result and die

Result would be something like this depending on your table:

array (size=12)
  0 => string 'id' (length=2)
  1 => string 'role_id' (length=7)
  2 => string 'first_name' (length=10)
  3 => string 'last_name' (length=9)
  4 => string 'email' (length=5)
  5 => string 'username' (length=8)
  6 => string 'password' (length=8)
  7 => string 'remember_token' (length=14)
  8 => string 'bio' (length=3)
  9 => string 'created_at' (length=10)
  10 => string 'updated_at' (length=10)
  11 => string 'deleted_at' (length=10)
The Alpha
  • 143,660
  • 29
  • 287
  • 307
15

You can dig down into DB's Doctrine instance.

$columns = DB::connection()
  ->getDoctrineSchemaManager()
  ->listTableColumns('table');

foreach($columns as $column) {
  print $column->getName();
  print $column->getType()->getName();
  print $column->getDefault();
  print $column->getLength();
}

edit: Doctrine is no longer (as of L4.1) installed by default (it's a 'suggested' rather than 'required' package), but can be added to your composer.json as doctrine/dbal to retain this functionality.

ceejayoz
  • 176,543
  • 40
  • 303
  • 368
  • Tried that too, but it doesn't work for SQL server: Class 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver' not found. – Antonio Carlos Ribeiro Nov 13 '13 at 13:06
  • @AntonioCarlosRibeiro I've never used Microsoft SQL Server with Doctrine, so you're on your own there. A raw query is probably your best bet if that's your underlying tech. The OP is using MySQL, though. – ceejayoz Nov 13 '13 at 13:08
  • 1
    This solution works, one thing to mention, if the table contains enum type , it throws this exception. Unknown database type enum requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it. – Centurion Nov 13 '13 at 13:36
  • @Centurion Laravel doesn't technically support enums at all - you can't create one via the Schema manager. – ceejayoz Nov 13 '13 at 14:42
  • 3
    @ceejayoz based on docs i created one, http://laravel.com/docs/schema, $table->enum('choices', array('foo', 'bar')); ENUM equivalent to the table, the truth is that Doctrine is not supporting them. – Centurion Nov 13 '13 at 14:45
  • Huh, I don't remember that being there for 4.0. Maybe it's a 4.1 thing? Neato. Related issue: https://github.com/laravel/framework/pull/2133 – ceejayoz Nov 13 '13 at 15:06
1

I think there's a couple different options, if you are using an Eloquent model, you can look at the getAccessibleAttributes() method, which in theory would give you all the columns of a model consider Eloquent seems them as properties.

For example, you'd be able to do something like this for your users table on a User Eloquent model.

$user = // Retrieve your User model.
$columns = User->getAccessibleAttributes();

Another Eloquent method to look at that's similar, but doesn't have the 'accessibility' requirement is the attributesToArray() method. The returned array of which should have your columns as a key. Then you can use the PHP function array_keys() to build an array of the keys, which would be your columns.

$user = // Retrieve your User model.
$columns = array_keys(User::attributesToArray());
Sajan Parikh
  • 4,668
  • 3
  • 25
  • 28
1

I know it might not be the answer for everyone, but maybe you can grab one record, and get all keys of the data. Ex.

array_keys(User::first()->toArray());
windmaomao
  • 7,120
  • 2
  • 32
  • 36
0

If you have a Model instance you can retrieve like following:

    $table_name = $model->getTable();
    $connection = $model->getConnection();
    $schemaBulder = $connection->getSchemaBuilder();

    $columns_array = $schemaBulder->getColumnListing($table_name);

works for Laravel 5

1210mk2
  • 31
  • 2
-1

You also can try this:

abstract class BaseModel extends Eloquent {

public function getColumnsNames()
{
    $connection = DB::connection();
    $connection->getSchemaBuilder();

    $table   = $connection->getTablePrefix() . $this->table;
    $grammar = $connection->getSchemaGrammar();
    $results = $connection->select($grammar->compileColumnExists(), array($connection->getDatabaseName(), $table));

    return $connection->getPostProcessor()->processColumnListing($results);
}
}
gvsrepins
  • 1,687
  • 2
  • 17
  • 20
  • This isn't working for me. The debugger says: $grammar->compileColumnExists($table) = "select column_name from information_schema.columns where table_schema = ? and table_name = ?" It's not substituting the values in the query when it compiles...what am I missing? – John Corry Jun 17 '14 at 17:59
  • Can you past in somewhere a example of how are you using it? The idea here is to use this only in your model classes. Wich they will have the table property setted. Also this working for me in a 4.1.* laravel app, may this have to change in more recent versions. – gvsrepins Jun 18 '14 at 19:18
  • I update the code making the BaseModel abscract, to force a implementation. – gvsrepins Jun 18 '14 at 19:19
-1

I use SQL Server and the Schema way worked for me:

$columns = array_keys(Schema::getConnection()
->getDoctrineSchemaManager()
->listTableColumns($yourModel->getTable()) );
Adam Rodriguez
  • 1,850
  • 1
  • 12
  • 15