Просто добавьте ;charset=utf8
в строку подключения.
$pdo = new PDO('mysql:host=localhost;dbname=leonzemaim;charset=utf8', 'leonzemaim', 'leonzemaim');
Используйте платформу с уровнем ORM (Object-Relational Mapping). Тем путем Вы не должны помещать прямой SQL нигде. Embedded SQL сосет для удобочитаемости, обслуживания и всего.
Это зависит от размера запроса и трудности.
Я лично как heredocs. Но я не использую его для простые запросы. Это не важно. Главное, "Никогда не забывают выходить из значений"
Всегда не забывайте выходить из входа. Не делайте этого вручную, используйте подготовленные операторы. Вот метод в качестве примера от моего класса создания отчетов.
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 вручную.
Необходимо всегда действительно действительно ВСЕГДА использовать, готовят операторы с заполнителями для переменных.
Его немного больше кода, но это работает более эффективно на большей части DBS и защищает Вас от атак с использованием кода на SQL.
Вы могли использовать ORM, или sql представляют разработчика в виде строки, но некоторые сложные запросы требуют писать sql. Когда запись sql, поскольку Michał Słaby иллюстрирует, использует привязку запроса. Привязка запроса предотвращает внедрение SQL и поддерживает удобочитаемость. Что касается того, где поместить Ваши запросы: используйте образцовые классы.
$sql = sprintf("SELECT * FROM users WHERE id = %d", mysql_real_escape_string($_GET["id"]));
Безопасный от инжекции MySQL
Я предпочитаю как таковой:
$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");
Надеюсь, это поможет.
Я обычно пишу им как аргумент функции:
db_exec ("SELECT ...");
Кроме случаев, когда sql, собирающийся быть очень большим, я передаю его как переменную:
$SQL = "SELECT ...";
$result = db_exec ($SQL);
(Я использую функции обертки или объекты для операций базы данных),
Мне нравится этот формат. Это было упомянуто в предыдущем комментарии, но выравнивание казалось прочь мне.
$query = "SELECT "
. " foo, "
. " bar "
. "FROM "
. " mytable "
. "WHERE "
. " id = $userid";
Достаточно легкий читать и понять. Точки выстраиваются в линию с, равняется знаку, сохраняющему все в чистой строке.
Мне нравится идея сохранить Ваш SQL в отдельном файле также, хотя я не уверен, как это работало бы с переменными как $userid в моем примере выше.
После того как Вы добираетесь до определенного уровня, Вы понимаете, что 99% SQL, который Вы пишете, могли быть автоматизированы. Если Вы пишете, что так много запрашивает, что Вы думаете о файле свойств, Вы, вероятно, делаете что-то, что могло быть более просто:
Большая часть материала мы, которых делают программисты, являемся CRUD: Создайте Обновление Чтения, Удаляют
Как инструмент для меня, я создал Pork.dbObject. Объектный Картопостроитель Отношения + Активная Запись в 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's 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>");
}
}
Объект блога был бы похож на это:
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
О, да я также создал элементарный GUI для своего инструмента лесов: Свинина. Генератор