@coder2
private $productRepository;
public function __construct()
{
$this->productRepository = new ProductRepository();
}
böyle kullanıyorsan serviceProvidera gerek yok.Service providerlar container denilen nesne ile doğrudan irtibatlı olduğu için container kayıtlarının dertli toplu yapıldığı yer olarak nitelendirebiliriz.Tabi sadece bununla sınırlı değil.
serviceproviderlar
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Support/ServiceProvider.php
bu sınıfla genişletilir ve incelediğinizde bir çok methodu mevcut.Bunlar ekseri laravel outsource (paket vs..) işler için applicationunuza entegrasyon methodlarıdır.Ancak genel olarak laravele katkısı,çekirdekte de kullanıldığı gibi container kayıtlarıdır.
bu methodlar da bind ve singleton dır.İkisi arasındaki fark aslında görünürde yok gibidir.singleton methoduda bind methodunu çalıştırır esasen tek farkı shared değerini true gönderir.
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Container/Container.php#L357
nedir peki shared değerinin true gönderilmesi.Aslında method izlenimi ile anlatmak isterim ama çok vaktim yok.Kısaca şöyle anlatayım.
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Container/Container.php#L656
bu satırda o değer direkt olarak döndürülüyor.Yani şu demek.
Herhangi bir abstract değeri objesinle beraber containere bind yada singleton ettiğinizde laravelin tek sihiri
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Container/Container.php#L36
/**
* The container's bindings.
*
* @var array[]
*/
protected $bindings = [];
bu diziye bunları kaydetmektir.Application nesnesi container ile genişletildiği için bu obje ve sahip olduğu propertyleri,laravelin başından sonuna kadar her yerinde okunabilir formattadır.
$this->app->singleton('test',function($app,$params){
return new Foo($app,$params);
});
$this->app->bind('test2',function($app,$params){
return new Foo2($app,$params);
});
yukarıdaki iki void tanımda aslında kayıt yapar.
Ve bu kayıtlar laravelin yaşam çemberinin ana damarıdır.Laravel tüm sistemini bu bindings propertysi üzerine inşa etmiştir.
peki bu kayıtlar nasıl çağrılır.
az öncede bahsettiğim gibi serviceproviderlar doğrudan serviceprovider sınıfı ile genişletilir ve bu sınıfa doğrudan application nesnesi construct olarak bind edilir..
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Foundation/Application.php#L670
new $provider($this);
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Support/ServiceProvider.php#L48
/**
* Create a new service provider instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct($app)
{
$this->app = $app;
}
$this->app mülkü doğrudan application nesnesini döndürür bize.yani kaydı ve okumayı direkt olarak bu mülk ile yapabiliyoruz.
Ancak serviceprovider nesnesinin olmadığı yerlerde napıcaz peki.application nesnesine nasıl ulaşıcaz.
bunun için laravel bize app() methodunu helper olarak sunmaktadır.
Serviceproviderin olmadığı yerlerde de container nesnesine kayıt ve okuma yapabiliriz..
app()->bind();
app()->singleton();
yalnız dikkat edilmesi gereken nokta,Cok onerilen bir şey değildir bu.Sadece kayıtları serviceprovider olarak kaydetmemiz daha mantıklıdır.
öbür türlü heryerde kayıt yapıldığında anti pattern bir mevzu ortaya cıkar ve neyin nerde oldugu cok belli olmaz.
Herşeyin yerli yerinde yapılması daha mantıklıdır..O yüzden serviceprovider dışı container kaydı yapılması çok onaylanan bir şey değildir.
laravel bu app() methodunu bize daha çok singleton ve bind icin değilde..
daha cok make() methodunun kullanımı icin vermiştir diye düşünenlerdenim.
app() yerine resolve() de kullanabilirsiniz.İkiside aynı şey ikiside app() methoduna kullanıyor..resolve appın aliası denebilir.
Gelelim singleton ve bind arasındaki farka.
Uzun uzadıya methodsal anlatmıcam..Direkt olarak sonuc gosteriyorum..
class foo
{
public $var;
}
class bar
{
public $var;
}
// make bind()
$container = app();
$container->bind('foo');
//reading bindings property
$instance = $container->make('foo');
$instance->var = 'laravel1';
$instance2 = $container->make('foo');
$instance2->value = 'laravel2';
echo "Bind: $instance->var --- $instance2->var";
//make singleton()
$container->singleton('bar');
$instance = $container->make('bar');
$instance->var = 'laravelsingleton1';
$instance2 = $container->make('bar');
$instance2->var = 'laravelsingleton2';
echo "Singleton: $instance->var --- $instance2->var";
//results :
Bind: test --- test2
Singleton: test2 --- test2
Gördüğünüz gibi singleton kayıtta.obje direkt olarak
// If an instance of the type is currently being managed as a singleton we'll
// just return an existing instance instead of instantiating new instances
// so the developer can keep using the same objects instance every time.
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
buradan döndürülüyor.
Neyse uzatmayalım.Az öncede dediğim gibi kayıtlar serviceprovider nesnesiyle yapılmalı ve app() yada resolve() yardımcı methodu kullanılarak ->make() methodu ile okunur...
burada tek bir ayrıntı var make methodu iki parametre alır bunlardan biri abstract olarak ulasılacak nesne,diğeride callback döndürülen singleton ve bind methodlarına parametre göndermek.
yani yukarıda yazdıgım singleton ve bind kullanımını çağırdığımızda.
app()->make('test',['x'=>'y'])->get();
//Foo.php
class Foo {
protected $params;
public function __construct($app,$params)
{
$this->params = $params;
}
public function get()
{
return $this->params; //['x'=>'y']
}
}
Bilmem anlatabildim mi.
İyi çalışmalar.