Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

Мой копирайтинг

  • записів
    7
  • коментарів
    29
  • переглядів
    3 346

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


esculapra

2 073 перегляди

Под понятием "универсальности" я подразумеваю совместимость с различными версиями и платформами (в данном случае 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 коментар


Recommended Comments

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

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

 

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

Цитата

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

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

Цитата

$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 користувачів

    • Ні користувачів, які переглядиють цю сторінку
×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.