Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?
  • YardımLaravel
  • Laravel Model Olaylarında (created, saved) İlişkili Veriler Neden Boş Geliyor?

mgsmus Olay ateşleniyor o durumda sorun yok, sorun ateşlendiği fonksiyonda Post'un ilişkilerini çekemiyor.
Tinkerwell üzerinden ilişkilerde sorun olmadığını şöyle doğrulayabilirim:

use App\Models\Post;

$latestPost = Post::factory()
  ->create()
  ->first();

return [
  "latest_posts_media" => $latestPost->media,
  "latest_posts_categories" => $latestPost->categories
];
[
    "latest_posts_media" => Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection {#2884
      all: [
        Spatie\MediaLibrary\MediaCollections\Models\Media {#2914
          id: 40,
          model_type: "App\Models\Post",
          model_id: 46,
          uuid: "7dcf4a64-9978-4e14-aeaf-39bd89b42719",
          collection_name: "post",
          name: "1316",
          file_name: "1316.jpeg",
          mime_type: "image/jpeg",
          disk: "custom_public",
          conversions_disk: "custom_public",
          size: 88288,
          manipulations: "[]",
          custom_properties: "[]",
          generated_conversions: "[]",
          responsive_images: "[]",
          order_column: 1,
          created_at: "2025-02-17 14:01:52",
          updated_at: "2025-02-17 14:01:52",
          +original_url: "https://05-example-project.web-artisan//custom-folder/40/1316.jpeg",
          +preview_url: "",
        },
      ],
    },
    "latest_posts_categories" => Illuminate\Database\Eloquent\Collection {#2887
      all: [
        App\Models\Category {#2868
          id: 47,
          name: "fugiat",
          sort_order: 47,
          status: 1,
          created_at: "2025-02-16 21:01:00",
          updated_at: "2025-02-16 21:01:00",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2882
            post_id: 46,
            category_id: 47,
          },
        },
      ],
    },
  ]

    mgsmus Kuyruk kullanmıyorum, paylaşımlı sunucuda barındırıyorum web siteyi. Kullanma imkanı yok

      mgsmus

      Post

      class Post extends Model implements HasMedia
      {
          use HasFactory;
          use InteractsWithMedia;
          use Searchable;
      
          public function toSearchableArray()
          {
              return [
                  'title' => $this->title,
              ];
          }
      
          protected static function boot()
          {
              parent::boot();
      
              // Varsayılan olarak ilişkili verileri yükle
              static::addGlobalScope('eagerLoadRelations', function ($query) {
                  $query->with(['media', 'categories']);
              });
              static::saved(function ($post) {
                  $freshPost = Post::with(['media', 'categories'])->find($post->id);
      
                  \Log::info('Post created.', [
                      'post_id' => $freshPost->id,
                      'media' => $freshPost->media,
                      'categories' => $freshPost->categories
                  ]);
              });
              static::creating(function ($post) {
                  $post->sort_order = static::max('sort_order') + 1;
              });
          }
      
          protected $fillable = [
              'title',
              'body',
              'status',
              'sort_order',
              'author_id',
              'mp3',
              'created_at',
              'updated_at',
          ];
      
          protected $casts = [
              'id' => 'integer',
              'status' => 'boolean',
              'sort_order' => 'integer',
              'author_id' => 'integer',
              'created_at' => 'datetime',
              'updated_at' => 'datetime',
          ];
      
          public function author(): BelongsTo
          {
              return $this->belongsTo(Author::class, 'author_id');
          }
      
          public function getFormattedCreatedAtAttribute()
          {
              Carbon::setLocale('tr'); // Türkçe locale ayarı
      
              return $this->created_at->translatedFormat('d F Y'); // Örneğin: 15 Haziran 2018
          }
      
          public function getPostUrl(): string
          {
              return url('/haber/'.Str::slug($this->title).'/'.$this->id);
          }
      
          public function getPostImage(): ?string
          {
              $mediaItem = $this->getFirstMedia('post');
      
              return $mediaItem ? $mediaItem->getUrl() : null;
          }
      
          public function categories()
          {
              return $this->belongsToMany(
                  Category::class,
                  'category_post',
                  'post_id',
                  'category_id'
              );
          }
      
          public function tags()
          {
              return $this->belongsToMany(Tag::class, 'post_tag', 'post_id', 'tag_id');
          }
      }
      class Category extends Model
      {
          use HasFactory;
      
          protected static function boot()
          {
              parent::boot();
      
              static::creating(function ($category) {
                  $category->sort_order = static::max('sort_order') + 1;
              });
          }
      
          protected $fillable = [
              'name',
              'sort_order',
              'status',
          ];
      
          protected $casts = [
              'id' => 'integer',
              'sort_order' => 'integer',
              'status' => 'boolean',
          ];
      
          public function posts()
          {
              return $this->belongsToMany(
                  Post::class,
                  'category_post',
                  'category_id',
                  'post_id'
              );
          }
      }

        macintyre Yani yeni bir Post'u ve ilişkileri oluşturduğunuz yeri görmek istedim. Post::create() yaptığınız yeri.

          mgsmus Filamentphp kullanıyorum resource tetikliyor

          <?php
          
          namespace App\Filament\Resources;
          
          use App\Filament\Resources\PostResource\Pages;
          use App\Models\Category;
          use App\Models\Post;
          use App\Models\Tag;
          use Filament\Forms;
          use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
          use Filament\Forms\Form;
          use Filament\Resources\Resource;
          use Filament\Tables;
          use Filament\Tables\Table;
          
          /**
           * @property \App\Models\Post $record
           */
          class PostResource extends Resource
          {
              protected static ?string $model = Post::class;
          
              protected static ?string $navigationIcon = 'gmdi-post-add-r';
          
              protected static ?string $navigationLabel = 'Haberler';
          
              protected static ?string $pluralLabel = 'Haberler';
          
              public static function form(Form $form): Form
              {
                  return $form
                      ->columns(4)
                      ->schema([
                          Forms\Components\Section::make([
                              Forms\Components\TextInput::make('title')
                                  ->required()
                                  ->columnSpan(2)
                                  ->maxLength(255),
                              Forms\Components\Select::make('author_id')
                                  ->relationship('author', 'name')
                                  ->default(1)
                                  ->columnSpan(2)
                                  ->required(),
                          ])->columns(4),
                          Forms\Components\Section::make([
                              Forms\Components\Select::make('categories')
                                  ->multiple()
                                  ->relationship('categories', 'name')
                                  ->options(Category::pluck('name', 'id'))
                                  ->searchable()
                                  ->required(),
                              Forms\Components\Select::make('tag')
                                  ->multiple()
                                  ->relationship('tags', 'name')
                                  ->options(Tag::pluck('name', 'id'))
                                  ->createOptionForm([
                                      Forms\Components\TextInput::make('name')
                                          ->required(),
                                  ])
                                  ->preload() // Optionally preload existing tags for faster selection
                                  ->searchable() // Allow searching tags
                                  ->required(),
                              Forms\Components\DatePicker::make('created_at')
                                  ->native(false)
                                  ->displayFormat('d F Y')
                                  ->required(),
                          ])->columns(3),
          
                          SpatieMediaLibraryFileUpload::make('post')->label('Baş Resim')
                              ->image()
                              ->columnSpanFull()
                              ->imageEditor()
                              ->collection('post')
                              ->disk('custom_public'), // Bu satırı ekledik
                          Forms\Components\FileUpload::make('mp3')
                              ->disk('custom_public')
                              ->acceptedFileTypes(['audio/mpeg']),
                          Forms\Components\RichEditor::make('body')
                              ->required()
                              ->fileAttachmentsDisk('custom_public')
                              ->columnSpanFull(),
                      ]);
              }
          
              public static function table(Table $table): Table
              {
                  return $table
                      ->columns([
                          Tables\Columns\TextColumn::make('title')
                              ->searchable(),
                          Tables\Columns\IconColumn::make('status')
                              ->boolean(),
                          Tables\Columns\TextColumn::make('sort_order')
                              ->numeric()
                              ->sortable(),
                          Tables\Columns\TextColumn::make('author.name')
                              ->numeric()
                              ->sortable(),
                          Tables\Columns\TextColumn::make('created_at')
                              ->dateTime()
                              ->sortable()
                              ->toggleable(isToggledHiddenByDefault: true),
                          Tables\Columns\TextColumn::make('updated_at')
                              ->dateTime()
                              ->sortable()
                              ->toggleable(isToggledHiddenByDefault: true),
                      ])
                      ->filters([
                          //
                      ])
                      ->actions([
                          Tables\Actions\ViewAction::make(),
                          Tables\Actions\EditAction::make(),
          
                      ])
                      ->bulkActions([
                          Tables\Actions\BulkActionGroup::make([
                              Tables\Actions\DeleteBulkAction::make(),
                          ]),
                      ]);
              }
          
              public static function getRelations(): array
              {
                  return [
                      //
                  ];
              }
          
              public static function getPages(): array
              {
                  return [
                      'index' => Pages\ListPosts::route('/'),
                      'create' => Pages\CreatePost::route('/create'),
                      'view' => Pages\ViewPost::route('/{record}'),
                      'edit' => Pages\EditPost::route('/{record}/edit'),
                  ];
              }
          }

            macintyre Anladım sanırım, sizinle ilgili değil. saved/created olayı model kaydedildikten sonra tetikleniyor. İlişkiler için ise model id gerektiği için sonradan oluşturuluyor. O yüzden saved sırasında sadece modeli dinleyebiliyorsunuz. İlişki saved olayından sonra gerçekleşiyor. Yani işlem sırası

            • Post
            • Post creating/saving
            • Post created/saved
            • Post retrieved (Eğer Post modeline erişmek için tekrar sorgu yapılıyorsa)
            • Category
            • Category creating/saving
            • Category created/saved

            şeklinde gerçekleşiyor. Bunun için model event değil normal event/listener kurgusu kullanmanız lazım. Filamentphp kullanmadığım için onda nasıl yapılır bilmiyorum.

              Filament kullanıyorsanız filament'in Hooklarını kullansanız daha sağlıklı olur ve yakalanması daha kolay olur diye düşünüyorum.

              https://filamentphp.com/docs/2.x/admin/resources/editing-records#lifecycle-hooks

              Örnek olarak

              protected function beforeSave(): void
              {
                  if (! $this->record->team->subscribed()) {
                      Notification::make()
                          ->warning()
                          ->title('You don\'t have an active subscription!')
                          ->body('Choose a plan to continue.')
                          ->persistent()
                          ->actions([
                              Action::make('subscribe')
                                  ->button()
                                  ->url(route('subscribe'), shouldOpenInNewTab: true),
                          ])
                          ->send();
                  
                      $this->halt();
                  }
              }

                koti42 Teşekkür ederim, ilgilendiğiniz için

                https://filamentphp.com/docs/3.x/actions/prebuilt-actions/create#lifecycle-hooks

                1. sürümdeki şu dökümanı kullandım ve işe yaramadı log dahi tetiklenmiyor. ilginç
                class ListPosts extends ListRecords
                {
                    protected static string $resource = PostResource::class;
                
                    protected function getHeaderActions(): array
                    {
                        return [
                            Actions\CreateAction::make()
                                ->after(function (Actions\CreateAction $action, Post $record) {
                                    Log::info("CreateAction after fn started");
                                    event(new CachePostsEvent());
                                    Log::info("CreateAction after fn completed");
                                }),
                        ];
                    }
                }

                mgsmus Bunun için model event değil normal event/listener kurgusu kullanmanız lazım.

                Mustafa Bey'in tavsiyesi ile event-listener ikilisi oluşturdum ve bunu Post modelin saved olayında tetikledim.

                Post Model

                static::saved(function ($post) {
                    try {
                        $i = 1;
                        while (Cache::has("posts-page-$i")) {
                            Cache::forget("posts-page-$i");
                            $i++;
                        }
                        Log::info("Pages Cache cleared");
                        event(new CachePostsEvent(postId: $post->id));
                    } catch (\Throwable $th) {
                        Log::error('Error clearing cache for posts-page-: ' . $th->getMessage(), ['exception' => $th]);
                    }
                });

                Listener

                    public function handle(CachePostsEvent $event): void
                    {
                        try {
                            $post_id = $event->postId;
                
                            $post = Post::with('categories', 'media')->find($post_id);
                            Log::info("Post ", ["Post" => $post]);
                        } catch (\Throwable $th) {
                            Log::error("Error sending GET requests to all pages: " . $th->getMessage(), [
                                "exception" => $th
                            ]);
                        }
                    }

                Bu sayede hedefime ulaştım çok çok teşekkürler.

                9 gün sonra

                Selam, bir diğer yöntem Observer da çözülebilir. Genelde ben bu şekilde kullanıyorum.

                  18 gün sonra

                  Funal Selam, Observer sınıfı olay ve dinleyici yapısını tek bir dosya içerisine topluyor. Depo (Repository) tasarım kalıbı gibi. Çalıştırdığı olay boot() içerisindeki static:: ile başlayan olaylar yine, bu yüzden bir farklılık yaratmıyor.

                  https://laravel.com/docs/12.x/eloquent#observers

                  Observers
                  Defining Observers

                  If you are listening for many events on a given model, you may use observers to group all of your listeners into a single class.