在这个简单的例子中,我应该如何设置我的DBIx :: Class结果类?

Sin*_*nür 7 perl dbix-class

假设我有一个由三个表组成的以下简化示例数据库:

CREATE TABLE people (
    person_id   INTEGER PRIMARY KEY,
    person_name VARCHAR(100)
);

CREATE TABLE events (
    event_id       INTEGER PRIMARY KEY,
    event_name     VARCHAR(100),
    event_creator  INTEGER
                   CONSTRAINT fk_event_creator REFERENCES people(person_id)
);

CREATE TABLE event_attendees (
    event_id  INTEGER NOT NULL
              CONSTRAINT fk_event_attendee_event
              REFERENCES events(event_id),
    person_id INTEGER NOT NULL
              CONSTRAINT fk_event_attendee_person
              REFERENCES people(person_id),
    role      CHAR(1), -- O: organizer, P: performer, S: speaker, G: guest
    CONSTRAINT pk_event_attendees PRIMARY KEY (event_id, person_id)
);
Run Code Online (Sandbox Code Playgroud)

给定一个event_id,我可能想要查询所有组织者的名字,考虑到person_id我可能想要找到这个人是该事件的客人或创建者的所有事件的名称,依此类推.

我知道如何使用简单的SQL做所有这些.你能告诉我在设置DBIx :: Class时需要设置哪些结果类以及需要指定哪种关系?

hob*_*bbs 6

你熟悉DBIx :: Class :: Schema :: Loader吗?虽然它可以一次性脚本中使用动态地在内存中创建一个DBIC模式,它也有在它写入模式定义磁盘为您编辑和建立在一个"一次性"模式运行的能力,和它的方式比你想象的更先进.

首先,您希望模式实际存在于数据库中,以便加载程序可以扫描它.然后你做的事情如下:

perl -MDBIx::Class::Schema::Loader=make_schema_at \
-e 'make_schema_at("MyApp::Schema", {dump_directory=>"schema_out"},' \
-e '["dbi:DBType:connstring", "user", "pass"]);'
Run Code Online (Sandbox Code Playgroud)

(其中"MyApp :: Schema"是您希望生成的模式类共享的包名称,"schema_out"是您希望它们生成的目录).

在此之后,您可以编辑生成的模式类,或者,如果您发现加载程序做得足够好(或者至少是一个足够好的工作,您不需要编辑任何上面的"不要编辑上面的内容")此行"行",您可以确定数据库中的模式是您的主要来源,并保存Schema :: Loader脚本以便再次运行以在数据库更改时自动重新生成类.

更新

使用DBIx :: Class :: Schema :: Loader v0.05002无法正确处理上述模式的某些部分,因为Sinan设法找到了错误!如果"引用"部分和列名不在同一行,则无法正确解析外键约束.

这个错误在DBICSL git中得到修复,但由于修复程序尚未发布,所以关系应该是这样的(我省略了列定义以节省空间;它们应该像加载器当前生成它们一样).

EventAttendee.pm

__PACKAGE__->set_primary_key(qw(event_id person_id));

__PACKAGE__->belongs_to(
    "event" => "MyApp::Schema::Result::Event",
    { event_id => "event_id" },
    {}
);

__PACKAGE__->belongs_to(
    "person" => "MyApp::Schema::Result::Person",
    { person_id => "person_id" },
    {}
);
Run Code Online (Sandbox Code Playgroud)

Event.pm

__PACKAGE__->set_primary_key("event_id");

__PACKAGE__->belongs_to(
    "event_creator" => "MyApp::Schema::Result::Person",
    { person_id => "event_creator" },
    { join_type => "LEFT" },
);

__PACKAGE__->has_many(
    "event_attendees" => "MyApp::Schema::Result::EventAttendee",
    { "foreign.event_id" => "self.event_id" },
);

# Not auto-generated, but you probably want to add it :)
__PACKAGE__->many_to_many(
    "people_attending" => "event_attendees" => "person"
);
Run Code Online (Sandbox Code Playgroud)

People.pm

__PACKAGE__->has_many(
    # It might be wise to change this to "events_created"
    "events" => "MyApp::Schema::Result::Event",
    { "foreign.event_creator" => "self.person_id" },
);

__PACKAGE__->has_many(
    "event_attendees" => "MyApp::Schema::Result::EventAttendee",
    { "foreign.person_id" => "self.person_id" },
);

# Not auto-generated, but you probably want to add it :)
__PACKAGE__->many_to_many(
    "events_attending" => "event_attendees" => "event"
);
Run Code Online (Sandbox Code Playgroud)