как вы встраиваете свои sql-скрипты в php? Вы просто пишете их в строке или heredoc или передаете их в файл sql? Существуют ли какие-либо рекомендации, когда их можно передать на аутсорсинг? Есть ли элегантный способ организовать это?
Как вы встроили свои sql-запросы в php-скрипты (стиль кодирования)?
Ответ 1
Используйте фреймворк с уровнем ORM (Object-Relational Mapping). Таким образом, вам не нужно размещать прямой SQL в любом месте. Встроенный SQL отстой для удобочитаемости, обслуживания и всего.
Ответ 2
Всегда помните, чтобы избежать ввода. Не делайте это вручную, используйте подготовленные заявления. Вот пример метода из моего класса отчетов.
public function getTasksReport($rmId, $stage, $mmcName) {
$rmCondition = $rmId ? 'mud.manager_id = :rmId' : 'TRUE';
$stageCondition = $stage ? 't.stage_id = :stageId' : 'TRUE';
$mmcCondition = $mmcName ? 'mmcs.username = :mmcName' : 'TRUE';
$sql = "
SELECT
mmcs.id AS mmc_id,
mmcs.username AS mmcname,
mud.band_name AS mmc_name,
t.id AS task_id,
t.name AS task,
t.stage_id AS stage,
t.role_id,
tl.id AS task_log_id,
mr.role,
u.id AS user_id,
u.username AS username,
COALESCE(cud.full_name, bud.band_name) AS user_name,
DATE_FORMAT(tl.completed_on, '%d-%m-%Y %T') AS completed_on,
tl.url AS url,
mud.manager_id AS rm_id
FROM users AS mmcs
INNER JOIN banduserdetails AS mud ON mud.user_id = mmcs.id
LEFT JOIN tasks AS t ON 1
LEFT JOIN task_log AS tl ON tl.task_id = t.id AND tl.mmc_id = mmcs.id
LEFT JOIN mmc_roles AS mr ON mr.id = t.role_id
LEFT JOIN users AS u ON u.id = tl.user_id
LEFT JOIN communityuserdetails AS cud ON cud.user_id = u.id
LEFT JOIN banduserdetails AS bud ON bud.user_id = u.id
WHERE mmcs.user_type = 'mmc'
AND $rmCondition
AND $stageCondition
AND $mmcCondition
ORDER BY mmcs.id, t.stage_id, t.role_id, t.task_order
";
$pdo = new PDO(.....);
$stmt = $pdo->prepare($sql);
$rmId and $stmt->bindValue('rmId', $rmId); // (1)
$stage and $stmt->bindValue('stageId', $stage); // (2)
$mmcName and $stmt->bindValue('mmcName', $mmcName); // (3)
$stmt->execute();
return $stmt->fetchAll();
}
В строках, обозначенных (1), (2) и (3), вы увидите способ условной привязки.
Для простых запросов я использую структуру ORM, чтобы уменьшить необходимость создания SQL вручную.
Ответ 3
Это зависит от размера и сложности запроса.
Мне лично нравится heredocs. Но я не использую его для простых запросов. Это не важно. Главное "Никогда не забывайте избегать значений"
Ответ 4
Вы всегда должны действительно действительно ВСЕГДА использовать инструкции подготовки с держателями мест для своих переменных.
Его немного больше кода, но он работает более эффективно на большинстве БД и защищает вас от атак SQL-инъекций.
Ответ 5
Я предпочитаю как таковой:
$sql = "SELECT tbl1.col1, tbl1.col2, tbl2.col1, tbl2.col2"
. " FROM Table1 tbl1"
. " INNER JOIN Table2 tbl2 ON tbl1.id = tbl2.other_id"
. " WHERE tbl2.id = ?"
. " ORDER BY tbl2.col1, tbl2.col2"
. " LIMIT 10, 0";
Может потребоваться немного времени на PHP, чтобы объединить все строки, но я думаю, что это выглядит намного приятнее и легче редактировать.
Конечно, для чрезвычайно длинных и специализированных запросов было бы целесообразно прочитать файл .sql или использовать хранимую процедуру. В зависимости от вашей структуры это может быть просто:
$sql = (string) View::factory('sql/myfile');
(дает вам возможность назначать переменные в представлении/шаблоне, если необходимо). Без помощи механизма шаблонов или фреймворка вы должны использовать:
$sql = file_get_contents("myfile.sql");
Надеюсь, что это поможет.
Ответ 6
Я обычно пишу их как аргумент функции:
db_exec ("SELECT ...");
За исключением случаев, когда sql будет очень большим, я передаю его как переменную:
$SQL = "SELECT ...";
$result = db_exec ($SQL);
(Я использую функции-обертки или объекты для операций с базой данных)
Ответ 7
$sql = sprintf("SELECT * FROM users WHERE id = %d", mysql_real_escape_string($_GET["id"]));
Безопасный запуск MySQL
Ответ 8
Вы можете использовать ORM или построитель строк sql, но некоторые сложные запросы требуют написания sql. При написании sql, как показывает Michał Słaby, используйте привязки запросов. Связывание запросов предотвращает внедрение sql и поддерживает читаемость. Что касается того, где поставить ваши запросы: использовать классы моделей.
Ответ 9
Как только вы доберетесь до определенного уровня, вы поймете, что 99% написанного SQL могут быть автоматизированы. Если вы пишете столько запросов, которые вы думаете о файле свойств, вы, вероятно, делаете то, что может быть проще:
Большая часть материала, который мы программисты, это CRUD: Create Read Update Delete
В качестве инструмента для себя я создал Pork.dbObject. Объектная привязка Mapper + Active Запись в 2 простых классах (класс абстракции базы данных + класс dbObject)
Несколько примеров из моего сайта:
Создать веб-журнал:
$weblog = new Weblog(); // create an empty object to work with.
$weblog->Author = 'SchizoDuckie'; // mapped internally to strAuthor.
$weblog->Title = 'A test weblog';
$weblog->Story = 'This is a test weblog!';
$weblog->Posted = date("Y-m-d H:i:s");
$weblog->Save(); // Checks for any changed values and inserts or updates into DB.
echo ($weblog->ID) // outputs: 1
И один ответ на него:
$reply = new Reply();
$reply->Author = 'Some random guy';
$reply->Reply = 'w000t';
$reply->Posted = date("Y-m-d H:i:s");
$reply->IP = '127.0.0.1';
$reply->Connect($weblog); // auto-saves $reply and connects it to $weblog->ID
И, выборка и отображение веб-журнала + все ответы:
$weblog = new Weblog(1); //Fetches the row with primary key 1 from table weblogs and hooks it values into $weblog;
echo("<h1>{$weblog->Title}</h1>
<h3>Posted by {$weblog->Author} @ {$weblog->Posted}</h3>
<div class='weblogpost'>{$weblog->Story}</div>");
// now fetch the connected posts. this is the real magic:
$replies = $weblog->Find("Reply"); // fetches a pre-filled array of Reply objects.
if ($replies != false)
{
foreach($replies as $reply)
{
echo("<div class='weblogreply'><h4>By {$reply->Author} @ {$reply->Posted}</h4> {$reply->Reply}</div>");
}
}
Объект weblog будет выглядеть так:
class Weblog extends dbObject
{
function __construct($ID=false)
{
$this->__setupDatabase('blogs', // database table
array('ID_Blog' => 'ID', // database field => mapped object property
'strPost' => 'Story', // as you can see, database field strPost is mapped to $this->Story
'datPosted' => 'Posted',
'strPoster' => 'Author',
'strTitle' => 'Title',
'ipAddress' => 'IpAddress',
'ID_Blog', // primary table key
$ID); // value of primary key to init with (can be false for new empty object / row)
$this->addRelation('Reaction'); // define a 1:many relation to Reaction
}
}
Смотрите, никаких ручных SQL-писем:) Ссылка + еще примеры: Pork.dbObject
О да, я также создал рудиментарный графический интерфейс для моего инструмента для строительных лесов: Pork.Generator
Ответ 10
Мне нравится этот формат. Это было упомянуто в предыдущем комментарии, но выравнивание показалось мне.
$query = "SELECT "
. " foo, "
. " bar "
. "FROM "
. " mytable "
. "WHERE "
. " id = $userid";
Достаточно легко читать и понимать. Точки выстраиваются в линию с помощью знака равенства, сохраняя все в чистой строке.
Мне нравится идея держать ваш SQL в отдельном файле, хотя я не уверен, как это работает с переменными типа $userid в моем примере выше.