daemonhk
@daemonhk
ПсиХоПат

Чего не хватает моим функциям?

Кажется тостер больше всего подходит для вопросов такого рода... Хочу чтобы другие программисты дали оценку моим функциям, чего не хватает и вообще всей логике написания. Функции представляют собой прослойку перед функцией запросов к БД с помощью PDO. Читал, что использование global ЗЛО, но таков стиль кода моего начальника (а у него опыт 15 лет). И да, сторонними библиотеками мы не пользуемся, только велосипеды свои.

//функция получения данных
	function getRecords($table,$settings){
		global $DataBase,$ActiveLanguage,$SortLanguage;

		//pre variables
		$SQL=array();
		$query="SELECT ";
		$what="*";
		$activeLanguage=$ActiveLanguage;
		$whereSQL=$orderSQL=$limitSQL=$innerSQL=$sortBy=null;
		$showSQL=false;
		//get all data
		//if(!empty($settings)){
		$settings=json_decode(json_encode($settings),false);
		//if empty $settings->table => return empty object
		if(!empty($table)){
			$tableName=$table;
		}else{
			return null;
		}
		//get non-standard fields for select
		if(isset($settings->what)){
			$what=$settings->what;
			if($settings->what=="break"){
				$what=null;
			}
		}
		//get fields for select
		if(isset($settings->as)){
			foreach($settings->as as $k=>$v){
				$SQL[]="{$k} AS {$v}";
				unset($k,$v);
			}
		}
		//get $activeLanguage
		if(isset($settings->from) && $settings->from=="admin"){
			$activeLanguage=$SortLanguage;
		}
		//default $settings->where is `Status`='Y'
		if(isset($settings->where)){
			$whereSQL=" WHERE {$settings->where}";
		}
		//default order by Position
		if(isset($settings->order)){
			$order=$settings->order;
			$orderSQL=" ORDER BY {$order}";
		}
		//group records
		if(isset($settings->group)){
			$orderSQL=" GROUP BY {$settings->group}";
		}
		//default limit is null
		if(isset($settings->limit)){
			$limitSQL=" LIMIT {$settings->limit}";
		}
		//default sort by autoincrement keys
		if(isset($settings->sort)){
			$sortBy=$settings->sort;
		}
		//get only one record
		if(isset($settings->one) && $settings->one==true){
			$isRecord=true;
		}
		//show SQL
		if(isset($settings->show) && $settings->show==true){
			$showSQL=true;
		}
		//get language fields
		if(!empty($settings->fields)){
			foreach($settings->fields as $field){
				$SQL[]="{$field}_{$activeLanguage->Prefix} AS {$field}";
				unset($field);
			}
		}
		//add comma
		if((!empty($settings->as) || !empty($settings->fields)) && !empty($what)){
			$what="*,";
		}
		//inner join
		if(!empty($settings->inner)){
			if(count($settings->inner->table)>1){
				$innerSQL=array();
				foreach($settings->inner->table as $key=>$table){
					$innerSQL[]="INNER JOIN {$table} ON {$settings->inner->on[$key]}";
					unset($key,$table);
				}
				$innerSQL=" ".join(" ",$innerSQL);
			}else{
				$innerSQL=" INNER JOIN {$settings->inner->table} ON {$settings->inner->on}";
			}
		}
		//get SQL
		$SQL=join(",",$SQL);
		$objectSQL=$query.$what.$SQL." FROM {$tableName}{$innerSQL}{$whereSQL}{$orderSQL}{$limitSQL};";
		if($showSQL){
			self::preDump($objectSQL);
		}

		if(!empty($sortBy)){
			$allData=$DataBase->Query($objectSQL,true,null,$sortBy);
		}else{
			$allData=$DataBase->Query($objectSQL,false);
		}
		return $allData;
	}
	//функция прочих запросов к БД
	function query($table,$settings=array()){
		global $DataBase;

		$SQL=array();
		if(!empty($settings)){
			$settings=json_decode(json_encode($settings),false);
			//if empty $settings->table => return empty object
			if(empty($table)){
				return null;
			}
			//set type to query
			if(isset($settings->type)){
				if($settings->type=="insert"){
					$SQL[]="INSERT INTO";
				}elseif($settings->type=="update"){
					$SQL[]="UPDATE";
				}elseif($settings->type=="delete"){
					$SQL[]="DELETE FROM";
				}else{
					return null;
				}
			}
			//set table for query
			$SQL[]=$table;
			//get SET param
			if(isset($settings->set)){
				$SQL[]="SET {$settings->set}";
			}
			//get WHERE param
			if(isset($settings->where)){
				$SQL[]="WHERE {$settings->where}";
			}
			if(!empty($SQL)){
				$SQL=join(" ",$SQL);
				if(isset($settings->show) && $settings->show==true){
					self::preDump($SQL);
				}
				if($settings->type=="insert"){
					return $DataBase->InsertQuery($SQL,null);
				}else{
					$DataBase->UpdateQuery($SQL);
					return true;
				}
			}else{
				return null;
			}
		}else{
			return null;
		}
	}
	//функция начальника для запросов к БД
	function Query($Query,$ReturnInArray=true,$Values=array(),$ArrayKey="Id",$ReturnLastId=false,$IsUpdate=false,$ArrayValues=array()){
		$QueryResults=$this->Connection->prepare($Query, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$QueryResults->execute($Values);

		if($IsUpdate)
			return true;

		if($ReturnLastId)
			return $this->Connection->lastInsertId();

		if(!$ReturnInArray){
			$QueryResults=$QueryResults->fetch();
			foreach($ArrayValues as $Value){
				$QueryResults->$Value=array();

				unset($Value);
			}
			unset($ArrayValues);
			return $QueryResults;
		}else{
			$Results=array();
			while($Row=$QueryResults->fetch()){
				//var_dump($Row);
				if(is_null($ArrayKey)){
					$Results[]=$Row;
				}elseif(is_array($ArrayKey)){
					$this->FillArray($Results,$Row,$ArrayKey,true);
				}elseif(!empty($ArrayKey))
					$Results[$Row->$ArrayKey]=$Row;
				else
					$Results[]=$Row;

				unset($Row);
			}
			unset($QueryResults);

			if(count($ArrayValues)){
				foreach($Results as $Key=>$Result){
					foreach($ArrayValues as $Value){
						$Result->$Value=array();
						$Results[$Key]=$Result;

						unset($Value);
					}
					unset($Result);
				}
				unset($ArrayValues);
			}

			return $Results;
		}
	}


Примеры использования по просьбе комментирующих:

$allData=$Kernel->getRecords($GLOBAL->Table,array(
	"where"=>"`Type`='Some' AND`Status`='Y'",
	"order"=>"`Position`",
	"sort"=>"Id"
));
$Kernel->query($GLOBAL->Table,array(
	"type"=>"insert",
	"set"=>"`Variable1`='{$data1}',`Variable2`={$data2}"
));

UPD1
Для любителей похоливарить на тему (object) vs json_encode: массивы всегда ассоциативные с большой вложенностью. При использовании (object) вся внутренняя структура созданных объектов остается массивами, а при json_decode(json_encode($array), false) массив ВЕСЬ становится объектом.
  • Вопрос задан
  • 613 просмотров
Пригласить эксперта
Ответы на вопрос 8
SerafimArts
@SerafimArts
Senior Notepad Reader
Друг, твой код - это феерический трешак, а начальник твой - хуже школьника. Так ему и передай, можешь на меня ссылаться.

Мой добрый совет - беги оттуда, пока не поздно.
Ответ написан
Комментировать
Sanasol
@Sanasol Куратор тега PHP
нельзя просто так взять и загуглить ошибку
$settings=json_decode(json_encode($settings),false);


11/10 госпади.

Очень интересно увидеть пример использования функций, а то такой треш в голове трудно представить.

И да, сторонними библиотеками мы не пользуемся, только велосипеды свои.

composer откройте для начальника и молча уйдите ;D

Бессмысленно что-то говорить/исправлять, код никакой.
Ответ написан
Комментировать
AlexMaxTM
@AlexMaxTM
До ООП еще не доросли?
А про PSR тоже не слышали? Все таки люди стараются привести код к единому стандарту.
Знаете чего не хватает вашему коду? Новизны. Он устарел лет на 15-20 уже.
Ответ написан
profesor08
@profesor08 Куратор тега PHP
Твой начальник не любит фреймворки, хочет скорости, и безопасность, но сам же наговнокодил такую парашу, которая пытается походить на фреймворк, но пользоваться этим без слез невозможно. Причем безопасность этой параши под вопросом. Все зависит что прилетит в settings, либо добротный запрос, либо инъекция. Так-же функция возвращает несколько типов данных, и как это проверять? Такой-же мотней кода как вот это?
Ответ написан
@AlexndrNovikov
Solution Architect in Spiral Scout
Если вы пишете такие продукты, что уперлись в производительности в PHP - мое почтение. (хотя что-то мне не верится). Особенно с такими примерами кода.

Как правило логичным шагом при получении таких ограничений - переписывание узких мест на более производительных языках, как например поступают в Badoo. на C/go. А основная кодовая база ТАК выглядеть не должна ни при каких условиях.
Используется функциональный подход - так где функции высшего порядка? где отсутствие глобальных состояний? Ваш начальник не умеет ни функциональный подход готовить, ни объектно-ориентированный.
По факту - вашего начальника я бы не взял даже на должность джуниора - 15 лет писать вот такое, принципиально считать что твои велосипеды лучше всех сложившихся практик, и быть намертво уверенным в собственной правоте - это смерть для разработчика и для коллектива, в котором он работает, а если уж он еще и начальник в нем... Из-за таких как он и ходит в сообществе мнение о PHP как о плохом языке для обезьян.

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

Ну это как и у других - оффтоп с критикой твоего начальства.

Что касается именно кода - обрати внимание на PSR соглашения - по форматированию кода, именованию переменных, сделаешь код более читаемым (www.php-fig.org/psr/) , это стандарт в индустрии и на скорость никак не повлияет, можешь даже начальнику показать.
Дальше познакомься с PDO и понятиям SQL инъекций. Код приведенный в вопросе абсолютно небезопасен, и то, что параметр $settings задается разработчиком - не аргумент. Новый джун может запросто туда отправить просто $_POST при сабмите формы - и вы никак от этого не защититесь. Код должен быть защищенным изначально, а не дырявым и "но вы эти дыры не используйте".
Листинги кода такой длины - нечитаемые, бейте на логические куски, книга Мартина Фаулера "Рефакторинг" в помощь, чтобы понять, как оптимально и правильно это сделать.
Ответ написан
FanatPHP
@FanatPHP
Чебуратор тега РНР
Ну, то что это адова жесть, уже все сказали.
Но я логики понять не могу. В чем профит?
Сравниваем код на этом адском поделии
$allData=$Kernel->getRecords($GLOBAL->Table,array(
  "where"=>"`Type`='Some' AND`Status`='Y'",
  "order"=>"`Position`",
  "sort"=>"Id"
));

И код на чистом PDO/SQL
$allData = $pdo
    ->query("SELECT * FROM $GLOBAL->Table WHERE `Type`='Some' AND `Status`='Y' ORDER BY `Position`")
    ->fetchAll();

В ЧЕМ ПРОФИТ?
Какой смысл разбивать SQL на массив и писать по отдельности, когда можно просто сразу написать нормальный SQL?

Ну и про безопасность тут уже все сказали. Я не знаю, за какой "безопасности" тут речь, но вот тут
$Kernel->query($GLOBAL->Table,array(
  "type"=>"insert",
  "set"=>"`Variable1`='{$data1}',`Variable2`={$data2}"
));

инъекция на инъекции и инъекцией погоняет.

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

Вот твой второй запрос с использованием его функции:

$Database->Query("INSERT INTO $GLOBAL->Table SET `Variable1`=?',`Variable2`=?", [$data1, $data2]);


это четкий, ясный и безопасный код.
Внимание, снова вопрос: НАФИГА?
ЗАЧЕМ ты нагородил вот это вот всё, если оно в 100 раз хуже чем было?
Ответ написан
oxyberg
@oxyberg
Продуктовый дизайнер ВКонтакте
Используйте внедрение зависимости, или на худой конец одиночку, вместо глобальных переменных. Еще привести бы все к одному стилю именования, а то у вас то со строчной, то с прописной.
Ответ написан
index0h
@index0h
PHP, Golang. https://github.com/index0h
чего не хватает и вообще всей логике написания.

качества, это ж полный П!

Читал, что использование global ЗЛО

Верно

но таков стиль кода моего начальника (а у него опыт 15 лет)

Твой начальник живет в 2002 году, что поделать, эт бывает когда не развиваешься, но с твоим мнением считаются.

И да, сторонними библиотеками мы не пользуемся, только велосипеды свои.

Это далеко не всегда так плохо, как кажется.

Приведенный вами код - говнище, начальник ваш - юниор, почитайте на досуге почему: Попросили проверить код, на что смотреть нужно?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы