我不确定如何才能使动态表名起作用。
考虑以下模型(表'test'不存在):
<?php
// app/models/Test.php
class Test extends Eloquent {
}
然后如果我这样做('fields'表确实存在):
<?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, ))"
请注意,从Test模型设置表名称可以正常工作。
L4实际上使用了setTable()方法,非常类似于我想要的方式,在vendor / laravel / framework / src / Illuminate / Database / Eloquent / Relations.Pivot.php构造函数中,尽管我无法得到它按照这个例子来工作。
感谢您的帮助。
答案 0 :(得分: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);
这不是我的最终实现,因为我的用例,它比那更复杂(更脏)。但我想这个例子可能会引导您达到您的需求。
答案 1 :(得分:0)
您需要覆盖Eloquent Model的静态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);
}
该方法正在创建模型类的新实例,而不是重用已启用的类。默认情况下,这会忘记&#34;你设定的表格。也许你需要为它传递表名。在我的用例中,我的代码根据id
推断出使用过的表,因此我不必传递整个表名。万岁的遗产; - )
其他选择是使用一些额外的工厂类,如 Daniel Cantarin 建议
您可能需要覆盖一些其他静态方法来处理所有用例。例如,我只是注意到使用急切加载会破坏我的表格模式,因此我需要复制with
方法的行为,而不会破坏它的调用API,yay -_____-
答案 2 :(得分:0)
Larvael的设计并不完全支持动态模型。虽然有setTable方法,但它的局限性是它的实例方法。此外,在框架内,许多查询都是从通过“new static”创建模型实例开始的,因此您无法在内部查询上设置表。是的,您可以根据自己的查询调用setTable,但是当您使用Laravel的更多功能开发更多应用程序时,例如SoftDeletes forceDelete你会逐渐碰到一堵砖墙。解决方法是使用PHP的eval函数在运行时生成模型类,这样新的静态将按其设计的方式工作。
// 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);
如果我有'Venue'记录类型,使用'场所'recordTable我现在有一个类\ App \ Records \ Venue使用表“场地”,因此我现在可以这样做
$class = "\App\Records\Venue";
$venue = $class::find(1);
现在您可以自由地使用Laravel,而不再使用任何hackery。这是一个非常强大的解决方法,存在安全风险,因此请务必清理eval中使用的任何参数。希望有一天Laravel将实施一种支持动态模型的方法。