Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: preg_replace_callback
Forum PHP.pl > Forum > PHP
Jarod
Natrafiem w manualu na taką funkcję jak preg_replace_callback. Wiem do czego to służy ale nie rozumiem poniższego wywołania

  1. <?php
  2. preg_replace_callback("|(d{2}/d{2}/)(d{4})|", array( __CLASS__, 'getRecord' ), $text);
  3. ?>


Wiem, że __CLASS__ zwraca nazwę bieżącej klasy ale nie rozumiem co daje:
  1. <?php
  2. array( __CLASS__, 'getRecord' )
  3. ?>


Może mi ktoś to wytłumaczyć?
cadavre
Wywołuje callback czyli funkcję - zdaje się zatem, że
  1. <?php
  2. array(__CLASS__,'getRecord')
  3. ?>
wywoła funkcję 'getRecord' klasy __CLASS__. Ale dlaczego wewnątrz klasy stosować __CLASS__ i takiego zapisu? Dlaczego nie $this->getRecord to ja już nie wiem...
Jarod
Podobną rzecz widziałem w klasie hwao (metoda generate)
  1. <?php
  2.  
  3. class ConfigCreator {
  4. public $sClassName = 'Config';
  5. static protected $aConfig = array();
  6. const RegEx = '@%([^%]+)%@';
  7.  
  8. public function __construct( $sClassName = 'Config' ) {
  9. $this->sClassName = $sClassName;
  10. }
  11.  
  12. public function Generate( $sPath = null, $sSavePath = null ) {
  13. $sPath  = is_null( $sPath ) ? './config.ini.php' : $sPath;
  14. $aConfig = parse_ini_file( $sPath, true );
  15. $sSource = $this->getHeader();
  16. $sSavePath = is_null( $sSavePath ) ? './config.php' : $sSavePath;
  17. foreach( $aConfig As $sKey => $aLine ) {
  18. foreach( $aLine As $sName => $sValue ) {
  19. $sValue = preg_replace_callback( self::RegEx, array( __CLASS__, '__ConfigPaser' ), $sValue );
  20. self::$aConfig[strtolower($sKey.$sName)] = $sValue;
  21. $sSource .= $this->getLine( $sKey.$sName, $sValue );
  22. }
  23. }
  24. $sSource .= $this->getFooter();
  25.  
  26. file_put_contents( $sSavePath, $sSource );
  27. }
  28.  
  29. static protected function & __ConfigPaser( & $aInput ) {
  30. return self::$aConfig[strtolower($aInput[1])];
  31. }
  32.  
  33. protected function getLine( $sName, $sValue ) {
  34. $sValue = str_replace( ''', ''', $sValue );
  35. if( substr( $sValue, -1, 1 ) == '' ) {
  36. $sValue .= '';
  37. }
  38.  
  39. return '
  40. static public $'.$sName.' = ''.$sValue.'';';
  41. }
  42.  
  43. }
  44. ?>
mysz
To jest sposób na poinformowanie funkcji preg_replace_callback, że ma wywołać (ta funkcja) metodę getRecord klasy __CLASS__. Nie można zastosować $this->getRecord(), bo ta funkcja by coś zwróciła, nie podziała też '$this->getRecord()', bo trzeba by to jakoś dziwnie ewalować (zmienna $this _wewnątrz_ funkcji preg_replace_callback nic nie znaczy), etc.
Polecam lekturę http://php.net/call_user_func
Jarod
Cytat(mysz @ 2.01.2007, 00:00:39 ) *
To jest sposób na poinformowanie funkcji preg_replace_callback, że ma wywołać (ta funkcja) metodę getRecord klasy __CLASS__. Nie można zastosować $this->getRecord(), bo ta funkcja by coś zwróciła, nie podziała też '$this->getRecord()', bo trzeba by to jakoś dziwnie ewalować (zmienna $this _wewnątrz_ funkcji preg_replace_callback nic nie znaczy), etc.
Polecam lekturę http://php.net/call_user_func

Czytałem. W powyższym przykłądzie zamieniłem __CLASS__ na this i też działa.
splatch
Callback pseudo type
Is callable
mike
Wszystko ładnie tylko ... jaki to ma związek z programowaniem obiektowym?
Przenoszę na php.
Jarod
Dobra załapałem. Tylko, że mam inny problem a nie chcę zakładać osobnego wątku.


Przypadek 1: Chciałbym znaleźć w ciągu tekstowym sad*.txtaaa ciąg *.txt i zamienić go na *.TXT. Problem w tym, że w funkcji show wogóle nie mogę się dostać do odnalezionego wzoru.
return $matches[0]; a return $matches[1].'-'.$matches[2]; dają inne wyniki.

Z godnie z tym co napisali w manualu to element $matches[0] powinien zawierać
Cytat
sad*.txtaaa
, element $matches[1] powinien zawierać
Cytat
sad
, element $matches[2] powinien zawierać *.txt a element $matches[3] powinien zawierać
Cytat
aaa
. Czyli w funkcji show powinienem dać zapis return strtoupper($matches[2]). Niestety to nie działa. Jak się dostać do dopasowanego wzorca?

  1. <?php
  2. function show($matches)
  3. {
  4. return $matches[0];
  5. }
  6.  
  7. $lanuch = 'sad*.txtaaa';
  8. $wzor = '@*.txt@';
  9.  
  10. echo preg_replace_callback($wzor, show, $lanuch );
  11. ?>
devnul
bo i nie ma prawa działać: zapomniałeś o cudzysłowiu:
  1. <?php
  2. function show($matches)
  3. {
  4. return $matches[0];
  5. }
  6.  
  7. $lanuch = 'sad*.txtaaa';
  8. $wzor = '@*.txt@';
  9.  
  10. echo preg_replace_callback($wzor, 'show', $lanuch );
  11. ?>

zresztą bardzo podobny przykład jest w manualu - example 2 - poza tym że tam jest strtolower działanie jest identyczne
Jarod
@devnul: To nie to - bez apostrofów też działa. Poradziłem sobie:
  1. <?php
  2. function show($matches)
  3. {
  4. return strtoupper($matches[0]);
  5. }
  6.  
  7. $lanuch = 'sad*.txtaaa';
  8. $wzor = '@*.txt@';
  9.  
  10. $lanuch = preg_replace_callback($wzor, 'show', $lanuch );
  11. echo $lanuch;
  12. ?>

Niezrozumiałe jest dla mnie w jaki sposób odwołać się do części znalezionego wzoru. Np chce wyświetlić całość przekazanego łańcucha, część lewą (czyli do części znalezionej), część odnalezioną, i część od znalezionej do końca. Wogóle nie pomyślał bym o tym ale zasugerowałem się przykładem w manualu.

Gdy zamienię return strtoupper($matches[0]); na
  1. <?php
  2. return $matches[1]; //otrzymuję ciąg bez części szukanej
  3. return $matches[0].'|'.$matches[1].'|'.$matches[2]; // tu już orzymuję dziwne rzeczy
  4. ?>


Wiecie o co z tym chodzi?

I jeszcze inne pytanie:
Mam np taki ciąg:
Kod
dwr2sdfFuser@domena.plsfsdRWE

I chcę zamienić znak kropki na \. a znak małpy na \@
Da się to zrobić za jednym razem czy muszę dwa razy wywoływać preg_replace_callback najpierw zamieniając wszystkie kropki a później znak małpy?
cadavre
Zrób str_replace - on udostępnia możliwość wstawienia arraya z danymi do podmiany.

A'propo jak to było z wydajnościa preg vs. str?
Jarod
Cytat(cadavre @ 3.01.2007, 22:01:02 ) *
Zrób str_replace - on udostępnia możliwość wstawienia arraya z danymi do podmiany.

Wolałbym preg_replace_callback bo chce zrozumieć.

Cytat(cadavre @ 3.01.2007, 22:01:02 ) *
A'propo jak to było z wydajnościa preg vs. str?

Ogólnie preg jest szybsze (gdzieś czytałem)
cadavre
Poprzez sam preg_replace
  1. <?php
  2. $str = "jakis@ciag.znakow";
  3. $str = preg_replace("/([@|.])/",""."1",$str);
  4. ?>
lub arraye
  1. <?php
  2. $arr[0] = "/@/";
  3. $arr[1] = "/./";
  4. $arrr[0] = "@";
  5. $arrr[1] = ".";
  6.  
  7. $str = "jakis@ciag.znakow";
  8. $str = preg_replace($arr,$arrr,$str);
  9. ?>
tomekp
Cytat(cadavre @ 4.01.2007, 00:01:02 ) *
A'propo jak to było z wydajnościa preg vs. str?

W jaki sposób mogę sprawdzić wydajność?
cadavre
Heh... byle profilerem czy też własnym skryptem, którego podstawą będzie microtime" title="Zobacz w manualu php" target="_manual. Zapętlasz kilkaset replaceów i liczysz czas.
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.