ubah image db ke blob
This commit is contained in:
parent
18ef3de34c
commit
4b2a9130cd
|
|
@ -16,7 +16,7 @@ class ProductController extends Controller
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$products = Product::with('criterias')
|
$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()
|
->latest()
|
||||||
->paginate(10)
|
->paginate(10)
|
||||||
->withQueryString();
|
->withQueryString();
|
||||||
|
|
@ -33,8 +33,11 @@ public function create()
|
||||||
public function store(StoreProductRequest $request)
|
public function store(StoreProductRequest $request)
|
||||||
{
|
{
|
||||||
$data = $request->validated();
|
$data = $request->validated();
|
||||||
if ($request->hasFile('image')) {
|
$imgFile = $request->file('image');
|
||||||
$data['image'] = $request->file('image')->store('products', 'public');
|
if ($imgFile) {
|
||||||
|
$binaryData = file_get_contents($imgFile->getRealPath());
|
||||||
|
$data['image'] = $binaryData;
|
||||||
|
$data['image_type'] = $imgFile->extension();
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteriaValuesById = $data['criteria_values'] ?? [];
|
$criteriaValuesById = $data['criteria_values'] ?? [];
|
||||||
|
|
@ -67,11 +70,11 @@ public function edit(Product $product)
|
||||||
public function update(UpdateProductRequest $request, Product $product)
|
public function update(UpdateProductRequest $request, Product $product)
|
||||||
{
|
{
|
||||||
$data = $request->validated();
|
$data = $request->validated();
|
||||||
if ($request->hasFile('image')) {
|
$imgFile = $request->file('image');
|
||||||
if ($product->image) {
|
if ($imgFile) {
|
||||||
Storage::disk('public')->delete($product->image);
|
$binaryData = file_get_contents($imgFile->getRealPath());
|
||||||
}
|
$data['image'] = $binaryData;
|
||||||
$data['image'] = $request->file('image')->store('products', 'public');
|
$data['image_type'] = $imgFile->extension();
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteriaValuesById = $data['criteria_values'] ?? [];
|
$criteriaValuesById = $data['criteria_values'] ?? [];
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,14 @@ class Product extends Model
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name', 'description', 'price', 'stock', 'age_range', 'category', 'image',
|
'name',
|
||||||
|
'description',
|
||||||
|
'price',
|
||||||
|
'stock',
|
||||||
|
'age_range',
|
||||||
|
'category',
|
||||||
|
'image',
|
||||||
|
'image_type'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
|
"doctrine/dbal": "^4.4",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/tinker": "^2.10.1"
|
"laravel/tinker": "^2.10.1"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "c514d8f7b9fc5970bdd94287905ef584",
|
"content-hash": "620aac251098636f5fe91599b3e050d2",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
|
|
@ -210,6 +210,160 @@
|
||||||
},
|
},
|
||||||
"time": "2024-07-08T12:26:09+00:00"
|
"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",
|
"name": "doctrine/inflector",
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
|
@ -2607,6 +2761,55 @@
|
||||||
],
|
],
|
||||||
"time": "2025-12-27T19:41:33+00:00"
|
"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",
|
"name": "psr/clock",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -25,8 +25,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1.5">Gambar (kosongkan jika tidak ubah)</label>
|
<label class="block text-sm font-medium text-gray-700 mb-1.5">Gambar (kosongkan jika tidak ubah)</label>
|
||||||
@if($product->image)
|
@if($product->image_type)
|
||||||
<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>
|
<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
|
@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">
|
<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>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
@forelse($products as $p)
|
@forelse($products as $p)
|
||||||
<tr class="hover:bg-gray-50/50 transition">
|
<tr class="hover:bg-gray-50/50 transition">
|
||||||
<td class="px-6 py-4">
|
<td class="px-6 py-4">
|
||||||
@if($p->image)
|
@if($p->image_type)
|
||||||
<img src="{{ Storage::url($p->image) }}" alt="" class="w-12 h-12 object-cover rounded-xl">
|
<img src="data:image/{{ $p->image_type }};base64,{{ base64_encode($p->image) }}" alt="" class="w-12 h-12 object-cover rounded-xl">
|
||||||
@else
|
@else
|
||||||
<span class="inline-flex w-12 h-12 items-center justify-center rounded-xl bg-gray-100 text-2xl">🧸</span>
|
<span class="inline-flex w-12 h-12 items-center justify-center rounded-xl bg-gray-100 text-2xl">🧸</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@
|
||||||
<td class="py-4">
|
<td class="py-4">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<div class="h-16 w-16 rounded-xl bg-gray-100 overflow-hidden shrink-0">
|
<div class="h-16 w-16 rounded-xl bg-gray-100 overflow-hidden shrink-0">
|
||||||
@if($item->product->image)
|
@if($item->product->image_type)
|
||||||
<img src="{{ Storage::url($item->product->image) }}" alt="" class="h-full w-full object-cover">
|
<img src="data:image/{{ $item->product->image_type }};base64,{{ base64_encode($item->product->image) }}" alt="" class="h-full w-full object-cover">
|
||||||
@else
|
@else
|
||||||
<div class="h-full w-full flex items-center justify-center text-2xl">🧸</div>
|
<div class="h-full w-full flex items-center justify-center text-2xl">🧸</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="aspect-square rounded-xl bg-gray-50 flex items-center justify-center overflow-hidden mb-4">
|
<div class="aspect-square rounded-xl bg-gray-50 flex items-center justify-center overflow-hidden mb-4">
|
||||||
@if($rec['product']->image)
|
@if($rec['product']->image_type)
|
||||||
<img src="{{ Storage::url($rec['product']->image) }}" alt="{{ $rec['product']->name }}" class="w-full h-full object-cover">
|
<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
|
@else
|
||||||
<span class="text-5xl">🧸</span>
|
<span class="text-5xl">🧸</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
:price="$product->price"
|
:price="$product->price"
|
||||||
:age-range="$product->age_range"
|
:age-range="$product->age_range"
|
||||||
:stock="$product->stock"
|
: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">
|
<form action="{{ route('cart.store') }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
:price="$product->price"
|
:price="$product->price"
|
||||||
:age-range="$product->age_range"
|
:age-range="$product->age_range"
|
||||||
:stock="$product->stock"
|
: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">
|
<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
|
Lihat
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue