yalcin FriendController::store() yöntemi verdiğiniz bir User'ı mevcut giriş yapmış kullanıcının arkadaşı yapmıyor mu? Yani iki tane User'a ihtiyacınız var:
auth()->user() : Giriş yapmış olan User
User $user : Giriş yapmış olan User'a arkadaş olarak eklenecek olan User
yalcin Call to undefined function App\Http\Controllers\User\add_friend() şeklinde
add_friend() şeklinde yazınca anonim bir yöntem kullanmış olursunuz ama add_friend() User modeli içinde (Friendable traiti ile ekleniyor). Neden durduk yere bu yöntemin anonim olduğunu düşündünüz anlamadım...
Aslında Request de içerisinde giriş yapmış kullancıyı içerir. O yüzden şöyle yapabilirsiniz:
public function store(Request $request, User $user) {
$request->user()->add_friend($user->id);
}
Tabi bu yaptıklarınızın özü hatalı. En büyük hatanız ise; User bir model, görevi veritabanındaki bir tabloyu temsil etmek, yeri veritabanı katmanı. Arkadaş eklemek ise bizim business logic dediğimiz uygulamanızın yapısı değil yaptığı işle alakalı bir olay ve çok daha üstte, HTTP katmanının altında yer alan bir katman. O yüzden ya servis bazlı ya da action bazlı bir yol izlemeniz lazım. Tabi önce veritabanı yapısı, model ve ilişkileri düzgün kurmanız lazım.
Sizin yaptığımız gibi iki ana modelimiz olsun: User ve Friend. User model hem kullanıcıyı hem de arkadaşı temsil ediyor; Friend ise arkadaşlık isteklerini temsil ediyor ve bu modelin pivot olması gerekiyor:
Friend modelinin temsil ettiği friends tablosunun migrasyonu:
Schema::create('friends', function (Blueprint $table) {
$table->foreignId('user_id')->index(); // İstek gönderilen
$table->foreignId('friend_id')->index(); // İsteği gönderen
$table->timestamp('accepted_at')->nullable(); // Kabul edilme tarihi
$table->timestamp('created_at'); // İstek tarihi
$table->unique(['user_id', 'friend_id']);
});
app/Models/Friend.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
class Friend extends Pivot
{
protected $table = 'friends';
const UPDATED_AT = null;
protected $casts = [
'accepted_at' => 'datetime'
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function friend(): BelongsTo
{
return $this->belongsTo(User::class, 'friend_id');
}
}
Şimdi User modeli ile ilişkiyi kuralım:
app/Models/User.php
public function friends(): BelongsToMany
{
return $this->belongsToMany(User::class, 'friends', 'user_id', 'friend_id')
->using(Friend::class)
->as('friendship')
->withPivot([
'accepted_at',
'created_at'
]);
}
Şimdi arkadaşlık isteğinin oluşturulması, kabul edilmesi, reddilmesi, tüm bekleyen isteklerin reddedilmesi ve arkadaşlıktan çıkarma şeklinde 5 işlemi içeren ya bir servis yazacaksınız ya da 5 tane action. Mesela servis olursa:
interface FriendshipServiceInterface
{
public function request(User $friend, User $user): bool;
public function accept(User $friend, User $user): bool;
public function reject(User $friend, User $user): bool;
public function rejectAll(User $user): bool;
public function unfriend(User $friend, User $user): bool;
}
class FriendshipService implemens FriendshipServiceInterface
{
public function request(User $friend, User $user): bool
{
$user
->friends()
->attach($friend);
return true;
}
public function accept(User $friend, User $user): bool
{
return $user
->friends()
->updateExistingPivot($friend, [
'accepted_at' => now(),
]);
}
public function reject(User $friend, User $user): bool
{
return $user
->friends()
->wherePivotNull('accepted_at')
->detach($friend);
}
public function rejectAll(User $user): bool
{
return $user
->friends()
->wherePivotNull('accepted_at')
->detach();
}
public function unfriend(User $friend, User $user): bool
{
return $user
->friends()
->wherePivotNotNull('accepted_at')
->detach($friend);
}
}
AppServiceProvider::register() içerisinde FriendshipServiceInterface'i FriendshipService'i kullanacak şekilde servis konteynerine kaydedeceğiz:
$this->app->bind(FriendshipServiceInterface::class, FriendshipService::class);
Artık bu servisi interface injection ile controller vb yerlerde kullanabilirsiniz:
class FriendController extends Controller
{
public function __construct(
public FriendshipServiceInterface $friendshipService,
)
{}
public function store(Request $request, User $user)
{
$result = $this
->friendshipService
->request(
friend: $user,
user: $request->user()
);
// ...
}
}
Elimizdeki ilişkiyi kullanırsak:
$user = Auth::user();
// Arkadaşlar (arkadaşlık isteği kabul edilenler)
$friends = $user->friends()->wherePivotNotNull('accepted_at')->get();
foreach($friends as $friend) {
$name = $friend->name; // Arkadaşın adı
$acceptedAt = $friend->friendship->accepted_at->format('d.m.Y H:i'); // Arkadaşlığın kabul edilme tarihi
$requestedAt = $friend->friendship->created_at->format('d.m.Y H:i'); // Arkadaşlık isteği tarihi
}
// Bekleyen arkadaşlık istekleri:
$friendshipRequests = $user->friends()->wherePivotNull('accepted_at')->get();
foreach($friendshipRequests as $friend) {
$name = $friend->name; // Arkadaşın adı
$requestedAt = $friend->friendship->created_at->format('d.m.Y H:i'); // Arkadaşlık isteği tarihi
}
gibi.
Bu bilgilerin neredeyse hepsi dokümanlarda yazmakta.