Home » Php » Autogenerate model classes with Laravel 4 (aka using an existing database with L4)

Autogenerate model classes with Laravel 4 (aka using an existing database with L4)

Posted by: admin November 29, 2017 Leave a comment

Questions:

I’ve designed my database in MySQL Workbench, and have all my foreign keys setup, etc.

I’m wanting to use this DB schema with Laravel 4, however from the docs there is no word of any sort of ability to work with an existing set of database tables. From my understanding, other frameworks such as Cake with its ‘Baking’ allow you to automatically generate your model classes based on the tables already in your database.

I’ve looked around everywhere and cant see anything about this at all for Laravel 4. The closest thing I’ve found is Jeffrey Way’s Generator package for artisan, however this only creates the base model, and doesn’t detect established foreign key relationships.

Is this even possible with Laravel 4 or am I going to have to just do it all manually?

Answers:

The good news is that Antonio just finished his MySQL WorkBench to Eloquent ORM converter
This is a beautiful solution but comes a way to late for me but may help you a lot.

Update: The link isn’t working in the moment. The wabpage says “We are redesigning things, will be back soon!”. I allready sent antonio an email asking him, when this service will be available again.

Antonio said that it’ll be back but there is no estimated time of arrival. We have to wait..

Questions:
Answers:

cakePHP does a great job at fleshing out your whole project from the DB schema already in place. Laravel currently does not support anything like this. One of the minor features still holding me back from adopting laravel.

Questions:
Answers:

Hmm I had the same issue and I wrote a little script myself which generates base classes and solves the foreign key issues. It’s a basic solution and only determines “hasOne” relations, which you might have to change to hasMany later on. I used a Controller and build my code Template in a view:

Controller:

namespace Admin;

/**
 * just a quick helper to generate model classes
 * from mysql to Eloquent style ones..
 * @author Mario
 */
class ModelController extends \BaseController {

    /**
     * save Classes in folder of choice
     *
     * @return void
     */
    public function create($folder)
    {
        $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'UR_SCHEMA'";
        $tables = \DB::select($sql); 

        $sql2 = "select * from information_schema.`KEY_COLUMN_USAGE` where constraint_schema = 'UR_SCHEMA' order by table_name";
        $keys = \DB::select($sql2);
        $meta = $this->sortOutMetadata($keys);

        foreach ($tables as $table) {
            $metaData = null;
            if(!empty($meta[$table->TABLE_NAME])){
                $metaData = $meta[$table->TABLE_NAME];
            }

            $code = \View::make('model.start', array('table' => $table, 'meta' => $metaData))->render();
            file_put_contents($folder.DIRECTORY_SEPARATOR.ucfirst(camel_case($table->TABLE_NAME).'.php'), $code);
        }

    }

    /**
     * provide structure indexed by table
     * 
     * @param type $keys
     * @return type
     */
    private function sortOutMetadata($keys)
    {
        $return = array();

        foreach ($keys as $key) {

            if ($key->CONSTRAINT_NAME == 'PRIMARY') {
                $return[$key->TABLE_NAME]['pk'] = $key->COLUMN_NAME;
            } elseif (!empty($key->REFERENCED_TABLE_NAME)) {
                //one way
                $return[$key->TABLE_NAME]['fk'][] = array('column' => $key->COLUMN_NAME,
                    'refColumn' => $key->REFERENCED_COLUMN_NAME,
                    'refTable' => $key->REFERENCED_TABLE_NAME,);
                //and the other
                $return[$key->REFERENCED_TABLE_NAME]['fk'][] = array('column' => $key->REFERENCED_COLUMN_NAME,
                    'refColumn' => $key->COLUMN_NAME,
                    'refTable' => $key->TABLE_NAME,);
            }
        }

        return $return;
    }
}

My view Template (pretty much my Class Template)

<?php echo '<?php'; ?>


namespace Model\Base;

use Model\Model;

class <?php echo ucfirst(camel_case($table->TABLE_NAME));?> extends Model {

    /**
     * @var String
     */
    protected $table = '<?php echo $table->TABLE_NAME;?>';
    <?php if (isset($meta['pk'])):?>
    /**
     * @var String
     */
    protected $primaryKey = '<?php echo $meta['pk'];?>';


    /**
     * attributes not writable from outside
     * @var mixed
     */
    protected $guarded = array('<?php echo $meta['pk'];?>');
    <?php endif;?>
    /**
     * Timestamps we dont want here
     * @var Boolean
     */
    public $timestamps = false;

    <?php if (isset($meta['fk'])):?>
        <?php foreach($meta['fk'] as $keys):?>
    /**
     * @return HasOne
     */
    public function <?php echo camel_case($keys['refTable']);?>()
    {
        return $this->hasOne('Model\<?php echo ucfirst(camel_case($keys['refTable']));?>', '<?php echo $keys['refColumn'];?>', '<?php echo $keys['column'];?>');
    }
        <?php endforeach;?>
    <?php endif;?>

}

Then Simply generate your base classes by giving it the folder: (from wherever you prefer)

$controller = new \Admin\ModelController();
$controller->create(__DIR__ . DIRECTORY_SEPARATOR . 'tmpModel');

This gave me some decent way to get my base classes Auto generated the way I needed. Remember you got to be able to see the information_schema schema with your db user.

Hope this helps