Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] Dynamiczne includowanie
Forum PHP.pl > Forum > PHP
tracerout
Chcial bym dynamicznie includowac pliki petla(chodzi o to zeby nie trzeba bylo ponownie odpalac skryptu przy zmienie jednej funkcji z includowanym pliku), PHP pluje sie ze nie mozna ponownie zadeklarowac funkcji. Wiem o tym ze mozna wykonywac evalem albo uzywac do tego "php -r" ale dla mnie to ostatecznosc. Prosze o pomoc.

Przykład:
  1. <?php
  2. while(1) {
  3.   include('plik.php');
  4.   ft();
  5. }
  6. ?>


Plik "plik.php":
  1. <?php
  2. function ft() {
  3.   echo "test";
  4. }
  5. ?>
wookieb
A może przykład?
kipero
A nie wystarczy:
  1. <?php
  2. include('plik.php');
  3. while(1) {
  4.  ft();
  5. }
  6. ?>

?
tracerout
Widzisz temat? Wyraznie wpisalem "DYNAMICZNE INCLUDOWANIE".
pyro
Cytat(tracerout @ 2.07.2009, 15:16:23 ) *
Widzisz temat? Wyraznie wpisalem "DYNAMICZNE INCLUDOWANIE".


Ale to NIEWIELE MÓWI. Podaj jakiś przykład o co Ci chodzi.
erix
Cytat
PHP pluje sie ze nie mozna ponownie zadeklarowac funkcji.

Zostaje Ci ew. definiowanie zmiennej jako funkcji, lambda jest tylko od PHP 5.3.

Poza tym, zupełnie nie rozumiem, po co chcesz w pętli nieskończonej tę funkcję wywoływać.
batman
function_exists" title="Zobacz w manualu PHP" target="_manual - dzięki temu będziesz miał pewność, że nie stworzysz funkcji o takiej samej nazwie. Jeżeli jednak masz kilka funkcji o takiej samej nazwie, ale o różnej funkcjonalności, to musisz przeprojektować aplikację.

Ewentualnie spróbuj użyć include_once" title="Zobacz w manualu PHP" target="_manual, jednak nie jestem pewien, czy uzyskasz pożądany efekt.
tracerout
Hmm.. sproboje jasniej:

Powiedzmy ze mam dwa pliki: start.php i inc.php.
Zawartosc start.php to:
  1. <?php
  2. while(1) {
  3.   include('inc.php');
  4.   jakas_funkcja();
  5. }
  6. ?>

Zawartosc inc.php to:
  1. <?php
  2. function jakas_funkcja() {
  3.   echo "Jakis text";
  4.   //inne instrukcje
  5. }
  6. ?>


PHP zglosi:
  1. <?php
  2. Fatal error: Cannot redeclare jakas_funkcja() ...
  3. ?>


Po co mi to? Zebym nie musial odpalac ciagle pliku start.php jesli chce zmienic cos tylko w funkcjach z inc.php.
Jesli w start.php include bylo by tylko przed while to po nim bedzie juz dostepna "jakas_funkcja()" i zwroci jako wynik "Jakis text", jesli w pliku inc.php zamienie "Jakis text" na "Jakis string" to petla nadal bedzie wyswietlala "Jakis text" dlatego chce includowac w petli zebym nie musial ciagle odpalac "start.php". Wszystko bylo by proste gdyby nie fakt ze nieda sie(przynajmniej tak mi sie wydaje) zniszczyc funkcji.

Juz prosciej nie potrafie tego napisac.
wookieb
Dlatego jest function exists
Kod
if(!function_exists('nazwa_funkcji'))
{
function nazwa_funkcji()
{

}
}
batman
~tracerout sprawdź podane przeze mnie funkcje. Powinny pomóc w rozwiązaniu Twojego problemu.
Z drugiej strony, Twoje rozumowanie jest co najmniej błędne. PHP jest językiem skryptowym, który nie wymaga kompilacji, a tym samym, nie wymaga dynamicznego ładowania funkcji, ponieważ po przeładowaniu strony/wykonaniu się skryptu, zmiany zostaną dołączone. Modyfikacja funkcji w trakcie działania skryptu nie należy do najlepszych pomysłów.
tracerout
KLIK <-- Prosze bardzo, oto jeden z przykladow, mojego autorstwa, ze PHP nie trzeba uzywac tylko w "konwencjonalny" sposob. Wystarczy na dowolnym shellu (z php) wydac komende "php jbot.php" (po edycji danych do zalogowania w pliku jbot.php ofc) i juz mamy dzialajcego przez kilka dni bota na jabbera.

A wracajac do tematu, wiem ze to nie najlepszy pomysl, biorac pod uwage to ze php ZEND(?) nie stworzylo do tego specjalnej funkcji, ale bardzo ulatwilo by to moja prace. Tak wiec ponawiam prosbe o pomoc.
batman
Czwarty raz piszę - sprawdź podane przeze mnie funkcje.
O samym użyciu nie będę się wypowiadał, by nie robić OT.
tracerout
function_exists - sprawdza czy dana funkcja juz istnieje
include_once - includuje plik jesli jeszcze nie zostal zaincludowany

IMHO zadna z tych funkcji niema nic wspolnego z rozwiazaniem mojego problemu bo jedna z nich zapobiega ponownemu dolaczeniu jakiegos pliku a druga pomaga zapobiedz redeklaracji funkcji.

Jesli sie NAPEWNO myle, pomozcie mi to zrozumiec.
erix
Powiedz, co w praktyce chcesz osiągnąć.
tracerout
Konkretnie potrzebuje sobie ulatwic tworzenie pewnego bota, nie moge go wylaczyc na dluzej, a jesli wylacze i wlacze z nieprzetestowanym wczesniej kodem to uzytkownicy(jest ich dosc duzo) beda mogli "pokrzaczyc" cos na serwerze lub swoich kontach(o ile w kodzie zrobie jakis blad). Nie mam mozliwosci innego testowania kodu, dlatego potrzebuje na bierzaco zmieniac tresc funkcji includowanych z pewnego pliku. Nie widze innej opcji poza includowaniem tego samego pliku podczas kazdego obiegu petli(da sie to zrobic za pomoca eval i popena ale bot musial by sie dluzej zastanowic, a przy kilku set userach niema prawa "przemyslec" nawet 1 s.
phpion
A nie możesz na tym samym serwerze utworzyć kopię systemu pod jakąś domeną dostępną po podaniu hasła? Użytkownicy wciąż korzystają z dotychczasowej wersji systemu, a ty spokojnie testujesz sobie nową.
tracerout
W tym problem ze nie moge. Gdyby to bylo tak proste to dawno bym to zrobil.
erix
No wreszcie wiadomo, o co chodzi.

Najlepszy byłby tu właśnie bot produkcyjny. Ale jeśli już musisz, to bym kombinował z czymś takim. Partyzantka, ale cóż - nie masz serwera produkcyjnego, to będziesz musiał przeboleć.

Do usmażenia jaje... ups [; Przydadzą się call_user_func" title="Zobacz w manualu PHP" target="_manual + file_exists" title="Zobacz w manualu PHP" target="_manual; raz na jakiś czas będziesz musiał zrestartować skrypt, ale to zależy od zużycia pamięci całego skryptu.

Robisz coś takiego: majstrujesz bibliotekę, którą trzymasz w osobnym katalogu; pliki mają nazewnictwo lib1, lib2, itd. Co teraz? Modyfikujesz wywołanie pętli:
  1. <?php
  2. while(1){
  3.    $counter = 0;
  4.    
  5.    require 'lib/lib'.$counter.'.php';
  6.    
  7.    call_user_func('lib'.$counter);
  8.    
  9.    if(file_exists('lib/lib'.$counter..php)){
  10.        ++$counter;
  11.    }
  12.    
  13. }
  14. ?>

Przy każdej modyfikacji tworzysz nowy plik o numerku większym niż poprzedni. Jeśli istnieje - zostanie wczytany i wykonana funkcja o jego nazwie.

Zaznaczam: rozwiązanie partyzanckie, stosujesz na własną odpowiedzialność.
tracerout
Chyba jednak bede zmuszony uzyc watkow, nie moge marnowac tyle pamieci. No coz, jesli ktos wymysli cos lepszego to prosze pisac, tymczasowo zastosuje watki, najwyzej mnie userzy powiesza:P
erix
A czemu nie zrobisz pośredniego wywołania do jakiejś osobnej biblioteki przez np. XML-RPC, czy SOAP? Możesz wtedy wykonywać tę samą funkcję, zmieniasz wtedy tylko skrypt serwera usługi.
batman
PHP nie był stworzony do takich rzeczy. Ale jest na to rada. Oczywiście nie jest to idealne rozwiązanie i na pewno można to lepiej napisać, ale działa i nie wymaga eval-a.
  1. <?php
  2. // glowny skrypt
  3. while(true) {
  4.    $nazwaFunkcji = include 'inc.php';
  5.  
  6.    $nazwaFunkcji();
  7.    sleep(1);
  8. }
  9.  
  10. // inc.php
  11. $nazwaFunkcji = 'wywolywanaFunkcja';
  12.  
  13. if(!function_exists($nazwaFunkcji)) {
  14.    function wywolywanaFunkcja() {
  15.        echo "test\n";
  16.    }
  17. }
  18.  
  19. return $nazwaFunkcji;
  20.  
  21. ?>

Wystarczy, że zmienisz zawartość zmiennej $nazwaFunkcji i tak samo nazwiesz funkcję. Błędu nie zgłosi, nie przestanie działać, a wynik będzie widać od razu. Nie wiem jak z wydajnością - nie sprawdzałem.
kipero
Cytat(tracerout @ 2.07.2009, 15:16:23 ) *
Widzisz temat? Wyraznie wpisalem "DYNAMICZNE INCLUDOWANIE".

To Ty zajrzyj jeszcze raz w swój pierwszy przykład i zastanów się, czy można z niego było wywnioskować, co chcesz osiągnąć.

Do zrobienia tego co chcesz osiągnąć przyda się http://pl.php.net/manual/pl/function.override-function.php

Wydaje mi się, że powinno zadziałać, ale nie sprawdzałem bo brakuje mi biblioteki.
index.php
  1. <?php
  2. while (true){
  3.   include 'plik.php';
  4.   ft();
  5. }
  6. ?>


plik.php
  1. <?php
  2. if (function_exists('ft')){
  3.   override_function('ft', '', 'return false;');
  4. }else{
  5.   function ft(){
  6.      //...
  7.      return true;
  8.   }
  9. }
  10. ?>
erix
Ale APD jest na mało którym serwerze...
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.