Cataly...:Schema(3pm)
π NAME π
okay so bestie, this is Catalyst::Model::DBIC::Schema β it's a DBIx::Class::Schema Model Class. that's the whole vibe. it's from the User Contributed Perl Documentation, and the manual page is literally called Cataly...:Schema(3pm) (they truncated it, iconic of them honestly).
β¨ SYNOPSIS β¨
first things first: build your database schema with DBIx::Class. if you wanna know how to generate a DBIx::Class::Schema from your actual database using the Helper script, go look at Catalyst::Helper::Model::DBIC::Schema and DBIx::Class::Schema::Loader::Base. they got you.
a typical run of the helper script looks like this, no cap:
script/myapp_create.pl model FilmDB DBIC::Schema MyApp::Schema::FilmDB \
create=static dbi:mysql:filmdb dbusername dbpass \
quote_names=1
if DBIx::Class is giving you "who is she" energy, please go read DBIx::Class::Manual::Intro first. like actually. do it. π
these examples are all assuming you already have a schema called MyApp::Schema::FilmDB that defines some Result classes for tables in MyApp::Schema::FilmDB::Result::Actor and MyApp::Schema::FilmDB::Result::Film. either the helper script made them (see above, bestie) or you made them by hand like a legend.
the helper also makes a Model in lib/MyApp/Model/FilmDB.pm. but if you already have a schema, you can just make the Model on its own:
script/myapp_create.pl model FilmDB DBIC::Schema MyApp::Schema::FilmDB
dbi:mysql:filmdb dbusername dbpass
the connect_info is optional, and if you give it, it gets hardcoded into the Model. ngl it's better to configure it in your Catalyst config file instead β that also overrides any hardcoded config, so it wins. check connect_info for examples. π
so now you have a working Model that accesses your separate DBIC Schema. use it the normal Catalyst way, via $c->model():
my $db_model = $c->model('FilmDB'); # a Catalyst::Model
my $dbic = $c->model('FilmDB')->schema; # the actual DBIC object
there's also a shortcut that hands you a DBIx::Class::ResultSet directly, no Catalyst::Model middleman:
my $rs = $c->model('FilmDB::Actor');
want to know what methods you can call on ResultSets? that's DBIx::Class::ResultSet, go read it.
you can also define your own ResultSet methods to wrap up your app's database/business logic. those live in, for example, lib/MyApp/Schema/FilmDB/ResultSet/Actor.pm. the class must inherit from DBIx::Class::ResultSet, and it gets loaded automatically. slay.
then you just call your methods like any other DBIx::Class::ResultSet method:
$c->model('FilmDB::Actor')->SAG_members
some examples π¦
# to access schema methods directly:
$c->model('FilmDB')->schema->source(...);
# to access the source object, resultset, and class:
$c->model('FilmDB')->source(...);
$c->model('FilmDB')->resultset(...);
$c->model('FilmDB')->class(...);
# For resultsets, there's an even quicker shortcut:
$c->model('FilmDB::Actor')
# is the same as $c->model('FilmDB')->resultset('Actor')
# To get the composed schema for making new connections:
my $newconn = $c->model('FilmDB')->composed_schema->connect(...);
# Or the same thing via a convenience shortcut:
my $newconn = $c->model('FilmDB')->connect(...);
# or, if your schema works on different storage drivers:
my $newconn = $c->model('FilmDB')->composed_schema->clone();
$newconn->storage_type('::LDAP');
$newconn->connection(...);
# and again, a convenience shortcut
my $newconn = $c->model('FilmDB')->clone();
$newconn->storage_type('::LDAP');
$newconn->connection(...);
to set up authentication, scroll down to "Setting up DBIC authentication" below. π
πΈ DESCRIPTION πΈ
this is a Catalyst Model for DBIx::Class::Schema-based Models. if you want the tea on generating these Models via Helper scripts, the documentation for Catalyst::Helper::Model::DBIC::Schema has it.
when your Catalyst app starts up, a thin Model layer gets created as an interface to your DBIC Schema. and important, listen up: the model object that $c->model('FilmDB') hands back is NOT itself a DBIC schema or resultset object. it's literally just a wrapper that proves methods to access the underlying schema. don't get it twisted.
on top of this model class, a shortcut class gets generated for every source in the schema, so you can get easy, direct access to a resultset of the corresponding type. and these generated classes are even thinner than the model class β like, zero public methods, they just hook into Catalyst's model() accessor via the ACCEPT_CONTEXT mechanism. the complete contents of each generated class is roughly equivalent to this:
package MyApp::Model::FilmDB::Actor
sub ACCEPT_CONTEXT {
my ($self, $c) = @_;
$c->model('FilmDB')->resultset('Actor');
}
so basically, there are three techniques for getting yourself a DBIC resultset object:
# the long way
my $rs = $c->model('FilmDB')->schema->resultset('Actor');
# using the shortcut method on the model object
my $rs = $c->model('FilmDB')->resultset('Actor');
# using the generated class directly
my $rs = $c->model('FilmDB::Actor');
now, if you wanna add methods to a DBIC resultset, you cannot just slap them onto the source (row, table) definition class. nope. you have to define a separate custom resultset class. it's easy though β just make a lib/MyApp/Schema/ResultSet/Actor.pm class that inherits from DBIx::Class::ResultSet, assuming you're using load_namespaces in DBIx::Class::Schema, which is the default for helper script generated schemas. β¨
want more? check out "Predefined searches" in DBIx::Class::Manual::Cookbook for how to define your own DBIx::Class::ResultSet classes for use with load_classes in DBIx::Class::Schema β that's the old default, fyi.
π CONFIG PARAMETERS π
schema_class
this is the classname of your DBIx::Class::Schema Schema. it needs to be findable in @INC, but honestly it does not need to live inside the Catalyst::Model:: namespace. this parameter is required. periodt.
connect_info
this is a hashref or arrayref of connection parameters, and they're specific to your storage_type (go check your storage type documentation for the deets). if you only need one parameter β like the DSN, for example β you can literally just pass a string.
this is not required if schema_class already has connection information defined inside itself. (which, ngl, isn't highly recommended, but it can be done. do with that what you will. π«Ά)
for DBIx::Class::Storage::DBI β which is the only supported storage_type in DBIx::Class at the time of this writing β the parameters are your dsn, username, password, and connect options hashref.
for a detailed explanation of the arguments supported, see "connect_info" in DBIx::Class::Storage::DBI.
examples π
connect_info => {
dsn => 'dbi:Pg:dbname=mypgdb',
user => 'postgres',
password => ''
}
connect_info => {
dsn => 'dbi:SQLite:dbname=foo.db',
on_connect_do => [
'PRAGMA synchronous = OFF',
]
}
connect_info => {
dsn => 'dbi:Pg:dbname=mypgdb',
user => 'postgres',
password => '',
pg_enable_utf8 => 1,
on_connect_do => [
'some SQL statement',
'another SQL statement',
],
}
or, using Config::General:
<Model::FilmDB>
schema_class MyApp::Schema::FilmDB
traits Caching
<connect_info>
dsn dbi:Pg:dbname=mypgdb
user postgres
password ""
auto_savepoint 1
quote_names 1
on_connect_do some SQL statement
on_connect_do another SQL statement
</connect_info>
user_defined_schema_accessor foo
</Model::FilmDB>
or:
<Model::FilmDB>
schema_class MyApp::Schema::FilmDB
connect_info dbi:SQLite:dbname=foo.db
</Model::FilmDB>
or, using YAML:
Model::MyDB:
schema_class: MyDB
traits: Caching
connect_info:
dsn: dbi:Oracle:mydb
user: mtfnpy
password: mypass
LongReadLen: 1000000
LongTruncOk: 1
on_connect_call: 'datetime_setup'
quote_names: 1
and yes, the old arrayref style with hashrefs for DBI then DBIx::Class options is also supported, because we respect the classics:
connect_info => [
'dbi:Pg:dbname=mypgdb',
'postgres',
'',
{
pg_enable_utf8 => 1,
},
{
auto_savepoint => 1,
on_connect_do => [
'some SQL statement',
'another SQL statement',
],
}
]
traits
an Array of Traits to apply to the instance. Traits are Moose::Roles. π
they're relative to the MyApp::TraitFor::Model::DBIC::Schema::, then the Catalyst::TraitFor::Model::DBIC::Schema:: namespaces β unless they're prefixed with "+", in which case they're taken to be a fully qualified name. like so:
traits Caching
traits +MyApp::TraitFor::Model::Foo
a new instance gets created at application time, so any consumed required attributes, coercions and modifiers will work. love that for us.
Traits are applied at "COMPONENT" in Catalyst::Component time using CatalystX::Component::Traits.
ref $self will be an anon class if any traits are applied, and $self->_original_class_name will be the original class.
when you're writing a Trait, the interesting points to modify are "BUILD", setup and ACCEPT_CONTEXT.
Traits that come with the distribution:
Catalyst::TraitFor::Model::DBIC::Schema::CachingCatalyst::TraitFor::Model::DBIC::Schema::ReplicatedCatalyst::TraitFor::Model::DBIC::Schema::SchemaProxyCatalyst::TraitFor::Model::DBIC::Schema::PerRequestSchema
compose_namespaces
this model calls "compose_namespace" in DBIx::Class::Schema by default to install classes into the model namespaces. you can turn that off by setting this attribute to false. Default is true.
install_model_shortcuts
if you don't want shortcut models β so you can't do stuff like $c->model('DB::Book') β set this attribute to false. Default is true.
storage_type
this lets you use a different "storage_type" than whatever is set in your schema_class (which in turn defaults to "::DBI" if it's not set in current DBIx::Class). Completely optional, and probably unnecessary for most people until other storage backends become available for DBIx::Class. π
...to be continued, bestie β part 2 is coming π
ATTRIBUTES β¨
okay so literally every key you drop into your model config? bestie, it just... becomes an attribute. that's the vibe. π
And then there's a lil bonus roster of attributes waiting for you:
connect_info
Your connect_info args, but normalized into hashref form (with dsn/user/password in there π«Ά). Want the actual deets on what the hashref form of connect_info looks like? Run, don't walk, to "connect_info" in DBIx::Class::Storage::DBI.
model_name
The model name Catalyst uses to resolve this model β specifically the part after ::Model:: or ::M:: in your class name. So like, if your class name is MyApp::Model::DB, then your model_name is DB. iconic. β¨
_default_cursor_class
What to reset your cursor_class in DBIx::Class::Storage::DBI to when a custom one just doesn't work out (it happens, we don't talk about it π). Defaults to DBIx::Class::Storage::DBI::Cursor.
ATTRIBUTES FROM MooseX::Traits::Pluggable π
_original_class_name
The class name of your model before any traits get applied to it. E.g. MyApp::Model::DB.
_traits
Unresolved arrayref of traits you passed in the config.
_resolved_traits
The traits you actually used, resolved all the way out to their full class names. π
CONFIGURING YOUR SCHEMA AND RESULTSETS π
Wanna know how to pass config values from your Catalyst config straight into your DBIx::Class::Schema and/or DBIx::Class::ResultSet classes? Go read the docs for Catalyst::TraitFor::Model::DBIC::Schema::SchemaProxy β it's all laid out there, no cap.
METHODS π
new
Instantiates the Model based on the ->config parameters we documented up above. The only required parameter is schema_class. Now β connect_info is required in the case that schema_class doesn't already have connection info defined for it. so like, if it's already got connection deets, you're free. π¦
schema
Accessor that returns the connected schema this model is using. And bestie, there are direct shortcuts on the model class itself for schema->resultset, schema->source, and schema->class. no extra steps, periodt.
composed_schema
Accessor that returns the composed schema β which has no connection info β that was used in constructing the schema. Super useful for spinning up new connections based on the same schema/model. And there are direct shortcuts from the model object for composed_schema->clone and composed_schema->connect.
Heads up tho: if compose_namespaces is not true, then composed_schema is equivalent to $model->schema_class->clone. π
clone
Shortcut for ->composed_schema->clone
connect
Shortcut for ->composed_schema->connect
source
Shortcut for ->schema->source
class
Shortcut for ->schema->class
resultset
Shortcut for ->schema->resultset
txn_do
Shortcut for ->schema->txn_do
txn_scope_guard
Shortcut for ->schema->txn_scope_guard
storage
Provides an accessor for the connected schema's storage object. ποΈ
See DBIx::Class::Storage and DBIx::Class::Storage::DBI.
setup
Called at BUILD time, before configuration but after connect_info is set. Want to do something after configuration instead? Use after BUILD =>. π«
Receives a hashref of args that were passed to BUILD.
ACCEPT_CONTEXT
The point of extension for doing things at $c->model time with context β returns the model instance. For more info, see "ACCEPT_CONTEXT" in Catalyst::Manual::Intro. π«Ά
ENVIRONMENT πΈ
CMDS_NO_SOURCESβ Set this variable if you're gonna be using schemas with no sources (Result classes), and it'll disable the warning. Why is there a warning at all? Because having no Result classes is usually a mistake, bestie. π
Setting up DBIC authentication π
You can set this whole thing up with Catalyst::Authentication::Store::DBIx::Class in MyApp.pm:
package MyApp;
use Catalyst qw/... Authentication .../;
...
__PACKAGE__->config('Plugin::Authentication' =>
{
default_realm => 'members',
members => {
credential => {
class => 'Password',
password_field => 'password',
password_type => 'hashed'
password_hash_type => 'SHA-256'
},
store => {
class => 'DBIx::Class',
user_model => 'DB::User',
role_relation => 'roles',
role_field => 'rolename',
}
}
});
METHOD PROXYING π§
okay so important lore: the automatic proxying to the underlying DBIx::Class::Schema was removed as of version 0.34. π If you want that feature back, add SchemaProxy to traits.
See Catalyst::TraitFor::Model::DBIC::Schema::SchemaProxy.
SEE ALSO π
General Catalyst stuff:
- Catalyst::Manual
- Catalyst::Test
- Catalyst::Request
- Catalyst::Response
- Catalyst::Helper
- Catalyst
Stuff related to DBIC and this Model style:
- DBIx::Class
- DBIx::Class::Schema
- DBIx::Class::Schema::Loader
- Catalyst::Helper::Model::DBIC::Schema
- CatalystX::Component::Traits
- MooseX::Traits::Pluggable
Traits:
- Catalyst::TraitFor::Model::DBIC::Schema::Caching
- Catalyst::TraitFor::Model::DBIC::Schema::Replicated
- Catalyst::TraitFor::Model::DBIC::Schema::SchemaProxy
- Catalyst::TraitFor::Model::DBIC::Schema::PerRequestSchema
- Catalyst::TraitFor::Model::DBIC::Schema::QueryLog
AUTHOR βοΈ
Brandon L Black blblack at gmail.com
CONTRIBUTORS π
- caelum: Rafael Kitover
rkitover at cpan.org - dandv: Dan Dascalescu
dandv at cpan.org - bluefeet: Aran Deltac
bluefeet@cpan.org - t0m: Tomas Doran
bobtfish@bobtfish.net - osfameron:
osfameron@cpan.org - ozum: Ozum Eldogan
ozum@ozum.net - Pavel I. Shaydo
zwon@trinitum.org - SineSwiper: Brendan Byrd
<byrd.b@insightcom.com>
COPYRIGHT π
Copyright (c) 2006 - 2010 the Catalyst::Model::DBIC::Schema AUTHOR and CONTRIBUTORS as listed above.
LICENSE π
This program is free software. You can redistribute it and/or modify it under the same terms as Perl itself.
and that's a wrap, bestie!! π«Ά this whole thing shipped with perl v5.36.0 back on 2023-10-26, and yeah the page title got truncated to Cataly...:Schema(3pm) because the manpage world simply cannot handle a long name. iconic behaviour honestly. go build something slay β¨π
π¦ where this page comes from
- debian trixie: libcatalyst-model-dbic-schema-perl 0.66-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libcatalyst-model-dbic-schema-perl 0.66-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libcatalyst-model-dbic-schema-perl 0.66-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libcatalyst-model-dbic-schema-perl 0.66-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms