👁 查看:ProductController.php
路径:/home/boguraj1/.trash/ProductController.php
大小:7.15 KB · 修改:2026-07-23 16:56:18 · 权限:0644 · 可写
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\Product;
use App\Models\ProductImage;
use App\Models\ProductVariation;
use App\Models\Tag;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ProductController extends Controller
{
    public function index(Request $request)
    {
        $query = Product::with('category')->latest();

        if ($request->filled('search')) {
            $query->where('name', 'like', '%' . $request->search . '%');
        }
        if ($request->filled('category')) {
            $query->where('category_id', $request->category);
        }

        $products   = $query->paginate(20)->withQueryString();
        $categories = Category::where('status', true)->get();

        return view('admin.products.index', compact('products', 'categories'));
    }

    public function create()
    {
        $categories = Category::where('status', true)->orderBy('name')->get();
        $tags       = Tag::orderBy('name')->get();
        return view('admin.products.create', compact('categories', 'tags'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'name'                   => 'required|string|max:255',
            'slug'                   => 'nullable|string|unique:products,slug',
            'category_id'            => 'nullable|exists:categories,id',
            'short_description'      => 'nullable|string',
            'description'            => 'nullable|string',
            'regular_price'          => 'required|numeric|min:0',
            'sale_price'             => 'nullable|numeric|min:0',
            'offer_text'             => 'nullable|string|max:255',
            'shipping_inside_dhaka'  => 'nullable|integer|min:0',
            'shipping_outside_dhaka' => 'nullable|integer|min:0',
            'stock'                  => 'required|integer|min:0',
            'status'                 => 'boolean',
            'featured'               => 'boolean',
            'thumbnail'              => 'nullable|image|max:4096',
            'images.*'               => 'nullable|image|max:4096',
            'tags'                   => 'nullable|array',
            'tags.*'                 => 'exists:tags,id',
        ]);

        $data['slug']     = $data['slug'] ?? Str::slug($data['name']);
        $data['status']   = $request->boolean('status', true);
        $data['featured'] = $request->boolean('featured', false);

        if ($request->hasFile('thumbnail')) {
            $data['thumbnail'] = $request->file('thumbnail')->store('products', 'public');
        }

        $product = Product::create($data);

        if ($request->has('tags')) {
            $product->tags()->sync($request->tags);
        }

        if ($request->hasFile('images')) {
            foreach ($request->file('images') as $i => $img) {
                $path = $img->store('products/gallery', 'public');
                ProductImage::create(['product_id' => $product->id, 'image' => $path, 'sort_order' => $i]);
            }
        }

        // Handle variations
        if ($request->filled('variation_types')) {
            $this->saveVariations($product, $request);
        }

        return redirect()->route('admin.products.index')->with('success', 'Product created successfully.');
    }

    public function edit(Product $product)
    {
        $product->load('images', 'variations', 'tags');
        $categories = Category::where('status', true)->orderBy('name')->get();
        $tags       = Tag::orderBy('name')->get();
        return view('admin.products.edit', compact('product', 'categories', 'tags'));
    }

    public function update(Request $request, Product $product)
    {
        $data = $request->validate([
            'name'                   => 'required|string|max:255',
            'slug'                   => 'nullable|string|unique:products,slug,' . $product->id,
            'category_id'            => 'nullable|exists:categories,id',
            'short_description'      => 'nullable|string',
            'description'            => 'nullable|string',
            'regular_price'          => 'required|numeric|min:0',
            'sale_price'             => 'nullable|numeric|min:0',
            'offer_text'             => 'nullable|string|max:255',
            'shipping_inside_dhaka'  => 'nullable|integer|min:0',
            'shipping_outside_dhaka' => 'nullable|integer|min:0',
            'stock'                  => 'required|integer|min:0',
            'status'                 => 'boolean',
            'featured'               => 'boolean',
            'thumbnail'              => 'nullable|image|max:4096',
            'images.*'               => 'nullable|image|max:4096',
            'tags'                   => 'nullable|array',
            'tags.*'                 => 'exists:tags,id',
        ]);

        $data['slug']     = $data['slug'] ?? Str::slug($data['name']);
        $data['status']   = $request->boolean('status', true);
        $data['featured'] = $request->boolean('featured', false);

        if ($request->hasFile('thumbnail')) {
            $data['thumbnail'] = $request->file('thumbnail')->store('products', 'public');
        }

        $product->update($data);
        $product->tags()->sync($request->tags ?? []);

        if ($request->hasFile('images')) {
            foreach ($request->file('images') as $i => $img) {
                $path = $img->store('products/gallery', 'public');
                ProductImage::create([
                    'product_id' => $product->id,
                    'image'      => $path,
                    'sort_order' => $product->images()->max('sort_order') + $i + 1,
                ]);
            }
        }

        if ($request->filled('variation_types')) {
            $this->saveVariations($product, $request);
        }

        return redirect()->route('admin.products.edit', $product)->with('success', 'Product updated successfully.');
    }

    public function destroy(Product $product)
    {
        $product->delete();
        return redirect()->route('admin.products.index')->with('success', 'Product deleted.');
    }

    public function deleteImage(ProductImage $image)
    {
        $image->delete();
        return back()->with('success', 'Image removed.');
    }

    public function deleteVariation(ProductVariation $variation)
    {
        $variation->delete();
        return back()->with('success', 'Variation removed.');
    }

    private function saveVariations(Product $product, Request $request): void
    {
        $types  = $request->input('variation_types', []);
        $values = $request->input('variation_values', []);
        $prices = $request->input('variation_prices', []);
        $stocks = $request->input('variation_stocks', []);

        foreach ($types as $i => $type) {
            if (empty($type) || empty($values[$i])) {
                continue;
            }
            ProductVariation::create([
                'product_id'       => $product->id,
                'type'             => $type,
                'value'            => $values[$i],
                'price_adjustment' => $prices[$i] ?? 0,
                'stock'            => $stocks[$i] ?? 0,
            ]);
        }
    }
}