Náhrada tagov zanorenych rekurzivne rubrika: Programování: PHP

4 mario2402
položil/-a 23.6.2018
 
upravil/-a 23.6.2018

Caute,

neviem si moc rady s jednou vecou, s dovodu, ze nie som az tak dobry kamarat s regularnymi vyrazmi v kombinacii s rekurziou.

Mam dajme tomu:

{form prvyForm}
 
  {label nazov}
 
  {form druhyForm}
 
    {label nazov}
 
  {/form}
 
.....
 
{/form}

a potreboval by som ziskat taketo nieco:

<?php if ($form->exists('prvyForm')) { $__form_prvyForm = $form->get('prvyForm'); ?>
 
  <?php echo $__form_prvyForm['nazov']->getLabel(); ?>
 
  <?php if ($form->exists('druhyForm')) { $__form_druhyForm = $form->get('druhyForm'); ?>
 
    <?php echo $__form_druhyForm['nazov']->getLabel(); ?>
 
  <?php } ?>
 
.....
 
<?php } ?>

V spolupraci s manualom php som sa dopracoval k regularnemu vyrazu ktory mi to "poseka" podla zanoreni:

function form ($input)
  {
 
    $regular = '~\{form ([a-zA-Z_]+)\}((?:[^{]|\{(?!/?form(.*)\})|(?R))+)\{/form\}~s';
 
 
    if (is_array($input)) {
 
 
      $input[2] = preg_replace('~\{label ([a-zA-Z0-9_]+)\}~', '<?php echo $__form_'.$input[1].'[\'\1\']->getLabel(); ?>', $input[2]); 
     // toto je samozrejme chybne, lebo prepise vsetky labely uz pri prvom prechode a teda budu mat vsetky labely $__form_prvyForm
 
 
      $input = '<?php if ($form->exists(\''.$input[1].'\')) { $__form_'.$input[1].' = $form->get(\''.$input[1].'\'); ?>'.$input[2].'<?php } ?>';
 
    }
 
 
    return preg_replace_callback($regular, [$this,'form'], $input);
 
  }
 
$vysledok = form($vstup);

a teraz neviem docielit to, aby sa v kazdom callbacku nahradil iba ten label ktory patri do zanorenia, ktore sa aktualne nahradza.. tie labely, ktore su hlbsie zanorene, aby ostaly nedotknute pokial na ne nepride rad..

uz som prehladal kde co, zda sa, ze neviem polozit otazku spravne po anglicky (moja slabina - slaba anglictina), lebo ani ujo google ma nechape..

vedel by niekto poradit?

Komentáře

  • Kit : Metoda $form->exists() je tam zcela zbytečná. Zkus to bez ní, celé se to zjednoduší. 23.6.2018
  • mario2402 : ak formular nebude existovat, chcem aby sa ta cast obisla, preto to overim na zaciatku (resp. nie ja, ale bude sa to diat automaticky)... 23.6.2018
odkaz
4 mario2402
odpověděl/-a 23.6.2018
 
upravil/-a 23.6.2018

Nastrel noveho riesenia (zatial funguje bez problemov)

pomocou preg_replace_callback si vyberiem vsetky tagy bez ohladu na ich obsah.. kedze sa callback vola pekne postupne od zaciatku obsahu po jeho koniec, viem si lepsie riesit zanorenie..

zavolame compile(' .... text .... ');

private $kolbeky = [
 
    '~{form ([a-zA-Z_]+)\}~' => '_form',
 
    '~{/form}~' => '_formEnd',
 
    '~\{label ([a-zA-Z_]+)\}~' => '_formLabel',
 
    '~\{description ([a-zA-Z_]+)\}~' => '_formDescription',
 
    '~\{input ([a-zA-Z_]+)\}~' => '_formInput'
  ];
 
function compile ($obsah) {
 
 $skompilovany_obsah = preg_replace_callback('~\{[\*\$/a-zA-Z0-9_ ]+\}~', [$this, 'callback'] , $obsah);
 
}
 
function callback($matches) {
 
 // tu hladame uz zhodu presne na dany tag + callback
 foreach($this->kolbeky as $k=>$v) { 
 
 $matches[0] = preg_replace_callback($k, [$this, $v], $matches[0]);
 
 }
 
 return $matches[0];
 
}
 
// a teraz podstata riesenia
 
$formNameBuffer = [];
 
function _form ($matches) {
 
 // otvarame zanorenie , vlozime na "koniec" bufferu jeho meno
 $this->formNameBuffer[] = $matches[1];
 
 return 'PHP KOD zamienajuci otvaraci tag {form}';
 
}
 
 
function _formLabel ($matches) {
 
 $aktualnyNazovFormu = end($this->formNameBuffer);
 
 return ' a tu uz vieme nazov - $aktualnyNazovFormu - formu v ktorom sme prave zanoreny, lebo je to posledny ktory sa do bufferu zapisal';
 
}
 
function _formEnd ($matches) {
 
 $aktualnyNazovFormu = array_pop($this->formNameBuffer);
 
 return ' kedze sa nam tag {form} zatvara, odoberame jeho nazov z bufferu, dalsi najdeny tag label bude mat nazov predchadzajuceho formu, 
lebo ten sa zapisal pred nim';
 
}

(kod neberte doslovne, je to len koncept pisany z hlavy, avsak overeny ze funguje)

ma to napr. aj dalsie vyhody, ze ak neexistuje zaznam vo formNameBuffer, je chyba v tagoch, to iste ak po konci kompilacie nebude formNameBuffer prazdny je to chyba (nie je uzavrety tag, nie je otvoreny atd) - skompilovany obsah bude neplatny..

Komentáře

  • Taco : No, když ti to funguje, tak ti to funguje, ale nemyslel jsem to takhle. Já bych to dělal rekurzí; oproti tvému řešení, kdy máš vlastně furt lineární seznam výrazů, a jen na ně uplatňuješ ty funkce. 23.6.2018
  • mario2402 : pri rekurzii mi ostaval ten problem, ze som nedokazal pri prvom prechode "vyclenit" tie dalsie zanorene tagy, resp. vedel.. ale uz by to bolo zlozitejsie ako toto riesenie, + tu je aj vyhoda, ze je lahko poznat ci su tagy spravne otvorene a uzavrete.. ale dakujem za radu, lebo si ma nakopol, aj ked inym smerom :) 23.6.2018

Pro zobrazení všech 3 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.