4

So as the title says, how can I know if a field of a Model is a foreign key in Laravel ?

Supose I have a FK column called show_type_id and a model named Event and I want to know if there is a function that given the model class or model table and the named field returns true if it is or false if is not.

...
$model = Event:class; // or Event::getTable();
$isFK = isFK('show_type_id', $model);
...

Edit

Thanks to @piscator this is what is worked:

use Illuminate\Support\Facades\Schema;

function isFK(string $table, string $column): bool
{
    $fkColumns = Schema::getConnection()
        ->getDoctrineSchemaManager()
        ->listTableForeignKeys($table);

    $fkColumns = collect($fkColumns);

    return $fkColumns->map->getColumns()->flatten()->search($column) !== FALSE;

}
didix16
  • 83
  • 1
  • 10

2 Answers2

2

Try this, assuming your table name is "events":

Schema::getConnection()
    ->getDoctrineSchemaManager()
    ->listTableForeignKeys('events')

This will return the Doctrine\DBAL\Schema\ForeignKeyConstraint object.

With this data you could write the isFK method like this:

use Illuminate\Support\Facades\Schema;

function isFK(string $table, string $column): bool
{  
    $fkColumns = Schema::getConnection()
        ->getDoctrineSchemaManager()
        ->listTableForeignKeys($table);

    return collect($fkColumns)->map(function ($fkColumn) {
        return $fkColumn->getColumns();
    })->flatten()->contains($column);
}
piscator
  • 8,028
  • 5
  • 23
  • 32
  • Thanks for the answer! I'm gonna try this – didix16 Oct 05 '20 at 07:14
  • 1
    It's almost what I'm looking for but getColumns() on index 0 on array is just returning me one foriegn key... Here is what I changed: $fkColumns = Schema::getConnection() ->getDoctrineSchemaManager() ->listTableForeignKeys('events'); return collect($fkColumns)->map->getColumns()->flatten()->search($column); Thank you! – didix16 Oct 05 '20 at 07:31
  • 1
    Thanks, that's much better. I've fixed the answer. – piscator Oct 05 '20 at 08:24
  • 1
    This is great, should be apart of laravel core – Ken Feb 28 '22 at 18:29
1

I created this Trait to use with my migrations:

<?php 

namespace App\Traits;

use Illuminate\Support\Facades\Schema;


trait ChecksForeignKeys {
    /**
     * Check if a foreign key exists
     *
     * @param string $table
     * @param string $column
     * @param string $foreignTable
     * @param string $foreignColumn
     * @param string $connection
     * @return boolean
     */
    public function hasForegin($table, $column, $foreignTable, $foreignColumn, $connection = null) {

        // Get the foreign keys for the table
        $fkColumns = Schema::getConnection()
        ->getDoctrineSchemaManager()
        ->listTableForeignKeys($table);

        // Check if the foreign key exists
        foreach($fkColumns as $fkColumn) {            
            if($fkColumn->getLocalColumns()[0] == $column && $fkColumn->getForeignColumns()[0] == $foreignColumn && $fkColumn->getForeignTableName() == $foreignTable) {
                return true;
            }
        }

        return false;        
    }
}
Javis
  • 843
  • 1
  • 9
  • 16