API های کامل برای مدیریت سامانه درج آگهی به زبان PHP
در اینجا API های کامل برای مدیریت سامانه درج آگهی به زبان PHP ارائه میدهم:
1. فایل پیکربندی (config.php
)
php
<?php
header("Content-Type: application/json; charset=utf-8");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
exit(0);
}
// تنظیمات دیتابیس
define('DB_HOST', 'localhost');
define('DB_USER', 'username');
define('DB_PASS', 'password');
define('DB_NAME', 'advertising_system');
define('DB_CHARSET', 'utf8mb4');
// تنظیمات آپلود
define('UPLOAD_DIR', 'uploads/');
define('MAX_FILE_SIZE', 5 * 1024 * 1024); // 5MB
define('ALLOWED_TYPES', ['jpg', 'jpeg', 'png', 'gif']);
// تابع اتصال به دیتابیس
function getDBConnection() {
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Database connection failed']);
exit;
}
$conn->set_charset(DB_CHARSET);
return $conn;
}
// تابع پاسخ استاندارد
function sendResponse($success, $data = null, $message = '', $statusCode = 200) {
http_response_code($statusCode);
echo json_encode([
'success' => $success,
'message' => $message,
'data' => $data,
'timestamp' => date('Y-m-d H:i:s')
], JSON_UNESCAPED_UNICODE);
exit;
}
// تابع اعتبارسنجی JWT
function validateToken() {
$headers = getallheaders();
$token = isset($headers['Authorization']) ? str_replace('Bearer ', '', $headers['Authorization']) : '';
if (empty($token)) {
sendResponse(false, null, 'Access token required', 401);
}
$userId = verifyJWT($token);
if (!$userId) {
sendResponse(false, null, 'Invalid or expired token', 401);
}
return $userId;
}
function verifyJWT($token) {
// پیادهسازی ساده JWT (در پروژه واقعی از کتابخانه استفاده کنید)
try {
$parts = explode('.', $token);
if (count($parts) !== 3) return false;
$payload = json_decode(base64_decode($parts[1]), true);
if (!$payload || !isset($payload['user_id']) || $payload['exp'] < time()) {
return false;
}
return $payload['user_id'];
} catch (Exception $e) {
return false;
}
}
// تابع تولید JWT
function generateJWT($userId, $userType) {
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
$payload = json_encode([
'user_id' => $userId,
'user_type' => $userType,
'iat' => time(),
'exp' => time() + (24 * 60 * 60) // 24 ساعت
]);
$base64Header = base64_encode($header);
$base64Payload = base64_encode($payload);
$signature = hash_hmac('sha256', $base64Header . "." . $base64Payload, 'your-secret-key');
$base64Signature = base64_encode($signature);
return $base64Header . "." . $base64Payload . "." . $base64Signature;
}
// تابع آپلود فایل
function uploadFile($file, $adId) {
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new Exception('File upload error');
}
// بررسی حجم فایل
if ($file['size'] > MAX_FILE_SIZE) {
throw new Exception('File size too large');
}
// بررسی نوع فایل
$fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($fileExtension, ALLOWED_TYPES)) {
throw new Exception('Invalid file type');
}
// ایجاد پوشه اگر وجود ندارد
if (!is_dir(UPLOAD_DIR)) {
mkdir(UPLOAD_DIR, 0755, true);
}
// تولید نام فایل
$fileName = uniqid() . '_' . $adId . '.' . $fileExtension;
$filePath = UPLOAD_DIR . $fileName;
if (!move_uploaded_file($file['tmp_name'], $filePath)) {
throw new Exception('Failed to save file');
}
// ایجاد thumbnail (ساده)
$thumbnailPath = UPLOAD_DIR . 'thumb_' . $fileName;
createThumbnail($filePath, $thumbnailPath, 200, 200);
return [
'path' => $filePath,
'thumbnail' => $thumbnailPath,
'filename' => $fileName
];
}
function createThumbnail($source, $dest, $width, $height) {
// پیادهسازی ساده ایجاد thumbnail
// در پروژه واقعی از GD یا Imagick استفاده کنید
copy($source, $dest);
}
?>
2. API مدیریت کاربران (auth_api.php
)
php
<?php
include 'config.php';
$method = $_SERVER['REQUEST_METHOD'];
$conn = getDBConnection();
switch ($method) {
case 'POST':
$action = $_GET['action'] ?? '';
switch ($action) {
case 'register':
registerUser();
break;
case 'login':
loginUser();
break;
case 'forgot-password':
forgotPassword();
break;
case 'reset-password':
resetPassword();
break;
default:
sendResponse(false, null, 'Invalid action', 400);
}
break;
case 'GET':
getProfile();
break;
case 'PUT':
updateProfile();
break;
default:
sendResponse(false, null, 'Method not allowed', 405);
}
function registerUser() {
global $conn;
$data = json_decode(file_get_contents("php://input"), true);
$required = ['username', 'email', 'password', 'first_name', 'last_name'];
foreach ($required as $field) {
if (!isset($data[$field]) || empty($data[$field])) {
sendResponse(false, null, "Field $field is required", 400);
}
}
// بررسی تکراری نبودن username و email
$checkQuery = "SELECT UserID FROM Users WHERE Username = ? OR Email = ?";
$checkStmt = $conn->prepare($checkQuery);
$checkStmt->bind_param("ss", $data['username'], $data['email']);
$checkStmt->execute();
if ($checkStmt->get_result()->num_rows > 0) {
sendResponse(false, null, 'Username or email already exists', 400);
}
// هش کردن رمز عبور
$passwordHash = password_hash($data['password'], PASSWORD_DEFAULT);
$verificationToken = bin2hex(random_bytes(32));
$query = "INSERT INTO Users (Username, Email, PasswordHash, FirstName, LastName, Phone, VerificationToken)
VALUES (?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($query);
$stmt->bind_param(
"sssssss",
$data['username'],
$data['email'],
$passwordHash,
$data['first_name'],
$data['last_name'],
$data['phone'] ?? null,
$verificationToken
);
if ($stmt->execute()) {
$userId = $stmt->insert_id;
// ایجاد پروفایل کاربر
$profileQuery = "INSERT INTO UserProfiles (UserID) VALUES (?)";
$profileStmt = $conn->prepare($profileQuery);
$profileStmt->bind_param("i", $userId);
$profileStmt->execute();
// فعالسازی بسته رایگان
activateFreePackage($userId);
// ارسال ایمیل verification (در پروژه واقعی)
sendResponse(true, [
'user_id' => $userId,
'message' => 'User registered successfully. Please check your email for verification.'
], 'Registration successful', 201);
} else {
sendResponse(false, null, 'Registration failed', 500);
}
}
function activateFreePackage($userId) {
global $conn;
$packageQuery = "SELECT PackageID FROM UserPackages WHERE PackageType = 'Free'";
$packageResult = $conn->query($packageQuery);
$freePackage = $packageResult->fetch_assoc();
if ($freePackage) {
$startDate = date('Y-m-d H:i:s');
$endDate = date('Y-m-d H:i:s', strtotime('+30 days'));
$subscriptionQuery = "
INSERT INTO UserSubscriptions (UserID, PackageID, StartDate, EndDate, IsActive)
VALUES (?, ?, ?, ?, TRUE)
";
$subscriptionStmt = $conn->prepare($subscriptionQuery);
$subscriptionStmt->bind_param("iiss", $userId, $freePackage['PackageID'], $startDate, $endDate);
$subscriptionStmt->execute();
}
}
function loginUser() {
global $conn;
$data = json_decode(file_get_contents("php://input"), true);
if (!isset($data['username']) || !isset($data['password'])) {
sendResponse(false, null, 'Username and password are required', 400);
}
$query = "
SELECT u.*, up.CompanyName, s.PackageID, p.PackageType, p.AutoApprove
FROM Users u
LEFT JOIN UserProfiles up ON u.UserID = up.UserID
LEFT JOIN UserSubscriptions s ON u.UserID = s.UserID AND s.IsActive = TRUE
LEFT JOIN UserPackages p ON s.PackageID = p.PackageID
WHERE u.Username = ? OR u.Email = ?
";
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $data['username'], $data['username']);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
sendResponse(false, null, 'Invalid credentials', 401);
}
$user = $result->fetch_assoc();
if (!password_verify($data['password'], $user['PasswordHash'])) {
sendResponse(false, null, 'Invalid credentials', 401);
}
if (!$user['IsActive']) {
sendResponse(false, null, 'Account is deactivated', 403);
}
// بهروزرسانی آخرین لاگین
$updateQuery = "UPDATE Users SET LastLogin = NOW() WHERE UserID = ?";
$updateStmt = $conn->prepare($updateQuery);
$updateStmt->bind_param("i", $user['UserID']);
$updateStmt->execute();
// تولید توکن
$token = generateJWT($user['UserID'], $user['UserType']);
sendResponse(true, [
'token' => $token,
'user' => [
'user_id' => $user['UserID'],
'username' => $user['Username'],
'email' => $user['Email'],
'first_name' => $user['FirstName'],
'last_name' => $user['LastName'],
'user_type' => $user['UserType'],
'company_name' => $user['CompanyName'],
'package_type' => $user['PackageType'],
'auto_approve' => (bool)$user['AutoApprove']
]
], 'Login successful');
}
function getProfile() {
global $conn;
$userId = validateToken();
$query = "
SELECT
u.UserID, u.Username, u.Email, u.FirstName, u.LastName, u.Phone, u.Avatar,
u.UserType, u.IsVerified, u.CreatedAt,
up.CompanyName, up.Website, up.Address, up.City, up.Province, up.PostalCode,
up.Bio, up.SocialMedia, up.NotificationPreferences,
s.PackageID, p.PackageName, p.PackageType, s.EndDate as SubscriptionEnd
FROM Users u
LEFT JOIN UserProfiles up ON u.UserID = up.UserID
LEFT JOIN UserSubscriptions s ON u.UserID = s.UserID AND s.IsActive = TRUE
LEFT JOIN UserPackages p ON s.PackageID = p.PackageID
WHERE u.UserID = ?
";
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
sendResponse(false, null, 'User not found', 404);
}
$user = $result->fetch_assoc();
// تبدیل JSON fields به array
if ($user['SocialMedia']) {
$user['SocialMedia'] = json_decode($user['SocialMedia'], true);
}
if ($user['NotificationPreferences']) {
$user['NotificationPreferences'] = json_decode($user['NotificationPreferences'], true);
}
sendResponse(true, $user, 'Profile retrieved successfully');
}
function updateProfile() {
global $conn;
$userId = validateToken();
$data = json_decode(file_get_contents("php://input"), true);
$conn->begin_transaction();
try {
// بهروزرسانی اطلاعات کاربر
$userFields = [];
$userParams = [];
$userTypes = "";
$updatableUserFields = ['FirstName', 'LastName', 'Phone', 'Avatar'];
foreach ($updatableUserFields as $field) {
if (isset($data[$field])) {
$userFields[] = "$field = ?";
$userParams[] = $data[$field];
$userTypes .= "s";
}
}
if (!empty($userFields)) {
$userParams[] = $userId;
$userTypes .= "i";
$userQuery = "UPDATE Users SET " . implode(", ", $userFields) . " WHERE UserID = ?";
$userStmt = $conn->prepare($userQuery);
$userStmt->bind_param($userTypes, ...$userParams);
$userStmt->execute();
}
// بهروزرسانی پروفایل
$profileFields = [];
$profileParams = [];
$profileTypes = "";
$updatableProfileFields = [
'CompanyName', 'Website', 'Address', 'City', 'Province', 'PostalCode', 'Bio',
'SocialMedia', 'NotificationPreferences'
];
foreach ($updatableProfileFields as $field) {
if (isset($data[$field])) {
$profileFields[] = "$field = ?";
if (in_array($field, ['SocialMedia', 'NotificationPreferences'])) {
$profileParams[] = json_encode($data[$field]);
} else {
$profileParams[] = $data[$field];
}
$profileTypes .= "s";
}
}
if (!empty($profileFields)) {
$profileParams[] = $userId;
$profileTypes .= "i";
$profileQuery = "UPDATE UserProfiles SET " . implode(", ", $profileFields) . " WHERE UserID = ?";
$profileStmt = $conn->prepare($profileQuery);
$profileStmt->bind_param($profileTypes, ...$profileParams);
$profileStmt->execute();
}
$conn->commit();
sendResponse(true, null, 'Profile updated successfully');
} catch (Exception $e) {
$conn->rollback();
sendResponse(false, null, 'Failed to update profile', 500);
}
}
?>
3. API مدیریت آگهیها (ads_api.php
)
php
<?php
include 'config.php';
$method = $_SERVER['REQUEST_METHOD'];
$conn = getDBConnection();
switch ($method) {
case 'GET':
getAds();
break;
case 'POST':
createAd();
break;
case 'PUT':
updateAd();
break;
case 'DELETE':
deleteAd();
break;
}
function getAds() {
global $conn;
$adId = $_GET['ad_id'] ?? null;
$userId = $_GET['user_id'] ?? null;
$categoryId = $_GET['category_id'] ?? null;
$status = $_GET['status'] ?? null;
$search = $_GET['search'] ?? null;
$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 20;
$offset = ($page - 1) * $limit;
$whereConditions = ["a.Status != 'Draft'"];
$params = [];
$types = "";
if ($adId) {
$whereConditions[] = "a.AdID = ?";
$params[] = $adId;
$types .= "i";
}
if ($userId) {
$whereConditions[] = "a.UserID = ?";
$params[] = $userId;
$types .= "i";
}
if ($categoryId) {
$whereConditions[] = "a.CategoryID = ?";
$params[] = $categoryId;
$types .= "i";
}
if ($status) {
$whereConditions[] = "a.Status = ?";
$params[] = $status;
$types .= "s";
}
$whereClause = implode(" AND ", $whereConditions);
// اگر جستجو وجود دارد
if ($search) {
$whereClause .= " AND (MATCH(a.Title, a.Description, a.ShortDescription) AGAINST(? IN NATURAL LANGUAGE MODE) OR a.Title LIKE ?)";
$params[] = $search;
$params[] = "%$search%";
$types .= "ss";
}
// گرفتن تعداد کل
$countQuery = "
SELECT COUNT(*) as total
FROM Advertisements a
WHERE $whereClause
";
$countStmt = $conn->prepare($countQuery);
if (!empty($params)) {
$countStmt->bind_param($types, ...$params);
}
$countStmt->execute();
$totalResult = $countStmt->get_result();
$total = $totalResult->fetch_assoc()['total'];
// گرفتن آگهیها
$query = "
SELECT
a.AdID, a.Title, a.Slug, a.ShortDescription, a.Price, a.Currency,
a.IsNegotiable, a.Status, a.IsPremium, a.IsUrgent, a.ViewCount,
a.LikeCount, a.ExpiryDate, a.CreatedAt,
c.CategoryName, c.CategorySlug,
u.UserID, u.Username, u.FirstName, u.LastName, up.CompanyName,
(SELECT ImagePath FROM AdImages WHERE AdID = a.AdID AND IsPrimary = TRUE LIMIT 1) as PrimaryImage,
COUNT(DISTINCT f.FavoriteID) as FavoriteCount
FROM Advertisements a
INNER JOIN Categories c ON a.CategoryID = c.CategoryID
INNER JOIN Users u ON a.UserID = u.UserID
LEFT JOIN UserProfiles up ON u.UserID = up.UserID
LEFT JOIN Favorites f ON a.AdID = f.AdID
WHERE $whereClause
GROUP BY a.AdID
ORDER BY
a.IsPremium DESC,
a.IsUrgent DESC,
a.FeaturedUntil DESC,
a.CreatedAt DESC
LIMIT ? OFFSET ?
";
$params[] = $limit;
$params[] = $offset;
$types .= "ii";
$stmt = $conn->prepare($query);
$stmt->bind_param($types, ...$params);
$stmt->execute();
$result = $stmt->get_result();
$ads = [];
while ($row = $result->fetch_assoc()) {
$ads[] = $row;
}
sendResponse(true, [
'ads' => $ads,
'pagination' => [
'page' => intval($page),
'limit' => intval($limit),
'total' => $total,
'pages' => ceil($total / $limit)
]
], 'Ads retrieved successfully');
}
function createAd() {
global $conn;
$userId = validateToken();
// بررسی subscription کاربر
$subscriptionQuery = "
SELECT p.*, s.EndDate
FROM UserSubscriptions s
INNER JOIN UserPackages p ON s.PackageID = p.PackageID
WHERE s.UserID = ? AND s.IsActive = TRUE AND s.EndDate > NOW()
";
$subscriptionStmt = $conn->prepare($subscriptionQuery);
$subscriptionStmt->bind_param("i", $userId);
$subscriptionStmt->execute();
$subscription = $subscriptionStmt->get_result()->fetch_assoc();
if (!$subscription) {
sendResponse(false, null, 'No active subscription found', 403);
}
// بررسی تعداد آگهیهای فعال کاربر
$activeAdsQuery = "SELECT COUNT(*) as active_ads FROM Advertisements WHERE UserID = ? AND Status IN ('Pending', 'Approved')";
$activeAdsStmt = $conn->prepare($activeAdsQuery);
$activeAdsStmt->bind_param("i", $userId);
$activeAdsStmt->execute();
$activeAds = $activeAdsStmt->get_result()->fetch_assoc()['active_ads'];
if ($activeAds >= $subscription['MaxAds']) {
sendResponse(false, null, 'Maximum ads limit reached for your package', 403);
}
$data = json_decode(file_get_contents("php://input"), true);
$required = ['title', 'category_id', 'description', 'contact_info'];
foreach ($required as $field) {
if (!isset($data[$field]) || empty($data[$field])) {
sendResponse(false, null, "Field $field is required", 400);
}
}
$conn->begin_transaction();
try {
// تولید slug
$slug = generateSlug($data['title']);
// تعیین وضعیت آگهی
$status = 'Pending';
if ($subscription['AutoApprove']) {
$status = 'Approved';
}
// تاریخ انقضا
$expiryDays = 30; // از تنظیمات سیستم بگیرید
$expiryDate = date('Y-m-d H:i:s', strtotime("+$expiryDays days"));
$query = "
INSERT INTO Advertisements (
UserID, CategoryID, Title, Slug, Description, ShortDescription,
Price, Currency, IsNegotiable, ContactInfo, LocationInfo,
Status, IsPremium, IsUrgent, ExpiryDate
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
";
$stmt = $conn->prepare($query);
$stmt->bind_param(
"iissssdssssssss",
$userId,
$data['category_id'],
$data['title'],
$slug,
$data['description'],
$data['short_description'] ?? null,
$data['price'] ?? 0,
$data['currency'] ?? 'IRT',
$data['is_negotiable'] ?? false,
json_encode($data['contact_info']),
isset($data['location_info']) ? json_encode($data['location_info']) : null,
$status,
$data['is_premium'] ?? false,
$data['is_urgent'] ?? false,
$expiryDate
);
$stmt->execute();
$adId = $stmt->insert_id;
// ذخیره ویژگیهای آگهی
if (isset($data['attributes']) && is_array($data['attributes'])) {
foreach ($data['attributes'] as $attributeId => $value) {
saveAttributeValue($adId, $attributeId, $value);
}
}
$conn->commit();
sendResponse(true, [
'ad_id' => $adId,
'slug' => $slug,
'status' => $status
], 'Ad created successfully', 201);
} catch (Exception $e) {
$conn->rollback();
sendResponse(false, null, 'Failed to create ad: ' . $e->getMessage(), 500);
}
}
function generateSlug($title) {
global $conn;
$slug = preg_replace('/[^\p{L}\p{N}\s]/u', '', $title);
$slug = str_replace(' ', '-', $slug);
$slug = strtolower($slug);
$slug = preg_replace('/-+/', '-', $slug);
$slug = trim($slug, '-');
// بررسی تکراری نبودن
$baseSlug = $slug;
$counter = 1;
while (true) {
$checkQuery = "SELECT AdID FROM Advertisements WHERE Slug = ?";
$checkStmt = $conn->prepare($checkQuery);
$checkStmt->bind_param("s", $slug);
$checkStmt->execute();
if ($checkStmt->get_result()->num_rows === 0) {
break;
}
$slug = $baseSlug . '-' . $counter;
$counter++;
}
return $slug;
}
function saveAttributeValue($adId, $attributeId, $value) {
global $conn;
$query = "
INSERT INTO AdAttributeValues (AdID, AttributeID, StringValue, NumberValue, BooleanValue, DateValue)
VALUES (?, ?, ?, ?, ?, ?)
";
$stmt = $conn->prepare($query);
// تشخیص نوع مقدار بر اساس نوع attribute
$attributeQuery = "SELECT AttributeType FROM AdAttributes WHERE AttributeID = ?";
$attributeStmt = $conn->prepare($attributeQuery);
$attributeStmt->bind_param("i", $attributeId);
$attributeStmt->execute();
$attributeType = $attributeStmt->get_result()->fetch_assoc()['AttributeType'];
$stringValue = null;
$numberValue = null;
$booleanValue = null;
$dateValue = null;
switch ($attributeType) {
case 'Text':
case 'Select':
$stringValue = $value;
break;
case 'Number':
$numberValue = $value;
break;
case 'Boolean':
$booleanValue = $value;
break;
case 'Date':
$dateValue = $value;
break;
}
$stmt->bind_param(
"iissis",
$adId, $attributeId, $stringValue, $numberValue, $booleanValue, $dateValue
);
$stmt->execute();
}
function updateAd() {
global $conn;
$userId = validateToken();
$adId = $_GET['ad_id'];
if (!$adId) {
sendResponse(false, null, 'Ad ID is required', 400);
}
// بررسی مالکیت آگهی
$ownershipQuery = "SELECT UserID, Status FROM Advertisements WHERE AdID = ?";
$ownershipStmt = $conn->prepare($ownershipQuery);
$ownershipStmt->bind_param("i", $adId);
$ownershipStmt->execute();
$ad = $ownershipStmt->get_result()->fetch_assoc();
if (!$ad) {
sendResponse(false, null, 'Ad not found', 404);
}
if ($ad['UserID'] != $userId) {
sendResponse(false, null, 'You are not authorized to update this ad', 403);
}
$data = json_decode(file_get_contents("php://input"), true);
$conn->begin_transaction();
try {
$fields = [];
$params = [];
$types = "";
$updatableFields = [
'Title', 'CategoryID', 'Description', 'ShortDescription', 'Price',
'IsNegotiable', 'ContactInfo', 'LocationInfo', 'IsPremium', 'IsUrgent'
];
foreach ($updatableFields as $field) {
if (isset($data[strtolower($field)])) {
$fields[] = "$field = ?";
$value = $data[strtolower($field)];
if (in_array($field, ['ContactInfo', 'LocationInfo'])) {
$value = json_encode($value);
}
$params[] = $value;
$types .= "s";
}
}
if (isset($data['title'])) {
// اگر عنوان تغییر کرده، slug جدید تولید کن
$fields[] = "Slug = ?";
$params[] = generateSlug($data['title']);
$types .= "s";
}
if (!empty($fields)) {
$params[] = $adId;
$types .= "i";
$query = "UPDATE Advertisements SET " . implode(", ", $fields) . " WHERE AdID = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param($types, ...$params);
$stmt->execute();
}
// بهروزرسانی ویژگیها
if (isset($data['attributes']) && is_array($data['attributes'])) {
// حذف ویژگیهای قبلی
$deleteQuery = "DELETE FROM AdAttributeValues WHERE AdID = ?";
$deleteStmt = $conn->prepare($deleteQuery);
$deleteStmt->bind_param("i", $adId);
$deleteStmt->execute();
// درج ویژگیهای جدید
foreach ($data['attributes'] as $attributeId => $value) {
saveAttributeValue($adId, $attributeId, $value);
}
}
$conn->commit();
sendResponse(true, null, 'Ad updated successfully');
} catch (Exception $e) {
$conn->rollback();
sendResponse(false, null, 'Failed to update ad: ' . $e->getMessage(), 500);
}
}
?>
4. API مدیریت تصاویر آگهی (images_api.php
)
php
<?php
include 'config.php';
$method = $_SERVER['REQUEST_METHOD'];
$conn = getDBConnection();
switch ($method) {
case 'POST':
uploadAdImage();
break;
case 'DELETE':
deleteAdImage();
break;
case 'PUT':
setPrimaryImage();
break;
default:
sendResponse(false, null, 'Method not allowed', 405);
}
function uploadAdImage() {
global $conn;
$userId = validateToken();
$adId = $_POST['ad_id'] ?? null;
if (!$adId || !isset($_FILES['image'])) {
sendResponse(false, null, 'Ad ID and image file are required', 400);
}
// بررسی مالکیت آگهی
$ownershipQuery = "SELECT UserID FROM Advertisements WHERE AdID = ?";
$ownershipStmt = $conn->prepare($ownershipQuery);
$ownershipStmt->bind_param("i", $adId);
$ownershipStmt->execute();
$ad = $ownershipStmt->get_result()->fetch_assoc();
if (!$ad || $ad['UserID'] != $userId) {
sendResponse(false, null, 'You are not authorized to upload images for this ad', 403);
}
// بررسی تعداد تصاویر
$subscriptionQuery = "
SELECT p.MaxImagesPerAd
FROM UserSubscriptions s
INNER JOIN UserPackages p ON s.PackageID = p.PackageID
WHERE s.UserID = ? AND s.IsActive = TRUE
";
$subscriptionStmt = $conn->prepare($subscriptionQuery);
$subscriptionStmt->bind_param("i", $userId);
$subscriptionStmt->execute();
$subscription = $subscriptionStmt->get_result()->fetch_assoc();
$imageCountQuery = "SELECT COUNT(*) as image_count FROM AdImages WHERE AdID = ?";
$imageCountStmt = $conn->prepare($imageCountQuery);
$imageCountStmt->bind_param("i", $adId);
$imageCountStmt->execute();
$imageCount = $imageCountStmt->get_result()->fetch_assoc()['image_count'];
if ($imageCount >= $subscription['MaxImagesPerAd']) {
sendResponse(false, null, 'Maximum images limit reached for this ad', 403);
}
try {
$fileInfo = uploadFile($_FILES['image'], $adId);
// بررسی اینکه آیا این اولین تصویر است
$isPrimary = ($imageCount === 0);
$query = "
INSERT INTO AdImages (AdID, ImagePath, ImageThumbnail, IsPrimary, SortOrder)
VALUES (?, ?, ?, ?, ?)
";
$sortOrder = $imageCount + 1;
$stmt = $conn->prepare($query);
$stmt->bind_param(
"sssii",
$adId,
$fileInfo['path'],
$fileInfo['thumbnail'],
$isPrimary,
$sortOrder
);
$stmt->execute();
$imageId = $stmt->insert_id;
sendResponse(true, [
'image_id' => $imageId,
'path' => $fileInfo['path'],
'thumbnail' => $fileInfo['thumbnail'],
'is_primary' => $isPrimary
], 'Image uploaded successfully', 201);
} catch (Exception $e) {
sendResponse(false, null, 'Failed to upload image: ' . $e->getMessage(), 500);
}
}
function deleteAdImage() {
global $conn;
$userId = validateToken();
$imageId = $_GET['image_id'];
if (!$imageId) {
sendResponse(false, null, 'Image ID is required', 400);
}
// بررسی مالکیت تصویر
$ownershipQuery = "
SELECT ai.ImageID, ai.ImagePath, ai.ImageThumbnail, ai.IsPrimary, a.UserID
FROM AdImages ai
INNER JOIN Advertisements a ON ai.AdID = a.AdID
WHERE ai.ImageID = ?
";
$ownershipStmt = $conn->prepare($ownershipQuery);
$ownershipStmt->bind_param("i", $imageId);
$ownershipStmt->execute();
$image = $ownershipStmt->get_result()->fetch_assoc();
if (!$image) {
sendResponse(false, null, 'Image not found', 404);
}
if ($image['UserID'] != $userId) {
sendResponse(false, null, 'You are not authorized to delete this image', 403);
}
$conn->begin_transaction();
try {
// حذف فایلهای فیزیکی
if (file_exists($image['ImagePath'])) {
unlink($image['ImagePath']);
}
if (file_exists($image['ImageThumbnail'])) {
unlink($image['ImageThumbnail']);
}
// حذف از دیتابیس
$deleteQuery = "DELETE FROM AdImages WHERE ImageID = ?";
$deleteStmt = $conn->prepare($deleteQuery);
$deleteStmt->bind_param("i", $imageId);
$deleteStmt->execute();
// اگر تصویر حذف شده primary بود، اولین تصویر دیگر را primary کن
if ($image['IsPrimary']) {
$newPrimaryQuery = "
SELECT ImageID FROM AdImages
WHERE AdID = (SELECT AdID FROM AdImages WHERE ImageID = ?)
ORDER BY SortOrder ASC
LIMIT 1
";
$newPrimaryStmt = $conn->prepare($newPrimaryQuery);
$newPrimaryStmt->bind_param("i", $imageId);
$newPrimaryStmt->execute();
$newPrimary = $newPrimaryStmt->get_result()->fetch_assoc();
if ($newPrimary) {
$updatePrimaryQuery = "UPDATE AdImages SET IsPrimary = TRUE WHERE ImageID = ?";
$updatePrimaryStmt = $conn->prepare($updatePrimaryQuery);
$updatePrimaryStmt->bind_param("i", $newPrimary['ImageID']);
$updatePrimaryStmt->execute();
}
}
$conn->commit();
sendResponse(true, null, 'Image deleted successfully');
} catch (Exception $e) {
$conn->rollback();
sendResponse(false, null, 'Failed to delete image: ' . $e->getMessage(), 500);
}
}
?>
5. API مدیریت دستهبندیها (categories_api.php
)
php
<?php
include 'config.php';
$method = $_SERVER['REQUEST_METHOD'];
if ($method == 'GET') {
getCategories();
} else {
sendResponse(false, null, 'Method not allowed', 405);
}
function getCategories() {
global $conn;
$parentId = $_GET['parent_id'] ?? null;
$includeAttributes = $_GET['include_attributes'] ?? false;
$query = "
SELECT
c.CategoryID, c.CategoryName, c.CategorySlug, c.Description,
c.Icon, c.ParentCategoryID, c.SortOrder, c.IsActive,
pc.CategoryName as ParentCategoryName,
COUNT(DISTINCT a.AdID) as AdCount
FROM Categories c
LEFT JOIN Categories pc ON c.ParentCategoryID = pc.CategoryID
LEFT JOIN Advertisements a ON c.CategoryID = a.CategoryID AND a.Status = 'Approved'
WHERE c.IsActive = TRUE
";
$params = [];
$types = "";
if ($parentId !== null) {
$query .= " AND c.ParentCategoryID = ?";
$params[] = $parentId;
$types .= "i";
} else {
$query .= " AND c.ParentCategoryID IS NULL";
}
$query .= " GROUP BY c.CategoryID ORDER BY c.SortOrder, c.CategoryName";
$stmt = $conn->prepare($query);
if (!empty($params)) {
$stmt->bind_param($types, ...$params);
}
$stmt->execute();
$result = $stmt->get_result();
$categories = [];
while ($row = $result->fetch_assoc()) {
if ($includeAttributes) {
$row['attributes'] = getCategoryAttributes($row['CategoryID']);
}
$categories[] = $row;
}
sendResponse(true, $categories, 'Categories retrieved successfully');
}
function getCategoryAttributes($categoryId) {
global $conn;
$query = "
SELECT AttributeID, AttributeName, AttributeType, IsRequired, Options
FROM AdAttributes
WHERE CategoryID = ? AND IsActive = TRUE
ORDER BY SortOrder
";
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $categoryId);
$stmt->execute();
$result = $stmt->get_result();
$attributes = [];
while ($row = $result->fetch_assoc()) {
if ($row['Options']) {
$row['Options'] = json_decode($row['Options'], true);
}
$attributes[] = $row;
}
return $attributes;
}
?>
6. فایل روتر اصلی (router.php
)
php
<?php
include 'config.php';
$request_uri = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($request_uri, PHP_URL_PATH);
// مسیرهای API
$routes = [
'GET' => [
'/api/ads' => 'ads_api.php',
'/api/categories' => 'categories_api.php',
'/api/profile' => 'auth_api.php',
'/api/user/ads' => 'ads_api.php?user_only=true'
],
'POST' => [
'/api/auth/register' => 'auth_api.php?action=register',
'/api/auth/login' => 'auth_api.php?action=login',
'/api/ads' => 'ads_api.php',
'/api/ads/images' => 'images_api.php'
],
'PUT' => [
'/api/profile' => 'auth_api.php',
'/api/ads' => 'ads_api.php',
'/api/ads/images/primary' => 'images_api.php?action=set_primary'
],
'DELETE' => [
'/api/ads' => 'ads_api.php',
'/api/ads/images' => 'images_api.php'
]
];
// پیدا کردن مسیر منطبق
$matched = false;
foreach ($routes[$method] as $route => $file) {
if (strpos($path, $route) === 0) {
include($file);
$matched = true;
break;
}
}
if (!$matched) {
sendResponse(false, null, 'Endpoint not found', 404);
}
?>
7. مثال استفاده از API ها
javascript
// ثبتنام کاربر fetch('/api/auth/register', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ username: 'user123', email: 'user@example.com', password: 'password123', first_name: 'علی', last_name: 'محمدی', phone: '09123456789' }) }); // ورود کاربر fetch('/api/auth/login', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ username: 'user123', password: 'password123' }) }); // ایجاد آگهی جدید fetch('/api/ads', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-jwt-token' }, body: JSON.stringify({ title: 'فروش خودروی صندوق دار', category_id: 2, description: 'خودروی سالم و بدون رنگ', short_description: 'فروش خودروی مدل 1400', price: 500000000, is_negotiable: true, contact_info: { phone: '09123456789', email: 'user@example.com' }, location_info: { city: 'تهران', province: 'تهران', address: 'میدان انقلاب' }, attributes: { 1: '1400', // سال ساخت 2: '150000' // کارکرد } }) }); // آپلود تصویر برای آگهی const formData = new FormData(); formData.append('ad_id', 123); formData.append('image', fileInput.files[0]); fetch('/api/ads/images', { method: 'POST', headers: { 'Authorization': 'Bearer your-jwt-token' }, body: formData }); // گرفتن لیست آگهیها fetch('/api/ads?page=1&limit=20&category_id=2') .then(response => response.json()) .then(data => console.log(data));
این API های کامل تمام نیازهای یک سامانه درج آگهی را پوشش میدهند و میتوانند بر اساس نیازهای خاص توسعه داده شوند.
نظرات (۰)
هیچ نظری هنوز ثبت نشده است