Ghid complet de instalare și configurare pentru Laravel
Descarcă pachetul Laravel pentru feed JSON:
După descărcare, extrage fișierele în directorul rădăcină al proiectului Laravel.
Asigură-te că ai un model Product cu următoarele câmpuri:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name',
'description',
'price',
'sale_price',
'sku',
'category',
'brand',
'subcategories',
'image_url',
'stock_quantity',
'is_active',
'tags',
'attributes'
];
protected $casts = [
'price' => 'decimal:2',
'sale_price' => 'decimal:2',
'is_active' => 'boolean',
'tags' => 'array',
'attributes' => 'array',
'subcategories' => 'array',
'created_at' => 'datetime',
'updated_at' => 'datetime'
];
}
Feed-ul generează un obiect JSON cu toate produsele indexate după SKU:
{
"SKU12345": {
"sku": "SKU12345",
"name": "Numele produsului",
"qty": "10",
"price": 150.50,
"sale_price": 120.00,
"last_update_date": "2025-08-08 10:30:00",
"description": "Descrierea completă a produsului...",
"weight": "2.5",
"images": [
{"src": "https://site-ul-vostru.com/wp-content/uploads/image1.jpg"},
{"src": "https://site-ul-vostru.com/wp-content/uploads/image2.jpg"}
],
"permalink": "https://site-ul-vostru.com/product/numele-produsului/",
"categories_tree": [
{
"id": 25,
"name": "Categoria Principală",
"parent": 0,
"image": "https://site-ul-vostru.com/category-image.jpg",
"subcategories": [
{
"id": 30,
"name": "Subcategoria",
"parent": 25,
"image": "https://site-ul-vostru.com/subcategory-image.jpg",
"subcategories": []
}
]
}
],
"breadcrumbs": [
"Categoria Principală > Subcategoria"
],
"brands": [
{
"name": "NUMELE BRANDULUI",
"image": "https://site-ul-vostru.com/brand-logo.jpg"
}
]
}
}
Adaugă ruta pentru feed în routes/web.php:
use App\Http\Controllers\ProductFeedController;
// Ruta pentru feed-ul public
Route::get('/api/products/feed', [ProductFeedController::class, 'feed']);
// Ruta pentru feed-ul cu autentificare (opțional)
Route::middleware(['auth:sanctum'])->get('/api/products/feed/private', [ProductFeedController::class, 'privateFeed']);
Creează controller-ul pentru gestionarea feed-ului:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class ProductFeedController extends Controller
{
public function feed(Request $request): JsonResponse
{
// Validare API key (opțional)
$apiKey = $request->query('api_key');
if ($apiKey && $apiKey !== config('app.feed_api_key')) {
return response()->json(['error' => 'Invalid API key'], 401);
}
// Parametri pentru paginare
$limit = $request->query('limit', 100);
$page = $request->query('page', 1);
$offset = ($page - 1) * $limit;
// Filtrare produse active
$query = Product::where('is_active', true);
// Filtrare după categorie (opțional)
if ($request->has('category')) {
$query->where('category', $request->query('category'));
}
// Filtrare după preț (opțional)
if ($request->has('min_price')) {
$query->where('price', '>=', $request->query('min_price'));
}
if ($request->has('max_price')) {
$query->where('price', '<=', $request->query('max_price'));
}
// Obține produsele
$products = $query->skip($offset)->take($limit)->get();
// Formatează datele pentru feed în formatul Mixbox
$feedData = [];
foreach ($products as $product) {
$sku = $product->sku ?: 'PROD-' . $product->id;
$feedData[$sku] = [
'sku' => $sku,
'name' => $product->name,
'qty' => (string)$product->stock_quantity,
'price' => (float)$product->price,
'sale_price' => $product->sale_price ?? null,
'last_update_date' => $product->updated_at?->format('Y-m-d H:i:s') ?? now()->format('Y-m-d H:i:s'),
'description' => $product->description,
'weight' => $product->weight ?? null,
'images' => $product->image_url ? [
['src' => $product->image_url]
] : [],
'permalink' => route('product.show', $product->id),
'categories_tree' => [
[
'id' => 25,
'name' => $product->category ?? 'Categoria Principală',
'parent' => 0,
'image' => 'https://site-ul-vostru.com/category-image.jpg',
'subcategories' => $product->subcategories ?? [
[
'id' => 30,
'name' => 'Subcategoria',
'parent' => 25,
'image' => 'https://site-ul-vostru.com/subcategory-image.jpg',
'subcategories' => []
]
]
]
],
'breadcrumbs' => [
$product->category ? $product->category . ' > Subcategoria' : 'Categoria Principală > Subcategoria'
],
'brands' => $product->brand ? [
[
'name' => $product->brand,
'image' => 'https://site-ul-vostru.com/brand-logo.jpg'
]
] : []
];
}
return response()->json($feedData);
}
public function privateFeed(Request $request): JsonResponse
{
// Feed pentru utilizatori autentificați cu date suplimentare
$user = $request->user();
// Log acces pentru audit
\Log::info('Private feed accessed', [
'user_id' => $user->id,
'user_email' => $user->email,
'ip' => $request->ip(),
'timestamp' => now()
]);
// Generează feed-ul de bază
$feedResponse = $this->feed($request);
$feedData = $feedResponse->getData(true);
// Adaugă informații private pentru fiecare produs
foreach ($feedData as $sku => &$product) {
$product['accessed_by'] = [
'user_id' => $user->id,
'user_name' => $user->name,
'access_level' => 'private',
'access_time' => now()->toISOString()
];
// Adaugă câmpuri suplimentare pentru feed privat
$product['internal_notes'] = 'Notițe interne pentru ' . $product['name'];
$product['supplier_info'] = 'Informații furnizor';
$product['profit_margin'] = 25.5;
}
return response()->json($feedData);
}
}
Pentru performanță, poți adăuga cache pentru feed:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Cache;
class ProductFeedController extends Controller
{
public function feed(Request $request): JsonResponse
{
$cacheKey = 'product_feed_' . md5(serialize($request->query()));
$feedData = Cache::remember($cacheKey, 300, function () use ($request) { // Cache 5 minute
// ... codul existent pentru generarea feed-ului
});
return response()->json($feedData);
}
}
Creează middleware pentru limitarea accesului:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Symfony\Component\HttpFoundation\Response;
class FeedRateLimit
{
public function handle(Request $request, Closure $next): Response
{
$key = 'feed_' . $request->ip();
if (RateLimiter::tooManyAttempts($key, 60)) { // 60 requests per minute
return response()->json([
'error' => 'Too many requests',
'retry_after' => RateLimiter::availableIn($key)
], 429);
}
RateLimiter::hit($key);
return $next($request);
}
}
Adaugă middleware-ul în app/Http/Kernel.php:
protected $middlewareAliases = [
// ... alte middleware-uri
'feed.rate.limit' => \App\Http\Middleware\FeedRateLimit::class,
];
Aplică middleware-ul pe ruta feed-ului:
Route::middleware(['feed.rate.limit'])->get('/api/products/feed', [ProductFeedController::class, 'feed']);
Testează feed-ul accesând:
# Feed de bază
GET /api/products/feed
# Cu parametri
GET /api/products/feed?limit=50&page=1&category=electronics
# Cu API key
GET /api/products/feed?api_key=your_api_key
Adaugă logging pentru monitorizarea accesului:
public function feed(Request $request): JsonResponse
{
// Log acces
\Log::info('Product feed accessed', [
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'parameters' => $request->query(),
'timestamp' => now()
]);
// ... restul codului
}
Asigură-te că: