DEV Community

Cover image for Laravel’de Neden Kod İçinde env() Kullanılmamalı?
Barış Bideratan
Barış Bideratan

Posted on

Laravel’de Neden Kod İçinde env() Kullanılmamalı?

Laravel projelerinde sık gördüğümüz bir kullanım var:

$apiKey = env('SMS_API_KEY');
Enter fullscreen mode Exit fullscreen mode

veya

if (env('PAYMENT_PROVIDER') === 'iyzico') {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

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 kodunda config() 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()
Enter fullscreen mode Exit fullscreen mode

Örneğin .env dosyasında şöyle değerler olsun:

SMS_API_KEY=example-key
SMS_API_SECRET=example-secret
SMS_SENDER=MYAPP
Enter fullscreen mode Exit fullscreen mode

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'),
    ],
];
Enter fullscreen mode Exit fullscreen mode

Sonra uygulama içinde şöyle kullanmalıyız:

$apiKey = config('services.sms.api_key');
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 .env dosyası doğrudan okunmayabilir.

Bu yüzden uygulama kodunda şu kullanım risklidir:

env('SMS_API_KEY');
Enter fullscreen mode Exit fullscreen mode

Çünkü production’da beklediğin değeri alamayabilirsin.

Ama şu kullanım güvenlidir:

config('services.sms.api_key');
Enter fullscreen mode Exit fullscreen mode

Çü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...
    }
}
Enter fullscreen mode Exit fullscreen mode

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'),
    ],
];
Enter fullscreen mode Exit fullscreen mode
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...
    }
}
Enter fullscreen mode Exit fullscreen mode

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),
];
Enter fullscreen mode Exit fullscreen mode

Kullanım:

$provider = config('sms.provider');
$timeout = config('sms.timeout');
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

Örneğin:

public function test_it_uses_fake_sms_provider(): void
{
    config()->set('sms.provider', 'fake');

    // test...
}
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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,
    ) {}
}
Enter fullscreen mode Exit fullscreen mode

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'),
    );
});
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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)