Резюме
на вакансию Php программиста
Камышин Константин Сергеевич


О разработке

За 17 лет в разработке, особенно за время пока я 5 лет руководил командой разработчиков в собственной компании я сделал ряд выводов и считаю важным поделится ими здесь, многие выводы кому-то покажутся очевидными, но уверяю вас для большинства людей работающих в it они не очевидны:

  • Разработчик не должен оценивать сроки, их оценивает тимлид и согласует с разработчиком, именно при разборе и выявлении обьективных причин меняются сроки
  • В компании именно тимлид отвечает за косяки на проекте, потому что именно он делает кодревью, он должен иметь представление в общем о развитии проекта, а также в его обязанности входит поддержка актуальной документации по проекту
  • Тимлид не должен писать код, может, но не должен, если все правильно организовать у него и времени на это не будет
  • Технический директор всегда в связке с тимлидом, он должен понимать актуальность и сроки релизов, а также документацию как для пользователя типа userstory так и для разработчиков
  • Именно благодаря документации новый тимлид может разобраться в проекте, а тех директор должен помочь ему пройти онбординг
  • На этапе онбординга тимлида нужно отложить все важные дедлайны, а лучше вообще все
  • Релизы выполняются из релизной дев ветки, именно дев ветка должна быть на деве и только после полной обкатки на деве новый функционал загружается в мастер
  • Слияние релиза в мастере - это не просто разрешить конфликты, это проверка каждого файла, потому как гит не безупречен и многие вещи такие как перезапись файлов может пропустить и не показать конфликта, также разработчик может разрешить какой-то конфликт на своей стороне
  • Доступ по ssh на дев должен иметь только тимлид и техдир, ни один разработчик не может пушить изменения ни на прод ни на дев, только через гит
  • Все изменения в гите необходимо вносить в консоли, разные сервисы типа гитлаба, гитхаба, гитфликса имеют свои особенности в том числе может просто оборваться интернет или что-то еще пойти не так, и такое случалось ни раз на моей практике
  • Agile,scrum,kanban - придумали не просто так, важно аргументированно подойти к вопросу выбора методологии и придерживаться этого на всем цикле разработки
  • Джуны, которые знают solid,dry,kiss и много других акронимов часто не понимают элементарных вещей в архитектуре построения проекта, про дизайн проекта часто не может быть и речи, поэтому контроль и обучение сотрудников должны начинаться именно с архитектуры
  • Рефакторинг должен производится поэтапно и не самостоятельно одним разработчиком, пожелания с обьективными причинами должно выноситься на митап не просто на дейлике, а как отдельный не параллельный этап разработки, иначе вы просто прогорите на слиянии, дешевле правда сделать все последовательно
  • Этапы рефакторинга: выявление медленных мест, сложных структур. вызовов ошибок Шредингера или же просто легаси. Легаси - это не плохой код - это старый код и не надо путать эти понятия, это важно. Это важно потому, что следующий этап - это именно переписать архитектуру, а не старые методы на новые, если они работают, то пусть работают. Для того, чтобы переписать архитектуру - нужно ее создать, нарисовать, согласовать и протестировать на прототипе. Далее создаем слои архитектруы, связи и сущности, находим и исправляем ошибки, обкатываем с тестерами и только потом переходим к легаси. Легаси не может помешать новой архитектуре, только если это php5.4-5.6 какой-нибудь, и то с 5.6 большинство решений для архитектуры построения проекта уже были добавлены, но в этом случае конечно начать разработку с нуля - это будет быстрее и дешевле, но конечно все зависит от проекта и нужно считать
  • Слияние в мастер происходит в конце определенного этапа разработки, а не когда вздумается, каждый из разработчиков поддерживает актуальной именно дев ветку, и только после релиза обновляется мастер
  • У каждого разработчика своя ветка и дев, все коммиты мержатся в дев в конце дня по каждому разработчику, все конфликты решаются именно в этот момент никак не позднее, ни завтра и не через неделю
  • Тестами должны заниматься только тестировщики, которые действительно знают как их писать и пишут согласно документации, а не по словам разработчика
  • Релизы в микросервисной архитектуре должны производится связанными пакетами при хореографии и при оркестрации одинаково, и иметь обьективную причину: рефакторинг, новый функционал, обновление внешнего api, не должно быть случайных включений, они потом могут принести огромные потери для бизнеса
  • Документация на проекте не отменяет файлов readme на проекте, особенно в модулях и микросервисах
  • Писать длинные комментарии в коде - это плохо, это затрудняет часто чтение кода, ухудшает обработку и приводит к ошибкам, оптимальный вариант - это указание пункта в документации. И да, документация обязательна
  • Длинные неймспейсы - это плохо, высокий уровень абстракции это сложность в понимании проекта и долгие этапы онбординга, особенно для джунов. Это сильно тормозит систему, даже если ваш автолоад очень хорош, было много практики и есть золотая середина - делать абстракции настолько, насколько они актуальны для данного проекта. Абстракции ради абстракций делать не нужно, лучше уделить внимание слоям проекта, вынесением настроек, для логики всегда есть слой настройки или надстройки, именно он играет ключеваую роль в рефакторинге, поэтому именно ему важно уделить внимание
  • Архитектура проекта должна быть не только в голове у тимлида, но и в проектной документации и поддерживать актуальное состояние этой документации на протяжении всей жизни проекта - обязанность тимлида, а контроль релизов, согласование и проверка на стороне тех директора
  • Паттерны, особенно поведенческие, часто становятся антипаттернами, использование каждого паттерна должно быть обосновано - как инструмент решения проблемы, не важно как вы его назовете, важно, чтобы было понимаение что он делает, какие есть плюсы и минусы и как это влияет на проект в целом.
  • Разработчикам категорически запрещается вносить новые инструменты в проект - самописные, коммерческие или опенсорс без согласования с тимлидом
  • Опенсорс - это далеко не всегда хорошо, в основном это плохо, и в последнее время это стало до многих доходить благодаря текущей политической ситуации, а я об этом говорил еще 10 лет назад в 2015 году. Ваш проект должен быть независимым и иметь свою ифраструктуру, всегда должен быть актуальный слепок каждого релиза, всегда должна быть актуальной система балансировки с правильным сочетанием шардирования и репликации на каждом этапе разработки
  • откат системы не должен влиять на инфраструктуру или влиять по минимуму, даже если вы используете докер обязательно в документации важно указывать все актуальные версии продуктов инфраструктуры на текущий релиз
  • Песочница должна быть структурирована, каждый паттерн, каждый модуль, каждый сервис с полноценной документацией и указанием мест использования
  • Важно понимать, что организация самих процессов в компании важнее всего, что описано выше - если разработчик общается с клиентом пол дня, доступы ему согласовывают еще пол дня, о какой работе вообще может идти речь.
    1. На нового сотрудника еще до этапа онбординга заводятся все доступы сразу, только не все даются.
    2. На созвоне с клиентом присутствует PM и тимлид, может еще тех директор и т.д., в зависимости от тематики обсуждения и сложности проекта, но никак не разработчик, разработчику тимлид приности условное тз с полным пониманием вариантов реализации проекта.

Хобби и увлечения

Велоспорт и горные лыжи любимые виды спорта
Также занимаюсь вокалом и хожу в спортзал
Изучаю нейрофизиологию, пишу статьи на эту тему, а также о проблемах разработки ИИ
группа https://vk.com/cmsinclude
канал на vc.ru https://vc.ru/u/803121-konstantin-kamyshin

Стек технологий
  • 1. Работа с компонентами 1С-Битрикс, написание модулей на 1С-Битрикс
  • 2. Работа с темами WordPress (Avada,u-design и т.д.),с плагином e-commerce, написание темы и плагинов на WordPress
  • 3. Работа с framework Yii2
  • 4. Работа с framework Laravel
  • 5. Drupal 7
  • 6. Работа с netcat, написание модулей на Netcat
  • 7. Html5,css3,sass,jquery,ui.jquery,Angular 6
  • 8. Работа с git bash,netbeanse,основные команды ssh,установка apache+php+mysql
  • 9. Curl,Soap,rest api,json,xml,сериализация
  • 10. Mysql,PDO,SQLite,rollback, transaction-sql
  • 11. Работа с библиотеками mpdo80,GD,OpenAL
Примеры кода

Модуль для Netcat (для кастомизации обмена с 1С)

   core = nc_Core::get_object();						
		$this->uid = $this->core->user->attempt_to_authorize();		
		$this->settings = $this->core->modules->get_vars( "bufer" );	
    }

	// Сбор метододов класса

    public static function get_object(){
        static $storage;
        if ( !isset( $storage ) ){ $storage = new self(); }
        return is_object( $storage ) ? $storage : false;
    }

	    	
    public function setting(){ return $this->settings; }  
 
 //функция для распечатки массива
 public function printarray($mass){
     echo '
';
     print_r($mass);
     echo '
'; } public function poletables($id_component){ //функция создает массив для запроса к базе // получаем все поля таблицы $pole_table = "EXPLAIN `Message".$id_component."`"; $this->core->db->query($pole_table,ARRAY_N); $mass_pole=$this->core->db->last_result; //создаем пустой массив $masspole2=array(); //перебираем массив с полями таблицы в цикле foreach($mass_pole as $key=>$pole){ //если поля не числовые пишем в новый массив int=0 if($pole[1]!='int(11)' && $pole[1]!='double'){ $masspole2[$key]=array($pole[0]=>array('int'=>'0','val'=>'')); } else{ //если поля числовые пишем в новый массив int=1 $masspole2[$key]=array($pole[0]=>array('int'=>'1','val'=>'')); } } // выводим новый массив return $masspole2; } public function dazapismass($mass1,$mass2){ //функция дозаписи массива в соответствии с другим foreach($mass1 as $key=>$val){ //перебираем массив 1 foreach($val as $key2=>$val2){ //перебираем массив элемента 1 массива if (array_key_exists($key2, $mass2)) { //если в 2 массиве есть ключ от первого массива дописываем в 1 массив значение из 2 массива $mass1[$key][$key2]['val']=$mass2[$key2]; } } } return $mass1; } public function vivodbuferid(){ //выводим список всех элементов каталога буфера для циклической js обработки select в файле admin.php //получаем id компонента буфера из настроек модуля $id=$this->settings['id2']; //получаем sub_id компонента буфера из настроек модуля $subid=$this->settings['id1']; //поле для вывода в select из настроек модуля $name=$this->settings['name']; //получаем sub_class_id компонента буфера из настроек модуля $classid=$this->settings['id_block1']; //делаем запрос в базу для вывода всех элементов $query2 = "SELECT `Message_ID`,`".$name."` FROM `Message".$id."` WHERE `Subdivision_ID`=".$subid." AND `Sub_Class_ID`=".$classid." "; $this->core->db->query($query2,ARRAY_N); $mass=$this->core->db->last_result; //создаем массив $massresult=array(); // перебираем массив из базы и дописываем в новый массив foreach($mass as $key=>$val){ $massresult[$key]['id']=$mass[$key][0]; $massresult[$key]['name']=$mass[$key][1]; } return $massresult; } //получение списка по названию списка id элемента в массиве public function vescateg($table,$id){ $query2 = "SELECT `Value` FROM `Classificator_".$table."` WHERE `".$table."_Name`='".$id."' "; $this->core->db->query($query2,ARRAY_A); $mass=$this->core->db->last_result; return $mass; } public function masselementa($id_elem){ //функция для упрощенного вывода массива данных элемента таблицы компонента //получаем id компонента буфера из настроек модуля $id=$this->settings['id2']; //получаем sub_id компонента буфера из настроек модуля $subid=$this->settings['id1']; //получаем sub_class_id компонента буфера из настроек модуля $classid=$this->settings['id_block1']; //делаем запрос в базу и получаем значения всех полей данного элемента $query2 = "SELECT * FROM `Message".$id."` WHERE `Subdivision_ID`=".$subid." AND `Sub_Class_ID`=".$classid." AND `Message_ID`=".$id_elem." "; $this->core->db->query($query2,ARRAY_N); $mass=$this->core->db->last_result; //получаем массив полей таблицы компонента с id=$id $mass_pole=$this->poletables($id); // создаем пустой массив $massnew=array(); // в цикле перезаписываем значения массива с полями данными с массива $mass foreach($mass_pole as $key=>$val){ foreach($val as $key2=>$val2){ // записываем в пустой массив значения в упрощенной записи $massnew[$key2]=$mass[0][$key]; } } return $massnew; } public function name_ves($mass){ $mass2=explode(':',$mass); $mass_ves = explode(',',$mass2[0]); return $mass_ves; } public function value_ves($mass){ $mass2=explode(':',$mass); $mass_ves = explode(',',$mass2[1]); return $mass_ves; } //функция получает массив готовых весовых категорий и общую массу, на выводе выдает массив с кол-вом на складе товара для каждого варианта public function chislo_tov($value_ves,$ves){ $mass_new=array(); foreach($value_ves as $val){ $chislo=ceil($ves/$val); $mass_new[] = $chislo; } return $mass_new; } //функция получает массив готовых весовых категорий и общую массу, на выводе выдает массив с кол-вом на складе товара для каждого варианта public function price_tov($value_ves,$price){ $mass_new=array(); foreach($value_ves as $val){ $chislo=$price*$val; $mass_new[] = $chislo; } return $mass_new; } //создание sql строки для записи элемента public function sql_insert($mass_sql){ $mass_poles=''; $mass_poles2=''; // записываем в строку для записи foreach($mass_sql as $key=>$val){ foreach($val as $key2=>$val2){ if($val2['int']=='0'){ $mass_poles.= "`".$key2."`,"; $mass_poles2.="'".$val2['val']."',"; } else{ $mass_poles.= "`".$key2."`,"; if($val2['val']!=''){ $mass_poles2.="".$val2['val'].","; } else{ $mass_poles2.="'".$val2['val']."',"; } } } } //обрезаем последний символ $mass_poles = substr($mass_poles,0,-1); $mass_poles2 = substr($mass_poles2,0,-1); //записываем в один массив $mass_new=array(); $mass_new[0]=$mass_poles; $mass_new[1]=$mass_poles2; return $mass_new; } //создание sql строки для обновления элемента public function sql_update($mass_sql){ // записываем с строку для обновления $mass_up=''; foreach($mass_sql as $key=>$val){ foreach($val as $key2=>$val2){ if($val2['int']=='0'){ $mass_up.= "`".$key2."`='".$val2['val']."',"; } else{ if($val2['val']!=''){ $mass_up.= "`".$key2."`=".$val2['val'].","; } else{ $mass_up.= "`".$key2."`='".$val2['val']."',"; } } } } //обрезаем последний символ $mass_up = substr($mass_up,0,-1); return $mass_up; } //записываем или обновляем записи в основном каталоге public function zapis_sql($table,$id,$mass_poles,$mass_poles2,$mass_up,$id1,$id2){ $query2 = "SELECT `Message_ID` FROM `Message".$table."` WHERE `Message_ID`=".$id." AND `Subdivision_ID`=".$id1." AND `Sub_Class_ID`=".$id2.""; $this->core->db->query($query2,ARRAY_N); $ids25=$this->core->db->last_result; $id_elem= $ids25[0][0]; if($id_elem){ $query2 = "UPDATE `Message".$table."` SET ".$mass_up." WHERE `Message_ID`=".$id." AND `Subdivision_ID`=".$id1." AND `Sub_Class_ID`=".$id2.""; $this->core->db->query($query2,ARRAY_N); return 'Обновление произведено успешно'; } else{ $query2 = "INSERT INTO `Message".$table."` (".$mass_poles.") VALUES (".$mass_poles2.")"; $this->core->db->query($query2,ARRAY_N); return 'Запись произведена успешно'; } } public function zapiscatalog($id_elem){ //id компонента каталога $id_cat = $this->settings['id4']; //Sub_class компонента каталога $id2 = $this->settings['id_block2']; //subvision_id компонента каталога $id1 = $this->settings['id3']; //функция записи элемента из каталога буфера в основной каталог // получаем массив для данного элемента //пустой массив для записи компонента для выгрузки $massedo = $this->poletables($this->settings['id4']); //массив со значениями данного элемента $massot=$this->masselementa($id_elem); //весовая категория $vescat = $massot['category_id']; //кол-во или вес, если вес, то замените StockUnits на Weight $ves = $massot['StockUnits']; // цена за 1 грамм $gramm = $massot['Price']; //массив с параметрами весовой группы $vesmass = $this->vescateg('ves_group',$vescat); //массив с названиями групп $name_ves = $this->name_ves($vesmass[0][Value]); //массив с весом в группах $value_ves = $this->value_ves($vesmass[0][Value]); //массив с кол-вом для вариаций товара $count_mass = $this->chislo_tov($value_ves,$ves); // массив с ценами для вариаций товаров $price_mass = $this->price_tov($value_ves,$gramm); $massot['User_ID']=1; $massot['Subdivision_ID']=$id1; $massot['Sub_Class_ID']=$id2; $massot['Checked']=1; $massot['IP']='127.0.0.1'; $massot['UserAgent']='Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'; $massot['created']=date("Y-m-d H:i:s"); $massot['LastUpdated']=date("Y-m-d H:i:s"); $massot['LastUser_ID']=1; $massot['LastIP']='127.0.0.1'; $massot['LastUserAgent']='Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'; $massot['Priority']=1; //меняем параметры вариаций в основном массиве и выполняем запись в базу данных #$massreturn_vars=array(); foreach($price_mass as $key=>$price){ $massot['Price']=$price; $massot['StockUnits']=$value_ves[$key]; $massot['Weight_variat']=$name_ves[$key]; $massot['Weight']=$value_ves[$key]; if($key==0){ $massot['Message_ID']=$id_elem; $massot['Parent_Message_ID']=0; //id для записи в базу $id_zapisi = $id_elem; } else{ $massot['Message_ID']=$id_elem.'500'.$key; $massot['Parent_Message_ID']=$id_elem; //id для записи в базу $id_zapisi = $id_elem.'500'.$key; } //получаем строку для обновления записи $mass_up=$this->sql_update($this->dazapismass($massedo,$massot)); //получаем строку полей для добавления записи $mass_insert1=$this->sql_insert($this->dazapismass($massedo,$massot))[0]; //получаем строку значений для добавления записи $mass_insert2=$this->sql_insert($this->dazapismass($massedo,$massot))[1]; $results = $this->zapis_sql($id_cat,$id_zapisi,$mass_insert1,$mass_insert2,$mass_up,$id1,$id2); //вывод оповещения echo $results; } } } ?>

Модуль для Netcat (парсинг XML и загрузка в каталог)


                    core = nc_Core::get_object();            
    $this->uid = $this->core->user->attempt_to_authorize();   
    $this->settings = $this->core->modules->get_vars( "xmlcurl" ); 
 
    }

  // Сбор метододов класса

    public static function get_object(){
        static $storage;
        if ( !isset( $storage ) ){ $storage = new self(); }
        return is_object( $storage ) ? $storage : false;
    }

        
    public function setting(){ return $this->settings; }  
  
public function masspost(){
$mass=array();
$mass_url=array('http://www.beleonb2b.com:82/services/webservice.asmx/MyContracts','http://www.beleonb2b.com:82/services/webservice.asmx/MyContracts','http://www.beleonb2b.com:82/services/webservice.asmx/HotelInfo','http://www.beleonb2b.com:82/services/webservice.asmx/HotelsSearch','http://www.beleonb2b.com:82/services/webservice.asmx/OfferList','http://www.beleonb2b.com:82/services/webservice.asmx/HotelsSearch');
$mass_items=array('0'=>'Curls','1'=>'Curlsid','2'=>'CurlsHid','3'=>'Pricehid','4'=>'CurlsHid','5'=>'Curlsnew');
$mass_data=array('**********','**********true|Cid|','**********|Hid|','**********2019-06-012019-06-08en|Hid|GRtruefalse','**********|Hid|','**********2019-06-012019-06-08enVGRtruefalse');

$mass['url']=$mass_url;
$mass['data']=$mass_data;
$mass['items']=$mass_items;
return $mass;
}




public function poletables(){

$pole_table = "EXPLAIN `Message139`";
 $this->core->db->query($pole_table,ARRAY_N);
      $mass_pole=$this->core->db->last_result;

$masspole2=array();
foreach($mass_pole as $key=>$pole){
  if($pole[1]!='int(11)' && $pole[1]!='double'){
  $masspole2[$key]=array($pole[0]=>array('int'=>'0','val'=>''));
}
else{
  $masspole2[$key]=array($pole[0]=>array('int'=>'1','val'=>''));
}
}
return $masspole2;

}



public function cdataf($mass){


$xml2 = simplexml_load_string($target_response2);
$json2 = json_encode($xml2);
$array2 = json_decode($json2,TRUE);
return $array2;
}

public function searchspisok($massxml,$lang=0){
$filesapp=array();


foreach($massxml as $key=>$val){
  if(gettype($val)=='string'){
    $val=str_replace('CH#','',$val);
    if($key==$lang){
      if (!in_array($val, $filesapp)) {

}
else{
  $filesapp[]=$val;
}
    
  }

  }
}

return $filesapp;

}


public function spiskifiles($sp_name,$spisok){
   $patchs1 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/';
   // проверяем, есть ли файлы списка, если есть подгружаем и сериализуем данные в массивы
$s1_ru = file_get_contents($patchs1.$sp_name.'_ru.php');
$s1_en = file_get_contents($patchs1.$sp_name.'_en.php');
if(!$s1_ru || $s1_ru==''){
$filesapp_ru=array();
}
else{
  $filesapp_ru=unserialize($s1_ru);
}

if(!$s1_en || $s1_en==''){
$filesapp_en=array();
}
else{
  $filesapp_en=unserialize($s1_en);
}



// проверяем, если нет значений в массиве, то дописываем его

foreach($spisok as $key=>$val){
  if(gettype($val)=='string'){
    $val=str_replace('CH#','',$val);
    if($key==0){
      if (!in_array($val, $filesapp_en)) {
$filesapp_en[]=$val;
}
    
  }
  else if($key==8){
    if (!in_array($val, $filesapp_ru)) {
    $filesapp_ru[]=$val;
  }

  }
  }
}

$f_ru = serialize($filesapp_ru);
$f_en = serialize($filesapp_en);
file_put_contents($patchs1.$sp_name.'_ru.php',$f_ru);
file_put_contents($patchs1.$sp_name.'_en.php',$f_en);
return 'Список '.$sp_name.' загружен > ';
}

  public function  Curls($url,$data){

$ch = curl_init();
curl_setopt($ch, CURLOPT_PORT, 82);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "xml=".$data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                                        'Content-Type: application/x-www-form-urlencoded') 
                                        );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$target_response = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string($target_response);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
$patchs1 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/';
$strings = serialize($array);

file_put_contents($patchs1.'files_xml.php',$strings);
return 'Список загружен';
}

public function printarray($array){
  echo '
';
  print_r($array);
  echo '
'; } public function dazapismass($mass1,$mass2){ foreach($mass1 as $key=>$val){ foreach($val as $key2=>$val2){ if (array_key_exists($key2, $mass2)) { $mass1[$key][$key2]['val']=$mass2[$key2]; } } } return $mass1; } public function Curlsnew($url,$data){ $ch = curl_init(); curl_setopt($ch, CURLOPT_PORT, 82); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "xml=".$data); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded') ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $target_response = curl_exec($ch); curl_close($ch); $patchs1 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'; preg_match_all('|implode_all($glue, $arr[$i]); } return implode($glue, $arr); } public function CurlsHid($id,$url,$data,$etap){ $id1=5; $id2=6; $patchs1 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'; $data=str_replace('|Hid|',$id,$data); $ch = curl_init(); curl_setopt($ch, CURLOPT_PORT, 82); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "xml=".$data); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded') ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $target_response = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($target_response); $json = json_encode($xml); $array = json_decode($json,TRUE); $strings = serialize($array); //$this->printarray($array); if($array["Response"]["Hotels"]["Hotel"]["TypeDescription"]["languages"]["lang"]["0"]!=''){ if($etap==2){ //загрузка параметров отеля $array_hotel_1uroven = array("Name"=>"Title","OurRating"=>"reiting","CheckInTime"=>"time1","CheckOUtTime"=>"time2","NumberOfRooms"=>"countnumber","CancellationPolicy"=>"TextFull","ImageThumbURL"=>"Фото отеля"); $polem=array(); foreach($array_hotel_1uroven as $key=>$val){ if($key=='ImageThumbURL'){ $img1 = $array["Response"]["Hotels"]["Hotel"][$key]; $img2=str_replace('\\','',$img1); $img2=str_replace(' ','',$img2); $img1=str_replace('\\','/',$img1); $img1=str_replace(' ','%20',$img1); $image_name = 'IMG_'.$img2.':image/jpeg:'.rand(100000,1000000).':'.$id1.'/'.$id2.'/'.'IMG_'.$img2; $polem['PhotoSmall']=$image_name; $polem['PhotoLarge']=$image_name; $patch1 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'.$id1; $patch2 = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'.$id1.'/'.$id2; if (!file_exists($patch1)) { mkdir($patch1, 0777, true); } if (!file_exists($patch2)) { mkdir($patch2, 0777, true); } file_put_contents($patch2.'/IMG_'.$img2, file_get_contents('http://www.beleonb2b.com:89/images/hotels/'.$img1)); } else{ $polem[$val]=$array["Response"]["Hotels"]["Hotel"][$key]; } } // записываем данные о номерах в отель $mass=$this->masspost(); $spisok1 = $array["Response"]["Hotels"]["Hotel"]["Rooms"]["Room"]; $massroom=$this->$mass['items']['3']($id,$mass['url']['3'],$mass['data']['3']); $this->$mass['items']['3']($id,$mass['url']['3'],$mass['data']['3']); foreach($spisok1 as $key=>$val){ $massroom[$key]["MaxPax"]=$val["MaxPax"]; $massroom[$key]["MinPax"]=$val["MinPax"]; $massroom[$key]["RoomType"]=$val["RoomType"]["languages"]["lang"][1]; $massroom[$key]["Type"]=$val["Type"]["languages"]["lang"][2]; } $str=''; foreach($massroom as $key=>$val){ foreach($val as $key2=>$val2){ $val2=str_replace(' ','_',$val2); if($key2=='name'){ $val2=preg_replace('#([0-9])#','',$val2); } $str.='$room_'.$key2.'='.$val2.';:::'; } $str.='%%%'; } $str=str_replace(':::%%%%%%','',$str); $str=str_replace(':::%%%','%%%',$str); $roomstr=$str; // статические параметры заносим в массив $dop=''; $sp1=file_get_contents($patchs1.'sp1_ru.php'); $sp1=unserialize($sp1); foreach($sp1 as $vals){ $dop.=$vals."\n"; } $sp1=file_get_contents($patchs1.'sp2_ru.php'); $sp1=unserialize($sp1); foreach($sp1 as $vals){ $dop.=$vals."\n"; } $polem['dopolnitelno']=$dop; $adress = $array["Response"]["Hotels"]["Hotel"]["Address1"].' '.$array["Response"]["Hotels"]["Hotel"]["Address1"].' '.$array["Response"]["Hotels"]["Hotel"]["Address3"]; $polem['adress']=$adress; $polem['Message_ID']=$id.'225'; $polem['User_ID']=1; $polem['Subdivision_ID']=$id1; $polem['Sub_Class_ID']=$id2; $polem['Checked']=1; $polem['IP']='127.0.0.1'; $polem['UserAgent']='Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'; $polem['created']=date("Y-m-d H:i:s"); $polem['LastUpdated']=date("Y-m-d H:i:s"); $polem['LastUser_ID']=1; $polem['LastIP']='127.0.0.1'; $polem['LastUserAgent']='Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'; $polem['Priority']=1; $polem['Parent_Message_ID']=0; $polem['ncTitle']=$array["Response"]["Hotels"]["Hotel"]["Name"]; $polem['ncDescription']=$array["Response"]["Hotels"]["Hotel"]["Name"]; $polem['ncSMO_Title']=$array["Response"]["Hotels"]["Hotel"]["Name"]; $polem['ncSMO_Description']=$array["Response"]["Hotels"]["Hotel"]["Name"]; $polem['Price']=$massroom['prices']; $polem['rooms']=$roomstr; //записываем списки в отеле $mass_sppole['pitanie'][2]="HasContinentalBreakfast"; $mass_sppole['pitanie'][1]="HasKitchen"; $mass_sppole['pitanie'][3]="HasInHouseDining"; $mass_sppole['pole_item_catalog'][1]="HasSauna"; $mass_sppole['pole_item_catalog'][2]="HasWhirlpool"; $mass_sppole['pole_item_catalog'][3]="HasInHouseBar"; $mass_sppole['dostopr'][1]="HasFitnessFacility"; $mass_sppole['dostopr'][2]="HasTennisCourt"; $mass_sppole['dostopr'][3]="HasGolfCourse"; $mass_sppole['dostopr'][4]="HasBusinessCenter"; $mass_sppole['usl_gosty'][1]="HasHandicapAccessible"; $mass_sppole['home_animal'][1]="HasPetsAllowed"; $mass_sppole['bassein'][1]="HasOutdoorPool"; $mass_sppole['bassein'][1]="HasIndoorPool"; $mass_sppole['innumber'][1]="HasAirConditioning"; $mass_sppole['innumber'][2]="HasRoomService"; $mass_sppole['innumber'][3]="HasHairDryer"; $mass_sppole['innumber'][4]="HasTVInRoom"; $mass_sppole['innumber'][5]="HasDataPorts"; $mass_sppole['family_number'][1]="HasFamilyRooms"; foreach($mass_sppole as $key=>$val){ foreach($val as $key2=>$val2){ if($array["Response"]["Hotels"]["Hotel"][$val2]==1){ if($polem[$key]){ $polem[$key].=','.$key2; } else{ $polem[$key]=$key2; } } } } // записываем фото галереи $files_sp=''; $massfoto = $array["Response"]["Hotels"]["Hotel"]["photos"]["photogallery"]; foreach($massfoto as $key=>$val){ $img1=$massfoto[$key]["photo"]["image"]; $img1=str_replace('\\','/',$img1); $files_sp.='http://www.beleonb2b.com:89/images/hotels/'.$img1.','; } $polem['files_sp']=$files_sp; // получаем массив значений в полном массиве для записи в mysql $mass_sql = $this->dazapismass($this->poletables(),$polem); $mass_poles=''; $mass_poles2=''; // записываем в строку для записи foreach($mass_sql as $key=>$val){ foreach($val as $key2=>$val2){ if($val2['int']=='0'){ $mass_poles.= "`".$key2."`,"; $mass_poles2.="'".$val2['val']."',"; } else{ $mass_poles.= "`".$key2."`,"; if($val2['val']!=''){ $mass_poles2.="".$val2['val'].","; } else{ $mass_poles2.="'".$val2['val']."',"; } } } } //обрезаем последний символ $mass_poles = substr($mass_poles,0,-1); $mass_poles2 = substr($mass_poles2,0,-1); // записываем с строку для обновления $mass_up=''; foreach($mass_sql as $key=>$val){ foreach($val as $key2=>$val2){ if($val2['int']=='0'){ $mass_up.= "`".$key2."`='".$val2['val']."',"; } else{ if($val2['val']!=''){ $mass_up.= "`".$key2."`=".$val2['val'].","; } else{ $mass_up.= "`".$key2."`='".$val2['val']."',"; } } } } //обрезаем последний символ $mass_up = substr($mass_up,0,-1); // проверяем существует ли id и смотрим в таблице, если есть, то обновляем, если нет, то записываем if($id && $id!='' && $array["Response"]["Hotels"]["Hotel"]["NumberOfRooms"]!='' && $array["Response"]["Hotels"]["Hotel"]["NumberOfRooms"] && $array["Response"]["Hotels"]["Hotel"]["NumberOfRooms"]!=0){ $query2 = "SELECT `Message_ID` FROM `Message139` WHERE `Message_ID`=".$id."225 AND `Subdivision_ID`=".$id1." AND `Sub_Class_ID`=".$id2.""; $this->core->db->query($query2,ARRAY_N); $ids25=$this->core->db->last_result; $id_elem= $ids25[0][0]; if($id_elem){ $query2 = "UPDATE `Message139` SET ".$mass_up." WHERE `Message_ID`=".$id."225 AND `Subdivision_ID`=".$id1." AND `Sub_Class_ID`=".$id2.""; $this->core->db->query($query2,ARRAY_N); } else{ $query2 = "INSERT INTO `Message139` (".$mass_poles.") VALUES (".$mass_poles2.")"; $this->core->db->query($query2,ARRAY_N); } } } else if($etap==1){ $array2=$this->cdataf($array); $massxml = $array2["Response"]["Hotels"]["Hotel"]["HotelAmenities"]["Amenities"]; // записываем списки в файлы $spisok1 = $array2["Response"]["Hotels"]["Hotel"]["HotelRecreation"]["Recreation"]["RecreationService"]["languages"]["lang"]; echo $this->spiskifiles('sp1',$spisok1); $spisok2 = $array2["Response"]["Hotels"]["Hotel"]["HotelAmenities"]["Amenities"]; echo $this->spiskifiles('sp2',$spisok2); $spisok3 = $array2["Response"]["Hotels"]["Hotel"]["Meals"]["AvailableMealCategory"]; echo $this->spiskifiles('sp3',$spisok3); $spisok4 = $array2["Response"]["Hotels"]["Hotel"]["HotelDining"]["DiningFacility"]; echo $this->spiskifiles('sp4',$spisok4); $spisok5 = $array2["Response"]["Hotels"]["Hotel"]["MeetingRooms"]["MeetingRoom"]; echo $this->spiskifiles('sp5',$spisok5); $spisok6 = $array2["Response"]["Hotels"]["Hotel"]["HotelAttractions"]["Attraction"]; echo $this->spiskifiles('sp6',$spisok6); } echo 'ID--'.$id; } else{ $patchs1s = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'; $files = file_get_contents($patchs1s.'files_xml5.php'); $files2=$files.','.$id; file_put_contents($patchs1s.'files_xml5.php',$files2); echo 'Не вилла'; } } public function Curlsid($id,$url,$data){ $data=str_replace('|Cid|',$id,$data); $ch = curl_init(); curl_setopt($ch, CURLOPT_PORT, 82); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "xml=".$data); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded') ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $target_response = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($target_response); $json = json_encode($xml); $array = json_decode($json,TRUE); $strings = serialize($array); return $array; } public function Pricehid($id,$url,$data){ $data=str_replace('|Hid|',$id,$data); $ch = curl_init(); curl_setopt($ch, CURLOPT_PORT, 82); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "xml=".$data); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded') ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $target_response = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($target_response); $json = json_encode($xml); $array = json_decode($json,TRUE); $strings = serialize($array); $massroom = $array["Response"]["Hotels"]["Hotel"]["Rooms"]["Rooms"]["Room"]; $price_room=array(); if(count($massroom)<=3){ $i=0; foreach($massroom as $key=>$room){ $price_room[$i]["name"]=$massroom["Name"]; if($massroom["Occupancy"]["RR"]["@attributes"]["value"]!=''){ $price_room[$i]["RR"]=$massroom["Occupancy"]["RR"]["@attributes"]["value"]; } else{ $price_room[$i]["RR"]='Уточните у менеджера'; } if($massroom["Occupancy"]["BB"]["@attributes"]["value"]!=''){ $price_room[$i]["BB"]=$massroom["Occupancy"]["BB"]["@attributes"]["value"]; } else{ $price_room[$i]["BB"]='Уточните у менеджера'; } if($massroom["Occupancy"]["HB"]["@attributes"]["value"]!=''){ $price_room[$i]["HB"]=$massroom["Occupancy"]["HB"]["@attributes"]["value"]; } if($massroom["Occupancy"]["FB"]["@attributes"]["value"]!=''){ $price_room[$i]["FB"]=$massroom["Occupancy"]["FB"]["@attributes"]["value"]; } if($massroom["Occupancy"]["AI"]["@attributes"]["value"]!=''){ $price_room[$i]["AI"]=$massroom["Occupancy"]["AI"]["@attributes"]["value"]; } if($massroom["Occupancy"]["UI"]["@attributes"]["value"]!=''){ $price_room[$i]["UI"]=$massroom["Occupancy"]["UI"]["@attributes"]["value"]; } $i=$i+1; } } else{ foreach($massroom as $key=>$room){ $price_room[$key]["name"]=$room["Name"]; if($room["Occupancy"][$key]["RR"]["@attributes"]["value"]!=''){ $price_room[$key]["RR"]=$room["Occupancy"][$key]["RR"]["@attributes"]["value"]; } else{ $price_room[$key]["RR"]='Уточните у менеджера'; } if($room["Occupancy"][$key]["BB"]["@attributes"]["value"]!=''){ $price_room[$key]["BB"]=$room["Occupancy"][$key]["BB"]["@attributes"]["value"]; } else{ $price_room[$key]["BB"]='Уточните у менеджера'; } if($room["Occupancy"][$key]["HB"]["@attributes"]["value"]!=''){ $price_room[$key]["HB"]=$room["Occupancy"][$key]["HB"]["@attributes"]["value"]; } if($room["Occupancy"][$key]["FB"]["@attributes"]["value"]!=''){ $price_room[$key]["FB"]=$room["Occupancy"][$key]["FB"]["@attributes"]["value"]; } if($room["Occupancy"][$key]["AI"]["@attributes"]["value"]!=''){ $price_room[$key]["AI"]=$room["Occupancy"][$key]["AI"]["@attributes"]["value"]; } if($room["Occupancy"][$key]["UI"]["@attributes"]["value"]!=''){ $price_room[$key]["UI"]=$room["Occupancy"][$key]["UI"]["@attributes"]["value"]; } } } $price_room['prices']=$array["Response"]["Hotels"]["Hotel"]["LowestPrice"]; return $price_room; } public function vivodarrays(){ $patchs1s = $_SERVER['DOCUMENT_ROOT'].'/netcat_files/'; $files = file_get_contents($patchs1s.'files_xml.php'); return unserialize($files); } } ?>

Старое Ядро Framework Foton (release 1.0.1) (собственная разработка)


 db = $this->db();
        $this->get_post = $this->post_get();
   
    }
    
   public function db(){

$dbh = new PDO('mysql:host='.$GLOBALS["host"].';dbname='.$GLOBALS["dbname"], $GLOBALS["login"], $GLOBALS["pass"]);
$dbh->exec("set names utf8");
      $connect = mysql_connect($GLOBALS["host"], $GLOBALS["login"], $GLOBALS["pass"]);
        if($connect){
            return $dbh;
        }
        else{
            return false;
        }
}
public function set($var){
    return $var;
    
}
public  function insert_db($table,$attr,$attr2){
     $attr=str_replace(';',',',$attr);
	 $attr2=str_replace(';','","',$attr2);
return $this->db->query('INSERT INTO '.$table.' ('.$attr.') VALUES ("'.$attr2.'")');
    
}

public  function select_db($table,$attr,$attr2,$vivod){
     $mass =array();
if(isset($attr)){
    if(stristr($attr, ';') === FALSE) {
   if(isset($vivod)){
       if(stristr($vivod, ';') === FALSE) {
 foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE `'.$attr.'`="'.$attr2.'"') as $row) {

 
   $mass[]=$row[$vivod];
 }
 }
 else{
     $vivod2=explode(';',$vivod);
     
     foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE `'.$attr.'`="'.$attr2.'"') as $row) {
   foreach($vivod2 as $val){

   $mass[]=$row[$val];
   }
 } 
     
 }
     
    }
    else{
       foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE `'.$attr.'`="'.$attr2.'"') as $row) {
   

   $mass[]=$row;
 }  
        
    }
    }
    else{
      ###  
       $attr2=explode(';',$attr2);
       $attr=explode(';',$attr);
       foreach($attr as $key2=>$atr){
           $atrs.='`'.$atr.'`="'.$attr2[$key2].'" AND ';
       }
       $atrs = substr($atrs,0,-4);
        if(isset($vivod)){
       if(stristr($vivod, ';') === FALSE) {
 foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE '.$atrs) as $row) {
   

   $mass[]=$row[$vivod];
 }
 }
 else{
     $vivod2=explode(';',$vivod);
     
     foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE '.$atrs) as $row) {
   foreach($vivod2 as $val){
  
   $mass[]=$row[$val];
   }
 } 
     
 }
     
    }
    else{
       foreach($this->db->query('SELECT * FROM `'.$table.'` WHERE '.$atrs) as $row) {
   
 
   $mass[]=$row;
 }  
        
    }
       
        ###
    }
} 
else{
  foreach($this->db->query('SELECT * FROM '.$table) as $row) {
   

   $mass[]=$row;
      
  
     
    }   
}

   
   

    
  return $mass;  
    
}


public  function update_db($table,$attr,$attr2,$where){
      $attr2=explode(';',$attr2);
       $attr=explode(';',$attr);
       foreach($attr as $key2=>$atr){
           $atrs.='`'.$atr.'`="'.$attr2[$key2].'",';
       }
	   $atrs = substr($atrs,0,-1);
return $this->db->query('UPDATE `'.$table.'` SET '.$atrs.' WHERE '.$where);
    
}


public  function delete_db($table,$attr,$attr2){
 
if(isset($attr)){
    if(stristr($attr, ';') === FALSE) {

       return $this->db->query('DELETE FROM `'.$table.'` WHERE `'.$attr.'`="'.$attr2.'"');
        
    }
    else{
      ###  
       $attr2=explode(';',$attr2);
       $attr=explode(';',$attr);
       foreach($attr as $key2=>$atr){
           $atrs.='`'.$atr.'`="'.$attr2[$key2].'" AND ';
       }
       $atrs = substr($atrs,0,-4);
      
 return $this->db->query('DELETE FROM `'.$table.'` WHERE '.$atrs);
 }
}
 else{
    
     
   return $this->db->query('TRUNCATE TABLE `'.$table.'`');
     
 }
}

public function post_get(){// проверяем используются ли в нашей версии php магические кавычки и экранируем кавычки в зависимости от этого для защиты от sql иньекций.
      $dannie = explode('/', $_SERVER['REQUEST_URI']);
    foreach($dannie as $key=>$val){
        if($key!=0 && $key!=1){
            $_GET[$key] = $val;
           
        }
    }

if (get_magic_quotes_gpc()) {
    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
    while (list($key, $val) = each($process)) {
        foreach ($val as $k => $v) {
            unset($process[$key][$k]);
            if (is_array($v)) {
                $process[$key][stripslashes($k)] = $v;
                $process[] = &$process[$key][stripslashes($k)];
            } else {
                $process[$key][stripslashes($k)] = stripslashes($v);
            }
        }
    }
    unset($process);
}
}



public function pole_tables($table){
$sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = :table";
$stmt = $this->db()->prepare($sql);
        $stmt->bindValue(':table', $table, PDO::PARAM_STR);
        $stmt->execute();
        $output = array();
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
            $output[] = $row['COLUMN_NAME'];                
        }
        return $output;
 }
 
public function meta(){
    	if(stristr($_SERVER['REQUEST_URI'],'-') === FALSE){
		    $urlnew=$_SERVER['REQUEST_URI'];
		    $urlnew = str_replace('/','',$urlnew);
		}else{
			$urlnew=explode('-',$_SERVER['REQUEST_URI']);
			$urlnew = str_replace('/','',$urlnew[0]);
		}
  
	$title=$this->select_db('opt','kod',$urlnew,'title')[0];
	if(isset($title) && $title!=''){
    $meta=$this->pole_tables('opt');
    $meta2=array();
    foreach($meta as $val){
        $meta2[$val]=$this->select_db('opt','kod',$urlnew,$val)[0];
    }
   	return $meta2;
	}
	else{
	    return false;
	}
}
}
?>select_db('chpu','kod',$urlnew,'view')[0];
	if(isset($str) && $str!=''){
    $reg=$this->select_db('chpu','kod',$urlnew,'chpu')[0];
    if(isset($reg) && $reg!=''){
    	 $url=preg_replace('#%([^%]+)%:([^:]+):#','([$2]+)',$reg);
       preg_match("/".$urlnew."-".$url."$/", $_SERVER['REQUEST_URI'],$search);
        if (count($search)>0) {
	preg_match_all("|".$url."$|U", $_SERVER['REQUEST_URI'],$out, PREG_PATTERN_ORDER);

	if(count($out[1])>0 && $out){
   		preg_match_all("|%([^%]+)%|U", $reg,    $out0, PREG_PATTERN_ORDER);
  		for($it=0;$itselect_db('chpu','kod',$urlnew,'view')[0];
	if(isset($str) && $str!=''){
    $reg=$this->select_db('chpu','kod',$urlnew,'chpu')[0];
    if(isset($reg) && $reg!=''){
        $url=preg_replace('#%([^%]+)%:([^:]+):#','([$2]+)',$reg);
       preg_match("/".$urlnew."-".$url."$/", $_SERVER['REQUEST_URI'],$search);
        if (count($search)>0) {
    	
	preg_match_all("|".$url."$|U", $_SERVER['REQUEST_URI'],$out, PREG_PATTERN_ORDER);

	if(count($out[1])>0 && $out){
   		preg_match_all("|%([^%]+)%|U", $reg,    $out0, PREG_PATTERN_ORDER);
  		for($it=0;$itselect_db('chpu','kod',$urlnew,'view')[0];
	if(isset($str) && $str!=''){
    $reg=$this->select_db('chpu','kod',$urlnew,'chpu')[0];
     if(isset($reg) && $reg!=''){
    	$url=preg_replace('#%([^%]+)%:([^:]+):#','([$2]+)',$reg);
	preg_match_all("|".$url."$|U", $_SERVER['REQUEST_URI'],$out, PREG_PATTERN_ORDER);

	if(count($out[1])>0 && $out){
   		preg_match_all("|%([^%]+)%|U", $reg,    $out0, PREG_PATTERN_ORDER);
  		for($it=0;$it$val();
			  }
		    	}
		    
		    	
             if(isset($controller_name)){
		// подключаем файл с классом контроллера
		$controller_file = strtolower($controller_name).'.php';
		$controller_path = "controller/".$controller_file;
		if(file_exists($controller_path))
		{
		    
			require_once "controller/".$controller_file;
			$model_class = new $model_name;
			$controller_class = new $controller_name;
		
		
			  
			foreach(get_class_methods($controller_name) as $val){
			  if(method_exists($model_class,$val)===false){
			      
	    $data[$val] = $controller_class->$val();
	   
			      
			     

			  }
			    
			}
			
		}}
	else{//если контроллера нет, то ничего не подключаем
	    
	}
	
		require_once "view/xml/".$view_file;
	
        
		
		
	     
		}
     else{
         $this->ErrorPage404();
     }
     
     
 }
		else{
		 $this->ErrorPage404();
		}
   }
   
   
   
   
   
      public function json(){
	   $pathjson=Constructor::pathview_to('json');
        // здесь подключаем файл представления, если он есть, а также определяем нужно ли нам подключать админку
		$view_name = $pathjson.'_view';
		$controller_name = 'controller_'.$pathjson;
		$model_name = 'model_'.$pathjson;
		
        if($pathjson!==false){
	
		$view_file = strtolower($view_name).'.php';
	$view_path = $GLOBALS["path"]."/view/json/".$view_file;


		if (file_exists($view_path)) {
		header('Content-Type: application/json');

        require_once 'core/modules.php';
        $model_file = strtolower($model_name).'.php';
		$model_path = "model/".$model_file;
		if(file_exists($model_path))
		{ 
		   require_once "model/".$model_file;
		}
		else{
		require_once "core/model.php";
		    
		}
		require_once "model/model_globals.php";
		
		require_once "controller/controller_globals.php";
		    $glob = new Controller_Globals;
		    	foreach(get_class_methods('Controller_Globals') as $val){
			  if(method_exists('Controller_Globals',$val)!==false){
			      
	    $global[$val] = $glob->$val();
			  }
		    	}
		    	
		    	
             if(isset($controller_name)){
		// подключаем файл с классом контроллера
		$controller_file = strtolower($controller_name).'.php';
		$controller_path = "controller/".$controller_file;
		if(file_exists($controller_path))
		{
		    
			require_once "controller/".$controller_file;
			$model_class = new $model_name;
			$controller_class = new $controller_name;
		
		
			  
			foreach(get_class_methods($controller_name) as $val){
			  if(method_exists($model_class,$val)===false){
			      
	    $data[$val] = $controller_class->$val();
	   
			      
			     

			  }
			    
			}
			
		}}
	else{//если контроллера нет, то ничего не подключаем
	    
	}
	
		require_once "view/json/".$view_file;
	
        
		
		
	     
		}
     else{
         $this->ErrorPage404();
     }
     
     
 }
		else{
		 $this->ErrorPage404();
		}
   }
   
   
   
    public function path(){
	   
			$path = Constructor::pathview();
		$dir = $this->scan_file($GLOBALS["path"]."/view/",strtolower($path).'_view.php');
		$dir=str_replace('_view.php','',$dir);
if($dir && $dir!==true){
	$file2=$dir;
}
else{
	$file2='interface';
}
	//если админка устанавливаем пути к стилям и js
	    	  if($path=='admin'){
            return 'work/';
            
        }
          elseif($path=='ajax'){
            return 'ajax';
        }
        elseif($path==$file2){
              return 'face/';
        }
        else{
       return 'view/site/';
        }
	}
    
    
    
    // здесь передаем все действия в представлении на контроллер
    public function views($init,$var){
        return Constructor::start($init,$var);
    }
    public function globw($init,$var){
        return Constructor::globstart($init,$var);
    }
    	public function scan($dir,$file){
$is=false;
		   if(file_exists($dir.$file)){
		     $is= 'true'; 
	
		 }   
		else{
		 	  foreach (glob($dir."*") as $filename) {
		        if(is_dir($filename)){
		        foreach (glob($filename."/*.*") as $filename2) {
		            
		        if(basename($filename2)==$file){
		          if (in_array("head.php", scandir($filename))) {
		              $is=$filename;
		          }
		          else{
		            $is= 'true';
		          }
		        }
		             }
		        }
		    }
		}
	if($is=='true'){
 return true;
	}
	else{
	    return $is;
	}
	}
	
	public function scan_file($dir,$file){
$is=false;
		   if(file_exists($dir.$file)){
		     $is= 'true'; 
	
		 }   
		else{
		 	  foreach (glob($dir."*") as $filename) {
		        if(is_dir($filename)){
		        foreach (glob($filename."/*.*") as $filename2) {
		            
		        if(basename($filename2)==$file){
		          if (in_array("head.php", scandir($filename))) {
		              $is=basename($filename2);
		          }
		          else{
		            $is= 'true';
		          }
		        }
		             }
		        }
		    }
		}
	if($is=='true'){
 return true;
	}
	else{
	    return $is;
	}
	}
	
	
	
   public function html(){
        // здесь подключаем файл представления, если он есть, а также определяемнужно ли нам подключать админку
		$view_name = Constructor::pathview().'_view';
		$controller_name = 'controller_'.Constructor::pathview();
		$model_name = 'model_'.Constructor::pathview();

        if(Constructor::pathview()!==false){
	
		$view_file = strtolower($view_name).'.php';
	$view_path = "view/".$view_file;
$res = $this->scan($GLOBALS["path"]."/view/",$view_file);

		if($res)
		{
			// событие входа в панель упраления
		if($view_name=='admin_view' && isset($_SESSION['login'])===FALSE){
	    	include 'work/key.php';
        if(isset($_POST['key'])!==FALSE && $_POST['key']==$date2){
            $_SESSION['login']='login';
           require_once "view/".$view_file;
        }
        else{
            include 'work/auth.php';
            exit();
        }
		}
		else{ // событие выхода
		if(isset($_POST['key'])!==FALSE && $_POST['key']=='destroy'){
            session_destroy();
            include 'work/auth.php';
        }
        else{
        require_once 'core/modules.php';
        
        
        $model_file = strtolower($model_name).'.php';
		$model_path = "model/".$model_file;
		if(file_exists($model_path))
		{ 
		   require_once "model/".$model_file;
		}
		else{
		require_once "core/model.php";
		    
		}
		require_once "model/model_globals.php";
		
		require_once "controller/controller_globals.php";
		    $glob = new Controller_Globals;
		    	foreach(get_class_methods('Controller_Globals') as $val){
			  if(method_exists('Controller_Globals',$val)!==false){
			      
	    $global[$val] = $glob->$val();
			  }
		    	}
		    	
		    	
             if(isset($controller_name)){
		// подключаем файл с классом контроллера
		$controller_file = strtolower($controller_name).'.php';
		$controller_path = "controller/".$controller_file;
		if(file_exists($controller_path))
		{
		    
			require_once "controller/".$controller_file;
		
			$model_class = new $model_name;
			$controller_class = new $controller_name;
		
			
			  
			foreach(get_class_methods($controller_name) as $val){
			  if(method_exists($model_class,$val)===false){
			      
	    $data[$val] = $controller_class->$val();
	   
			      
			     

			  }
			    
			}
			
			
		}}
	else{//если контроллера нет, то ничего не подключаем
	    
	}
	
	//если есть метод dir берем файл из папки dir
	if(method_exists($controller_class,'dir')!==false){
	    $dir_view=$controller_class->dir();
	    if($res!==true){
	        require_once "view/".$dir_view."/head.php";
	    }
	    require_once "view/".$dir_view."/".$view_file;
	     if($res!==true){
	        require_once "view/".$dir_view."/foot.php";
	    }
	}else{
		require_once "view/".$view_file;
	}
        }
		}
		
	     
		}
     else{
         $this->ErrorPage404();
     }
     
     
 }
		else{
		//если имени нет подключае стандартный шаблон html
		require_once "view/html.php";
		}
   }
   
   function ErrorPage404()
	{
        $host = 'http://'.$_SERVER['HTTP_HOST'].'/';
        header('HTTP/1.1 404 Not Found');
		header("Status: 404 Not Found");
		header('Location:'.$host.'error404');
    }
   
   
   
}?> 
                
                
Пример модуля
Пример компонента
Пример платежной системы
Тестовое задание

Тестовое задание - очень интересный подход к проверке квалификации кандидата.
На мой взгляд столь же интересный как и бесполезный (в частности в web разработке).
Во первых веб разработка настолько широкая сфера, что подготовить одно т.з. на все случаи жизни не представляется возможным.
Во вторых, если человек выполняет задание у вас в офисе, будьте готовы он его выполнит в 10 раз хуже чем в реальности, так как большинство кандидатов настолько нервничают плюс чужое присутствие, что они вообще не способны сосредоточится.

В третьих, дома у кандидата есть вариант списать, и это будет вызывать в любом случае недоверие, и весь смысл затеи будет бесполезен.
Если же это удаленное тестирование, то ограниченность во времени и другие факторы сделают свое дело, и опять результат будет далек от реальности.

Часто присылают большие и даже огромные тестовые задания. Задания вроде создания нового приложения, нового сайта или какого-либо сложного функционала. В данном случае - это более правильный подход, нет конкретного ограничения по времени, но разработчик чувствует себя в этой ситуации не комфортно, так как слишком высока вероятность того, что результат его работы будет где-либо использован.
Кроме того, разработчику просто жалко своего времени на задание, ведь зачастую рассылаются они нескольким кандидатам, и даже если выполнить это задание хорошо, кто-то может выполнить лучше, и работодатель ответит, что "к сожалению вы нам не подходите".

Исходя из всего этого, и того, что работа программиста творческая, и зачастую те навыки, которые будут нужны в работе, о них работодатель даже не знает, потому что IT сфера так быстро меняется, и задание, которое поступит от клиента, даже если клиентом будет сам работодатель, может включать в себя совершенно другие подходы, технологии и задачи, можно сказать, что лучшим решением всегда была стажировка после обыкновенного собеседования, на котором вы можете поговорить как люди, и увидеть, вы вообще хотите вместе работать или нет.
Стажировка к примеру в 1 день - это не так уж и много времени, но если правильно организовать этот день (не на сборку рабочей станции, а на реальные дела), то можно увидеть насколько вы подходите друг другу.

Но за многие годы у меня накопилось множество интересных заданий, и если вам будет интересно, некоторые я приведу здесь, порядок не хронологический, и я их не отбирал по какому-либо принципу:
1. можно ли обойтись в программировании без циклов, и если можно, то с помощью чего?
Ответ: с помощью использования рекурсии и ветвлений.
2. Какая-нибудь задачка на сложный запрос к базе данных, использующий left join, например.
user:id,name,login,age. zakaz:id,date,login,tovar.
Получить имя и возраст покупателя заказа под номером id из таблицы zakaz. И именно в такой не очень внятной формулировке их зачастую и ставили.
Ответ: SELECT user.name,user.are FROM zakaz LEFT JOIN user ON user.login=zakaz.login WHERE zakaz.id=2
3. Какие вы используете паттерны проектирования?
Ответ: очень частый вопрос на собеседованиях, в основном в веб студиях требуется работать с cms bitrix, wordpress, drupal, netcat и очень редко хотя бы с фреймворками типа Yii2 или Laravel, исходя из этого вы как думаете какие я использую паттерны проектирования?
В общем веб программисты их редко используют, а учат лишь для собеседования.
Часто используют только один всем известный шаблон проектирования MVC.

наиболее интересные шаблоны:
мост - через интерфейс мы переопределяем метод заданный в абстракции, где конструктор, и сам метод наследования имеет свойства необходимой абстракции, все остальное создается на уровень ниже. после интерфейса.
абстрактная фабрика - группируем через интерфейс связанные объекты (правильнее методы) по какому либо признаку, можно связать через абстракцию определения связи.

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

С чем мне часто приходится работать?:
фабричный метод - часто нужен для обращения к методам другого класса, и вообще необходим для создания работы с многими классами
прототип - используется повсеместно, так как часто необходимо использовать один и тот же объект несколько раз.
одиночка - используется иногда для создания общего глобального класса в некоторых системах - класса ядра системы.
Вот здесь очень кратко - https://habr.com/ru/post/210288/
Вот здесь подробнее с примерами и описанием проблемы и решения - https://refactoring.guru/ru/design-patterns/

Опыт разработки (только активные проекты на данный момент)
Что я ожидаю от работодателя

Итак, что же я ожидаю от работодателя?
Работодатель обычно ожидает качественного исполнения работы, и соответствующей квалификации у сотрудника.
Это нормально - ведь за это сотруднику и платят.
Но вот о чем обычно не говорят, так это о том, а какие задачи будут ставится и как их нужно выполнять.
Ведь по факту платят именно за это.

И нерациональное использование ресурсов имеет место быть. Это как нанять Билла Гейтса разносчиком пиццы, он возможно хорошо справится, а возможно и нет, но это даже звучит странно, просто режет слух.
Также и с любым сотрудником компании, часто так бывает, что в этот же день собеседования принимают на работу. За 8 лет работы так было несколько раз, и это правильный подход, потому что, только попробовав, можно узнать, насколько человек готов к такого рода работе.

По этому же принципу, если на собеседовании меня спрашивают, о моих навыках, я бы на собеседовании хотел узнать, а какие конкретно задачи мне нужно будет выполнять, и в каком виде я их получу: техническое задание, чек лист, произвольная форма, пояснительная записка, коллективное изучение и т.д.
Для меня очень важна четкость поставленных задач, так как от нее зависит правильность выполнения работы. А вообще, зачем компания ищет разработчика. По моему опыту в основном потому, что накопилось много незакрытых проектов, и компании дешевле нанять еще одного сотрудника, чем потерять клиентов.

В связи с этим на нового сотрудника наваливается огромная куча работы, которую он должен был сделать еще вчера, хотя пришел на работу только сегодня. Я считаю такой подход неправильным.
Во первых, программист, особенно если это одно из первых его рабочих мест, вообще не в курсе насколько такой цейтнот затянется, и не обычный ли это режим работы в компании (это желательно пояснить, чтобы не было паники).

Во вторых, рациональнее распределить не завершенные задачи по всей команде равносильно их знаниям и занятостью по другим проектам, и даже если все-все заняты, можно составить график выполнения задач поочередно.
Вот в принципе и все - четкость поставленных задач, разумные сроки выполнения.

Опыт и Образование

Знакомство с IT и веб технологиями у меня началось еще в 2006 году с написания своего проекта (интернет магазин совмещенный с биржей фриланса, с посылом заработал и потратил прямо здесь). Писалась система на языке perl.

Это было время табличной верстки, первой сборки денвера, зарождения новых смартфонов в России под управлением android, появления первых приложений для android.
В то время я работал преподавателем и параллельно изучал perl, css, html, js. Затем, в 2008 решил перейти на php, появились первые заказы. Первой моей официальной работой в IT была должность seo-специалиста в 2013 году (Brand-print).

2013 - 2014 год
Brand-print.ru
- Seo специалист (техническое сео на Друпал 6)
- рост видимости сайта на 70% (по выбранным заказчиком кластерам СЯ)
2014 - 2015 год
Симметрия
- Project manager + full stack (написание и утверждение т.з., работа с Agile,scrum, разработка проектов на CMS NETCAT)
- 8 закрытых сделок, 5 сданных проектов.
2015 - 2017 год
АРМАВИРФОН
- Full-stack разработчик (разработка сайтов на WP,Drupal,Bitrix)
- разработано более 30-ти сайтов
2017 - 2019 год
СиДжейЭм
- fullStack разработчик (удаленная попроектная разработка проектов на Yii2, работа с api Glonass как подрядчик, поддержка CRM систем)
- разработка 2-х крупных проектов, на поддержке 7 компаний с ежемесячной отчетностью.
2017 - 2019 год
ВИСТ компани
генеральный директор и главный разработчик (разработка проекта купец онлайн, разработка проектов под заказчика, разработано более 50-ти проектов
2019 январь - 2019 ноябрь
Техносклад
- fullStack разработчик (разработка нового сайта на 1С битрикс. Тестирование и адаптирование под safari,ie9,ie10,edge. Интеграция с 1С 6 и 1С 8, разработка проекта дочерней компании smartsatellit.ru, работа с 1c-bitrix, написение компонента форума, компоненты меню и каталога, написание различных парсеров).
2019 ноябрь- по настоящее время
Кубаньинструмент
- fullStack разработчик (разработка нового сайта на 1С битрикс. Оптимизация скорости главной страницы сайта с 35% до 95%, оптимищация остальных страниц сайта с 25% до 50-65%. Оптимизация работы внутренней поисковой системы. Разработка функционала слайдера, доставок, брендов, отзывов и т.д. Разработка нового сайта с сохранением дизайна на написанном фреймворке внутри шаблона битрикс. Как результат - увеличение скорости в 10 раз, легкая управляемость через mvc, быстрое и гибкое управление ЧПУ через роутер. Постоянная работа с акциями по доставке, скидкам, купонам и подаркам).

Образование