Перейти к публикации
  • разработка интернет магазинов на opencart
  • доработка интернет магазинов на opencart
  • записей
    7
  • комментариев
    29
  • просмотр
    2 521

Как создавать "универсальные модули"


esculapra

1 842 просмотра

 Поделиться

Под понятием "универсальности" я подразумеваю совместимость с различными версиями и платформами (в данном случае Opencart и oStore).

эту статью я пишу для опытных разработчиков, которым не нужно объяснять, что в различных версиях магазина наблюдается отличие в структуре некоторых таблиц в БД. Также отличаются некоторые таблицы Opencart и oStore. Например, в Opencart отсутсвует таблица manufacturer_description, а в высших версиях таблица url_alias заменена на seo_url.

О программирование "универсального модуля" я расскажу на примере своего генератора ЧПУ.

Итак, в самом начале класса объявляю несколько переменных

     private $ext=''; // расширение файла
     private $opencart=false; // идентификатор платформы
     private $taba='url_alias'; // специфическое название таблицы
     private $token=null; // токен сессии
     private $token_indent='token'; // идентификатор токена

 

 public function index()
     {
       $this->load->language('supertools/sef');
       $this->document->setTitle($this->language->get('heading_title'));
       $this->load->model('supertools/sef');
     if(!$this->token)
       {
       if(VERSION<3) // проверяем версию
         {
           $this->token=$this->session->data['token'];
         if(VERSION<2.3) // также проверяем нижние версии, так как для версий меньше 2.3 при выводе необходимо указывать расширение файла шаблона
           {
             $this->ext='.tpl';
           }
         }
          else
         {
           $this->token=$this->session->data['user_token'];
           $this->token_indent='user_token';
           $this->taba='seo_url';
         }
       }
// тут мы проверяем переменную task, отправленную методом post, или же включенную в ссылку. задача нам указывает, какая функция затребована
     if(isset($this->request->post['task'])&&!empty($this->request->post['task']))
          $function=$this->request->post['task'];
      elseif(isset($this->request->get['task']))
          $function=$this->request->get['task'];
          // проверяем наличие функции и вызываем ее
          // такой подход полезен при отладке, когда в контроллере еще не прописанывсе функции, так как не вызовет фатальное ошибки 500
     if(isset($function))
       {
         $this->$function();
       }
        else
          $this->getList();
     }

      // вот пример универсальной ссылки
       $data['breadcrumbs'][]=array(
       'text'=>$this->language->get('text_home'),
       'href'=>$this->url->link('common/dashboard',$this->token_indent.'='.$this->token, 'SSL')
);
// а тут универсальный вывод шаблона
$this->response->setOutput($this->load->view('supertools/sef'.$this->ext, $data));


// а это одна функция из модели, демонстрирующая "универсальность"
 public function emptySef($taba,$id,$target,$if_opencart)
     {
       $field_title=($target=='information')?'title':'name';
       $description=($target=='manufacturer'&&$if_opencart)?'':'_description';
       $query=$this->db->query("SELECT query FROM `".DB_PREFIX.$taba."` WHERE `".$taba."_id`=".$id);
       $target_id=substr($query->row['query'],strpos($query->row['query'],'=')+1);
       $query=$this->db->query("SELECT ".$field_title." as name FROM `".DB_PREFIX.$target.$description."` WHERE `".$target."_id`=".$target_id);
       $alias=TransliterateCls::_transliterate($query->row['name']);
       $this->db->query("UPDATE `".DB_PREFIX.$taba."` SET `keyword`='".$alias."' WHERE `".$taba."_id`=".$id);
     return $alias;
     }

 

Разумеется, что для каждой конкретной задачи необходим  свой подход, но все в ваших руках. Я показал то, что реально работает.

 

 Поделиться

21 комментарий


Рекомендованные комментарии

Здравствуйте

Тут так и хочется привести слова из некоторого мема "На... - а главное зачем?"

 

Если вы пишите это с целью поделится своими наработками то зачем это

Цитата

эту статью я пишу для опытных разработчиков

ведь у всех, как вы говорите опытных разработчик есть свои наработки, и хочу заметить даже получше ваших, так как здесь:

Цитата

$query=$this->db->query("SELECT query FROM `".DB_PREFIX.$taba."` WHERE `".$taba."_id`=".$id);

$query=$this->db->query("SELECT ".$field_title." as name FROM `".DB_PREFIX.$target.$description."` WHERE `".$target."_id`=".$target_id);

$this->db->query("UPDATE `".DB_PREFIX.$taba."` SET `keyword`='".$alias."' WHERE `".$taba."_id`=".$id);

вы не пользуетесь системным методом экранирования вводимых данных $this->db->escape(), и было бы здорово(необходимо) указывать тип переменной (int)$target_id

Ссылка на комментарий
7 минут назад, OCdevWizard сказал:

вы не пользуетесь системным методом экранирования вводимых данных $this->db->escape(), и было бы здорово(необходимо) указывать тип переменной (int)$target_id

Да, в этом примере я взял код из старой версии, но так и было задумано. Действительно, экранирование и указание типа переменной - большое дело. Вот сразу видно, что не профан...

Ссылка на комментарий

А как тебе такой вариант?

 

 class ModelBase extends Model
   {
    
   public function _FUN($type,$fn,$options=null)
     {
       $function=$type.$fn;
        return $this->$function($options);
     }

 

   public function _get($fn,$options=null)
     {
       $function='get'.$fn;
        return $this->$function($options);
     }

   public function _set($fn,$options=null)
     {
       $function='set'.$fn;
        return $this->$function($options);
     }

   public function _update($fn,$options=null)
     {
       $function='update'.$fn;
        return $this->$function($options);
     }

   public function _delete($fn,$options=null)
     {
       $function='delete'.$fn;
        return $this->$function($options);
     }

***********************************

 

 class ModelShops extends ModelBase
   {

   public function __construct()
     {
       parent::__construct();
     }

   protected function getProductsTotal()
     {
       $query=$this->_db->getQuery(true);
       $query->select('count(*)');
       $query->from('#__shops_cat');
       $query->where('parent=0');
       $this->_db->setQuery($query);
       $total=$this->_db->loadResult();
        return $total;
     }

 

***************************

 

$total=$model->_get('ProductsTotal');

 

 

Это не касается Опенкарт - это моя система. Может я зациклился на проблемах безопасности? Я так не думаю - мой модуль модели имеет одну публичную функцию, а остальные или протект, или приват.

Ссылка на комментарий
32 минуты назад, OCdevWizard сказал:

опытных разработчик есть свои наработки, и хочу заметить даже получше ваших

я не собираюсь писюнами мерятся. есть лучше? - окей! под "кубом" - вонна!

Ссылка на комментарий
1 час назад, esculapra сказал:

я не собираюсь писюнами мерятся. есть лучше? - окей! под "кубом" - вонна!

Человек, который публикует такой бред! По умолчанию сам идет вонна!

Ссылка на комментарий

Мне плевать на комменты неадекватов - а кому-то пригодится, и если это будет один, то уже хорошо. У меня такие модули отлично работают, и экономят мое время и дисковое пространство.

Ссылка на комментарий

С самого начала у вас идут "вредные" советы уже в области именования переменных:

Цитата

private $ext=''; // расширение файла
     private $opencart=false; // идентификатор платформы
     private $taba='url_alias'; // специфическое название таблицы
     private $token=null; // токен сессии
     private $token_indent='token'; // идентификатор токена

Что за taba? Что за indent? В английском есть table и id (identifier, он же идентификатор, но никак не индентификатор), а есть indent - отступ, поэтому человек, хоть немного знающий английский, запутается в вашем коде уже с самого начала, не понимая, что за бессмыслица – отступ у токена? Хорошо хоть не tablica, но подозреваю, что даже такое название будет понятнее, чем taba, учитывая, что tab - это вкладки.

  • +1 1
Ссылка на комментарий
6 минут назад, RGB сказал:

Хорошо хоть не tablica

2 минуты назад, RGB сказал:

Что за taba? Что за indent?

Зачем придираться к переменным? Мне так удобно. Token_indent - сокращенно (подразумевается identifier).

tablica? Смешно. Такая шняга встречается у других прогеров, но не у меня. "Лодер эгог" - если такое слышу, меня коробит.

Я не претендую на звание самого-самого, просто привел пример, который работает.

Ссылка на комментарий
29 минут назад, RGB сказал:

а есть indent - отступ

Но также принимает значение порядок (order)? А в переводчике гугла есть "зазубринка" (акцент), то есть указание на что-либо. Может также означать "заявка". Выбирай себе любой... Taba не переводится, но если на то уж пошло, путь будет target _table_in_database, и session_identifier

Изменено пользователем esculapra
Ссылка на комментарий
В 23.08.2020 в 11:42, esculapra сказал:

Зачем придираться к переменным?

Потому что неопытный разработчик начитается таких статей и будет использовать такую же систему именования, в которой никто, кроме него, не разберется. Если вы хотите кого-то учить, то должны сами знать эти элементарные вещи, а не использовать аргументацию "мне так удобно"

 

Ссылка на комментарий
48 минут назад, RGB сказал:

Потому что неопытный разработчик

А "опытый" закубит гамно- код, и ура! вы меня уже довели до белого каления!  выложу свой мод, а вы целуйте сео-про. Тут кто-то упрекал за инглиш, так у меня ЧПУ (search ebgin friendly ), никак не СЕО (search ebgine optimization) , потому что СЭО подразумевает структуру (мета- название, мета-описание, мета-ключевы...)

Ссылка на комментарий
1 час назад, spectre сказал:

 

Это все фигня!

На форуме половина модулей/шаблонов не поддерживают эти стандарты и делают модули как им удобно и как хотят.

 

Пример из этой же статьи, делают один модуль для всех версия, а потом удивляешься откуда в ОС 3.x появились файлы tpl или наоборот откуда в ОС 2.x файлы twig-а или вообще почему папка module появилась в корне controller если она должна быть в controller/extension

Ссылка на комментарий
15 часов назад, Bn174uk сказал:

На форуме половина модулей/шаблонов не поддерживают эти стандарты и делают модули как им удобно и как хотят.

Я и не спорю. Просто поделился своими наработками. Конструкция

if(isset($function))
       {
         $this->$function();
       }

позволяет подключать protected и private, что в ставндартном обработчике невозможно. У меня только одна общедоступная public function index() Да, в модели приходится объявлять публичне, или же сделать одну, типа

  public function _FUN($type,$fn,$options=null)
     {
       $function=$type.$fn;
        return $this->$function($options);
     }

Та я понял, шо тут все умные, а кто показывает нестандартное решение - дураки сразу.

Ссылка на комментарий
15 часов назад, Bn174uk сказал:

а потом удивляешься откуда в ОС 3.x появились файлы tpl или наоборот откуда в ОС 2.x файлы twig

Ну на работу это же не влият. Хорошо, можно сделать отдельные архивы контроллеров и моделей для разных платформ и версий, а можно один. Нус  шаблами, разумеется, ьтакая шняга не проходит. Врочем, 2 и 2.3 отличаются token и user_token - у меня предусмотрено.

Ссылка на комментарий

Ну и я поделюсь админкой:

Спойлер
if (version_compare(VERSION, '2.2.0', '<')) {
	class ControllerModuleMyModule extends ControllerExtensionModuleMyModule {}
}

class ControllerExtensionModuleMyModule extends Controller {
	private $error = array();
	private $name_arhive = 'My Module';
	private $code = '0000000001';
	private $mame = 'Мой модуль - "My Module"';
	private $version = '1.0.0';
	private $author = 'My Module';
	private $link = '';
	private $version_oc = 2.2;
	private $paths = array();

	public function __construct($foo) {
		parent::__construct($foo);
		if (version_compare(VERSION, '3.0.0', '>=')) {
			$this->language->set('my_module_version', $this->version);
			$this->version_oc = 3;
			$this->paths = array(
				'controller' => array(
					'my_module' => 'extension/module/my_module',
					'extension' => 'marketplace/extension',
					'modification' => 'marketplace/modification',
				),
				'language' => array(
					'my_module' => 'extension/module/my_module',
				),
				'model' => array(
					'my_module' => 'extension/module/my_module',
					'my_module_path' => 'model_extension_module_my_module',
					'module' => 'setting/module',
					'module_path' => 'model_setting_module',
					'extension' => 'setting/extension',
					'extension_path' => 'model_setting_extension',
					'modification' => 'setting/modification',
					'modification_path' => 'model_setting_modification',
					'event' => 'setting/event',
					'event_path' => 'model_setting_event',
				),
				'view' => array(
					'my_module' => 'extension/module/my_module',
				),
				'token' => 'user_token=' . $this->session->data['user_token']
			);
		} elseif (version_compare(VERSION, '2.2.0', '>=')) {
			$this->language->set('my_module_version', $this->version);
			$this->version_oc = 2.2;
			$this->paths = array(
				'controller' => array(
					'my_module' => 'extension/module/my_module',
					'extension' => 'extension/extension',
					'modification' => 'extension/modification',
				),
				'language' => array(
					'my_module' => 'extension/module/my_module',
				),
				'model' => array(
					'my_module' => 'extension/module/my_module',
					'my_module_path' => 'model_extension_module_my_module',
					'module' => 'extension/module',
					'module_path' => 'model_extension_module',
					'extension' => 'extension/extension',
					'extension_path' => 'model_extension_extension',
					'modification' => 'extension/modification',
					'modification_path' => 'model_extension_modification',
					'event' => 'extension/event',
					'event_path' => 'model_extension_event',
				),
				'view' => array(
					'my_module' => 'extension/module/my_module',
				),
				'token' => 'token=' . $this->session->data['token']
			);
		} else {
			$this->version_oc = 2;
			$this->paths = array(
				'controller' => array(
					'my_module' => 'module/my_module',
					'extension' => 'extension/module',
					'modification' => 'extension/modification',
				),
				'language' => array(
					'my_module' => 'module/my_module',
				),
				'model' => array(
					'my_module' => 'module/my_module',
					'my_module_path' => 'model_module_my_module',
					'module' => 'extension/module',
					'module_path' => 'model_extension_module',
					'extension' => 'extension/extension',
					'extension_path' => 'model_extension_extension',
					'modification' => 'extension/modification',
					'modification_path' => 'model_extension_modification',
					'event' => 'extension/event',
					'event_path' => 'model_extension_event',
				),
				'view' => array(
					'my_module' => 'module/my_module.tpl',
				),
				'token' => 'token=' . $this->session->data['token']
			);
		}
	}

	public function index() {
		foreach ($this->load->language($this->paths['language']['my_module']) as $key => $lang) {
			$data[$key] = $lang;
		}



		if ($this->version_oc >= 3) {
			$template_engine = $this->registry->get('config')->get('template_engine');
			$this->registry->get('config')->set('template_engine', 'template');
		}

		$template = $this->load->view($this->paths['view']['my_module'], $data);

		if ($this->version_oc >= 3) {
			$this->registry->get('config')->set('template_engine', $template_engine);
			$this->response->addHeader('Content-Type: text/html; charset=utf-8');
		}

		$this->response->setOutput($template);
	}
}

 

 

  • +1 1
Ссылка на комментарий

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас
  • Сейчас на странице   0 пользователей

    • Нет пользователей, просматривающих эту страницу.
×
×
  • Создать...

Важная информация

На нашем сайте используются файлы cookie и происходит обработка некоторых персональных данных пользователей, чтобы улучшить пользовательский интерфейс. Чтобы узнать для чего и какие персональные данные мы обрабатываем перейдите по ссылке. Если Вы нажмете «Я даю согласие», это означает, что Вы понимаете и принимаете все условия, указанные в этом Уведомлении о Конфиденциальности.