📚 Tutorial Laravel

Ghid complet de instalare și configurare pentru Laravel

← Înapoi la Tutoriale

🚀 Tutorial Laravel - Feed JSON Mixbox

🎯 Acest tutorial te va ajuta să integrezi un feed JSON pentru produse în aplicația ta Laravel.

📋 Cerințe Preliminare

  • Laravel 8.x sau mai nou
  • PHP 8.0+
  • Composer
  • Bază de date configurată
  • Model pentru produse

📦 Pasul 1: Instalare Pachet

Descarcă pachetul Laravel pentru feed JSON:

După descărcare, extrage fișierele în directorul rădăcină al proiectului Laravel.

🔧 Pasul 2: Configurare Model

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'
    ];
}

📄 Formatul feed-ului JSON

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"
      }
    ]
  }
}

🌐 Pasul 3: Configurare Route

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']);

🎮 Pasul 4: Creare Controller

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);
    }
}

⚙️ Pasul 5: Configurare Cache (Opțional)

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);
    }
}

🔒 Pasul 6: Middleware pentru Rate Limiting

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']);

🧪 Pasul 7: Testare 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

📊 Pasul 8: Monitorizare și Logging

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
}

🚀 Pasul 9: Deployment

Asigură-te că:

  • Rutele sunt accesibile public
  • Configurația cache-ului este optimizată
  • Rate limiting este configurat corespunzător
  • Logging-ul este activat pentru monitorizare
✅ Felicitări! Ai implementat cu succes un feed JSON pentru produse în Laravel. Feed-ul tău este acum gata să fie consumat de alte aplicații!

🔗 Link-uri Utile