Jump to content
  • entries
    8
  • comments
    31
  • views
    2,098

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

esculapra

1,477 views

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

 

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

 



22 Comments


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

Share this comment


Link to comment
7 минут назад, OCdevWizard сказал:

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

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

Share this comment


Link to comment

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

 

 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');

 

 

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

Share this comment


Link to comment
32 минуты назад, OCdevWizard сказал:

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

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

Share this comment


Link to comment
1 час назад, esculapra сказал:

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

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

Share this comment


Link to comment

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

Share this comment


Link to comment

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

Цитата

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

Share this comment


Link to comment
6 минут назад, RGB сказал:

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

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

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

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

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

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

Share this comment


Link to comment
29 минут назад, RGB сказал:

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

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

Edited by esculapra

Share this comment


Link to comment
31 минуту назад, RGB сказал:

Что за taba?

Если я запишу как, table_in_version, это на код повлияет?

Share this comment


Link to comment
В 23.08.2020 в 11:42, esculapra сказал:

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

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

 

Share this comment


Link to comment
48 минут назад, RGB сказал:

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

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

Share this comment


Link to comment
1 час назад, spectre сказал:

 

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

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

 

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

Share this comment


Link to comment
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);
     }

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

Share this comment


Link to comment
15 часов назад, Bn174uk сказал:

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

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

Share this comment


Link to comment

Вот еще 

Названия созданных мною тем и модулей не гуглятся)

  • +1 1

Share this comment


Link to comment

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

Спойлер
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);
	}
}

 

 

Share this comment


Link to comment

тут же есть вставка КОД. отформатируй статейку как следует, ибо не читаемо

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

On our site, cookies are used and personal data is processed to improve the user interface. To find out what and what personal data we are processing, please go to the link. If you click "I agree," it means that you understand and accept all the conditions specified in this Privacy Notice.