4

I am trying to create a table observer in a module. I am using the Table Advanced API guide in the Joomla documentation https://docs.joomla.org/Table_Advanced_API_Guide. When I use the code provided, the class MyObserver does not work. I have tried making the class abstract, and I have tried extending AbstractObserver instead of implementing JObserverInterface. When I try to make MyObserver abstract, then the createObserver function does not work. When I try to extend AbstractObserver, then it states that it cannot find the class AbstractObserver. How do I get the class MyObserver to work?

I am running Joomla 3.9.22 with PHP 7.0.33. My database is a MySQL version database 10.1.47-MariaDB-0+deb9u1.

myobserver.php

<?php
    
    defined('JPATH_PLATFORM') or die;
    
    class MyObserver implements JObserverInterface
    {
        // Usually you would define your class as
        // class MyObserver extends AbstractObserver
        // and then the $table variable and a basic constructor would be included for you
        protected $table;
        public function __construct($table)
        {
            $table->attachObserver($this);
            $this->table = $table;
            $observers = $table->getObserverOfClass("MyObserver");
            $observersClass = get_class($observers);
            echo "<br>In MyObserver constructor.<br>";
            echo "<br>Object returned from getObserverOfClass() has class {$observersClass}<br>";
        }
        
        public static function createObserver($table, $params = array())
        {
            $observer = new self($table);
            return $observer;
        }
    
        public function onAfterStore(&$result)
        {
            echo "<br>In observer onAfterStore()<br>";
            if ($result)
            {
                echo "Got table store method notification for table {$this->table->getTableName()}, id {$this->table->id}<br>";
            }
        }
    }

demomodules.php

<?php
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Table\Table;
class TableDemoModules extends Table

{
protected $_jsonEncode = array('params');

    function __construct(&$db)
    {
        parent::__construct('#__modules', 'id', $db);
        require 'myobserver.php';
        MyObserver::createObserver($this);
    }
    
    function check()
    {
        $this->note .= " added via module";
    }
    
    protected function _getAssetName()
    {
        return "com_modules.module." . $this->id;
    }
    
    protected function _getAssetTitle()
    {
        return $this->title;
    }
    
    protected function _getAssetParentId(Table $table = null, $id = null)
    {
        $assets = self::getInstance('Asset', 'JTable', array('dbo' => $this->getDbo()));
        $assets->load(array("name" => "com_modules"));
        return $assets->id;
    }
}

mod_advanced_table.php

<?php
defined('_JEXEC') or die('Restricted Access');

use Joomla\CMS\Factory;
use Joomla\CMS\Table\Table;

$app = Factory::getApplication();
$input = $app->input;
$user = Factory::getUser();

echo "Module id is {$module->id}<br>";

// Tell Joomla to look in the current (module) directory for our table class file
Table::addIncludePath(__DIR__);
$moduleTable = Table::getInstance('DemoModules', 'Table', array());

if ($moduleTable->load($module->id))
{
    echo "<br>Module title is {$moduleTable->title}<br>";
    // checkout/checkin
    if ($moduleTable->isCheckedOut($user->id))
    {
        echo "<br>module record isCheckedOut call returned true<br>";
    }
    else
    {
        echo "<br>module record isCheckedOut call returned false<br>";
    }
    // ACL rules
    if ($rules = $moduleTable->getRules())
    {
        $rulesString = (string) $rules;
        echo "<br>ACL Rules: $rulesString <br>";
    }
    else
    {
        echo "<br>getRules() didn't return anything<br>";
    }
    $userGroups = $user->getAuthorisedGroups();
    $randomIndex = array_rand($userGroups);
    $newRule = array("core.edit" => array($userGroups[$randomIndex] => 1));
    echo "Setting rules to " . json_encode($newRule) . "<br>";
    $moduleTable->setRules($newRule);
    $moduleTable->store();
    // ordering
    $where = 'POSITION = "' . $moduleTable->position . '"';
    echo "<br>Next order value: " . $moduleTable->getNextOrder($where) . "<br>";
    
    $moduleTable->move(2, $where);
    echo "Ordering value is now: {$moduleTable->ordering}<br>";
    
    $where .= " and published = 1";
    $moduleTable->reorder($where);
}
6

This was working ok on my instance Joomla 3.9.22 with PHP 7.3.5 (and mysql). Then to test this I selected PHP 7.0.33 instead and it gave me an error:

Fatal error: Declaration of MyObserver::createObserver($table, $params = Array) must be compatible with JObserverInterface::createObserver(JObservableInterface $observableObject, $params = Array) in C:\wamp64\www\...\modules\mod_advanced_table\myobserver.php on line 5

I managed to fix the problem by replacing

public static function createObserver($table, $params = array())

with

public static function createObserver(JObservableInterface $table, $params = array())

(Alternative if you can upgrade your version of php this problem might right itself).

Incidentally, you can define your class using

class MyObserver extends AbstractObserver

but you would have to precede that with:

use Joomla\CMS\Table\Observer\AbstractObserver;

Can you let me know if this fixes things as I'd like to update the Joomla documentation on that page with this issue.

2
  • Adding JObservableInterface to the function worked for me. Thank you for the solution. – rancper Dec 18 '20 at 23:28
  • 1
    Great, thanks for the confirmation. I've updated that Joomla docs page now. – Robbie Jackson Dec 19 '20 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.