/
delphin
/
CatRW
Обзор
Документация
Войти
/
delphin
/
CatRW
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
multilang
api/ManufacturerService.php
347 строк
13 KB
delphin
start project
02 мар 2026, 09:14
Верифицирован
02 мар 2026, 09:14
4b0ee03
Код
Авторство
О чём код?
<?php // /api/ManufacturerService.php - ПОЛНЫЙ КОД class ManufacturerService { // Получить всех производителей public static function getAll($limit = 1000) { try { $sql = "SELECT * FROM manufacturers ORDER BY name LIMIT :limit"; $stmt = Database::connect()->prepare($sql); $stmt->bindParam(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } catch (Exception $e) { error_log("ManufacturerService::getAll error: " . $e->getMessage()); return []; } } // Получить одного public static function get($id) { try { return Database::selectOne( "SELECT * FROM manufacturers WHERE id = :id", [':id' => $id] ); } catch (Exception $e) { error_log("ManufacturerService::get error for id $id: " . $e->getMessage()); return null; } } // Добавить - СТРОКА 50, ГДЕ ОШИБКА! public static function add($data) { try { // Валидация if (empty($data['name'])) { throw new Exception("Название обязательно"); } // Проверка уникальности $existing = Database::selectOne( "SELECT id FROM manufacturers WHERE name = ?", [$data['name']] ); if ($existing) { throw new Exception("Производитель с таким названием уже существует"); } // Очистка данных $cleanData = [ 'name' => trim($data['name']), 'country_code' => !empty($data['country_code']) ? strtoupper(trim($data['country_code'])) : null, 'website' => !empty($data['website']) ? filter_var($data['website'], FILTER_SANITIZE_URL) : null, 'founded_year' => !empty($data['founded_year']) ? (int)$data['founded_year'] : null, 'closed_year' => !empty($data['closed_year']) ? (int)$data['closed_year'] : null, 'notes' => !empty($data['notes']) ? trim($data['notes']) : null ]; return Database::insert('manufacturers', $cleanData); } catch (Exception $e) { error_log("ManufacturerService::add error: " . $e->getMessage()); throw $e; } } // Обновить public static function update($id, $data) { try { error_log("=== ManufacturerService::update() START ==="); error_log("Updating manufacturer ID: $id"); error_log("Data: " . print_r($data, true)); // Проверяем существование $manufacturer = self::get($id); if (!$manufacturer) { error_log("ERROR: Manufacturer not found ID: $id"); throw new Exception("Производитель не найден"); } error_log("Found manufacturer: " . $manufacturer['name']); // Если меняем название - проверяем уникальность if (!empty($data['name']) && $data['name'] !== $manufacturer['name']) { error_log("Name changed from '{$manufacturer['name']}' to '{$data['name']}'"); $existing = Database::selectOne( "SELECT id FROM manufacturers WHERE name = :name AND id != :id", [':name' => trim($data['name']), ':id' => $id] ); if ($existing) { error_log("ERROR: Duplicate name found"); throw new Exception("Производитель с таким названием уже существует"); } } // Очистка данных $cleanData = []; if (isset($data['name'])) { $cleanData['name'] = trim($data['name']); } if (isset($data['country_code'])) { $cleanData['country_code'] = !empty($data['country_code']) ? strtoupper(trim($data['country_code'])) : null; } else { $cleanData['country_code'] = null; } if (isset($data['website'])) { $cleanData['website'] = !empty($data['website']) ? filter_var($data['website'], FILTER_SANITIZE_URL) : null; } else { $cleanData['website'] = null; } if (isset($data['founded_year'])) { $cleanData['founded_year'] = !empty($data['founded_year']) ? (int)$data['founded_year'] : null; } else { $cleanData['founded_year'] = null; } if (isset($data['closed_year'])) { $cleanData['closed_year'] = !empty($data['closed_year']) ? (int)$data['closed_year'] : null; } else { $cleanData['closed_year'] = null; } if (isset($data['notes'])) { $cleanData['notes'] = !empty($data['notes']) ? trim($data['notes']) : null; } else { $cleanData['notes'] = null; } error_log("Clean data for update: " . print_r($cleanData, true)); // Используем Database::update() с именованными параметрами $result = Database::update( 'manufacturers', $cleanData, 'id = :id', [':id' => $id] ); error_log("Update result: $result"); error_log("=== ManufacturerService::update() SUCCESS ==="); return $result; } catch (Exception $e) { error_log("ManufacturerService::update ERROR: " . $e->getMessage()); throw $e; } } // Удалить (с проверкой на наличие моделей) public static function delete($id) { try { error_log("ManufacturerService::delete called for ID: " . $id); // 1. Проверяем существование производителя $manufacturer = self::get($id); if (!$manufacturer) { throw new Exception("Производитель #$id не найден"); } error_log("Manufacturer found: " . $manufacturer['name']); // 2. Проверяем, есть ли модели у этого производителя $modelsCount = Database::selectOne( "SELECT COUNT(*) as cnt FROM catalog_models WHERE manufacturer_id = :id", [':id' => $id] ); error_log("Models count: " . ($modelsCount['cnt'] ?? 0)); if ($modelsCount && $modelsCount['cnt'] > 0) { // Не удаляем, а помечаем как закрытого error_log("Marking as closed instead of deleting"); Database::update( 'manufacturers', ['closed_year' => date('Y')], 'id = :id', [':id' => $id] ); return [ 'type' => 'marked_closed', 'message' => 'Производитель помечен как закрытый (есть модели в каталоге)' ]; } // 3. Удаляем логотип если есть error_log("Deleting logo..."); $logoDeleted = self::deleteLogo($id); error_log("Logo deleted: " . ($logoDeleted ? 'YES' : 'NO')); // 4. Удаляем производителя error_log("Deleting manufacturer from database..."); $result = Database::delete('manufacturers', 'id = :id', [':id' => $id]); error_log("Database delete result: " . $result . " rows affected"); return [ 'type' => 'deleted', 'message' => 'Производитель удалён' ]; } catch (Exception $e) { error_log("ManufacturerService::delete ERROR for id $id: " . $e->getMessage()); error_log("Trace: " . $e->getTraceAsString()); throw $e; } } // Поиск public static function search($query) { try { if (empty($query)) { return self::getAll(); } $searchPattern = "%" . $query . "%"; // Используем анонимные параметры через Database::select() return Database::select( "SELECT * FROM manufacturers WHERE name LIKE ? ORDER BY name", [$searchPattern] ); } catch (Exception $e) { error_log("ManufacturerService::search error for query '$query': " . $e->getMessage()); return []; } } // Получить статистику public static function getStats() { try { return Database::selectOne(" SELECT COUNT(*) as total, SUM(CASE WHEN closed_year IS NULL THEN 1 ELSE 0 END) as active, COUNT(DISTINCT country_code) as countries FROM manufacturers "); } catch (Exception $e) { error_log("ManufacturerService::getStats error: " . $e->getMessage()); return ['total' => 0, 'active' => 0, 'countries' => 0]; } } // ===== РАБОТА С ЛОГОТИПАМИ ===== public static function getLogoUrl($id) { try { $dir = ROOT_PATH . '/uploads/manufacturers/'; $extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; foreach ($extensions as $ext) { $filename = $id . '.' . $ext; if (file_exists($dir . $filename)) { return '/uploads/manufacturers/' . $filename; } } return null; } catch (Exception $e) { error_log("ManufacturerService::getLogoUrl error for id $id: " . $e->getMessage()); return null; } } public static function deleteLogo($id) { try { $dir = ROOT_PATH . '/uploads/manufacturers/'; $extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; foreach ($extensions as $ext) { $filepath = $dir . $id . '.' . $ext; if (file_exists($filepath)) { unlink($filepath); return true; } } return false; } catch (Exception $e) { error_log("ManufacturerService::deleteLogo error for id $id: " . $e->getMessage()); return false; } } public static function uploadLogo($id, $file) { try { $dir = ROOT_PATH . '/uploads/manufacturers/'; // Создаём папку если нет if (!is_dir($dir)) { if (!mkdir($dir, 0777, true)) { throw new Exception("Не удалось создать папку для логотипов"); } } // Проверяем файл if ($file['error'] !== UPLOAD_ERR_OK) { throw new Exception("Ошибка загрузки файла: код " . $file['error']); } if ($file['size'] > 2 * 1024 * 1024) { // 2MB throw new Exception("Файл слишком большой (макс. 2MB)"); } // Определяем расширение $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); $allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp']; if (!in_array($ext, $allowed)) { throw new Exception("Допустимые форматы: " . implode(', ', $allowed)); } // Удаляем старый логотип self::deleteLogo($id); // Сохраняем $filename = $id . '.' . $ext; $filepath = $dir . $filename; if (move_uploaded_file($file['tmp_name'], $filepath)) { // Меняем права chmod($filepath, 0644); return '/uploads/manufacturers/' . $filename; } throw new Exception("Не удалось сохранить файл"); } catch (Exception $e) { error_log("ManufacturerService::uploadLogo error for id $id: " . $e->getMessage()); throw $e; } } } ?>