2013-08-04 4 views
2

Я не уверен, что мне нужно сделать, чтобы получить динамические имена таблиц.Laravel 4: Динамические имена таблиц с помощью setTable()

Рассмотрим следующую модель (таблица 'тест' не существует):

<?php 

// app/models/Test.php 

class Test extends Eloquent { 

} 

, а затем, если я (таблица 'поля' существует):

<?php 

// app/routes.php 

$test = new \Test; 
$test->setTable('fields'); 
$data = $test->find(1); 
dd($data); 

Я получаю сообщение об ошибке:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.tests' doesn't exist (SQL: select * from `tests` where `id` = ? limit 1) (Bindings: array (0 => 1,))" 

Обратите внимание, что установка имени таблицы из тестовой модели работает очень хорошо.

L4 на самом деле использует метод setTable(), который я бы хотел, в конструкторе vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations.Pivot.php, хотя я просто не мог получить он должен работать, следуя этому примеру.

Спасибо за помощь.

+0

Вы используете Laravel 3? – msturdy

+0

Кто-нибудь решил это? –

+0

Вы когда-нибудь находили решение? – SPillai

ответ

7

Может быть, это полезно для вас: http://laravel.io/forum/08-01-2014-defining-models-in-runtime

Более точно, отсюда: http://laravel.io/forum/08-01-2014-defining-models-in-runtime?page=1#reply-11779

class ModelBuilder extends Eloquent { 

    protected static $_table; 


    public static function fromTable($table, $parms = Array()){ 
     $ret = null; 
     if (class_exists($table)){ 
      $ret = new $table($parms); 
     } else { 
      $ret = new static($parms); 
      $ret->setTable($table); 
     } 
     return $ret; 
    } 

    public function setTable($table) 
    { 
     static::$_table = $table; 
    } 

    public function getTable() 
    { 
     return static::$_table; 
    } 
} 

$user = ModelBuilder::fromTable("users")->find(1); 

Это не моя окончательная реализация, которая гораздо более сложным (и грязнее), чем из-за моего использования случаев. Но я думаю, что пример может привести вас к тому, что вам нужно.

+0

Ты действительно спас мой день, спасибо –

+0

Это действительно полезно Даниэлю. Большое спасибо. – suarsenegger

0

Вам необходимо переопределить статический метод find красноречивых с моделью, как она используется для находки:

public static function find($id, $columns = array('*')) 
{ 
    if (is_array($id) && empty($id)) return new Collection; 

    $instance = new static; 

    return $instance->newQuery()->find($id, $columns); 
} 

Этого метод создает новый экземпляр вашей модели класса вместо повторного использования instiated класса. По умолчанию это «забывает» таблицу, которую вы установили. И, вероятно, вам нужно передать имя таблицы для него. В моем случае использования мой код вводит использованную таблицу на основе id, поэтому мне не нужно передавать имя всей таблицы. Ура наследие ;-)

Другой вариант заключается в использовании некоторых дополнительных класса фабрики, как Daniel Cantarin предложил

Вы, возможно, потребуется переопределить некоторые дополнительные статические методы для обработки всех случаев использования. Например, я только заметил, что использование нетерпеливой загрузки ломает мои моды таблицы, поэтому мне нужно скопировать поведение метода with, не нарушая его API вызовов, yay -_____-

0

Дизайн Larvael не поддерживает полностью динамические модели. Хотя существует метод setTable, его ограничение является его методом экземпляра. Кроме того, в рамках много запросов начинается с создания экземпляра модели через «новый статический», поэтому нет возможности установить таблицу во внутренних запросах. Да, вы можете вызвать setTable по своим собственным запросам, но по мере того, как вы разрабатываете больше своего приложения, используя больше возможностей Laravel, например, SoftDeletes forceDelete вы постепенно придете к кирпичной стене. Работа вокруг заключается в использовании функции eval PHP для создания классов модели во время выполнения, таким образом, новый статический будет работать так, как он был разработан.

// load all the models 
    $eval = "namespace App\\Records;"; 
    foreach($container->tables()->get() as $table){ 
     $recordType = $table->recordType; 
     $recordTable = $table->getRecordTableName(); 
     $eval .= "class $recordType extends \\App\\Record { protected \$table = '$recordTable'; }"; 

    } 
    eval($eval); 

В случае, когда у меня есть RECORDTYPE «Место проведения», который использует «место проведения» recordTable теперь у меня есть класс \ App \ Отчеты \ Место, который использует таблицу «место», таким образом, я могу теперь сделать это

$class = "\App\Records\Venue"; 
$venue = $class::find(1); 

Теперь вы можете использовать Laravel, как и без хакеров. Это очень мощное решение, связанное с угрозой безопасности, поэтому обязательно выполните дезинфекцию любых параметров, используемых в eval. Надеюсь, что когда-нибудь Laravel будет реализовывать способ поддержки динамических моделей.

Смежные вопросы