Name

QBit::Application::Model::DBManager - Class for smart working with DB.

GitHub

https://github.com/QBitFramework/QBit-Application-Model-DBManager

Install

  • cpanm QBit::Application::Model::DBManager

  • apt-get install libqbit-application-model-dbmanager-perl (http://perlhub.ru/)

For more information. please, see code.

Package methods

remove_model_fields

Removes the model fields. Use this method if you want to set an entirely different set of fields for the model.

No arguments

Return value: $model_fields (type: ref of a hash)

Example:

my $model_fields = $app->users->remove_model_fields();
# set new fields.
$app->users->model_fields(...);

model_fields

Set model fields. Save into package stash with key __MODEL_FIELDS__

Arguments:

  • %fields - Fields (type: hash)

Example:

package Sellers;
__PACKAGE__->model_accessors(
db => 'Application::Model::DB', # your DB model, see QBit::Application::Model::DB
items => 'Application::Model::Items', # your model (base from QBit::Application::Model::DBManager)
);
__PACKAGE__->model_fields(
id => {
pk => TRUE, # primary key for this model
db => 'sellers', # this field is from the table
default => TRUE, # this field returns if fields were not requested
},
caption => {
db => 'sellers', # this field is from the table
default => TRUE, # this field returns if fields were not requested
i18n => TRUE, # this field depends on current locale, (in DB this field i18n too)
check_rights => 'sellers_view_field__caption',
# your right for "caption", see check_rights from QBit::Application
# Try not to use this key.
},
id_with_caption => {
depends_on => [qw(id caption)], # this field depends on "id" and "caption"
get => sub {
my $fields = shift; # object QBit::Application::Model::DBManager::_Utils::Fields
# access to model: $fields->model
my $row = shift; # hash from db: {id => 1, caption => 'Happy Milkman'}
return $row->{'id'} . ': ' . $row->{'caption'};
}
},
id_with_caption_db => {
db => 'sellers',
db_expr => {CONCAT => ['id', \': ', 'caption']}, # see QBit::Application::Model::DB::Query
},
name => {
# relation "one to one". Use it if you want use join
db => 'users', # this field is from the table, but the tables are different
},
items => {
# relation "one to one", "one to many" or "many to many"
depends_on => [qw(id)],
get => sub {
my $fields = shift; # object QBit::Application::Model::DBManager::_Utils::Fields
my $row = shift; # hash from db: {id => 1}
# $fields->{'__ITEMS__'} created in pre_process_fields
return $fields->{'__ITEMS__'}{$row->{'id'}} // [];
}
}
);
# returns query (class: QBit::Application::Model::DB::Query)
sub query {
my ($self, %opts) = @_;
my $filter = $self->db->filter($opts{'filter'});
unless ($self->check_rights('sellers_view_all')) {
my $cur_user = $self->cur_user();
$filter->and({user_id => $cur_user->{'id'}};
}
my $query = $self->db->query->select(
table => $self->db->sellers,
fields => $opts{'fields'}->get_db_fields('sellers'), # returns db expression for fields with "db" = 'sellers'
filter => $filter
);
my $users_fields = $opts{'fields'}->get_db_fields('users');
# join users only if needed (field "name" was requested)
$query->join(
table => $self->db->users,
fields => $users_fields,
) if %$users_fields;
return $query;
}
# used for dictionaries
sub pre_process_fields {
my $self = shift; # model
my $fields = shift; # object QBit::Application::Model::DBManager::_Utils::Fields
my $result = shift; # data from db
if ($fields->need('items')) {
# gets items only if needed (field "items" was requested)
my $items = $self->items->get_all(
fields => [qw(id seller_id caption)],
filter => {seller_id => [map {$_->{'id'}} @$result]}, # key "id" exists because fields "items" depends on "id"
);
# create dictionaries {<SELLER_ID> => <ITEM>}
$fields->{'__ITEMS__'} = {map {$_->{'seller_id'} => $_} @$items};
}
}
TRUE;
# in your code
my $sellers = $app->sellers->get_all(fields => [qw(id id_with_caption_db name items)]);
#$sellers = [
# {
# id => 1,
# id_with_caption_db => '1: Happy Milkman',
# name => 'Petr Ivanovich',
# items => [
# {
# id => 1,
# seller_id => 1,
# caption => 'milk'
# },
# {
# id => 2,
# seller_id => 1,
# caption => 'cheese'
# },
# ],
# }
#]

model_filter

Set model filters. Save into package stash with key __DB_FILTER__

Types: namespace (QBit::Application::Model::DBManager::Filter)

  • boolean

  • dictionary

  • multistate

  • number

  • subfilter

  • text

Arguments:

  • %opts - Options (type: hash)

    • db_accessor - name db accessor

    • fields - filter fields

Example:

__PACKAGE__->model_filter(
db_accessor => 'db', # your db accessor
fields => {
id => {type => 'number'},
caption => {type => 'text'},
active => {type => 'boolean'},
product => {
type => 'dictionary',
values => sub {
[
{id => 1, label => gettext('Milk')},
{id => 2, label => gettext('Cheese')},
];
},
}
multistate => {type => 'multistate'},
# you can filtered by field from other model
user => {
type => 'subfilter',
model_accessor => 'users', # accessor related model
field => 'user_id', # field from this model
fk_field => 'id', # field from model "users"
},
},
);
# in your code
my $items = $app->model->get_all(
filter => [
'OR',
[
['id', '=', 1],
['caption', 'LIKE', 'Nike'],
['active', '=', 1],
['product', '=', [1, 2]],
['multistate', '=', 'approved and working'],
['user', 'MATCH', ['login', '=', 'ChuckNorris']] # login is a filter in model "users"
]
]
);

get_model_fields

Returns a model fields.

No arguments.

Return value: $model_fields (type: ref of a hash)

Example:

my $model_fields = $app->model->get_model_fields(); # getter for method "model_fields"

get_all

Returns model items.

Arguments:

  • %opts - Options (type: hash)

    • fields

      returns "id" and "caption"
      my $data = $app->model->get_all(fields => [qw(id caption)]);
      # returns fields with key "default"
      my $data = $app->model->get_all();
      # return all fields
      my $data = $app->model->get_all(fields => ['*']);
    • filter - see QBit::Application::Model::DB::Query. Unlike filters from the database, model filters can not use field names and scalars are used without reference.

      # mysql: name = caption
      # db: ['name', '=', 'caption']
      # model: no way
      # mysql: id = 12
      # db: ['id', '=', \12]
      # model: ['id', '=', 12]
      my $data = $app->model->get_all(filter => {id => 1});
    • distinct - unique rows from table

      my $data = $app->model->get_all(fields => [qw(caption)], distinct => TRUE);
    • for_update - get lock

      # get
      my $data = $app->model->get_all(fields => [qw(id)], filter => ["caption", "LIKE", "milk"]}, for_update => TRUE);
      # update
      $app->db->table->edit($app->db->filter({id => [map {$_->{'id'}} @$data]}), {caption => 'Milk'});
    • order_by - set order

      my $data = $app->model->get_all(
      fields => [qw(caption)],
      order_by => [
      'caption', # asc
      [
      'price', # field
      1 # order: 0 - asc, 1 - desc
      ]
      ]
      );
    • limit

      my $data = $app->model->get_all(limit => 100);
    • offset

      my $data = $app->model->get_all(limit => 100, offset => 1000);
    • calc_rows

      my $data = $app->model->get_all(limit => 100, calc_rows => TRUE);
      my $all_data = $app->model->found_rows(); # 1_000_000
    • all_locales

      my $data = $app->model->get_all(fields => [qw(id caption)], all_locales => TRUE);
      #$data = [
      # {
      # id => 1,
      # caption => {
      # ru => 'Веселый молочник',
      # en => 'Happy Milkman',
      # },
      # },
      # ...
      #]

Return value: Data (type: ref of a array)

Example:

my $data = $app->model->get_all(
fields => [qw(id caption)],
filter => ['OR', [
['id', '=', 10],
['caption', '=', 'milk']
]],
limit => 100,
offset => 10_000,
order_by => ['caption']
);

found_rows

Returns count of a rows.

No arguments.

Return value: $found_rows (type: scalar or undef)

Example:

my $data = $app->model->get_all(limit => 3, calc_rows => TRUE);
my $found_rows = $app->model->found_rows();

last_fields

Returns a last fields was requested.

No arguments.

Return value: $last_fields (type: scalar or undef)

Example:

my $data = $app->model->get_all(fields => [qw(id caption)]);
my $last_fields = $app->model->last_fields();
# $last_fields = {
# id => '',
# caption => '',
# };

get

Returns row by primary key.

Arguments:

  • $pk - primary key (type: scalar or hash)

  • %opts - options (type: hash; see get_all)

Return value: Row (type: ref of a hash or undef)

Example:

my $item = $app->model->get(1, fields => [qw(id caption)]);
# or
my $item = $app->model->get({id => 1}, fields => [qw(id caption)]);

get_pk_fields

Returns primary keys.

No arguments.

Return value: fields (type: ref of a array)

Example:

my $pk = $app->model->get_pk_fields(); # ['id']

pre_process_fields

used for dictionaries.

No arguments.

Return value: undef

Example:

# see method: model_fields
$app->model->pre_process_fields();