This package implements the pj DataProvider Framework library under Joomla! CMS. Refer there for detailed description of InfoBase, SearchKey, IDataProvider and MySqlDataProvider.

This documentation is powered by the Dispute component based on the pj DataProvider for Joomla! and pj DataProvider Framework respectively.

Usage:

pj DataProvider Framework package (lib_pj) is an alternative database concept beside of Joomla's JDatabase framework.

The developer designs new classes extending the InfoBase class and registers them at start-up in the singleton DataProviderBase instance. It is not necessary to add any code to bare class declarations, although it is convenient to outsource specific functionality there.

The framework offers full database access for registered InfoBase classes, including retrieving by ID or by queries passed either as string or as SearchKey structure. It recognizes changes of instance data and inserts, updates and deletes instances together with corresponding table rows, optionally in nested transactions. It ensures that at any time, there exists just one unique instance of InfoBase extending class corresponding to one database table row.

The developer has to write an extension of the DataProviderBase class and outsource his/her business layer functions there.

Encapsulates interface to the actual database.

The DataProviderBase class is located in the file /libraries/pj/DataProvider.php. It implements several concepts:

  • It is the interface between Joomla! CMS and the actual DataProvider (MySqlDataProvider only implemented yet). It reads connection settings from JFactory::getConfig(), instantiates the DataProvider, opens database connection and registers several basic Joomla! and PJ classes1;
  • intermediates general DataProvider functions like retrieving tables and fields information and executing queries;
  • implements basic handling functions for counting, retrieving, listing, updating and deleting of InfoBase objects;
  • implements recursive transaction mechanism;
  • implements the concept of PJVisitorInfo;
  • provides base for development of extension and module specific Joomla! DataProvider classes.

The DataProviderBase class isn't intended for instantiating itself. Instead, the extending class should declare a static instance() function creating a singleton instance. See DataProviderBase API and DataProviderBase Example for further details.


1 The basic registered Joomla! classes are UserInfo, UserProfileInfo, MenuInfo, ModuleInfo, ModuleMenuInfo and ExtensionInfo. Other defined, yet not registered Joomla! classes are CategoryInfo, ContentInfo and LanguageInfo. All predefined Joomla! classes are located in the file /libraries/pj/JoomlaInfo.php. Registered PJ classes are PJVisitorInfo and PJVisitorTcpipInfo, both located in the file /libraries/pj/VisitorInfo.php.

// declare own provider class
// assume there are tables and InfoBase classes like those in constructor's $knownTables

class MyDataProvider extends DataProviderBase
{

  // declare singleton instance
  private static $instance;
  static function instance()
  {
    if (!self::$instance)
      self::$instance = new MyDataProvider ();
    return self::$instance;
  }

  // protected constructor
  protected function __construct()
  {
    $knownTables = array(
      'MyPersonInfo' => 'persons',
      'MyCompanyInfo' => 'companies',
      'MyRelationInfo' => 'person2company'
    );
    parent::__construct($knownTables);
  }

  // implement some simple retrieving functions

  function GetPerson ($personId)
  {
    return $this->GetItem('MyPersonInfo', $personId);
  }

  function GetCompany ($companyId)
  {
    return $this->GetItem('MyCompanyInfo', $companyId);
  }

  // implement some more complex functions

  function HireEmployee (MyCompanyInfo $company, MyPersonInfo $employee)
  {
    // check if already employed
    $key = new SearchKey('id_company', $company->ID());
    $key->AddAndKey(new SearchKey('id_employee', $employee->ID()));
    // look for such relation
    if (!$this->ListItems('MyRelationInfo', $key))
    {
      // not employed yet, create relation
      $rel = new MyRelationInfo ($employee->ID(), $company->ID());
      $this->UpdateItem($rel);
      return true; // we have hired him
   }
  }

  function FireEmployee (MyCompanyInfo $company, MyPersonInfo $employee)
  {
    // check if employed
    $key = new SearchKey('id_company', $company->ID());
    $key->AddAndKey(new SearchKey('id_employee', $employee->ID()));
    // look for such relation
    if ($list = $this->ListItems('MyRelationInfo', $key))
    {
      // is employed, delete relation
      $this->DeleteItem($list[0]);
      return true; //we have fired him
    }
  }

  function ListEmployees (MyCompanyInfo $company)
  {
    // PersonInfo->id is related to MyRelationInfo->id_person
    $rel = new SearchRelation ('id', 'MyRelationInfo', 'id_person');
    // query where MyRelationInfo->id_company points to our $company
    $key = new RelatedKey ($rel, 'id_company', $company->ID());
    // get all such MyPersonInfo instances
    return $this->ListItems ('MyPersonInfo', $key);
  }

  // implement some transaction Update functions
  // assume MyPersonInfo has a function Company() returning CompanyInfo or null

  function UpdatePerson (MyPersonInfo $person)
  {
    $trans = $this->BeginTransaction();
    try
    {
      if ($person->isDirty)
        // update $person itself
        $this->UpdateInfo ($person);
      if ($company = $person->Company())
      {
        // first update $company as it could be a new one
        $this->UpdateCompany ($company);
        // now ensure $person is employed there
        $this->HireEmployee ($company, $person);
      }
      // OK, commit
      $this->CommitTransaction ($trans);
    }
    catch (Exception $ex)
    {
      // something went wrong, rollback and throw again
      $this->RollbackTransaction ($trans);
      throw $ex;
    }
  }

  function UpdateCompany (MyCompanyInfo $company)
  {
    if ($company->isDirty) // else ignore
    {
      $trans = $this->BeginTransaction();
      try
      {
        // update $company
        $this->UpdateItem($company);
        // do what else necessary
        // ...

        // and commit
        $this->CommitTransaction ($trans);
      }
     catch (Exception $ex)
      {
        // something went wrong, rollback and throw again
        $this->RollbackTransaction ($trans);
        throw $ex;
      }
    }
  }