Laravel projelerinde sık gördüğümüz bir kullanım var:
$apiKey = env('SMS_API_KEY');
veya
if (env('PAYMENT_PROVIDER') === 'iyzico') {
// ...
}
Local ortamda bu kod çoğu zaman çalışır. Bu yüzden ilk bakışta yanlış gibi görünmez. Ama Laravel’de genel kural şudur:
env()sadece config dosyalarında kullanılmalı, uygulama kodundaconfig()tercih edilmelidir.
Yani controller, service, job, command, middleware veya model içinde doğrudan env() kullanmak iyi bir pratik değildir.
Doğru akış
Laravel’de ideal akış şudur:
.env -> config/*.php -> config()
Örneğin .env dosyasında şöyle değerler olsun:
SMS_API_KEY=example-key
SMS_API_SECRET=example-secret
SMS_SENDER=MYAPP
Bu değerleri doğrudan uygulama kodunda okumak yerine config dosyasına taşımalıyız:
// config/services.php
return [
'sms' => [
'api_key' => env('SMS_API_KEY'),
'api_secret' => env('SMS_API_SECRET'),
'sender' => env('SMS_SENDER', 'APP'),
],
];
Sonra uygulama içinde şöyle kullanmalıyız:
$apiKey = config('services.sms.api_key');
Bu küçük fark, özellikle production ortamında önem kazanır.
Asıl sebep: config cache
Production ortamında Laravel projelerinde genellikle şu komut çalıştırılır:
php artisan config:cache
Bu komut, tüm config dosyalarını tek bir cache dosyasında toplar. Böylece Laravel her request’te config dosyalarını tekrar tekrar okumaz.
Ama bunun önemli bir sonucu vardır:
Config cache aktifken
.envdosyası doğrudan okunmayabilir.
Bu yüzden uygulama kodunda şu kullanım risklidir:
env('SMS_API_KEY');
Çünkü production’da beklediğin değeri alamayabilirsin.
Ama şu kullanım güvenlidir:
config('services.sms.api_key');
Çünkü bu değer config cache içine zaten alınmıştır.
Yanlış kullanım
namespace App\Services;
final class SmsService
{
public function send(string $phone, string $message): void
{
$apiKey = env('SMS_API_KEY');
// SMS gönder...
}
}
Bu kod localde çalışıp production’da sorun çıkarabilir. Çünkü localde genellikle config cache yoktur, production’da ise vardır.
Doğru kullanım
// config/services.php
return [
'sms' => [
'api_key' => env('SMS_API_KEY'),
'api_secret' => env('SMS_API_SECRET'),
'sender' => env('SMS_SENDER', 'APP'),
],
];
namespace App\Services;
final class SmsService
{
public function send(string $phone, string $message): void
{
$apiKey = config('services.sms.api_key');
$apiSecret = config('services.sms.api_secret');
$sender = config('services.sms.sender');
// SMS gönder...
}
}
Burada servis artık .env dosyasına doğrudan bağımlı değildir. Laravel’in config sistemi üzerinden çalışır.
Büyük servislerde ayrı config dosyası daha iyi olabilir
Eğer ayarlar büyüyorsa config/services.php içine her şeyi koymak yerine ayrı bir dosya oluşturmak daha okunabilir olur.
Örneğin:
// config/sms.php
return [
'provider' => env('SMS_PROVIDER', 'netgsm'),
'api_key' => env('SMS_API_KEY'),
'api_secret' => env('SMS_API_SECRET'),
'sender' => env('SMS_SENDER', 'APP'),
'timeout' => (int) env('SMS_TIMEOUT', 10),
];
Kullanım:
$provider = config('sms.provider');
$timeout = config('sms.timeout');
Bu yapı özellikle SMS, ödeme, yapay zeka, takvim, WhatsApp veya dış servis entegrasyonlarında daha düzenli olur.
Test yazarken de config daha kullanışlıdır
Doğrudan env() kullanırsan testlerde değer değiştirmek zahmetli hale gelir.
Ama config kullanıyorsan test içinde kolayca override edebilirsin:
config()->set('sms.provider', 'fake');
Örneğin:
public function test_it_uses_fake_sms_provider(): void
{
config()->set('sms.provider', 'fake');
// test...
}
Bu, testleri daha kontrollü ve temiz hale getirir.
Bir adım ileri: typed config object
Daha büyük projelerde config değerlerini sürekli string key ile çağırmak da dağınıklık oluşturabilir:
config('sms.api_key');
config('sms.api_secret');
config('sms.sender');
config('sms.timeout');
Bu durumda küçük bir config object kullanılabilir:
final readonly class SmsConfig
{
public function __construct(
public string $apiKey,
public string $apiSecret,
public string $sender,
public int $timeout,
) {}
}
Service provider içinde bağlanabilir:
$this->app->singleton(SmsConfig::class, function () {
return new SmsConfig(
apiKey: config('sms.api_key'),
apiSecret: config('sms.api_secret'),
sender: config('sms.sender'),
timeout: config('sms.timeout'),
);
});
Sonra servis içinde:
final readonly class SmsService
{
public function __construct(
private SmsConfig $config,
) {}
public function send(string $phone, string $message): void
{
// $this->config->apiKey
}
}
Bu Laravel’in zorunlu standardı değildir. Her config için object yazmak da gereksizdir. Ama kritik ve büyüyen entegrasyonlarda tip güvenliği, IDE desteği ve test edilebilirlik açısından temiz bir mimari tercih olabilir.
env()config dosyalarında,config()uygulama kodunda kullanılır.
Bu basit alışkanlık, localde çalışan ama production’da sorun çıkaran birçok hatanın önüne geçer.
Top comments (0)