Ticket #706 (closed defect: invalid)

Opened 7 years ago

Last modified 1 month ago

If custom module calls setFetchMode(DB_FETCHMODE_ASSOC) on SGL_DB object, block loading breaks

Reported by: jsheth Assigned to: jsheth
Priority: normal Milestone: 0.4.8
Component: SGL - BlockLoader Severity: normal
Keywords: Cc:

Description

If one develops a custom module that contains the following code, block loading will break. The error received will be:

MESSAGE: is not a valid block classname TYPE: NO CLASS DEBUG INFO: CODE: -104

The code to use in a custom module to trigger this error would be: $dbh = & SGL_DB::singleton(); $dbh->setFetchMode(DB_FETCHMODE_ASSOC);

The error above is triggered by the _buildBlocks method in the SGL_Blockloader class.

function _buildBlocks()
    {
        // render content
        if (count($this->_aData) > 0 ) {
            foreach ($this->_aData as $index => $oBlock) {
                $blockClass = $oBlock->name;
                $blockPath = SGL_BLK_DIR . '/' . $blockClass . '.php';
                //echo "<h1>blockPath is $blockPath</h1>";
                @include_once $blockPath;
                if (!class_exists($blockClass)) {
                    unset($this->_aData[$index]);
                    SGL::raiseError($blockClass . ' is not a valid block classname',
                        SGL_ERROR_NOCLASS);
                } else {
                    @$obj = & new $blockClass();
                    $this->_aData[$index]->content = $obj->init($this->output);
                }
            }
            $this->_sort();
        }
    }

The specific point it fails at in the method above is: '$blockClass = $oBlock->name;'

Here, if the default Seagull behavior for the singleton instance of the SGL_DB object is preserved, thus enabling us to access $oBlock as an object (instead of as an array). This default behavior is triggered by this code in the setConnection method of the SGL_DB class:

$GLOBALS_SGL?CONNECTIONS?[$dsnMd5]->setFetchMode(DB_FETCHMODE_OBJECT);

Because the Singleton pattern is used to access an instance of the SGL_DB class, state settings such as setting the fetch mode to use objects will persist across method calls, even in different functions / classes / scripts, as long as they are all in the same webserver request.

This error message is hard to diagnose, and does look like a bug. There are various workarounds, including setting conventions for correct usage of the SGL_DB object. These could be:

1) Never set the fetch mode for the SGL_DB global singleton instance. If one wants something different from the default DB_FETCHMODE_OBJECT behavior, one could pass it as an additonal parameter to getAll(), getRow(), etc. This can get a bit cumbersome though.

2) Whenever you are SELECTing data using SGL_DB, explicitly set the fetch mode to what you want it to be, and do not assume the default value set by the setConnection method will remain the same.

There is not one clear answer to this problem, so it would be best to see what consensus emerges.

In the mean time. the following line should probably ensure that the list of blocks is always loaded correctly:

Insert this after the first line of the _loadBlocks method in SGL_Blockloader: $dbh->setFetchMode(DB_FETCHMODE_OBJECT);

Change History

01/03/13 12:04:29 changed by demian

  • status changed from new to closed.
  • resolution set to invalid.