validate([ 'search' => ['nullable', 'string', 'max:255'], 'sort' => ['nullable', Rule::in(['name', 'quantity'])], 'order' => ['nullable', Rule::in(['asc', 'desc'])], 'per_page' => ['nullable', 'integer', 'min:1', 'max:200'], ]); $search = $validated['search'] ?? null; $sort = $validated['sort'] ?? 'name'; $order = $validated['order'] ?? 'asc'; $perPage = $validated['per_page'] ?? 2; // dd($search); $title = '상품목록'; $products = Product::searchkeyword($search, $sort, $order, $perPage); return view('product.list', compact('title', 'products')); } public function input() { $title = '상품추가'; return view('product.input', compact('title')); } public function edit(Product $product) { $title = '상품수정'; return view('product.edit', compact('product', 'title')); } public function update(Request $request, Product $product) { // 1) 입력 값 검증 $data = $request->validate([ 'name' => ['required', 'string'], 'sku' => [ 'required', 'string', Rule::unique('products', 'sku')->ignore($product->id), // 현재 상품은 예외 ], 'price' => ['required', 'numeric', 'min:0'], 'image' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'], ]); // 2) 텍스트 데이터 업데이트 $product->name = $data['name']; $product->sku = $data['sku']; $product->price = $data['price']; // 3) 이미지 처리 if ($request->hasFile('image')) { // 기존 이미지가 있으면 삭제 if ($product->image && Storage::disk('public')->exists($product->image)) { Storage::disk('public')->delete($product->image); // Storage 파사드를 이용하면, 저장소 드라이버가 바뀌어도 코드 수정 최소화 } // 새 이미지 저장 $path = $request->file('image')->store('uploads', 'public'); $product->image = $path; } // 4) 저장 $product->save(); // 5) 결과 응답 return redirect() ->route('product') ->with('success', '상품정보가 수정되었습니다.'); } public function destroy($id) { // 1. 모델을 먼저 가져온다 $product = Product::findOrFail($id); // 2. 이미지가 있는 경우만 삭제 if (!empty($product->image)) { Storage::disk('public')->delete($product->image); } // 3. DB 레코드 삭제 $product->delete(); // 4. 목록으로 이동 return redirect() ->route('product') ->with('success', '상품이 삭제되었습니다.'); } public function store(Request $request, StockService $stock) { // 1) 검증 $data = $request->validate([ 'name' => ['required', 'string', 'max:100'], 'sku' => ['required', 'string', 'max:255', 'unique:products,sku'], 'quantity' => ['nullable', 'numeric', 'min:0'], // 초기 재고, 없어도 됨 'price' => ['required', 'numeric', 'min:0'], 'image' => ['nullable', 'image', 'max:2048'], ], [ 'name.required' => '상품명은 필수 입력 항목입니다.', 'sku.required' => 'SKU는 필수 입력 항목입니다.', 'sku.unique' => '이미 등록된 SKU입니다.', 'quantity.numeric' => '수량은 숫자여야 합니다.', 'quantity.min' => '수량은 0 이상이어야 합니다.', 'price.required' => '가격은 필수 입력 항목입니다.', 'price.numeric' => '가격은 숫자여야 합니다.', 'price.min' => '가격은 0 이상이어야 합니다.', 'image.image' => '업로드된 파일은 이미지여야 합니다.', 'image.max' => '이미지 파일 크기는 2MB 이하만 가능합니다.', ]); // 2) 초기 수량은 따로 빼 둔다 (입출고 처리용) $initialQty = isset($data['quantity']) ? (int) $data['quantity'] : 0; // 3) 상품 생성용 배열 (동영상처럼 quantity는 0으로 고정) $productData = [ 'name' => $data['name'], 'sku' => $data['sku'], 'price' => $data['price'], 'quantity' => 0, // 상품 재고는 0으로 생성 ]; // 이미지가 있으면 경로만 추가 if ($request->hasFile('image')) { $productData['image'] = $request ->file('image') ->store('products', 'public'); } // 4) 상품 등록 $product = Product::create($productData); // 5) 초기 재고가 있으면 세팅 + 입출고 로그 기록 if ($initialQty > 0) { // StockService 안에서 product.quantity 업데이트 + stock_logs 기록 $stock->setInitialStock($product, $initialQty); } // 6) 리다이렉트 return redirect() ->route('product') // 실제 목록 라우트명에 맞게 수정 ->with('success', '상품이 등록되었습니다.'); } }