|
@@ -5,38 +5,87 @@ namespace App\Casts;
|
|
|
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
|
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Class BinaryTextCast
|
|
|
|
|
+ *
|
|
|
|
|
+ * Пользовательский класс для приведения типов, который обеспечивает преобразование
|
|
|
|
|
+ * текстовых данных, хранящихся в бинарном формате (VARBINARY) в базе данных,
|
|
|
|
|
+ * в строку UTF-8 для использования в приложении, и обратно.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Это необходимо для корректной работы с данными, которые хранятся в кодировке (Windows-1251),
|
|
|
|
|
+ * отличной от используемой в приложении.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @package App\Casts
|
|
|
|
|
+ */
|
|
|
class BinaryTextCast implements CastsAttributes
|
|
class BinaryTextCast implements CastsAttributes
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Преобразует значение из базы данных для использования в приложении.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Этот метод вызывается, когда мы получаем значение атрибута из модели Eloquent.
|
|
|
|
|
+ * Он обрабатывает бинарные данные, конвертируя их из Windows-1251 в UTF-8.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param \\Illuminate\\Database\\Eloquent\\Model $model
|
|
|
|
|
+ * @param string $key
|
|
|
|
|
+ * @param mixed $value
|
|
|
|
|
+ * @param array $attributes
|
|
|
|
|
+ * @return string|null
|
|
|
|
|
+ */
|
|
|
public function get($model, string $key, $value, array $attributes)
|
|
public function get($model, string $key, $value, array $attributes)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Если значение из БД равно null, возвращаем null
|
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Проверяем, является ли значение шестнадцатеричной строкой (например, '0x...').
|
|
|
|
|
+ // Некоторые драйверы баз данных могут возвращать бинарные данные в таком формате.
|
|
|
if (ctype_xdigit($value) && str_starts_with(strtolower($value), '0x')) {
|
|
if (ctype_xdigit($value) && str_starts_with(strtolower($value), '0x')) {
|
|
|
|
|
+ // Если да, убираем префикс '0x' и конвертируем из hex в бинарные данные.
|
|
|
$binary_data = hex2bin(substr($value, 2));
|
|
$binary_data = hex2bin(substr($value, 2));
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ // В противном случае, считаем, что значение уже является бинарными данными.
|
|
|
$binary_data = $value;
|
|
$binary_data = $value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Конвертируем бинарные данные из кодировки Windows-1251 в UTF-8
|
|
|
|
|
+ // и удаляем пробельные символы в конце строки.
|
|
|
return rtrim(mb_convert_encoding($binary_data, 'UTF-8', 'Windows-1251'));
|
|
return rtrim(mb_convert_encoding($binary_data, 'UTF-8', 'Windows-1251'));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * Подготавливает строку к сохранению в VARBINARY: CP1251 → двойной base64 → HEX 0x...
|
|
|
|
|
|
|
+ * Преобразует значение из приложения для сохранения в базу данных.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Этот метод вызывается, когда мы устанавливаем значение атрибута в модели Eloquent.
|
|
|
|
|
+ * Он конвертирует строку из UTF-8 в Windows-1251 и подготавливает ее
|
|
|
|
|
+ * для сохранения в поле типа VARBINARY.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param \\Illuminate\\Database\\Eloquent\\Model $model
|
|
|
|
|
+ * @param string $key
|
|
|
|
|
+ * @param mixed $value
|
|
|
|
|
+ * @param array $attributes
|
|
|
|
|
+ * @return array
|
|
|
*/
|
|
*/
|
|
|
public function set($model, string $key, $value, array $attributes)
|
|
public function set($model, string $key, $value, array $attributes)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Если устанавливаемое значение равно null, сохраняем null в БД.
|
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
|
return [$key => null];
|
|
return [$key => null];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Конвертируем строку из UTF-8 в Windows-1251.
|
|
|
$win1251_string = mb_convert_encoding($value, 'Windows-1251', 'UTF-8');
|
|
$win1251_string = mb_convert_encoding($value, 'Windows-1251', 'UTF-8');
|
|
|
|
|
+
|
|
|
|
|
+ // Преобразуем строку в ее шестнадцатеричное представление.
|
|
|
$hex_string = bin2hex($win1251_string);
|
|
$hex_string = bin2hex($win1251_string);
|
|
|
|
|
|
|
|
|
|
+ // Формируем бинарный литерал для SQL-запроса (например, 0x...).
|
|
|
$binary_literal = '0x' . $hex_string;
|
|
$binary_literal = '0x' . $hex_string;
|
|
|
|
|
|
|
|
|
|
+ // Возвращаем массив, где ключ - это имя атрибута, а значение -
|
|
|
|
|
+ // сырое SQL-выражение для преобразования hex-строки в VARBINARY(MAX).
|
|
|
|
|
+ // Это специфично для MS SQL Server.
|
|
|
return [
|
|
return [
|
|
|
$key => DB::raw("CONVERT(VARBINARY(MAX), " . $binary_literal . ")")
|
|
$key => DB::raw("CONVERT(VARBINARY(MAX), " . $binary_literal . ")")
|
|
|
];
|
|
];
|