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 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.