ФорумПрограммированиеPHP для идиотов → Пилят втишь

Пилят втишь

  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 19:49

    
    class A {
      function run($fn){
        return $fn();
      }
    }
    
    class B {
      function foo(){
        $a = new A;
        return $a->run(function(){ return "I am ".get_class($this).", bar() return ".$this->bar(); });
      }
    
      function bar(){
        return 'bar';
      }
    }
    
    $b = new B;
    print $b->foo();
    

    вернёт "I am B, bar() return bar"

    То есть, анонимные функции выполняются в контексте, где были объявлены. Для пхп это значительный прогресс, просто, я бы сказал, ебической силы рывок вперёд. Теперь можно писать нормальные фреймворки.

    Проверено в 7.0.6

    не всё полезно, что в swap полезло
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 20:04, спустя 14 минут 43 секунды

    И ещё, можно выполнить анонимную лямбду в контексте любого объекта:

    
    class A {
      function foo(){
        return 'foo_a';
      }
    }
    
    class B {
      function foo(){
        return 'foo_b';
      }
    }
    
    $a = new A;
    $b = new B;
    
    $fn = function($arg){ return get_class($this). ' ' . $this->foo().' '.$arg; };
    
    print $fn->call($a, 'str1')."<br>\n";
    print $fn->call($b, 'str2');
    

    вернёт
    A foo_a str1
    B foo_b str2

    Описано здесь PHP: New features - Manual [php.net] , в разделе Closure::call()

    не всё полезно, что в swap полезло
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 20:52, спустя 48 минут 32 секунды

    
    /// Declare mini-framework skeleton
    
    class Model {
      var $id, $data;
      function __construct($id){
        $this->id = $id;
      }
    
      function name(){
        return $this->data['name'];
      }
    }
    
    class Dataset {
      static function get($id){
        $mock_data = [
          123 => ['name' => 'Vasya Pupkin'],
          456 => ['name' => 'Petya Zalupkin'],
        ];
        $model_obj = new Model($id);
        $model_obj->data = $mock_data[$id];
        return $model_obj;
      }
    }
    
    class Transform {
      function up($arg){
        return strtoupper($arg);
      }
    
      function down($arg){
        return strtolower($arg);
      }
    }
    
    class Cache {
      private static $instance = null;
      protected $data = [];
    
      function try($key, $fn){
        if (!array_key_exists($key, $this->data)){
          $this->data[$key] = $fn();
        }
        return $this->data[$key];
      }
    
      static function instance(){
        if (is_null(self::$instance)){
          self::$instance = new self;
        }
        return self::$instance;
      }
    }
    
    class Context {
      function __construct(){
        $this->transform = new Transform;
        $this->cache = Cache::instance();
      }
    
      function with_cache($key, $fn){
        return $this->cache->try($key, $fn);
      }
    }
    
    
    //// Define actions
    
    $foo = function(){
      $item = Dataset::get(123);
      $name = $this->cache->try(123,
        function() use($item) {
          return $this->transform->up($item->name());
        }
      );
      return $name;
    };
    
    $bar = function(){
      $item = Dataset::get(456);
      $this->with_cache(456,
        function() use($item, &$name) {
          return $name = $this->transform->down($item->name());
        }
      );
      return $name;
    };
    
    
    //// Imitate HTTP queries
    
    print $foo->call(new Context)."<br>\n"; // some request
    print $bar->call(new Context)."<br>\n"; // other request
    
    
    //// Dump shared object
    
    print_r(Cache::instance());
    

    вернёт:

    VASYA PUPKIN
    petya zalupkin
    Cache Object ( [data:protected] => Array ( [123] => VASYA PUPKIN [456] => petya zalupkin ) )

    То есть,
    - описываем экшны в форме анонимных функций, не привязанных к какому-либо классу
    - выполняем их каждую в изолированном контексте. В пхп в принципе не актуально, но для standalone-приложений необходимо
    - легко и естественно работаем с shared-объектами, передавая им в лямбдах тот же, какой использовали бы и без них (пример с кэшем, не используем многословную схему if ($cache->exists()){ ...get_cache... } else { ...create_value... ...save_value... }).

    не всё полезно, что в swap полезло
  • kostyl

    Сообщения: 5210 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 21:56, спустя 1 час 3 минуты 20 секунд

    Круто, только поздновато ))

  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 22:17, спустя 21 минуту 1 секунду

    @kostyl, что, интернет умирает?

    не всё полезно, что в swap полезло
  • kostyl

    Сообщения: 5210 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 22:39, спустя 21 минуту 47 секунд

    @kostyl, что, интернет умирает?

    @master, нет, я думаю что кто не успевает, тот отстаёт, а кто отстаёт, тот не успевает

  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 9 мая 2016 г. 22:44, спустя 5 минут 45 секунд

    @kostyl, кто куда не успевает?

    не всё полезно, что в swap полезло
  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 10 мая 2016 г. 20:25, спустя 21 час 40 минут 47 секунд

    Вот ещё. Не описано, но весьма упрощает жизнь. null[] возвращает null:

    
    error_reporting(E_ALL);
    $a = null;
    $b = $a[1];
    var_export($b);
    

    покажет NULL

    Появилось в 5.6

    не всё полезно, что в swap полезло
  • Sinkler

    Сообщения: 7958 Репутация: N Группа: в ухо

    Spritz 10 мая 2016 г. 20:43, спустя 17 минут 28 секунд

    а вот это весьма спорное удобство

    если ты берёшь элемент из чего-то, то ожидаешь, что это массив (или что-то, у чего можно взять элемент)

    со-но, если там не массив, то с большой вероятностью тут может быть логическая ошибка и лучше бы выкидывать эксепшн

  • master

    Сообщения: 3244 Репутация: N Группа: Джедаи

    Spritz 10 мая 2016 г. 23:38, спустя 2 часа 55 минут 9 секунд

    @Sinkler, если ты ожидаешь эксепшн - то можно вручную проверить на is_array и array_key_exists

    не всё полезно, что в swap полезло

Пожалуйста, авторизуйтесь, чтобы написать комментарий!