Перед прочтением этого материала рекомендуем вам ознакомиться со следующими материалами:

Содержание

Вступление

Работу с базой данных условно можно разделить на две группы:

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

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

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

Вставка данных

Используя SQL

Класс JDatabaseQuery предоставляет несколько методов для вставки данных: insert(), columns() и values().

// Получаем объект коннектора базы данных
$db = JFactory::getDbo();
 
// Получаем объект запроса
$query = $db->getQuery(true);
 
// Колонки для вставки
$columns = array(
    'user_id', 
    'profile_key', 
    'profile_value', 
    'ordering'
);
 
// Значения для вставки
$values = array(
    42, 
    $db->quote('custom.message'), 
    $db->quote('Вставка данных с помощью insert()'), 
    1
);
 
// Составляем запрос
$query->insert($db->quoteName('#__user_profiles'))
    ->columns($db->quoteName($columns))
    ->values(implode(',', $values));
 
// Устанавливаем и выполняем запрос
$db->setQuery($query)
    ->execute();

(Здесь функция quoteName() добавляет соответствующие кавычки вокруг имен таблицы и столбцов, чтобы избежать конфликтов с любым зарезервированным словом базы данных, сейчас или в будущем). Чтобы получить идентификатор только что вставленной строки, вы можете использовать, например, метод 'insertid'.

// Получить строку, которая была только что вставлена
$new_row_id = $db->insertid();

Как сохранить пустое значение как NULL

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

// Получить подключение к базе данных.
$db = JFactory::getDbo();

// Создать новый объект запроса.
$query = $db->getQuery(true);

/** Первый случай [значение по умолчанию - NULL] **/
// Столбец 'profile_value' имеет значение NULL 
// в качестве значения по умолчанию. Итак, мы не будем 
// добавлять его в массив. Компонент database engine сохранит 
// значение NULL в качестве значения для столбца 'profile_value'.
$columns = array('user_id', 'profile_key', 'ordering');

// Вставить значения.
$values = array(1001, $db->quote('custom.message'), 1);

/** Второй случай [строка в качестве значения по умолчанию, 
// и вы также можете сохранить нулевое значение] **/
// Столбец 'profile_value' имеет пустую строку " 
// в качестве значения по умолчанию, но мы также можем 
// сохранить нулевое значение. Итак, мы должны добавить имя 
// столбца и нулевое значение в $columns и $values.
$columns = array('user_id', 'profile_key', 'profile_value', 'ordering');

// Вставить значения.
$values = array(1001, $db->quote('custom.message'), $db->quote('NULL'), 1);

Используя объект

Класс JDatabaseDriver предоставляет удобный метод insertObject($table, &$object, $key = null) для сохранения объекта напрямую в базу данных:

  • $table – имя таблицы
  • &$object – объект, публичные свойства которого соответствуют полям в таблице
  • $key – первичный ключ

В случае если мы передаем третий параметр, то свойству $key объекта присваивается значение идентификатора последней вставленной записи.

Метод insertObject() автоматически экранирует данные: применяет quoteName() к имени таблицы и колонкам, а также quote() к значениям.

// Создаем и заполняем объект
$profile = new stdClass();
$profile->user_id = 42;
$profile->profile_key = 'custom.message';
$profile->profile_value= 'Вставка данных с помощью insertObject()';
$profile->ordering = 1;
 
$db = JFactory::getDbo();
// Вставляем объект в таблицу профиля пользователя
$result = $db->insertObject('#__user_profiles', $profile);

Метод возвращает true, если вставка прошла успешно, в противном случае false.

Ещё раз!!! (для тупых).  Методы insert  и  insertObject  находятся в РАЗНЫХ классах, и соответственно в разных объектах. Метод insert находится в классе JDatabaseQuery  (объект $query), а метод insertObject в классе JDatabaseDriver (объект  $db). Соответственно и методы update и  updateObject. Я тут дня 2 не мог понять, куда метод потерялся. ;=)) Переписал код примера подробнее.

Обратите внимание, что нам не нужно экранировать имя таблицы; метод insertObject делает это за нас.

Метод insertObject выдаст ошибку, если возникнет проблема с вставкой записи в таблицу базы данных.

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

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

Например, с учетом следующего утверждения:

$result = $dbconnect->insertObject('#__my_table', $object, 'primary_key');

после выполнения $object->primary_key будет обновлено значением первичного ключа вновь вставленной строки.

ПОДСКАЗКА: Установите $object->primary_key в null или 0 (ноль) перед вставкой.

Как сохранить пустое значение как NULL при вставке объекта.

Если значение столбца по умолчанию равно NULL, вам не следует добавлять это имя столбца к объекту. Пусть система баз данных сохранит значение NULL в качестве значения по умолчанию. Если значение столбца по умолчанию не равно NULL и разрешено хранить нулевые значения, вы должны указать это в коде. Смотрите, как это сделать, в следующем примере.

// Создать и заполнить объект.
$profile = new stdClass();
$profile->user_id = 1001;
$profile->profile_key='custom.message';
$profile->ordering=1;

/** Первый случай [значение по умолчанию - NULL] **/
// Столбец 'profile_value' имеет значение NULL в качестве 
// значения по умолчанию. Итак, мы не будем добавлять его 
// к объекту. Компонент database engine сохранит значение 
// NULL в качестве значения для столбца 'profile_value'.
// $profile->profile_value='Вставка записи с помощью insertObject()';

/** Второй случай [строка в качестве значения по умолчанию, 
// и вы также можете сохранить нулевое значение] **/
// Столбец 'profile_value' имеет пустую строку " в качестве 
// значения по умолчанию, но мы также можем сохранить нулевое 
// значение. Итак, мы должны добавить имя столбца и нулевое 
// значение в качестве его значения.
$profile->profile_value = $db->quote('NULL');

// Вставить объект в таблицу профиля пользователя.
$result = JFactory::getDbo()->insertObject('#__user_profiles', $profile);

Обновление данных

Используя SQL

Класс JDatabaseQuery предоставляет два метода для обновления данных: update() и set().

// Получаем объект коннектора базы данных
$db = JFactory::getDbo();
 
// Получаем объект запроса
$query = $db->getQuery(true);
 
// Поля для обновления
$fields = array(
    $db->quoteName('profile_value') . ' = ' . $db->quote('Обновление данных для пользователя 42.'),
    $db->quoteName('ordering') . ' = 2'
);
 
// Условия обновления
$conditions = array(
    $db->quoteName('user_id') . ' = 42', 
    $db->quoteName('profile_key') . ' = ' . $db->quote('custom.message')
);
 
$query->update($db->quoteName('#__user_profiles'))
    ->set($fields)
    ->where($conditions);
 
// Устанавливаем и выполняем запрос
$db->setQuery($query)
    ->execute();



Используя объект

По аналогии с методом insertObject() класс JDatabaseDriver предоставляет метод updateObject($table, &$object, $key, $nulls = false) для обновления данных:

  • $table – имя таблицы
  • &$object – объект, публичные свойства которого соответствуют полям в таблице
  • $key – первичный ключ
  • $nulls – передаем true, если хотим обновить NULL значения

Ниже мы обновляем нашу таблицу, используя существующий первичный ключ id:

// Создаем и заполняем объект
$object = new stdClass();
$object->id = 1; // должен быть валидный первичный ключ
$object->title = 'Моя запись';
$object->description = 'Запись, которая будет обновлена.';
 
$db = JFactory::getDbo();
// Обновляем данные, используя id в качестве первичного ключа
$result = $db->updateObject('#__custom_table', $object, 'id');

 

Так же как и insertObject(), метод updateObject() автоматически экранирует данные: применяет quoteName() к имени таблицы и колонкам, а также quote() к значениям.

Метод возвращает true, если обновление прошло успешно или не было найдено полей для обновления, в противном случае - выдаст ошибку RuntimeException.

Мы должны убедиться, что запись уже существует, прежде чем пытаться обновить ее, поэтому мы, можем, добавить какую-то проверку записи перед выполнением метода updateObject.

Удаление данных

Удаление записи выполняется с помощью метода delete() класса JDatabaseQuery.

// Получаем объект коннектора базы данных
$db = JFactory::getDbo();
 
// Получаем объект запроса
$query = $db->getQuery(true);
 
// Удаляем все custom-ключи пользователя 42
$conditions = array(
    $db->quoteName('user_id') . ' = 42', 
    $db->quoteName('profile_key') . ' = ' . $db->quote('custom.%')
);
 
$query->delete($db->quoteName('#__user_profiles'))
    ->where($conditions);
 
// Устанавливаем и выполняем запрос
$db->setQuery($query)
    ->execute();

Пример Кода модуля

Ниже приведен код простого модуля Joomla, который вы можете установить и запустить, чтобы продемонстрировать использование функциональности JDatabase для обновления записей в базе данных, и который вы можете адаптировать для экспериментов с некоторыми из концепций, описанных выше. Если вы не уверены в разработке и установке модуля Joomla, то вам поможет руководство по созданию простого модуля. Важное примечание: В любых расширениях Joomla, которые вы разрабатываете, вам следует избегать прямого доступа к основным таблицам Joomla подобным образом и вместо этого использовать API-интерфейсы Joomla, если это вообще возможно, потому что структуры базы данных могут измениться без предупреждения. В папке mod_db_update создайте следующие 2 файла:

mod_db_update.xml

 

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
    <name>Database update demo</name>
    <version>1.0.1</version>
    <description>Code demonstrating use of Joomla Database class to perform SQL UPDATE statements</description>
    <files>
        <filename module="mod_db_update">mod_db_update.php</filename>
    </files>
</extension>

 

mod_db_update.php

 

<?php
defined('_JEXEC') or die('Restricted Access');

use Joomla\CMS\Factory;

$db = Factory::getDbo();

$me = Factory::getUser();

if ($me->id == 0)
{
	echo "Not logged on!";
}
else
{
	$email = $me->email; 
	// измените регистр адреса электронной почты
	$email_uppercase = strtoupper($email);
	if ($email == $email_uppercase)
	{
		$new_email = strtolower($email);
	}
	else
	{
		$new_email = $email_uppercase;
	}
	
	$query = $db->getQuery(true);

	$fields = array($db->quoteName('email') . " = '{$new_email}'");

	$conditions = array($db->quoteName('id') . ' = ' . $me->id); 

	$query->update($db->quoteName('#__users'))->set($fields)->where($conditions);

	echo $db->replacePrefix((string) $query);
	
	$db->setQuery($query);

	if ($result = $db->execute())
	{
		echo "Адрес электронной почты успешно изменен!";
	}
}

 

Приведенный выше код обновляет поле адреса электронной почты в записи пользователя текущего вошедшего в систему пользователя, переключаясь между верхним и нижним регистром при последовательных перезагрузках веб-страницы. Метод Factory::getUser() возвращает объект user текущего вошедшего в систему пользователя, или, если он не вошел в систему, то пустой объект user, поле id которого равно нулю. Выражение $db->replacePrefix((string) $query) возвращает фактическую инструкцию SQL, и вывод этого может быть полезен при отладке.

Заархивируйте каталог mod_db_update, чтобы создать mod_db_update.zip .

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

Сделайте этот модуль видимым, отредактировав его (нажмите на него на странице Модулей), затем:

  1. опубликование его статуса
  2. выбор позиции на странице для ее отображения
  3. на вкладке назначение меню укажите страницы, на которых оно должно отображаться

Когда вы посещаете веб-страницу сайта, вы должны увидеть модуль в выбранной вами позиции, и он должен вывести инструкцию SQL UPDATE и подтвердить, что он успешно обновил запись. Чтобы убедиться, что он правильно обновил запись, зайдите в phpmyadmin и просмотрите таблицу пользователей в базе данных Joomla. Обновления не отображаются с помощью функции admin Users на серверной части, так как Joomla отображает в нижнем регистре все адреса электронной почты в записях.