Кешування _table_columns в ORM Kohana 3.3

Використовуючи ORM в фреймворку Kohana 3.3, і проглядаючи профайлер запитів до бази даних, мене здивував запит типу SHOW FULL COLUMNS FROM `TABLE`, бо він виявився найбільш тривалим з усіх запитів. По замовчуванню ORM (Kohana 3) робить такі селекти за кожним запитом сторінки і по кожній таблиці, яка бере участь в моделях даних. Трохи пошукавши вирішення цієї проблеми в інтернет, я знайшов два варіанти:
  1. Фіксований перелік полів в моделі ORM
  2. Кешування переліку полів для ORM

Фіксований перелік полів в моделі ORM

Жорстко зафіксувати перелік полів, які буде показувати ORM-модель можна з допомогою визначення protected $_table_columns; у відповідній моделі. Спочатку необхідно вивести всі поля через метод list_columns():
<?php
echo '<pre>';
var_export(ORM::factory('User')->list_columns()); // Виводяться всі поля із моделі 'User'
echo '</pre>';
Після чого отриманий вивід можна повністю копіювати і вставляти в модель так:
<?php defined('SYSPATH') or die('No direct access allowed.');
 
class Model_Wordpress_Menu extends ORM {
	protected $_table_columns = array (
	  'id' => 
	  array (
		'type' => 'int',
		'min' => '0',
		'max' => '4294967295',
		'column_name' => 'id',
		'column_default' => NULL,
		'data_type' => 'int unsigned',
		'is_nullable' => false,
		'ordinal_position' => 1,
		'display' => '11',
		'comment' => '',
		'extra' => 'auto_increment',
		'key' => 'PRI',
		'privileges' => 'select,insert,update,references',
	  ),
	  'email' => 
	  array (
		'type' => 'string',
		'column_name' => 'email',
		'column_default' => NULL,
		'data_type' => 'varchar',
		'is_nullable' => false,
		'ordinal_position' => 2,
		'character_maximum_length' => '254',
		'collation_name' => 'utf8_general_ci',
		'comment' => '',
		'extra' => '',
		'key' => 'UNI',
		'privileges' => 'select,insert,update,references',
	  ),
	  'username' => 
	  array (
		'type' => 'string',
		'column_name' => 'username',
		'column_default' => '',
		'data_type' => 'varchar',
		'is_nullable' => false,
		'ordinal_position' => 3,
		'character_maximum_length' => '32',
		'collation_name' => 'utf8_general_ci',
		'comment' => '',
		'extra' => '',
		'key' => 'UNI',
		'privileges' => 'select,insert,update,references',
	  ),
	  'password' => 
	  array (
		'type' => 'string',
		'column_name' => 'password',
		'column_default' => NULL,
		'data_type' => 'varchar',
		'is_nullable' => false,
		'ordinal_position' => 4,
		'character_maximum_length' => '64',
		'collation_name' => 'utf8_general_ci',
		'comment' => '',
		'extra' => '',
		'key' => '',
		'privileges' => 'select,insert,update,references',
	  ),
	  'logins' => 
	  array (
		'type' => 'int',
		'min' => '0',
		'max' => '4294967295',
		'column_name' => 'logins',
		'column_default' => '0',
		'data_type' => 'int unsigned',
		'is_nullable' => false,
		'ordinal_position' => 5,
		'display' => '10',
		'comment' => '',
		'extra' => '',
		'key' => '',
		'privileges' => 'select,insert,update,references',
	  ),
	  'last_login' => 
	  array (
		'type' => 'int',
		'min' => '0',
		'max' => '4294967295',
		'column_name' => 'last_login',
		'column_default' => NULL,
		'data_type' => 'int unsigned',
		'is_nullable' => true,
		'ordinal_position' => 6,
		'display' => '10',
		'comment' => '',
		'extra' => '',
		'key' => '',
		'privileges' => 'select,insert,update,references',
	  ),
	);
}
Даний варіант мабуть найкращий що стосується швидкодії, та ручного контролю переліку полів. Поганий даний варіант тим, що його потрібно буде вручну змінювати кожен раз, коли ви вносите відповідні зміни в структуру ваших таблиць.

Кешування переліку полів для ORM

Для автоматичного кешування переліку полів можна перевизначити клас ORM наступним чином:
<?php defined('SYSPATH') OR die('No direct script access.');

class ORM extends Kohana_ORM{

	protected $_cached_fields = array();

	public function reload_columns($force = FALSE)
	{
		if($force === TRUE or empty($this->_table_columns))
		{
			$this->_table_columns = Cache::instance('file')->get('ORM_list_columns_'.$this->_table_name);
			if($force === TRUE or empty($this->_table_columns))
			{
				parent::reload_columns($force);
				Cache::instance('file')->set('ORM_list_columns_'.$this->_table_name, $this->_table_columns, Date::DAY);
			}
		}
	}
	
// Слідуючий метод не має відношення до кешування, але ви його теж можете використовувати,
// він робить запити типу select * from table замість переліку всіх полів таблиці
	protected function _build_select()
	{
		/*$columns = array();
		foreach ($this->_table_columns as $column => $_)
		{
			$columns[] = array($this->_object_name.'.'.$column, $column);
		}

		return $columns;*/
		
		return $columns = array($this->_object_name.'.*');
	}
}
Якщо ви знайшли помилку, прохання - виділіть текст помилки (максимум 127 символів) і натисніть Ctrl+Enter.