Skip to content

Instantly share code, notes, and snippets.

@tzkmx
Created October 3, 2015 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tzkmx/a4456b831dbfeb91b2d9 to your computer and use it in GitHub Desktop.
Save tzkmx/a4456b831dbfeb91b2d9 to your computer and use it in GitHub Desktop.
Mixing Stream Wrappers & filters to create custom and lightweight views of database
<?php
/**
* @author Jesus Franco Martinez <jefrancomix@gmail.com>
*/
class DBStream {
/**
*
* @var mysqli
*/
private $mysql;
/**
*
* @var mysqli_stmt
*/
private $stmt;
private $position = 0;
private $size = 0;
/**
*
* @var mysqli_result
*/
private $result;
/*
public function __construct()
{
return true;
}
*
*/
public function stream_open($path, $mode, $options, &$opath)
{
$url = parse_url($path);
$url['path'] = array_slice(split('/', substr($url['path'], 1)), 0, 2);
//echo '<pre>', print_r($url, false), '</pre>';
$this->mysql = new mysqli(DB_HOST, DB_USER, DB_PASS, $url['path'][0], DB_PORT);
if ($this->mysql->connect_errno) {
throw new Exception($this->mysql->connect_error, $this->mysql->connect_errno);
}
switch ($mode){
case 'r' :
$this->result = $this->mysql->query('SELECT * FROM ' . implode('.', $url['path']));
if ('mysqli_result' !== get_class($this->result)) {
$e = $this->mysql->error_list;
array_push($e, 'Unable to get data from: ' . implode('.', $url['path']));
throw new Exception(implode("\n", $e), $this->mysql->errno);
}
$this->size = $this->result->num_rows;
break;
default : return false;
}
return true;
}
public function stream_read()
{
$out = $this->result->fetch_row();
$this->position++;
return implode(';;;', $out);
}
public function stream_tell()
{
return $this->position;
}
public function stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset < $this->size) {
$this->position = $offset;
$this->result->data_seek($offset);
}
break;
case SEEK_CUR:
if ($offset >= 0) {
$this->position += $offset;
$this->result->data_seek($this->position);
return true;
} else {
return false;
}
break;
case SEEK_END:
if (($this->size + $offset) >= 0) {
$this->position += $offset;
$this->result->data_seek($this->position);
return true;
} else {
return false;
}
break;
default:
return false;
}
}
public function stream_eof()
{
return ($this->position >= $this->size);
}
public function stream_close()
{
$this->result->free();
$this->mysql->close();
}
public function stream_stat()
{
$moment = time();
return array(
0 => 0,
1 => 0,
2 => 0666,
3 => 0,
4 => 0,
5 => 0,
6 => 2,
7 => $this->size,
8 => $moment,
9 => $moment,
10 => $moment,
11 => -1,
12 => -1,
'dev' => 0,
'ino' => 0,
'mode' => 0666,
'nlink' => 0,
'uid' => 0,
'gid' => 0,
'rdev' => 0,
'size' => $this->size,
'atime' => $moment,
'mtime' => $moment,
'ctime' => $moment,
'blksize' => -1,
'blocks' => -1,
);
}
}
<?php
require 'bootstrap.php';
?>
<html>
<body>
<?php
stream_register_wrapper('db', 'DBStream', STREAM_IS_URL);
stream_filter_register('prewrap', 'WrapperFilter');
try {
$fr=fopen('php://filter/read=prewrap/resource=db://user:pass@host/schema/table','r');
echo stream_get_contents($fr);
fclose($fr);
} catch (Exception $e) {
echo $e->getCode() , ': ' , $e->getMessage();
echo $e->getTraceAsString();
}
?>
</body>
</html>
<?php
/**
* Description of WrapperFilter
*
* @author Jesus Franco Martinez <jefrancomix@gmail.com>
*/
class WrapperFilter extends php_user_filter {
private $rows = 0;
protected function wrapCell($item)
{
return '<td>' . $item . '</td>';
}
public function filter($in, $out, &$consumed, $closing) {
while ($bucket = stream_bucket_make_writeable($in)) {
//$d = ($this->rows === 0) ? 'HEADER TEXT' : '';
$d = array_map(array($this, 'wrapCell'), split(';;;', $bucket->data));
$bucket->data = '<tr id="' . $this->rows++ . '">' . implode('', $d) . '</tr>';
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
public function onClose() {
echo '</table>';
parent::onClose();
}
public function onCreate() {
echo '<table>';
parent::onCreate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment