Ankündigung

Einklappen
Keine Ankündigung bisher.

PHP Stream Implementierung

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • PHP Stream Implementierung

    Hallo,

    ich habe vor einiger Zeit eine kleine Bibliothek zum Streamen von PHP Arrays entwickelt. Ich bin momentan dabei die Bibliothek zu überarbeiten. Habt ihr Vorschläge oder Kritikpunkte? Der Link zum Blogartikel: https://fetzi.io/list-streaming-implementation-for-php/

    Lg & danke,
    Johannes

  • #2
    About 2 months ago I released a*Java like Stream*library because I was very bugged by code for iterating over PHP arrays and do some stuff with the actual data.
    Kleiner Tipp: Java Streams sind Monads. Das was du da baust, sind convenience-filter-functions. In PHP wären am ehesten Generatoren (yield) mit den Streams von Java8 vergleichbar.

    Ich sehe zwar den Sinn bei sowas nicht, denn derartige Filter gibt es abhängigkeitsfrei bereits in PHP. Ich wünsche dir auf jeden Fall viel Erfolg bei dem Projekt.

    Kann man die Listen auch ohne statische Fassade erzeugen? Um es mit den Worten von Tim Cook zu sagen: Statische Fassaden sind der neue Krebs

    Kommentar


    • #3
      Hi,

      interessante Sache - ich hab mir eine ähnliche Klasse geschrieben. Was du vielleicht berücksichtigen/nachimplementieren könntest:
      * uasort()
      * slice()
      * Verwendung eines Indexers
      * Beschränkung auf bestimmte Array-Elemente (instanceof-Check)
      * Immutable-Flag - ich gebe bei filter(), uasort() usw. immer eine frische Instanz zurück und manipuliere nicht die existierende

      Der Indexer war bei mir der entscheidende Punkt, durch den ich erst einen echten Mehrwert hatte.

      PHP-Code:
      <?php
      $users 
      = new UserList();
      $users->setIndexer(new UserIdIndexer());
      $users->append(new User(array('id' => 1'email' => 'foo@bar.com''name' => 'Foobar')));
      $users->append(new Other()); // Exception
      $users->append(new User(array('id' => 2'email' => 'bar@foo.com''name' => 'Barfoo')));

      echo 
      $users->get(1)->getName(); // Foobar

      $users->setIndexer(new UserEmailIndexer());

      echo 
      $users->get('foo@bar.com')->getName(); // Foobar

      $userIds $users->getIds();
      $allFriends $manager->getList(array('id' => $userIds));
      $allFriends->setIndexer(new UserIdIndexer()); // elements must implement UserAwareInterface or be integer

      foreach ($users as $user) {
        
      $friends $allFriends->get($user);
        echo 
      '<h1>'$user->getName(), '</h1>';
        echo 
      $friends->implode(', '); // implode() hab ich allerdings nicht implementiert
      }
      ?>
      Grade bei Verknüpfungstabellen (z.B. user_has_friends) sehr hilfreich, da kann sich die "Richtung" aus der ich zugreifen ja ändern (will ich über die user-ID oder friend-ID auf die Inhalte der Liste zugreifen). Hier mal mein Code, vielleicht kannst ja was von gebrauchen als Idee.
      PHP-Code:
      <?php
      <?php
      namespace MyNamespace\Util;

      use 
      MyNamespace\Util\Indexer\IndexerInterface;

      abstract class 
      AbstractList implements \IteratorAggregate, \Countable
      {
          protected 
      $elements = array();
          protected 
      $indexer;

          public function 
      __clone()
          {
              if (
      $this->indexer !== null) {
                  
      $this->indexer = clone $this->indexer;
              }
          }

          public function 
      getIterator()
          {
              return new \
      ArrayIterator($this->elements);
          }

          public function 
      count()
          {
              return 
      count($this->elements);
          }

          public function 
      append($element)
          {
              
      $this->check($element);
              
      $index $this->index($element);
              
      $this->elements[$index] = $element;
          }

          public function 
      get($element)
          {
              
      $index $this->index($element);
              if (!
      array_key_exists($index$this->elements)) {
                  throw new \
      RuntimeException(sprintf('List index [%s] not found'$index));
              }
              return 
      $this->elements[$index];
          }

          public function 
      has($element)
          {
              
      $index $this->index($element);
              return 
      array_key_exists($index$this->elements);
          }

          public function 
      getIndexer()
          {
              if (
      $this->indexer === null) {
                  
      $this->indexer $this->getDefaultIndexer();
              }
              return 
      $this->indexer;
          }

          public function 
      setIndexer(IndexerInterface $indexer)
          {
              
      $this->indexer $indexer;

              
      $elements = array();
              foreach (
      $this as $element) {
                  
      $index $this->index($element);
                  
      $elements[$index] = $element;
              }
              
      $this->elements $elements;
          }

          public function 
      slice($offset$length null)
          {
              
      $elements = new static();
              
      $elements->setIndexer($this->getIndexer());
              foreach (
      call_user_func_array('array_slice'array_merge(array($this->elements), func_get_args())) as $element) {
                  
      $elements->append($element);
              }
              return 
      $elements;
          }

          public function 
      first()
          {
              foreach (
      $this as $element) {
                  return 
      $element;
              }
              throw new \
      RuntimeException('Could not retrieve first element; list is empty');
          }

          public function 
      merge($others)
          {
              if (!
      $others instanceof \Traversable && !is_array($others)) {
                  throw new \
      InvalidArgumentException('Can not merge non-traversable object');
              }
              
      $elements = new static();
              
      $elements->setIndexer($this->getIndexer());
              foreach (
      $this as $element) {
                  
      $elements->append($element);
              }
              foreach (
      $others as $element) {
                  
      $elements->append($element);
              }
              return 
      $elements;
          }


          public function 
      reverse()
          {
              
      $elements = new static();
              
      $elements->setIndexer($this->getIndexer());
              foreach (
      array_reverse($this->elements) as $element) {
                  
      $elements->append($element);
              }
              return 
      $elements;
          }

          public function 
      filter($callback)
          {
              
      $elements = new static();
              
      $elements->setIndexer($this->getIndexer());
              foreach (
      array_filter($this->elements$callback) as $element) {
                  
      $elements->append($element);
              }
              return 
      $elements;
          }

          public function 
      map($callback)
          {
              return 
      array_map($callback$this->elements);
          }
          
          public function 
      clear()
          {
              
      $this->elements = array();
          }

          abstract protected function 
      is($element);
          abstract protected function 
      getDefaultIndexer();

          protected function 
      index($element)
          {
              
      $indexer $this->getIndexer();
              
      $index $indexer->index($element);
              return 
      $index;
          }

          protected function 
      uasort($callback)
          {
              
      $data $this->elements;
              
      uasort($data$callback);

              
      $elements = new static();
              
      $elements->setIndexer($this->getIndexer());
              foreach (
      $data as $element) {
                  
      $elements->append($element);
              }
              return 
      $elements;
          }

          protected function 
      check($element)
          {
              if (!
      $this->is($element)) {
                  
      $type is_object($element) ? get_class($element) : gettype($element);
                  throw new \
      InvalidArgumentException(sprintf('Invalid list element [%s]'$type));
              }
          }

      }
      ?>
      Weitere Klassen wären dann in etwa:
      PHP-Code:
      <?php
      interface UserAwareInterface {
        public function 
      hasUserId();
        public function 
      getUserId();
      }
      class 
      User extends \ArrayObject implements UserAwareInterface {
        
      // ..
      }
      class 
      UserList extends AbstractList {
        protected function 
      is($element) { return $element instanceof User; }
        protected function 
      getDefaultIndexer() { return new UserIdIndexer(); }
      }
      class 
      UserIdIndexer implements MyNamespace\Util\Indexer\IndexerInterface {
        public function 
      index($element) {
          if (
      $element instanceof UserAwareInterface) {
            return 
      $element->getUserId();
          }
          return (int)(string)
      $element;
      }
      ?>
      Du legst deinen Fokus wohl eher auf skalare Array-Elemente .. da sehe ich kaum Mehrwert, weil die kann ich ja direkt mit den array_*-Funktionen selbst verarbeiten. Der Mehrwert entsteht - zumindest meiner Meinung nach - eher wenn du Objekt-Listen behandelst.

      Gruß,
      Chriz
      "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

      Kommentar

      Lädt...
      X