如何在Laravel中创建hasManyThrough关系?

时间:2015-10-13 16:03:11

标签: php mysql laravel orm laravel-5

我正在尝试在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');
}

2 个答案:

答案 0 :(得分:1)

此错误可能是因为您错误地使用了hasManyThrough()方法。

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

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

来源:DocumentationAPI Usage

答案 1 :(得分:1)

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

  

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

和外键

  

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

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

如果您为模型和数据库表使用了正确的驼峰和蛇形外壳,并根据实际的相关表名称命名外键,则所有这些都是自动的。