Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jrean's avatar

Test attributes/columns existence

Hi,

Lets say I take the App\User model and I create a User instance. I would like to know if the model table has a column named foo. Better, I would like know if the model has a foo attribute and so the table a foo column.

How could I achieve this the clean way?

I writing a small package where users should add one column to the App\User model. Before running a certain method of the package I perform a quick check to see if the User instance has that column. If no I will throw an Exception.

Until now the only solution I found is $user->getAttributes() which return an array of the existing attributes. Then I can perform a search in the array to check if the mandatory attributes exists.

Thank you :)

0 likes
11 replies
loshMiS's avatar

@jrean Well you if that column cannot be null, then you can simply check it like this

if (is_null($user->column_name)) ...

If attribute doesn't exist, null will be returned. However, if that column is nullable, then this won't work. Instead, I would do add a method inside User model to check if attribute exist, like this:

public function hasAttribute($attr)
{
    return array_key_exists($attr, $this->attributes);
}
5 likes
jrean's avatar
jrean
OP
Best Answer
Level 8

Thank you @loshMiS.

I managed it with :

Schema::hasColumn($model->getTable(), $column);
13 likes
ValsiS's avatar

A solution I've found is to use Model's getAttributeValue('attribute'). Be careful that this method returns null if no such attribute exists.

Cyrille37's avatar

There is a performance problem with Schema::hasColumn, it make a database query at each call. It could be a big problem when many calls occured.

3 likes
Cyrille37's avatar

the solution like

public function hasAttribute($attr)
{
    return array_key_exists($attr, $this->attributes);
}

could be missing a call to Model::hasGetMutator().

3 likes
drubie87's avatar

I have to admit, this would be a really great feature.

Eloquent should allow you to access a singleton of the Table Scheme out of the box and just save everyone a lot of time. You only have one Table Scheme per each Eloquent model. Each eloquent model should only have one 'table_name' as well.

So allowing the developer to fetch column names with a static call, without having to "new" up an eloquent model makes perfect sense.

Now, we can manually do this by creating a singleton in one of our classes and then calling DBAL. Just seems Eloquent could easily do this for everyone. And us PHP developers are willing to add it does not have to take any time or effort on Taylor Otwell's part.

Also I am petty sure would be a very small amount of code that would be fairly easy to maintain.

Oh well.

drubie87's avatar

This was bugging me so I created a trait that will add this function to any model:

For example if you have a simple model:

// Example mode
class SaleOrder extends Model
{
    // Add the trait
    use HasSchemaAccessors;

    // All fields are assignable except the id
    protected $guarded = ['id'];
}

Then you add this class to your project. Make sure the folder matches its namespace:

namespace App\Models\Eloquent\Traits;

use Illuminate\Support\Facades\Schema;

trait HasSchemaAccessors {
    public static $schemaInstance;
    public static $schemaColumnNames;
    public static $schemaTableName;

    /**
     * @return Illuminate\Database\Eloquent\Model
     * Returns singleton of model
     */
    protected static function schemaInstance() {
        if(empty(static::$schemaInstance)) {
            static::$schemaInstance = new static;
        }
        return static::$schemaInstance;
    }

    /**
     * @return string
     * Returns the table name for a given model
     */
    public static function getSchemaTableName() {
        if(empty(static::$schemaTableName)) {
            static::$schemaTableName = static::schemaInstance()->getTable();
        }
        return static::$schemaTableName;
    }

    /**
     * @return array
     * Fetches column names from the database schema
     */
    public static function getSchemaColumnNames() {
        if(empty(static::$schemaColumnNames)) {
            static::$schemaColumnNames = Schema::getColumnListing(static::getSchemaTableName());
        }
        return static::$schemaColumnNames;
    }

    /**
     * @param $name
     * @return bool
     */
    public static function schemaHasColumn($name) {
        return in_array( $name, static::getSchemaColumnNames() );
    }
}

Now let's say you are in a Controller and you want to know if a column exists in the sale order table all you need to do is this:

/**
 * index
 *
 * @return \Illuminate\Http\Response
 */
public function index(Request $request) {
    ...
    $columns = [Array of column names]
    ...
    foreach ($columns as $column) {
        if(SaleOrder::schemaHasColumn($column)) {
            dump( "Sale Order table DOES have the column '$column'" );
        }
    }
}

Every time you call Illuminate\Support\Facades\Schema::getColumnListing Or when you call Illuminate\Support\Facades\Schema::hasColumnName($tableName, $columnName)

Laravel just passes it on to Doctrine DBAL Schema object which then queries your database. This is the safest way to get column names, as even if the table is empty it will still return valid results. However if you do it from within a looping structure, you might accidentally create many, many requests to your database.

So.... I had to get this info from within a looping structure which is why I made this code.

I hope someone sees it and feels it is helpful.

4 likes

Please or to participate in this conversation.