PHP betiklerinde, include()
, require()
, fopen()
veya bunların include_once
, require_once
ve hatta move_uploaded_file()
gibi türevleri çağrılırken, sıklıkla bir hata veya uyarı ile karşılaşılır:
Akış açılamadı: Böyle bir dosya veya dizin yok.
Sorunun temel nedenini hızlı bir şekilde bulmak için iyi bir süreç nedir?
Bu hatayla karşılaşmanın birçok nedeni vardır ve bu nedenle ilk olarak nelerin kontrol edilmesi gerektiğine dair iyi bir kontrol listesi önemli ölçüde yardımcı olur. Aşağıdaki satırda sorun giderme işlemi yaptığımızı düşünelim:
require "/path/to/file"
require*
ya da include*
tarafından çağrılan şeyi kendi değişkenine taşıyın, eko yapın, kopyalayın ve bir terminalden erişmeyi deneyin:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
Sonra, bir terminalde:
cat <dosya yolu yapıştırıldı>
require __DIR__ . "/relative/path/from/current/file"
kullanın. DIR` sihirli sabiti]magicconst-docs geçerli dosyanın dizinini döndürür.SITE_ROOT
sabiti tanımlayın :config.php
config.php
yi ekleyin ve ardından SITE_ROOT
sabitini istediğiniz yerde kullanın:
require_once DIR."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Bu 2 uygulama aynı zamanda uygulamanızı daha taşınabilir hale getirir çünkü include yolu gibi ini ayarlarına bağlı değildir.
Dosyaları ne göreceli olarak ne de tamamen mutlak bir şekilde dahil etmenin bir başka yolu da include path'a güvenmektir. Bu genellikle kütüphaneler veya Zend çerçevesi gibi çerçeveler için geçerlidir. Böyle bir dahil etme şu şekilde görünecektir :
include "Zend/Mail/Protocol/Imap.php"
Bu durumda, "Zend" klasörünün include yolunun bir parçası olduğundan emin olmak isteyeceksiniz. Dahil etme yolunu şu şekilde kontrol edebilirsiniz :
echo get_include_path();
ile bir klasör ekleyebilirsiniz:
set_include_path(get_include_path().":"."/path/to/new/folder");
Sunucu sürecini (Apache veya PHP) çalıştıran kullanıcının bu dosyadan okuma veya bu dosyaya yazma izni olmayabilir. Sunucunun hangi kullanıcı altında çalıştığını kontrol etmek için posix_getpwuid kullanabilirsiniz:
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Dosyanın izinlerini öğrenmek için terminale aşağıdaki komutu yazın:
ls -l <path/to/file>
ve [izin sembolik gösterimi][izinler-notasyonu]'na bakın
Yukarıdakilerin hiçbiri işe yaramadıysa, sorun muhtemelen bazı PHP ayarlarının bu dosyaya erişmesini yasaklamasıdır. Üç ayar ilgili olabilir :
phpinfo()
çağrısı yapılarak ya da ini_get("open_basedir")
kullanılarak kontrol edilebilir.ini_get("allow_url_include")
ile kontrol edilebilir ve ini_set("allow_url_include", "1")
ile ayarlanabilir
Yukarıdakilerin hiçbiri sorunu teşhis etmeyi sağlamadıysa, olabilecek bazı özel durumlar aşağıda verilmiştir:
Örneğin Zend framework gibi bir kütüphaneyi göreli veya mutlak bir yol kullanarak dahil edebilirsiniz. Örneğin :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Ancak yine de aynı tür bir hata alırsınız. Bunun nedeni, (başarılı bir şekilde) dahil ettiğiniz dosyanın kendisinin başka bir dosya için include deyimine sahip olması ve bu ikinci include deyiminin o kütüphanenin yolunu include yoluna eklediğinizi varsayması olabilir. Örneğin, daha önce bahsedilen Zend framework dosyası aşağıdaki include ifadesine sahip olabilir:
include "Zend/Mail/Protocol/Exception.php"
Bu da ne göreli yol ne de mutlak yol ile bir içerme değildir. Zend framework dizininin dahil etme yoluna eklendiği varsayılır.
Böyle bir durumda, tek pratik çözüm dizini dahil etme yolunuza eklemektir.
Eğer Security-Enhanced Linux kullanıyorsanız, sunucudan dosyaya erişimi reddederek sorunun nedeni olabilir.
Sisteminizde SELinux'un etkin olup olmadığını kontrol etmek için bir terminalde sestatus
komutunu çalıştırın. Eğer komut mevcut değilse, SELinux sisteminizde yok demektir. Eğer varsa, o zaman size SELinux'un uygulanıp uygulanmadığını söyleyecektir.
Sorunun nedeninin SELinux politikaları olup olmadığını kontrol etmek için, geçici olarak kapatmayı deneyebilirsiniz. Ancak DİKKATLİ olun, çünkü bu korumayı tamamen devre dışı bırakacaktır. Bunu üretim sunucunuzda yapmayın.
setenforce 0
SELinux kapalıyken artık sorun yaşamıyorsanız, temel neden budur. Çözmek için SELinux'u uygun şekilde yapılandırmanız gerekecektir. Aşağıdaki bağlam türleri gerekli olacaktır :
httpd_sys_content_t
httpd_sys_rw_content_t
httpd_log_t
httpd_cache_t
Örneğin, web sitenizin kök dizinine httpd_sys_content_t
bağlam türünü atamak için :semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Dosyanız bir ev dizinindeyse, httpd_enable_homedirs
boolean'ını da açmanız gerekecektir:
setsebool -P httpd_enable_homedirs 1
Her durumda, politikalarınıza bağlı olarak SELinux'un bir dosyaya erişimi reddetmesinin çeşitli nedenleri olabilir. Bu yüzden bunu araştırmanız gerekecektir. Burada özellikle bir web sunucusu için SELinux yapılandırması hakkında bir öğretici bulunmaktadır.
Symfony kullanıyorsanız ve bir sunucuya yükleme yaparken bu hatayla karşılaşıyorsanız, uygulamanın önbelleği sıfırlanmamış olabilir, çünkü app/cache
yüklenmiştir veya önbellek temizlenmemiştir.
Aşağıdaki konsol komutunu çalıştırarak bunu test edebilir ve düzeltebilirsiniz:
cache:clear
Görünüşe göre bu hata, zip içindeki bazı dosyaların dosya adlarında "é" gibi ASCII olmayan karakterler olduğunda zip->close()
çağrısı yapıldığında da meydana gelebilir.
Potansiyel bir çözüm, hedef dosyayı oluşturmadan önce dosya adını utf8_decode()
içine sarmaktır.
Bu sorunu tanımladığı ve bir çözüm önerdiği için Fran Cano'ya teşekkür ederiz
Mevcut (gerçekten iyi) cevaba eklemek için
open_basedirsizi şaşırtabilir çünkü bir web sunucusu yapılandırmasında belirtilebilir. Kendi tahsis edilmiş sunucunuzu çalıştırıyorsanız bu durum kolayca çözülebilirken, alan bazında bir yapılandırma yönergesi yapılandıracak bazı paylaşılan barındırma yazılım paketleri (Plesk, cPanel vb.) vardır. Yazılım yapılandırma dosyasını (yani
httpd.conf`) oluşturduğundan, bu dosyayı doğrudan değiştiremezsiniz çünkü barındırma yazılımı yeniden başlatıldığında dosyanın üzerine yazacaktır.
Plesk ile, sağlanan httpd.conf
dosyasını geçersiz kılmak için vhost.conf
adlı bir yer sağlarlar. Bu dosyayı yalnızca sunucu yöneticisi yazabilir. Apache için yapılandırma şuna benzer
<Directory /var/www/vhosts/domain.com>
<IfModule mod_php5.c>
php_admin_flag engine on
php_admin_flag safe_mode off
php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR"
</IfModule>
</Directory>
Sunucu yöneticinizin kullandıkları barındırma ve web sunucusu yazılımının kılavuzuna başvurmasını sağlayın.
Web sunucunuz üzerinden bir dosya yürütmenin komut satırı veya cron işi yürütmeden çok farklı olduğunu unutmamak önemlidir. En büyük fark, web sunucunuzun kendi kullanıcısına ve izinlerine sahip olmasıdır. Güvenlik nedeniyle bu kullanıcı oldukça kısıtlıdır. Örneğin Apache, genellikle apache
, www-data
veya httpd
(sunucunuza bağlı olarak) şeklindedir. Bir cron işi veya CLI yürütmesi, onu çalıştıran kullanıcının sahip olduğu izinlere sahiptir (örneğin, bir PHP betiğini root olarak çalıştırmak root izinleriyle yürütülür).
Çoğu zaman insanlar bir izin sorununu aşağıdakileri yaparak çözerler (Linux örneği)
chmod 777 /path/to/file
Bu akıllıca bir fikir değildir, çünkü dosya veya dizin artık dünya çapında yazılabilir hale gelmiştir. Eğer sunucunun sahibi ve tek kullanıcısı sizseniz, bu o kadar da önemli değildir, ancak paylaşımlı bir barındırma ortamındaysanız, sunucunuzdaki herkese erişim izni vermiş olursunuz.
Yapmanız gereken, erişime ihtiyacı olan kullanıcı(lar)ı belirlemek ve yalnızca bu kullanıcılara erişim vermektir. Hangi kullanıcıların erişime ihtiyacı olduğunu öğrendikten sonra şunlardan emin olmak isteyeceksiniz
Bu kullanıcı dosyanın ve muhtemelen üst dizinin sahibidir (özellikle dosya yazmak istiyorsanız üst dizinin). Çoğu paylaşılan barındırma ortamında bu bir sorun olmayacaktır, çünkü kullanıcınız kök dizininizin altındaki tüm dosyalara sahip olmalıdır. Bir Linux örneği aşağıda gösterilmiştir
chown apache:apache /path/to/file
Kullanıcı ve sadece o kullanıcının erişimi vardır. Linux'ta iyi bir uygulama chmod 600
(sadece sahip okuyabilir ve yazabilir) veya chmod 644
(sahip yazabilir ancak herkes okuyabilir) olacaktır.
Linux/Unix izinleri ve kullanıcıları hakkında daha geniş bir tartışmayı buradan okuyabilirsiniz](https://unix.stackexchange.com/questions/35711/giving-php-permission-to-write-to-files-and-folders)
Başka bir olası neden: Bir metin editöründeyken dosyaları yeniden adlandırmak ve/veya taşımak. Bu hatayı vermeye devam eden dosyayı silip yeni bir tane oluşturana kadar yukarıdaki tüm adımları başarıyla uyguladım ve sorun çözüldü.