About Sitellite       Screenshots       Downloads       Forge      Documentation       Community       Support

You are here: Home / Documentation / Dynamic Object-Generation with saf.Database.Generic

Dynamic Object-Generation with saf.Database.Generic

Generic Table Relations

Table relations add several new methods to Generic-based objects, which allow you to control and query the relationships between the tables. These are dynamically generated methods, so their names are dependent on your object names. In the example to follow, which will be based on the above objects and tables, the new methods would be as follows:

For the Product object:

  • setCategory (&$category_object)
  • unsetCategory (&$category_object)
  • getCategories ()

For the Category object:

  • setProduct (&$product_object)
  • unsetProduct (&$product_object)
  • getProducts ()

Note that the get methods are pleuralized correctly according to their spelling, so Category correctly becomes Categories instead of Categorys, while Product simply becomes Products.

The second benefit of object relations isn't in the relations themselves, but in the method Generic uses to generate the dynamic methods. Generic 2.0 introduces a new load() method which integrates with the saf.Loader package to allows Generic to dynamically generate the object definitions we created above based exclusively on an INI file, and to be imported via saf.Loader as if the package being called was perfectly normal. Let's create a new file called inc/app/myapp/lib/Objects.ini.php with the following contents:

; <?php /*

[Product]

table = myapp_products
pkey = id
; permissions = on ; uncomment this if your table has the sitellite_* fields

[Category]

table = myapp_categories
pkey = id

[rel:Category:Product]

type = 1x ; one-to-many
Product field = category
cascade = on ; delete products when a category is deleted

; */ ?>

The first two INI blocks are the equivalents of the class definitions we created earlier. The third rel block defintes a one-to-many relationship between the tables. Generic also supports many-to-many relationships as well. Supposing a joining table of the form:

CREATE TABLE myapp_product_category (
	product_id INT NOT NULL,
	category_id INT NOT NULL,
	primary key (product_id, category_id)
);

A many-to-many relationship could be specified as follows:

[rel:Category:Product]

type = xx ; many-to-many
join_table = myapp_product_category
Product field = product_id
Category field = category_id

Back to our original example. We can now call these objects as follows:

<?php

loader_import ('myapp.Objects');

$category = new Category;

$cat_id = $category->add (
	array (
		'name' => 'Hosting Packages',
	)
);

$product = new Product;

$product->add (
	array (
		'name' => 'Basic Hosting',
		'price' => 9.95,
		'category' => $cat_id,
		'description' => '250MB Space, 5GB Transfer, etc.',
	)
);

?>

Note that our code is identical to the previous example, except for the 'myapp.Objects' inclusion instead of 'myapp.Product'. The lib/Product.php file can safely be eliminated now, as it is superceded by the new Objects.ini.php file. Note that if we need to add additional objects and relationships, we can have as many as we need in a single configuration file. Using this technique, you could potentially expose an entire API for your Sitellite-based apps without writing any code at all, just a simple INI file.

Now let's take a look at how the relationship methods work. Using these new methods, we could rewrite the box code above as follows:

<?php

loader_import ('myapp.Objects');

$product = new Product (
	array (
		'name' => 'Basic Hosting',
		'price' => 9.95,
		'description' => '250MB Space, 5GB Transfer, etc.',
	)
);

$category =& $product->setCategory (
	new Category (
		array (
			'name' => 'Hosting Packages',
		)
	)
);

?>

Alternately, we could have said:

<?php

loader_import ('myapp.Objects');

$category = new Category (
	array (
		'name' => 'Hosting Packages',
	)
);

$product =& $category->setProduct (
	new Product (
		array (
			'name' => 'Basic Hosting',
			'price' => 9.95,
			'description' => '250MB Space, 5GB Transfer, etc.',
		)
	)
);

?>

A few things to note in the examples above are: Passing an associative array to the creation of an object actually creates the object in the database for you automatically. Similarly, passing a primary key value upon creation of the object retrieves the appropriate database entry. This allows you to begin coding functionality immediately, instead of concerning yourself with the retrieval of data. When you're done making changes to an object, you can simply call save().

Also note that the set methods return a reference to the object being passed to them, allowing you to pass them a new object instantiation, but still to capture it and manipulate it further below.

A Brief Performance Tip

To eliminate the performance hit of regenerating the underlying dynamic class definitions on each use of the objects, make sure your app's lib folder is writeable by the web server, and the code will be saved to a file named lib/_Objects.php on the first time through. This file will automatically be updated if either the Objects.ini.php file or the Generic package itself are modified, so your code will always be automatically managed for you.



Page 1: Introduction to Generic
Page 2: Generic Table Relations
Page 3: A Complete Example
Page 4: Custom Objects

All Tutorials

Members

Note: You can use your SitelliteForge.com account here and vice versa.

Username

Password

Forgot your password?

Not a member? Click here to register

Sitellite 5 Beta


Copyright © 2008, SIMIAN systems Inc.
All rights reserved. Privacy policy
Some of the icons on this site were created by the Gnome Project.