Developing ATK modules - Part 2 (Advanced)
Pizza Guides Index | Part 1 | Part 2 | Part 3
Introduction
So, you’ve read part 1 of the guide, perhaps even created some modules for Achievo, and you are ready to read about the more powerful features of the software.
In part 1, you’ve seen how you can build nodes, which represent management of information. In this guide, I will show you how these nodes can have relationships with other nodes. After that, I will explain ‘triggers’, functions that you can implement that are executed at certain events (for example after the insertion of a new record). Finally, I will explain some smaller topics that can make your application more user-friendly, like how to make your module support multiple languages. These three topics aren’t really related, but it’s better for you general understanding of the inner workings of Achievo, to discuss them in this order.
Prerequisites
Before starting to work with this guide, you should have at least read part 1. If you have a fair understanding of the things discussed there, and have toyed around with the example code, this guide should not be too hard to understand.
Some knowledge about relations in a database context (referential keys, etc.) is practical, but not absolutely necessary, as I will try to explain the relationships in very basic terms.
I will continue to use the example of the Pizza management application, so you should use the code from part 1 as a starting point for the examples in this guide. If you haven’t implemented the classes from the previous guide, check out its appendix, which contains the complete example code.
Relationships
Entities in a data model (tables) are seldom ‘stand alone’. Most of the time, they have some kind of relationship with surrounding entities. For example in Achievo, a project is related to a customer, a coordinator and to phases. A phase is related to activities, etc. Achievo’s backend contains features to quickly implement these relations in a user-friendly manner.
In the previous guide, you have seen that nodes contain attributes, that represent fields in the database. Just like attributes, a node can contain relations to other nodes. The addition of a relationship is just as easy as adding an attribute. There are several types of relations, each of which will be discussed in this chapter. The difference between the types of relations is made based on their ‘cardinality’ (for those of you unfamiliar with that term: cardinality indicates how many items can be involved in a relationship).
Many-to-one relation
Description
Of the three basic relation types, the many-to-one relation is probably the hardest to explain, but the easiest to implement, so I’ll start with this type of relation. Many-to-one means, as seen from our node, that many records of this type have a relationship with one record of some other node. As an example to explain this mumbo jumbo, we’re going to introduce ‘pizza categories’ and create a relationship between pizzas and categories.
Suppose we have a set of categories, (for example ‘small’, ‘medium’ and ‘large’). Suppose each pizza falls into one category. In one category, there can be many pizzas. So, from the pizza point of view, you might say there is a many-to-one (many-pizzas-in-one-category) relation with categories.
Pizza * <--------------> 1 Category
Such a many-to-one relation is represented in the pizza edit-screen by a dropdown box from which the user can select in which category the pizza belongs.
Ok, let’s implement this.
Preparations
First, we need a place to store categories. A category will only have a name, and of course, a primary key. This will lead to a simple table definition. For MySql, executing the following SQL statement on the Achievo database, should create the table for storing the categories:
<sql> CREATE TABLE pizza_categories (
id int(10) NOT NULL, name varchar(50) , PRIMARY KEY(id)
); </sql>
Then, we need to create a node in the pizza module. I’m not going to explain how to do this, as you already know everything you need to know to create such a node. But, just in case, here’s the basic implementation:
<?php
class pizza_category extends atkNode
{
function pizza_category()
{
$this->atkNode("pizza_category");
$this->add(new atkAttribute("id", AF_AUTOKEY));
$this->add(new atkAttribute("name", AF_OBLIGATORY|AF_UNIQUE|AF_SEARCHABLE));
$this->setTable("pizza_categories");
$this->setOrder("name");
}
}
?>
This should all look familiar to you. The only new thing you might have noticed is the use of the flag AF_AUTOKEY for the id attribute. In the previous guide, we used the flags AF_PRIMARY|AF_HIDE|AF_AUTO_INCREMENT. Actually, AF_AUTOKEY is a kind of 'shortcut flag', which does exactly the same as specifying the three flags separately. Saves you some typing on those primary key fields, which usually have these flags.
Save this code as class.pizza_category.inc in the pizza module directory. Next, we must add a menu-item to the Achievo menu, and setup access rights for the new node, by adding two lines to the appropriate functions in our module.inc:
In the getMenuItems() function, add this line:
$this->menuitem("pizza_categories", dispatch_url("pizzaman.pizza_category","admin"));
In the getNodes() function, add this line:
registerNode("pizzaman.pizza_category", array("admin", "add","edit", "delete"));
If these lines are not clear to you, read over the parts that deal with these issues in part 1 of this guide.
If you browse the Achievo installation now, you should be able to add some categories to the database. Add a few (‘Small’, ‘Medium’, ‘Large’ for example), we’ll use them later on.
There’s one preparation left to do, before we can implement the relation. In the pizza table, we need a new field to store the chosen category. Let’s call this field ‘category’. People might be in favor of calling such a referential key ‘category_id’, but I prefer to just name the field after the ‘role’ it performs. Use whatever you’re used to. The referential key must be of the same field type as the key it refers to (the id field in the pizza_categories table), so the following statement should alter the pizza table to add the correct field:
<sql> ALTER TABLE pizza ADD category int(10) NOT NULL DEFAULT ‘0‘; </sql>
(todo, copy/pate from the pdf version, starting page 6)