Laravel神秘-两个相似的项类型在同一用例中产生两个不同的查询字符串
好吧,这很奇怪。。。准备好了吗 我的网站上有一个项目类型,我们把它叫做Laravel神秘-两个相似的项类型在同一用例中产生两个不同的查询字符串,laravel,Laravel,好吧,这很奇怪。。。准备好了吗 我的网站上有一个项目类型,我们把它叫做SomeItem 它可以通过一对多关系将标记与之关联 在处理SomeItem的标记时,Laravel构建的查询类型如下,例如响应routeapi/SomeItem/10: select `tags`.*, `someitem_tag`.`someitem_id` as `pivot_someitem_id`, `someitem_tag`.`tag_id` as `pivot_tag_id` from `tags` inner
SomeItem
它可以通过一对多关系将标记与之关联
在处理SomeItem
的标记时,Laravel构建的查询类型如下,例如响应routeapi/SomeItem/10
:
select `tags`.*, `someitem_tag`.`someitem_id` as `pivot_someitem_id`, `someitem_tag`.`tag_id` as `pivot_tag_id` from `tags` inner join `someitem_tag` on `tags`.`id` = `someitem_tag`.`tag_id` where `someitem_tag`.`someitem_id` in (10)
当我创建具有相同设置的第二个项时(我们称之为其他项
),它以不同的方式处理数据库查询以提取标记
,在查询中使用不同的语法。非常奇怪。
(是的,我在型号名称的末尾有一个s
)
例如,此路由api/anotheritems/1
产生以下错误:
Base table or view not found: 1146 Table 'mysite.tag_anotheritems' doesn't exist (SQL: select `tags`.*, `tag_anotheritems`.`anotheritems_id` as `pivot_anotheritems_id`, `tag_anotheritems`.`tag_id` as `pivot_tag_id` from `tags` inner join `tag_anotheritems` on `tags`.`id` = `tag_anotheritems`.`tag_id` where `tag_anotheritems`.`anotheritems_id` in (1))
看看发生了什么?当然,我得到了这个错误-在数据库中,AnotherItems
的这个标记表被创建为AnotherItems\u tag
。这类似于SomeItem
Laravel究竟是如何对一个项目使用语法someitem\u tag
,而对另一个项目使用语法tag\u anotheritems
首先,让我向您展示如何设置SomeItem
以下是与标记相关的数据库结构:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSomeItemTagTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('someitem_tag', function (Blueprint $table) {
$table->integer('tag_id')->unsigned();
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
$table->integer('someitem_id')->unsigned();
$table->foreign('someitem_id')->references('id')->on('someitems')->onDelete('cascade');
$table->primary(array('tag_id', 'someitem_id'));
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('someitem_tag');
}
}
有一个标记模型/类具有以下特性:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
protected $fillable = ['name'];
protected $hidden = [];
public $timestamps = false;
public function someitems()
{
return $this->belongsToMany(SomeItem::class);
}
}
以下是一些项目模型/类别的相关行:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use App\Presenters\Presentable;
use Illuminate\Notifications\Notifiable;
use Auth;
class Exercise extends Model
implements Presentable
{
use Traits\SerializesUniversalDate;
use Traits\Presents;
use Notifiable;
protected $presenter = 'App\Presenters\SomeItemPresenter';
protected $fillable = ['title', etc];
protected $hidden = [];
public function parentitem()
{
return $this->belongsTo(ParentItem::class);
}
public function tags()
{
return $this->belongsToMany(Tag::class);
}
/**
* Update lesson tag array.
*
* @param array \App\Tag $tags
* @return void
*/
public function updateTags($tagsArray)
{
foreach ($tagsArray as &$value)
{
$tag = Tag::where('name', $value['name'])->first();
if (is_null($tag))
{
$tag = new Tag([
'name' => $value['name']
]);
$tag->save();
}
if (!$this->tags->contains($tag->id))
{
$this->tags()->attach($tag->id);
}
}
foreach($this->tags as &$existingTag)
{
if (!self::arrayContains($tagsArray, 'name', $existingTag->name))
{
$this->tags()->detach($existingTag->id);
}
}
$this->load('tags');
}
private static function arrayContains($array, $key, $value)
{
foreach ($array as $item)
{
if($item[$key] == $value) return true;
}
return false;
}
}
下面是SomeItem API控制器的一些相关代码:
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
class SomeItemController extends Controller
{
public function index(Request $request)
{
$query = \App\SomeItem::query();
return $query->get()->load('parentitem')->load('tags');
}
//show item for editing
public function show($id)
{
$someitem = \App\SomeItem::find($id);
$someitem->load('parentitem')->load('tags');
$someitem->attachKindToFiles();
return $someitem;
}
//store new entry to db
public function store()
{
$someitem = \App\SomeItem::create(Input::all());
isset(Input::all()['tags']) ? $someitem->updateTags(Input::all()['tags']) : '';
return $someitem;
}
//update/save
public function update($id)
{
$someitem = \App\SomeItem::find($id);
$someitem->update(Input::all());
$someitem->updateTags(Input::all()['tags']);
$someitem->load('tags');
return $someitem;
}
还有一个SomeItem presenter和composer,但它们不使用标记
使用其他项
,我复制了某个项
中的所有内容,并根据需要更改名称
因此,在标记模型中存在
public function anotheritems()
{
return $this->belongsToMany(AnotherItems::class);
}
例如,在另一个项目
模型中就有这样一个项目
public function tags()
{
return $this->belongsToMany(Tag::class);
}
例如,在AnotherItems
API控制器中(用于路由API/AnotherItems/1):
所以,这完全是个谜。我两天来一直在想这个问题。我继续问自己
Laravel究竟是如何为一个项目使用语法someitem\u tag
,而为另一个项目使用语法tag\u anotheritems
我从laravel 5.2升级到了5.3,在升级之后,我添加了这个其他项
。但我不知道这如何可能改变这些数据库查询的情况
我尝试了大量artisan命令来清除所有可以想象的内容,但在框架中的某个地方,它希望在构建这些连接查询以提取/保存标记时,以不同的方式处理SomeItem
和anotheritem
想法
谢谢,
布莱恩
决定在调试器中单步执行代码。似乎Str.php中的各种snake
相关函数出现了故障,我还注意到了snakeCache调用,不管是什么。不知道为什么用这种奇怪的方法来确定表名。。。在这些函数中还有一些复数相关检查,因此这可能与我在项目名称末尾使用s
有关。如果一个模型名称末尾的s会导致两个不同的逻辑分支,那就相当糟糕了…好吧,我把表名改成了tag\u anotheritems
,一切正常,但这真的是一团糟,不是我想求助的解决方案。如果模型的名称会导致Laravel以两种不同的方式确定联接表的名称,可能是基于复数化与非复数化,那么这意味着逻辑是错误的。也许它在以后版本的Laravel中得到了修复。但是说真的,我们应该能够调用模型,不管他们想要什么(在合理的范围内),并且不必担心这样的命名实际上会破坏查询生成器中的某些东西<代码>返回$this->belongToMany(AnotherItem::class,“anotheritems_标记”)
和您的另一个项目
类也是如此。问题是,我与这个新项目有一些其他的一对多关系,我只是更改了表名,一切正常。我不想编辑代码,因为跟踪表名比修改代码更容易。但我想我会编辑Laravel5.3的源代码,这样就不会发生这种情况,并跟踪编辑过程。如果这对你来说更简单,就这么做吧!另一个注意事项:阅读您的标签系统,我认为这可能是一个好主意。:)好的,我将表名更改为标记其他项
,一切正常,但这真的是一团糟,不是我想要的解决方案。如果模型的名称会导致Laravel以两种不同的方式确定联接表的名称,可能是基于复数化与非复数化,那么这意味着逻辑是错误的。也许它在以后版本的Laravel中得到了修复。但是说真的,我们应该能够调用模型,不管他们想要什么(在合理的范围内),并且不必担心这样的命名实际上会破坏查询生成器中的某些东西<代码>返回$this->belongToMany(AnotherItem::class,“anotheritems_标记”)和您的另一个项目
类也是如此。问题是,我与这个新项目有一些其他的一对多关系,我只是更改了表名,一切正常。我不想编辑代码,因为跟踪表名比修改代码更容易。但我想我会编辑Laravel5.3的源代码,这样就不会发生这种情况,并跟踪编辑过程。如果这对你来说更简单,就这么做吧!另一个注意事项:阅读您的标签系统,我认为这可能是一个好主意。:)
public function index(Request $request)
{
$query = \App\AnotherItems::query();
if ($request->has('id')) {
$query->where('id', $request['id']);
}
return $query->get()->load('parentitem')->load('tags');
}