Registry პატერნი, array_map და ტექსტში შაბლონით ძებნა

ამ დღეებში ვატარებდი მცირე ექსპერიმენტებს ტექსტში შაბლონებით ძიებაზე, და მცირე სასარგებლო აღმოჩენები გავაკეთე. ჩემი ამოცანა მდგომარეობდა იმაში რომ ტექსტში მომეძებნა გარკვეული ფრაგმენტები და შემდეგ ჩამენაცვლებინა ისინი სხვა მნიშვნელობებით, ეს მნიშვნელობები კი სისტემის გლობალური ცვლადები იყო. ფრაგმენტებს ტრადიციული სახე მივეცი რადგან შაბლონებით ძიება მარტივი ყოფილიყო, ანუ რაღაც ამის მსგავსი {var:encoding}, ყველასათვის ცნობილი და მიღებული ფორმით…

როგორ გადავწყვიტე საბოლოოდ ეს ამოცანა? პირველ რიგში მინდა ავღნიშნო რომ არ მიყვარს ე.წ. გლობალური ცვლადების გამოყენება და ამის თავიდან ასარიდებლად ყოველთვის ვიყენებ Registry პატერნს, რომლის მეშვეობითაც იოლად ვირიდებ თავიდან გლობალურ ცვლადებთან მუშაობის არასასიამოვნო დეტალებს.

პატერნის რეალიზაცია PHP5 – ისთვის გამოიყურება შემდეგნაირად(დეტალური ახსნა თუ რანაირად მუშაობს ეს პატერნი იხილეთ ზემოთ მითითებულ ბმულზე):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Registry {
 
  private static $stack = array();
 
  public static function add($key, $value) {
    self::$stack[$key] = $value;
  }
 
  public static function get($key) {
    if (isset(self::$stack[$key])) {
      return self::$stack[$key];
    }
  }
 
  public static function has($key) {
    return isset(self::$stack[$key]);
  }
 
}

ამ პატარა კლასის დახმარებით ძალიან მარტივად და ელეგანტურად შეგვიძლია ვიმუშავოთ სისტემის გლობალურ ცვლადებთან, მაგალითად:

1
2
3
4
5
6
7
8
9
//მონაცემების დამატება
Registry::add('encoding', 'UTF-8');
Registry::add('url', 'http://www.code.ge');
Registry::add('test', 'testvar');

//მონაცემების წაკითხვა
Registry::get('encoding');
Registry::get('url');
Registry::get('test');

როგორც ხედავთ ყველაფერი ძალიან მარტივია, და რაც მთავარია არ ვიყენებთ საშინელ $GLOBALS მასივს…

რაც შეეხება თავად ტექსტს, და მასში ძიებას, პირველ რიგში განვიხილოთ მსგავსი ტექსტი:

<ul>
    <li><strong> {var:encoding} </strong></li>
    <li><strong> {var:url} </strong></li>
    <li><strong> {var:test} </strong></li>
    <li><strong> {var:fake_variable} </strong></li>
</ul>

ეს არის ჩვეულებრივი HTML კოდი რომელშიც ჩასმული გვაქვს ე.წ. ცვლადები, შემდეგი სახით: {var:encoding}, {var:url} და ა.შ. ასეთი ტექსტისათვის რეგულარული გამოსახულების შაბლონის დაწერა ძალიან მარტივია /\{(?:var:)(\w+)}/, მისი მეშვეობით შეგვიძლია მოვძებნოთ ყველა საჭირო ფრაგმენტი ტექსტში:

1
2
3
4
5
if (preg_match_all('/\{(?:var:)(\w+)}/', $template, $vars)) {
    echo '<pre>';
    print_r($vars);
    echo '</pre>';
}

კოდის შესრულების შედეგად ვღებულობთ მასივს, რომლის პირველი ელემენტი შეიცავს ყველა მოძებნილი ფრაგმენტის მასივს, ხოლო მეორე ელემენტი შეიცავს უშუალოდ ამ ფრაგმენტებიდან ამოღებულ ცვლადების სახელებს:

Array
(
    [0] => Array
        (
            [0] => {var:encoding}
            [1] => {var:url}
            [2] => {var:test}
            [3] => {var:fake_variable}
        )

    [1] => Array
        (
            [0] => encoding
            [1] => url
            [2] => test
            [3] => fake_variable
        )

)

მაშ ასე, ხელთ გვაქვს ყველაფერი, ერთადერთი რჩება ამ ფრაგმენტების ჩანაცვლება ნამდვილი ცვლადების მნიშვნელობებით:

1
2
3
4
5
if (preg_match_all('/\{(?:var:)(\w+)}/', $template, $vars)) {
  $values = array_map(array('Registry', 'get'), $vars[1]);
  $template = str_replace($vars[0], $values, $template);
}
echo $template;

ამ კოდის შესრულების შედეგად მივიღებთ უკვე დამუშავებულ შედეგს:

<ul>
    <li><strong> UTF-8 </strong></li>
    <li><strong> http://www.code.ge </strong></li>
    <li><strong> Test Variable </strong></li>
    <li><strong>  </strong></li>
 </ul>

როგორ მუშაობს ეს კოდი:

  1. preg_match_all ფუნქციის და რეგულარული გამოსახულების მეშვეობით ვპოულობთ ყველა საჭირო ფრაგმენტს;
  2. array_map ფუნქციის მეშვეობით ვამზადებთ მნიშვნელობების მასივს. თუმცა ამ ფუნქციის მუშაობა უფრო დეტალურ განხილვას ითხოვს.

    ამ ფუნქცის პირველი პარამეტრი არის ე.წ. callback ტიპის. თავისთავად callback PHP – ში წარმოადგენს რთულ ტიპს, ნებისმიერი ფუნქცია რომელიც ღებულობს ამ ტიპის პარამეტრს, შეგვიძლია გადავცეთ ნებისმიერი ფუნქციის სახელი, მაგ: array_map(‘trim’). მასივის მეშვეობით შეგვიძლია გადავცეთ კლასის სახელი და კლასის მეთოდი, მაგ: array_map(array(‘Registry’, ‘get’)) სადაც Registry არის კლასის სახელი, ხოლო get სტატიკური მეთოდის სახელი, და ასევე შეგვიძლია მასივის მეშვეობით გადავცეთ ნებისმიერი კლასის ობიექტი და მეთოდის სახელი, მაგ: array_map(array(new MyClass, ‘myMethod’)).

    მეორე პარამეტრად კი მას გადაეცემა მასივი. ეს ფუნქცია მასივის ყოველ ელემენტს გადასცემს callback ფუნქციას/მეთოდს ხოლო ამ მნიშვნელობას ჩაანაცვლებს callback ფუნქციის მიერ დაბრუნებული მნიშვნელობით. საბოლოო ჯამში კი მივიღებთ მასივს ჩვენი სურვილის მიხედვით დამუშავებული მნიშვნელობებით.

    სწორედ ამ ფუნქციის მეშვეობით ვიღებთ Registry კლასიდან ჩვენთვის საჭირო მნიშვნელობებს (რამდენადაც get მეთოდს გადაეცემა $vars მასივის პირველი ელემენტის სათითაო ელემენტი იგი დაგვიბრუნებს შესაბამის მნიშვნელობას ამ key – სთვის, თუ ასეთი არსებობს) და ვანიჭებთ მის მიერ დაბრუნებულ მასივს $values ცვლადს.

  3. str_replace ფუნქციის მეშვეობით ვახორციელებთ საჭირო ფრაგმენტების ჩანაცვლებას მოპოვებული მნიშვნელობებით. ამ ფუნქციას პირველ პარამეტრად გადავცემთ ჩასანაცვლებელი ფრაგმენტების მასივს ($vars[0] მასივი) და მეორე პარამეტრად გადავცმეთ საბოლოო მნიშვნელობებს (array_map – ის მეშვეობით მოვპოვებული $values მასივი), ხოლო მესამე პარამეტრად დაუმუშავებელ შაბლონს, შედეგად ვღებულობთ უკვე დამუშავებულ ტექსტს.

შედეგად მივიღეთ ძალიან მარტივი, სწრაფი და ეფექტური გადაწყვეტა ყოველგვარი ზედმეტი იტერაციებისა და დამატებითი არასაჭირო ოპერაციების გარეშე.

ტეგები: ,

დატოვე კომენტარი:

ქართული კლავიატურა, ჩართვა/გამორთვა კლავიშით "~"