ubah image db ke blob

This commit is contained in:
iFannJR 2026-06-01 00:54:18 +07:00
parent 18ef3de34c
commit 4b2a9130cd
11 changed files with 257 additions and 20 deletions

View File

@ -16,7 +16,7 @@ class ProductController extends Controller
public function index(Request $request)
{
$products = Product::with('criterias')
->when($request->search, fn ($q, $v) => $q->where('name', 'like', "%{$v}%"))
->when($request->search, fn($q, $v) => $q->where('name', 'like', "%{$v}%"))
->latest()
->paginate(10)
->withQueryString();
@ -33,8 +33,11 @@ public function create()
public function store(StoreProductRequest $request)
{
$data = $request->validated();
if ($request->hasFile('image')) {
$data['image'] = $request->file('image')->store('products', 'public');
$imgFile = $request->file('image');
if ($imgFile) {
$binaryData = file_get_contents($imgFile->getRealPath());
$data['image'] = $binaryData;
$data['image_type'] = $imgFile->extension();
}
$criteriaValuesById = $data['criteria_values'] ?? [];
@ -67,11 +70,11 @@ public function edit(Product $product)
public function update(UpdateProductRequest $request, Product $product)
{
$data = $request->validated();
if ($request->hasFile('image')) {
if ($product->image) {
Storage::disk('public')->delete($product->image);
}
$data['image'] = $request->file('image')->store('products', 'public');
$imgFile = $request->file('image');
if ($imgFile) {
$binaryData = file_get_contents($imgFile->getRealPath());
$data['image'] = $binaryData;
$data['image_type'] = $imgFile->extension();
}
$criteriaValuesById = $data['criteria_values'] ?? [];

View File

@ -11,7 +11,14 @@ class Product extends Model
use HasFactory;
protected $fillable = [
'name', 'description', 'price', 'stock', 'age_range', 'category', 'image',
'name',
'description',
'price',
'stock',
'age_range',
'category',
'image',
'image_type'
];
protected $casts = [

View File

@ -7,6 +7,7 @@
"license": "MIT",
"require": {
"php": "^8.2",
"doctrine/dbal": "^4.4",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1"
},

205
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c514d8f7b9fc5970bdd94287905ef584",
"content-hash": "620aac251098636f5fe91599b3e050d2",
"packages": [
{
"name": "brick/math",
@ -210,6 +210,160 @@
},
"time": "2024-07-08T12:26:09+00:00"
},
{
"name": "doctrine/dbal",
"version": "4.4.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "61e730f1658814821a85f2402c945f3883407dec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/61e730f1658814821a85f2402c945f3883407dec",
"reference": "61e730f1658814821a85f2402c945f3883407dec",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^1.1.5",
"php": "^8.2",
"psr/cache": "^1|^2|^3",
"psr/log": "^1|^2|^3"
},
"require-dev": {
"doctrine/coding-standard": "14.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.2",
"phpstan/phpstan": "2.1.30",
"phpstan/phpstan-phpunit": "2.0.7",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "11.5.50",
"slevomat/coding-standard": "8.27.1",
"squizlabs/php_codesniffer": "4.0.1",
"symfony/cache": "^6.3.8|^7.0|^8.0",
"symfony/console": "^5.4|^6.3|^7.0|^8.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\DBAL\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
"keywords": [
"abstraction",
"database",
"db2",
"dbal",
"mariadb",
"mssql",
"mysql",
"oci8",
"oracle",
"pdo",
"pgsql",
"postgresql",
"queryobject",
"sasql",
"sql",
"sqlite",
"sqlserver",
"sqlsrv"
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/4.4.3"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal",
"type": "tidelift"
}
],
"time": "2026-03-20T08:52:12+00:00"
},
{
"name": "doctrine/deprecations",
"version": "1.1.6",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
"reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
"reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"phpunit/phpunit": "<=7.5 || >=14"
},
"require-dev": {
"doctrine/coding-standard": "^9 || ^12 || ^14",
"phpstan/phpstan": "1.4.10 || 2.1.30",
"phpstan/phpstan-phpunit": "^1.0 || ^2",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0",
"psr/log": "^1 || ^2 || ^3"
},
"suggest": {
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Deprecations\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
"source": "https://github.com/doctrine/deprecations/tree/1.1.6"
},
"time": "2026-02-07T07:09:04+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.1.0",
@ -2607,6 +2761,55 @@
],
"time": "2025-12-27T19:41:33+00:00"
},
{
"name": "psr/cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/3.0.0"
},
"time": "2021-02-03T23:26:27+00:00"
},
{
"name": "psr/clock",
"version": "1.0.0",

View File

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
DB::statement('ALTER TABLE `products` CHANGE `image` `image` LONGBLOB NULL DEFAULT NULL;');
Schema::table('products', function (Blueprint $table) {
$table->enum('image_type', ['jpg', 'png', 'webp', 'gif'])->nullable()->after('image');
});
}
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
$table->string('image', 255)->nullable()->change();
});
}
};

View File

@ -25,8 +25,8 @@
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">Gambar (kosongkan jika tidak ubah)</label>
@if($product->image)
<p class="text-gray-500 text-sm mb-1">Saat ini: <img src="{{ Storage::url($product->image) }}" alt="" class="inline w-12 h-12 object-cover rounded-xl"></p>
@if($product->image_type)
<p class="text-gray-500 text-sm mb-1">Saat ini: <img src="data:image/{{ $product->image_type }};base64,{{ base64_encode($product->image) }}" alt="" class="inline w-12 h-12 object-cover rounded-xl"></p>
@endif
<input type="file" name="image" accept="image/*" class="w-full rounded-xl border border-gray-200 bg-white px-4 py-2.5 file:mr-3 file:rounded-lg file:border-0 file:bg-primary-50 file:px-4 file:py-2 file:text-primary-700 file:font-medium focus:border-primary-500 focus:ring-2 focus:ring-primary-500/20">
</div>

View File

@ -34,8 +34,8 @@
@forelse($products as $p)
<tr class="hover:bg-gray-50/50 transition">
<td class="px-6 py-4">
@if($p->image)
<img src="{{ Storage::url($p->image) }}" alt="" class="w-12 h-12 object-cover rounded-xl">
@if($p->image_type)
<img src="data:image/{{ $p->image_type }};base64,{{ base64_encode($p->image) }}" alt="" class="w-12 h-12 object-cover rounded-xl">
@else
<span class="inline-flex w-12 h-12 items-center justify-center rounded-xl bg-gray-100 text-2xl">🧸</span>
@endif

View File

@ -33,8 +33,8 @@
<td class="py-4">
<div class="flex items-center gap-4">
<div class="h-16 w-16 rounded-xl bg-gray-100 overflow-hidden shrink-0">
@if($item->product->image)
<img src="{{ Storage::url($item->product->image) }}" alt="" class="h-full w-full object-cover">
@if($item->product->image_type)
<img src="data:image/{{ $item->product->image_type }};base64,{{ base64_encode($item->product->image) }}" alt="" class="h-full w-full object-cover">
@else
<div class="h-full w-full flex items-center justify-center text-2xl">🧸</div>
@endif

View File

@ -34,8 +34,8 @@
</div>
</div>
<div class="aspect-square rounded-xl bg-gray-50 flex items-center justify-center overflow-hidden mb-4">
@if($rec['product']->image)
<img src="{{ Storage::url($rec['product']->image) }}" alt="{{ $rec['product']->name }}" class="w-full h-full object-cover">
@if($rec['product']->image_type)
<img src="data:image/{{ $rec['product']->image_type }};base64,{{ base64_encode($rec['product']->image) }}" alt="{{ $rec['product']->name }}" class="w-full h-full object-cover">
@else
<span class="text-5xl">🧸</span>
@endif

View File

@ -66,7 +66,7 @@
:price="$product->price"
:age-range="$product->age_range"
:stock="$product->stock"
:image="$product->image ? Storage::url($product->image) : null"
:image="$product->image_type ? 'data:image/' . $product->image_type . ';base64,' . base64_encode($product->image) : null"
>
<form action="{{ route('cart.store') }}" method="POST">
@csrf

View File

@ -48,7 +48,7 @@
:price="$product->price"
:age-range="$product->age_range"
:stock="$product->stock"
:image="$product->image ? asset('storage/' . $product->image) : null"
:image="$product->image_type ? 'data:image/' . $product->image_type . ';base64,' . base64_encode($product->image) : null"
>
<a href="{{ route('login') }}" class="block w-full text-center py-2.5 rounded-xl font-semibold text-white bg-primary-500 hover:bg-primary-600 transition duration-300 mt-2">
Lihat