在上一节,已经完成了mysql数据库迁移到人大金仓数据库了,接下来将配置joomla让它运行在人大金仓数据库上。理论上如果人大金仓数据库的SQL语法和mysql 的SQL语法差别不大的话,当配置数据库为人大金仓后系统应该能够跑起来的。当然,这是最好的期待。

调整数据库的链接


在这里,直接修改configuration.php文件,找到其中的数据库设置参数,设置为人大金仓的数据库即可。具体修改的地方如下:

	public $dbtype = 'pdokdb'; //数据库类型
	public $host = '127.0.0.1';//数据库主机地址
	public $user = 'JOOMLA';//数据库用户名
	public $password = 'zmax99';//数据库密码
	public $db = 'JOOMLA';//数据库名称
	public $dbprefix = 'a3bav_';//数据表前缀

 做了这些设置,保存后就完成了数据库链接的调整了。

SQL语句的调整策略


当完成了数据库的调整后,你的Joomla系统大概率是不能跑起来的,我们需要进一步进行适配。此时有一个好的调试策略是非常重要的,我们需要有一个方法捕捉到系统抛出的错误信息,从中得到一些解决的提示。最好能够得到出错的SQL代码。当出现错误的时候,可以直接将出错的代码放到数据库自带的客户端中执行,这样可以得到更加丰富的错误信息。

实现execute()方法,直接复制父类的execute()方法的代码,在其中加入调试信息。因为所有执行的SQL语句都会执行这个方法,因此,在这里可以获得最终执行的SQL语句。具体的代码如下:

	public function execute()
	{
		$this->connect();

		// Take a local copy so that we don't modify the original query and cause issues later
		$query = $this->replacePrefix((string) $this->sql);
		//echo "SQL:".$query."<br/><br/><br/>";

		if (!is_object($this->connection))
		{
			JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database');
			throw new JDatabaseExceptionExecuting($query, $this->errorMsg, $this->errorNum);
		}

		// Increment the query counter.
		$this->count++;

		// Reset the error values.
		$this->errorNum = 0;
		$this->errorMsg = '';

		// If debugging is enabled then let's log the query.
		if ($this->debug)
		{
			// Add the query to the object queue.
			$this->log[] = $query;

			JLog::add($query, JLog::DEBUG, 'databasequery');

			$this->timings[] = microtime(true);
		}

		// Execute the query.
		$this->executed = false;

		if ($this->prepared instanceof PDOStatement)
		{
			// Bind the variables:
			if ($this->sql instanceof JDatabaseQueryPreparable)
			{
				$bounded = $this->sql->getBounded();
				
				foreach ($bounded as $key => $obj)
				{
					
					$this->prepared->bindParam($key, $obj->value, $obj->dataType, $obj->length, $obj->driverOptions);
				}
			}
			try{
				
				
				$this->executed = $this->prepared->execute();	
			}
			catch(PDOException $e){

				echo "<pre>";
					print_r($this->prepared);
				echo "</pre>";
				echo $e->getMessage();
				die("zmax pdo debug stop file pdokdb.php");
			}
		
			
		}

		if ($this->debug)
		{
			$this->timings[] = microtime(true);

			if (defined('DEBUG_BACKTRACE_IGNORE_ARGS'))
			{
				$this->callStacks[] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
			}
			else
			{
				$this->callStacks[] = debug_backtrace();
			}
		}
	
		// If an error occurred handle it.
		if (!$this->executed)
		{
		
			// Get the error number and message before we execute any more queries.
			$errorNum = $this->getErrorNumber();
			$errorMsg = $this->getErrorMessage();

			// Check if the server was disconnected.
			if (!$this->connected())
			{
				
				try
				{
			
					// Attempt to reconnect.
					$this->connection = null;
					$this->connect();
				}
				// If connect fails, ignore that exception and throw the normal exception.
				catch (RuntimeException $e)
				{
					// Get the error number and message.
					$this->errorNum = $this->getErrorNumber();
					$this->errorMsg = $this->getErrorMessage();

					// Throw the normal query exception.
					JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database-error');

					throw new JDatabaseExceptionExecuting($query, $this->errorMsg, $this->errorNum, $e);
				}

				// Since we were able to reconnect, run the query again.
				return $this->execute();
			}
			// The server was not disconnected.
			else
			{
				// Get the error number and message from before we tried to reconnect.
				$this->errorNum = $errorNum;
				$this->errorMsg = $errorMsg;

				// Throw the normal query exception.
				JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database-error');

				throw new JDatabaseExceptionExecuting($query, $this->errorMsg, $this->errorNum);
			}
		}

		return $this->prepared;
	}

 重点关注其中的try ,catch部分:

try{
				
				
				$this->executed = $this->prepared->execute();	
			}
			catch(PDOException $e){

				echo "<pre>";
					print_r($this->prepared);
				echo "</pre>";
				echo $e->getMessage();
				die("zmax pdo debug stop file pdokdb.php");
			}

 一旦检测到了SQL执行异常,就打印出错误的SQL语句。这样非常的方便。如果错误信息不够直观,将出错的SQL复制到客户端自带的SQL编辑器中执行。

初步的数据库驱动类的调整


设置$nameQuote属性

由于人大金仓只支持双引号来包裹字段,因此,需要重新设置驱动类的 $nameQuote属性。

	/**
	 * The character(s) used to quote SQL statement names such as table names or field names,
	 * etc. The child classes should define this as necessary.  If a single character string the
	 * same character is used for both sides of the quoted name, else the first character will be
	 * used for the opening quote and the second for the closing quote.
	 *
	 * @var    string
	 * @since  3.4
	 */
	protected $nameQuote = '"'; //人大金仓只能使用双引号

设置$nullDate属性

由于在导入的时候我们将0000-00-00 00:00:00 设置为0001-01-01 00:00:00.1 因此,也需要对应的设置nullDate属性。

	/**
	 * The null or zero representation of a timestamp for the database driver.  This should be
	 * defined in child classes to hold the appropriate value for the engine.
	 *
	 * @var    string
	 * @since  3.4
	 */
	protected $nullDate = '0001-01-01 00:00:00.0'; //数据库空日期的表示

调整replacePrefix方法

在实际调试中发现数据库的前缀无法替换,具体哪里引起的,没有仔细分析。因此,也需要重新实现一下replacePrefix方法。

	/**
	 * This function replaces a string identifier <var>$prefix</var> with the string held is the
	 * <var>tablePrefix</var> class variable.
	 *
	 * @param   string  $sql     The SQL statement to prepare.
	 * @param   string  $prefix  The common table prefix.
	 *
	 * @return  string  The processed SQL statement.
	 *
	 * @since   1.7.0
	 */
	public function replacePrefix($sql, $prefix = '#__')
	{
		$literal = parent::replacePrefix($sql, $prefix);
		$literal = str_replace($prefix,$this->tablePrefix,$literal);
		return $literal;
	}

做完了这些,基本上你可以成功的打开前台和登录后台了。下面是测试之后的效果:

kdb_ok.png

 解决全局设置无法保存的问题


当使用人大金仓数据库后,在全局设置中,如果点击保存,会提示无法链接到数据库。要解决这个问题,只需要修改administrator/components/com_config/model/form/application.xml 文件。将其中的dbtype字段的supported属性增加pdokdb的支持即可

		<field
			name="dbtype"
			type="databaseconnection"
			label="COM_CONFIG_FIELD_DATABASE_TYPE_LABEL"
			description="COM_CONFIG_FIELD_DATABASE_TYPE_DESC"
			supported="mysql,mysqli,pgsql,pdomysql,pdokdb,postgresql,sqlsrv,sqlazure"
			filter="string"
		/>

在编辑界面可以看到系统已经识别了pdokdb这个数据库类型了。

kdb_support.png

是否已经适配完成?


上面虽然已经能够进入系统,但适配并没有完成。相反,可以说是刚刚才正式开始。我们需要列出一个新的适配计划:

  • 1,点击各个菜单项,看看是否有问题
  • 2,尝试新建,保存文章是否有问题
  • 3,测试,新建保存,编辑用户是否问题
  • 4,测试新建保存用户组是否有问题
  • 6,测试新建保存编辑菜单是否有问题
  • 7,测试各种排序过滤是否有问题
  • 8,测试扩展的安装卸载是否有问题
  • 9,系统上能点的链接都试一下是可以不错的建议

以上还只是对joomla核心的测试,如果是对一个已经完成的项目进行迁移,那么需要做的适配就更多了。这个和具体的代码编写有关。 

目前我的迁移测试工作只做到了系统的各个核心组件增删改查都没有问题。但安装卸载扩展还是有一些问题没有解决。主要的解决思路已经有了,剩下的部分只是时间问题。如果有朋友对迁移有兴趣,可以和我探讨。

已经适配的代码


源文件

libraries/joomla/database/driver/pdokdb.php文件:

pdokdb.php

libraries/joomla/database/query/pdokdb.php文件:

pdokdb.php

用法

设置好PDO后,直接将这两个文件放到对应的位置,然后就可以使用pdokdb这个数据库了。如果数据库已经成功迁移,调整confiration.php文件的数据库链接,即可直接将joomla运行在人大金仓数据库上了。

在整个的适配过程中,我们基本上没有修改任何的Joomla核心,因此,之后的升级都不会有任何的问题。同时,可以看到joomla底层对数据库的抽象是做得非常好的。

评论 (0)

  • 最新在前
  • 最佳在前