Sorular
- Soru= laravel de özellikle laravel 8 den sonra Trait işlemleri niye artisan kodlarda yok laravel kullanmamızı istemiyormu?
- Soru= Eğer trait kullanmamızı istemiyorsa yerine neyi öneriyor.?
- Soru= Medya modele kayıtları MediaHelper damı yapmalıyım yoksa ilgili model controller damı?
- Soru= Örneğin ProductControllerda mediatrait üzerinden attach yaparken Transaction kullanmalımıyım?
İstek 1 => Vaktiniz olursa kodlarımı inceleyip gereksiz grdüğünüz yerleri belirtirmisiniz.
Herkese merhaba pratik olması ve composer paketlerinin nasıl oluşturulduklarını anlamak için adına media system dediğim bir sytem kodlamaya çalışıyorum. Bu system hem kod kirliliğini hem kod tekrarını ortadan kaldıracak. Evet biliyorum bununla ilgili bir çok profesyonel paket var. Ama bunu ben yapıyorum 😞 Şimdi burada üzerinde çalıştığım dosyalar ve gerekli bilgiler aşağıda.
Media Model => Mediaların yollarının tutulduğu model.
Mediagable Model = > İlişki bilgilerinin saklandığı model.
MediaHelper => media dediğim yani resimler ve videoların işlemlerini yapar.
MediaTrait => Mediahelper yardımıyla medialar yüklenecek modeller ile ilişkilendirir
Media.Js = > bu daha bitmedi bitecek çok önemli değil çünkü medialar direk media modele değil modeller üzerinden yüklenecek örneğin; ProductModel, GalleryModel,PostModel v.s. gibi .
Şimdi kodlar
Media migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('medias', function (Blueprint $table) {
$table->id();
$table->string('path');
$table->boolean('is_video')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('medias');
}
};
Media Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Media extends Model
{
use HasFactory;
protected $table = 'medias';
protected $fillable = ['path', 'is_video'];
public function mediagable()
{
return $this->morphMany(Mediagable::class, 'media');
}
}
Mediagable Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('mediagables', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('media_id'); // İlişkilendirilen medyanın ID'si
$table->unsignedBigInteger('mediagable_id'); // İlişkilendirilen modelin ID'si
$table->string('mediagable_type', 191); // İlişkilendirilen modelin türü
$table->timestamps();
// Medyaları ilişkilendirme alanlarını ekler
$table->index(['mediagable_id', 'mediagable_type']);
// Media tablosuna referanslar
$table->foreign('media_id')->references('id')->on('medias')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('mediagables');
}
};
Medigable Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Mediagable extends Model
{
use HasFactory;
protected $fillable = ['media_id', 'mediagable_id','mediagable_type'];
public function media()
{
return $this->morphTo();
}
}
MediaHelper
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use App\Models\Media;
class MediaHelper
{
public static function storeMedia(array $mediaFiles): array
{
$mediaIds = [];
foreach ($mediaFiles as $file) {
$uniqueName = self::generateUniqueFileName($file);
$storedPath = self::storeFile($file, $uniqueName);
if ($storedPath) {
$media = self::saveMediaRecord($storedPath, self::isVideo($file));
$mediaIds[] = $media->id; // Dosya yolu yerine medya ID'sini döndür
}
}
return $mediaIds;
}
public static function deleteMedia(array $mediaPaths): void
{
foreach ($mediaPaths as $path) {
if ($media = Media::where('path', $path)->first()) {
$media->delete();
Storage::delete($path);
}
}
}
public static function getMediaIds(array $mediaPaths): array
{
return Media::whereIn('path', $mediaPaths)->pluck('id')->toArray();
}
protected static function generateUniqueFileName($mediaFile): string
{
return Str::random(20) . '.' . $mediaFile->getClientOriginalExtension();
}
protected static function isVideo($mediaFile): bool
{
$extension = $mediaFile->getClientOriginalExtension();
return in_array($extension, ['webm', 'mp4']);
}
private static function storeFile($mediaFile, $fileName): ?string
{
return $mediaFile->storeAs('media', $fileName);
}
private static function saveMediaRecord(string $path, bool $isVideo): Media
{
$media = new Media();
$media->path = $path;
$media->is_video = $isVideo;
$media->save();
return $media; // Media nesnesini döndür
}
}
MediaTrait
<?php
namespace App\Traits;
use App\Helpers\MediaHelper;
use App\Models\Media;
trait MediaTrait
{
public function media()
{
return $this->morphToMany(Media::class, 'mediagable');
}
public function attachMedia($mediaFiles)
{
// Bu, medyayı sakladıktan sonra bir dizi medya ids döndürmelidir.
$mediaIds = MediaHelper::storeMedia($mediaFiles, $this);
// Mevcut medyaları çıkarmadan senkronize etme işlemi için medya ids kullanılarak senkronize edilir.
$this->media()->syncWithoutDetaching($mediaIds);
}
public function detachMedia($mediaPaths)
{
// Sağlanan yollardan medya ids dizisini döndürmelidir.
$mediaIds = MediaHelper::getMediaIds($mediaPaths);
// Medya dosyalarını depodan sil.
MediaHelper::deleteMedia($mediaPaths);
// Medyayı modelden medya ids kullanarak ayır.
$this->media()->detach($mediaIds);
}
public function syncMedia($mediaPaths)
{
// Sağlanan yollardan medya ids dizisini döndürmelidir.
$mediaIds = MediaHelper::getMediaIds($mediaPaths);
// Medya ids kullanarak modele medya senkronize et.
$this->media()->sync($mediaIds);
}
public function hasMedia($mediaPath)
{
// Modelin belirtilen yol ile medya öğesini içerip içermediğini kontrol et.
return $this->media->contains('path', $mediaPath);
}
protected static function bootMediaTrait()
{
// Medya ilişkisini açgözlü yüklemek için global bir kapsam uygula.
static::addGlobalScope(function ($query) {
$query->with('media');
});
}
}
Son not : Bu sistem şuanda çalışıyor. Ama hala geliştiriyorum Özellikle Requestler yazılacak ve media.js bitecek.(Tabii bi sorun veya öneriniz yoksa) Sonrada paketlenip github'a atacağım benim için ilk olacak. 😃
Şimdiden yardımlarınıza teşekkürler.....