【问题标题】:How to create a hasManyThrough relation in Laravel?如何在 Laravel 中创建 hasManyThrough 关系?
【发布时间】:2016-01-11 11:38:31
【问题描述】:

我正在尝试在 Laravel 中为我的表格创建一个 hasManyThrough

这是我的表结构的高层次

我有survey_questions 表。 (一个问题属于多个控件survey_questions.id = survey_question_controls.question_id

我有survey_question_controls 表(许多控件属于一个问题,即survey_question_controls.question_id = survey_questions.id

我也有survey_control_items(许多项目属于一个控件,即survey_control_items.control_id = survey_question_controls.id

我需要为问题与项目建立hasManyThrough 关系。

这是我的表定义

CREATE TABLE `survey_questions` (
   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `title` varchar(120) COLLATE utf8_unicode_ci NOT NULL,
   `survey_id` int(10) unsigned NOT NULL,
   `sort` mediumint(9) NOT NULL DEFAULT '0',
   `page_number` smallint(5) unsigned NOT NULL,
   `is_required` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
   `visible_level` enum('All','store','region','district','division') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'All',
   `visible_to` varchar(120) COLLATE utf8_unicode_ci NOT NULL,
   `visible` enum('Always','conditional') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Always',
   `status` enum('active','inactive') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'active',
   `created_at` timestamp NULL DEFAULT NULL,
   `updated_at` timestamp NULL DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `survey_questions_survey_id_index` (`survey_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `survey_question_controls` (
   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
   `question_id` int(10) unsigned NOT NULL,
   `input_type` enum('text','textarea','radio','checkbox','menu','list') COLLATE utf8_unicode_ci NOT NULL,
   `sort` mediumint(9) NOT NULL DEFAULT '0',
   `validation_rule` enum('none','number','text') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'none',
   `min_length` int(10) unsigned DEFAULT NULL,
   `max_length` int(10) unsigned DEFAULT NULL,
   `min_value` int(11) DEFAULT NULL,
   `max_value` int(11) DEFAULT NULL,
   `refuse` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
   `disqualify` enum('0','1') COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
   `status` enum('active','inactive') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'active',
   `created_at` timestamp NULL DEFAULT NULL,
   `updated_at` timestamp NULL DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `survey_question_controls_question_id_index` (`question_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 CREATE TABLE `survey_control_items` (
   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `title` varchar(120) COLLATE utf8_unicode_ci NOT NULL,
   `control_id` int(10) unsigned NOT NULL,
   `sort` mediumint(9) NOT NULL DEFAULT '0',
   `created_at` timestamp NULL DEFAULT NULL,
   `updated_at` timestamp NULL DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `survey_control_items_control_id_index` (`control_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我正在尝试使用 Laravel 的 ORM 获取与此问题类似的数据。

SELECT * FROM survey_questions AS q
INNER JOIN survey_question_controls AS c ON c.question_id = q.id
LEFT JOIN survey_control_items AS i ON i.control_id = c.id

在我的 SurveyQuestions 模型中,我添加了这个关系

 /**
 * Get items for the controls that belongs to the question
 * Questions > controls > 
 */
public function items()
{
    return $this->hasManyThrough(Surveyquestioncontrols::class, Surveycontrolitems::class, 'question_id', 'id', 'control_id', 'control_id');
}

这给了我以下 SQL 错误

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'survey_control_items.surveyquestioncontrols_id' in 'where clause' (SQL: select * from `survey_control_items` where `survey_control_items`.`surveyquestioncontrols_id` = 1 and `survey_control_items`.`surveyquestioncontrols_id` is not null)

问题 如何创建 hasManyThrough 关系?

已编辑

当您阅读上面的错误时,您会注意到一个不存在的列名survey_control_items.surveyquestioncontrols_id,此列应该是survey_control_items.control_id

另外,根据下面的反馈,我的 items() 方法应该是这样的

 /**
 * Get items for the controls that belongs to the question
 * Questions > controls > 
 */
public function items()
{
    return $this->hasManyThrough(Surveycontrolitems::class, Surveyquestioncontrols::class, 'question_id', 'control_id');
}

【问题讨论】:

  • 我意识到我写的是错误的,这就是我删除它的原因。道歉

标签: php mysql laravel orm laravel-5


【解决方案1】:

这个错误可能是因为你错误地使用了hasManyThrough()方法。

如果您的模型类位于命名空间“App”中,请尝试:

return $this->hasManyThrough('App\Surveycontrolitems', 'App\Surveyquestioncontrols', 'question_id', 'control_id');

来源:DocumentationAPI Usage

【讨论】:

  • 还是同样的问题。如果您查看我在问题中列出的错误,您会注意到生成的 WHERE 子句具有以下列 survey_control_items.surveyquestioncontrols_id 无效。它应该是 survey_control_items.control_id 我知道 Laravel 假设 surveyquestioncontrols_id 应该存在但在我的情况下想用“id”替换它,即survey_control_items.id
【解决方案2】:

您为模型使用了错误的参数顺序

传递给 hasManyThrough 方法的第一个参数是我们希望访问的最终模型的名称,而第二个参数是中间模型的名称。

对于外键

第三个参数是中间模型的外键名称,第四个参数是最终模型的外键名称。

public function items()
{
    return $this->hasManyThrough(
        Surveycontrolitems::class,
        Surveyquestioncontrols::class,
        'question_id',
        'control_id'
    );
}

如果您对模型和数据库表使用适当的驼峰式和蛇式外壳,并根据实际相关的表名命名外键,所有这些都将是自动的。

【讨论】:

  • 还是同样的问题。请看我对凯文回答的回应。必须有第五和第六个参数,以便适应自定义表命名
  • 中间键应该是“id”,最终键应该是“control_id”所以我这样做了return $this->hasManyThrough(Surveycontrolitems::class, Surveyquestioncontrols::class, 'id', 'control_id');,但错误消息仍然假设 ids
  • 现在有两个人告诉你如何使用 hasManyThrough 方法,但你坚持无视我们的建议。请阅读文档。你会看到方法中的第三个参数不应该是id,而应该是question_id。这是因为它是中间模型的外键。在你的情况下,这是SurveyquestioncontrolsSurveyquestioncontrols 必须引用回父模型,它代表survey_questions 表。
  • @KevinLee 不是我坚持正确,而是我试图解决即使在您的推荐之后仍然存在的问题。无论如何, items() 现在返回以下 $this->hasManyThrough(Surveycontrolitems::class, Surveyquestioncontrols::class, 'question_id', 'control_id'); 但仍然相同的错误 Column not found: 1054 Unknown column 'survey_control_items.surveyquestioncontrols_id' in 'where clause' (SQL: select * from survey_control_items` 其中 survey_control_items.surveyquestioncontrols_id = 1 和 survey_control_items.surveyquestioncontrols_id 不为空)`
  • @MikeA,对不起,但我只是尝试完全按照文档中的方式进行操作,并且效果很好。如果您查看 hasManyThrough 的来源,则没有第六个参数,并且没有任何意义。 local_id 有一个 fith 参数,在您的情况下不需要(仅当 'survey_questions' 上的 'id' 命名不同时。另请参阅我关于正确命名外键的建议。
猜你喜欢
  • 1970-01-01
  • 2018-10-18
  • 2023-03-09
  • 1970-01-01
  • 2018-07-24
  • 2020-10-14
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
相关资源
最近更新 更多