dsmndhm A controller'ın store metod'undan aldığım request input değerini
B controller Store metod'una nasıl gönderirim.
A::store() ve B::store() içinde bir işlem yapıyorsunuz. A::store() içine bir değer geliyor ve siz bu değer ile B::store() içinde yaptığınız işlemi yapmak istiyorsunuz. Öyleyse size bu işlemi yapacak ayrı bir sınıf lazım çünkü bu controller'ın işi değil. Controller sadece rotadan gelen isteği işlemeli.
Önce bir tane servis sınıfı yazalım. Adına servis dememizin nedeni görevinden dolayı, yoksa yapısal olarak normal bir PHP sınıfından bir farkı yok.
app/Services/MyService.php:
namespace App\Services;
class MyService
{
public function myMethod(string $data)
{
// Burada $data ile ilgili işlemler...
}
}
Neden app klasörü içerisine Services isimli bir klasör açıp içine koyduk?
Çünkü app klasörü PSR-4 kapsamındadır. Laravel'in composer.json dosyasında tanımlandığı yeri görebilirsiniz. Kısaca değinmek gerekirse, PSR-4 sınıfların dosya yollarından çözümlenerek otomatik yüklenmelerini sağlayan bir yazım standardıdır. Eskiden PHP'de bir dosyanın içindeki sınıfı yüklemek için önce include "MyService.php"
şeklinde dosyaya dahil ederdik, ondan sonra new MyService;
şeklinde kullanabilirdik. PSR-4 ve Composer sayesinde artık sadece use App\Services\MyService;
şeklinde namespace kullanarak otomatik yüklenmesini sağlayabiliyoruz (namespace sadece ön hazırlık; ne zaman new ile sınıfı çağırırsınız o zaman yüklenir). O yüzden bu tür sınıfları app klasörü içerisine koymanız lazım. Standartta belirttiği gibi; klasör ve dosya isimleri büyük harfle başlar, PascalCase kullanılır ve sınıfın olduğu dosyada sadece o sınıf olur ve sınıfın adı ile dosya adı aynı olmalıdır. PHP standardlarını inceleyin.
// app/Services/MyService.php
use App\Services\MyService;
// ya da
// app/Services/MyService.php
$myService = new \App\Services\MyService;
Artık namespace ile bu sınıfı app klasörü içindeki herhangi bir PSR-4 kapsamındaki dosyada çağırabilirsiniz. Bu anlattığım modern PHP'nin temelidir. Bazen forumda paylaşılan kodlarda atıyorum my_model::all()
gibi kullanımlar görebilirsiniz, bunlar çok yanlış kullanımlar. Eskiden uyarırdım ama artık önemsemiyorum. Kaygısı olmayan insan düzgün iş yapamaz; ben insanlara kaygıyı aşılayamam, kişide yoksa başarısı tamamen kendine bağlı olmuş oluyor...
Gelelim controller olayına. Ne demiştik;
A::store() ve B::store() içinde bir işlem yapıyorsunuz. A::store() içine bir değer geliyor ve siz bu değer ile B::store() içinde yaptığınız işlemi yapmak istiyorsunuz (ve belki aynı işlemi A::store() içinde de yapacaksınız). Öyleyse size bu işlemi yapacak ayrı bir sınıf lazım çünkü bu controller'ın işi değil. Controller sadece rotadan gelen isteği işlemeli.
namespace App\Http\Controllers;
use App\Services\MyService;
class B extends Controller
{
public function store(Request $request, MyService $myService)
{
$myService->myMethod($request->input('hidden_input'));
}
}
namespace App\Http\Controllers;
use App\Services\MyService;
class A extends Controller
{
public function store(Request $request, MyService $myService)
{
$myService->myMethod($request->input('hidden_input'));
//...
}
}
Ne yapmış oldunuz? B::store() içinde yaptığınız işlemi B controller'ı ile haşır neşir olmadan A::store() içinde de yapmış oldunuz.
public function store(Request $request, MyService $myService) kısmında new MyService; yapmadan MyService sınıfını $myService değişkenine yükledik. Bu nasıl oldu?
Buna Dependency Injection ya da kısaca DI denir. Laravel bunu Service Container özelliği ile yapıyor. PHP'de bir sınıfı yüklemenin yolu new kelimesini kullanmaktır. Laravel B::store() yöntemini çağırırken store yönteminin parametrelerini kontrol ederek otomatik çözümleme yapıyor ve sizin adınıza sınıfı yüklüyor. DI için bir container nasıl yazılır, bu makaleye bakabilirsiniz.
dsmndhm Ama benim gibi alaylı ve eksik olanlar için korkutucu bir yazışma olmuş.
Bu, okuyup öğrenmenize bir engel değil. Ben de alaylıyım, sosyoloji mezunuyum. Yazıların içine linkler koyarım, bazı şeyleri eğik ya da kalın yazarım, dikkat çekmek için, girip okuyun araştırın diye.