Now that we’ve created the ability to manage our fancy words list with basic SQL, let’s simplify working with the table by implementing a DBIx::Class schema file for it!

Generating the schema file

Although we could craft the schema file by hand, there is a much more efficient solution. Once the table has been created in the database, Koha can create our class with the command: /kohadevbox/koha/misc/devel/update_dbix_class_files.pl --koha-conf /etc/koha/sites/kohadev/koha-conf.xml This example is using koha-testing-docker, so you may need to find update_dbix_class_files.pl elsewhere if you are not using that.

Once we have run the command, it will create the schema file in the directory /kohadevbox/koha/Koha/Schema/Result/, and the file will be named KohaPluginFancypluginWordsList.pm based on the table name.

Adding the schema file to our plugin

Now that we have our schema file, we need to create a directory in our plugin where it will live. For us, this command will be mkdir -p Koha/Plugin/FancyPlugin/lib/Koha/Schema/Result.

Next we can copy the schema file there with the command cp /kohadevbox/koha/Koha/Schema/Result/KohaPluginFancypluginWordsList.pm /var/lib/koha/kohadev/plugins/Koha/Plugin/FancyPlugin/lib/Koha/Schema/Result/.

Now, we need to do one more important thing, which is to tell our schema file the names of the Koha::Object(s) we are about to create for it. To do that, add the following to the schema file after the line # DO NOT MODIFY THIS OR ANYTHING ABOVE! but before the line 1; in the file:

sub koha_object_class {
    'Koha::FancyWord';
}

sub koha_objects_class {
    'Koha::FancyWords';
}

Creating the Koha::Object(s)

Koha::FancyWord

First we will create the ‘singular’ object, that will represent one fancy word. The file FancyWord.pm will need to in the plugin’s subdirectory Koha/Plugin/FancyPlugin/lib/Koha/FancyWord.pm.

The contents of this file will look like:

package Koha::FancyWord;

use Modern::Perl;

use base qw(Koha::Object);

=head1 NAME

Koha::FancyWord - Koha Fancy Word Object class

=head1 API

=head2 Internal methods

=head3 _type

=cut

sub _type {
        return 'KohaPluginFancypluginWordsList';
}

1;

That’s it! The important parts to note are the first line, where we give this module its’ name, and the return value of the _type method. This value needs to be the same as what we find in the schema file that Koha generated for us.

Koha::FancyWords

Next, we will create our ‘plural’ object that will represent a set of fancy workds. Similar to what we did above, we will create the file Koha/Plugin/FancyPlugin/lib/Koha/FancyWords.pm with the contents:

package Koha::FancyWord;

use Modern::Perl;

use base qw(Koha::Objects);

=head1 NAME

Koha::FancyWord - Koha Fancy Word Object set class

=head1 API

=head2 Internal methods

=head3 _type

=cut

sub _type {
        return 'KohaPluginFancypluginWordsList';
}

=head3 object_class

=cut

sub object_class {
        return 'Koha::FancyWord';
}

1;

Very similar, right? The key differences are that this file uses Koha::Objects as it’s base, rather than Koha::Object, and that it includes a new method object_class that tells Koha what the class name for the singular version of an element in the set is called.

Telling our plugin about Koha::FancyWords

Before you can start using the new Koha FancyWord(s) we’ve created, we need to tell our plugin to load them. This can be done by adding the following near the top of our FancyPlugin module:

use Module::Metadata;
use Koha::Schema;
BEGIN {
    my $path = Module::Metadata->find_module_by_name(__PACKAGE__);
    $path =~ s!\.pm$!/lib!;
    unshift @INC, $path;

    require Koha::FancyWords;
    require Koha::Schema::Result::KohaPluginFancypluginWordsList;

    # register the additional schema classes
    Koha::Schema->register_class(KohaPluginFancypluginWordsList => 'Koha::Schema::Result::KohaPluginFancypluginWordsList');
    # force a refresh of the database handle so that it includes the new classes
    Koha::Database->schema({ new => 1 });
}

This code let’s us now use Koha::FancyWord(s) in our plugin!

Replacing hand crafted SQL with Koha::FancyWord(s)

Now that we have our fully function Koha objects, we can update the tool method of our plugin to use them!

Here is a diff of how the tool method will change:

     my $action = $cgi->param('action');
     my $word = $cgi->param('word');
+    my $word_id = $cgi->param('word_id');

     if ( $action eq 'delete' ) {
-        my $sth = $dbh->prepare("DELETE FROM $words_list_table WHERE fancy_word = ?");
-        $sth->execute($word);
+        my $fancy_word = Koha::FancyWords->find($word_id);
+        $fancy_word->delete() if $fancy_word;
     } elsif ( $action eq 'add' ) {
-        my $sth = $dbh->prepare("INSERT INTO $words_list_table ( fancy_word ) VALUES ( ? )");
-        $sth->execute($word);
+        my $fancy_word = Koha::FancyWord->new({ fancy_word => $word })->store();
     }

-    my $words = $dbh->selectcol_arrayref( "SELECT fancy_word FROM $words_list_table" );
-    $template->param( words => $words );
+    my $fancy_words = Koha::FancyWords->search();
+    $template->param( fancy_words => $fancy_words );
     $self->output_html( $template->output() );
 }

We also need to update the template tool.tt a bit as well, because now instead of a list of words, we are passing in a set of Koha::FancyWord objects:

             <tbody>
-                [% FOREACH word IN words %]
+                [% FOREACH fw IN fancy_words %]
                     <tr>
-                        <td>[% word | html %]</td>
+                        <td>[% fw.fancy_word | html %]</td>
                         <td>
                             <form method="post" class="form">
                                 <input type="hidden" name="class" value="[% CLASS %]"/>
                                 <input type="hidden" name="method" value="[% METHOD %]"/>
                                 <input type="hidden" name="action" value="delete"/>
-                                <input type="hidden" name="word" value="[% word %]"/>
+                                <input type="hidden" name="word_id" value="[% fw.id %]"/>
                                 <p>

I hope this introduction to using Koha::Object(s) in plugins will make your plugin development much easier and quicker!