Show your support for Zikula! Sign up at Github account and watch the Core project!
A short look at what PNObject is
More and more developers are working with the cool util classes of the object library. DataUtil, DateUtil, DBUtil, FileUtil, and so on... most people recognized the important ones already. While also other technologies like pnForm, hooks and PageLock are used, it seems that not that many devs are familiar yet with the object-oriented component model in Zikula. This article takes a look into the powerful PNObject architecture and what it can do for you.
DBUtil implements different default database operations and encapsulates manual SQL completely except complex cases. Whole object sets can be selected, inserted and updated with one call. ObjectUtil adds several services like attributes, categories or an object logging for all changes being made to particular objects. We will look at ObjectUtil later on again. Important for now is that DBUtil offers another level of database abstraction compared to direct use of the adodb library.
Some enhanced concepts like PNObject and PNObjectArray build up on that. PNObject represents a database object based on DBUtil and instantiates a data row of that. The PNObjectArray subclass instantiates multiple rows at once. Using objects results in a clean code structure separating the object-specific functionality and offering a standardized API to the outside. This makes it possible to apply central functions to multiple object types and safe a lot of redundant code. The way the component model works is based on the row data pattern and the active record pattern, unifying the data operations of DBUtil with business logic in classes. For this reason a PNObject represents a table row including additional domain logic being defined by the active record pattern. PNObjectArray realizes the table data gateway pattern. DBUtil offers the possibility to filter selections by assigning arrays with permission checks. This feature is supported in every PNObjectArray.
So where are the concrete advantages? Since every PNObject bases on a table, this is a very clean way to have all code for this table within the according class. So instead of calling DBUtil methods directly, you call methods of your object instances which include not only the DBUtil support, but also all additional logic at a central place. So this structured component model separates object-specific functionality and ensures an abstraction of default operations like selection and changes of the managed data object.You can easily define internal arrays for joins, permission filters. Furthermore PNObject instances can be enhanced with additional functionality by ObjectUtil. Every object can contain a set of default fields to store common information like date and author of the last update automatically. Every object can also have an attribute array which will be saved and loaded in the background. An attribute is a dynamic property with which you can enhance your object by additional fields without having to change the table structure. There are further services like extendable meta data and categorization, but this is not our topic today - let's return to PNObject.
As always the best aspect comes at last, hehe. PNObject offers some more predefined methods to allow further customizing while implementing your object's behavour. A realisation consists of reimplementing such methods like updatePreProcess(). The most important (and obvious) ones are insertPreProcess, updatePreProcess, deletePreProcess, selectPostProcess, insertPostProcess, updatePostProcess and deletePostProcess. This allows a flexible integration of a great amount of your business logic. And you can also do any further extensions - it is OO feel free to use the powerful means of object-oriented design, like inheritance and especially polymorphism.
So PNObject offers an abstraction of your data objects with a separated code structure. Your object can be managed with a generic interface which means an important step to component orientation. For example you need only one admin_view() function which delivers different view templates depending on the object type currently being treated.
Too see and download examples for refer to the ModuleStudio examples where all this stuff is at least partly used. Those modules also show how to combine pnForm, PageLock and other technologies with the PNObject architecture. Look especially at AutoBugs and AutoCocktails which are customized examples. For instance I implemented delete cascades in deletePostProcess to delete all affected ingredient assignments after a cocktail recipe has been deleted.
One last additional information: two new render plugins are going to get contributed to the core soon: getmodobject and getmodobjectarray will allow fetching PNObject-based data from any template. The reason for those being needed is that you do not need an api for pure data fetching tasks, so the pnmodapifunc is not sufficient in this case.
Have fun while experiencing the component-oriented code structure. Feel free to post a comment about your experience or any questions you want to be answered. Also ideas for upcoming blog articles are appreciated
Share This | Print