Warm greetings! This lesson introduces data streams, which are essentially continuous datasets. Imagine monitoring a weather station or a gaming application that gathers data per second — both generate data streams! We will master handling these data streams using PHP, learning how to access elements, slice segments, and even convert these streams into strings for easier handling.
In PHP, data streams can be represented using arrays and associative arrays. Let’s consider a straightforward PHP class named DataStream
. This class encapsulates operations related to data streams in our program:
php1<?php 2 3class DataStream { 4 private $data; 5 6 public function __construct(array $data) { 7 $this->data = $data; 8 } 9}
To use it, we create a sample data stream as an instance of our DataStream
class, where each element is an associative array:
php1$data = [ 2 ["id" => 1, "value" => 100], 3 ["id" => 2, "value" => 200], 4 ["id" => 3, "value" => 300], 5 ["id" => 4, "value" => 400], 6]; 7$stream = new DataStream($data);
To look into individual elements of a data stream, we use indexing. The get()
method we introduce below fetches the i+1
-th element from the data stream:
php1<?php 2 3class DataStream { 4 private $data; 5 6 public function __construct(array $data) { 7 $this->data = $data; 8 } 9 10 public function get(int $i): array { 11 if ($i < 0) { 12 $i += count($this->data); 13 } 14 if ($i >= 0 && $i < count($this->data)) { 15 return $this->data[$i]; 16 } else { 17 throw new OutOfRangeException("Index out of range"); 18 } 19 } 20}
Here, we can see the get()
method in action:
php1<?php 2 3$data = [ 4 ["id" => 1, "value" => 100], 5 ["id" => 2, "value" => 200], 6 ["id" => 3, "value" => 300], 7 ["id" => 4, "value" => 400], 8]; 9$stream = new DataStream($data); 10 11try { 12 $elem = $stream->get(2); 13 echo "id: " . $elem["id"] . ", value: " . $elem["value"] . "\n"; 14 15 $elem = $stream->get(-1); 16 echo "id: " . $elem["id"] . ", value: " . $elem["value"] . "\n"; 17} catch (OutOfRangeException $e) { 18 echo $e->getMessage() . "\n"; 19}
In essence, $stream->get(2)
fetched us ["id" => 3, "value" => 300]
— the third element (since indexing starts from 0
). Meanwhile, $stream->get(-1)
fetches the last element, which is ["id" => 4, "value" => 400]
.
The code snippet if ($i < 0) { $i += count($this->data); }
allows negative indexing by converting a negative index into the corresponding positive index, effectively letting -1
refer to the last element, -2
to the second last, and so on. This approach is useful for accessing elements from the end of the data stream efficiently.
Fetching a range of elements rather than a single one is facilitated by slicing. We introduce a slice()
method to support slicing:
php1<?php 2 3class DataStream { 4 private $data; 5 6 public function __construct(array $data) { 7 $this->data = $data; 8 } 9 10 public function get(int $i): array { 11 if ($i < 0) { 12 $i += count($this->data); 13 } 14 if ($i >= 0 && $i < count($this->data)) { 15 return $this->data[$i]; 16 } else { 17 throw new OutOfRangeException("Index out of range"); 18 } 19 } 20 21 public function slice(int $i, int $j): array { 22 if ($i < 0) { 23 $i += count($this->data); 24 } 25 if ($j < 0) { 26 $j += count($this->data); 27 } 28 if ($i >= 0 && $j <= count($this->data) && $i < $j) { 29 return array_slice($this->data, $i, $j - $i); 30 } else { 31 throw new OutOfRangeException("Slice indices out of range"); 32 } 33 } 34}
Here's a quick usage example:
php1<?php 2 3$data = [ 4 ["id" => 1, "value" => 100], 5 ["id" => 2, "value" => 200], 6 ["id" => 3, "value" => 300], 7 ["id" => 4, "value" => 400], 8]; 9$stream = new DataStream($data); 10 11try { 12 $slice = $stream->slice(1, 3); 13 foreach ($slice as $elem) { 14 echo "id: " . $elem["id"] . ", value: " . $elem["value"] . "\n"; 15 } 16} catch (OutOfRangeException $e) { 17 echo $e->getMessage() . "\n"; 18}
For better readability, we may wish to convert our data streams into strings. To ensure the conversion works consistently, we will create a custom string representation for our data elements. Have a look at the toString()
method in action:
php1<?php 2 3class DataStream { 4 private $data; 5 6 public function __construct(array $data) { 7 $this->data = $data; 8 } 9 10 public function get(int $i): array { 11 if ($i < 0) { 12 $i += count($this->data); 13 } 14 if ($i >= 0 && $i < count($this->data)) { 15 return $this->data[$i]; 16 } else { 17 throw new OutOfRangeException("Index out of range"); 18 } 19 } 20 21 public function slice(int $i, int $j): array { 22 if ($i < 0) { 23 $i += count($this->data); 24 } 25 if ($j < 0) { 26 $j += count($this->data); 27 } 28 if ($i >= 0 && $j <= count($this->data) && $i < $j) { 29 return array_slice($this->data, $i, $j - $i); 30 } else { 31 throw new OutOfRangeException("Slice indices out of range"); 32 } 33 } 34 35 public function toString(): string { 36 $elements = array_map(function($item) { 37 return json_encode($item); 38 }, $this->data); 39 return '[' . implode(', ', $elements) . ']'; 40 } 41}
To see it in action:
php1<?php 2 3$data = [ 4 ["id" => 1, "value" => 100], 5 ["id" => 2, "value" => 200], 6 ["id" => 3, "value" => 300], 7 ["id" => 4, "value" => 400], 8]; 9$stream = new DataStream($data); 10 11echo $stream->toString();
It prints: [{"id":1,"value":100}, {"id":2,"value":200}, {"id":3,"value":300}, {"id":4,"value":400}]
.
In this lesson, we've explored data streams, discovered how to represent and manipulate them using PHP arrays and associative arrays, and encapsulated operations on data streams with PHP classes. Now, it’s your turn to apply your newfound knowledge in the practice exercises that follow!