Skip to content
Standard library for php
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib
src
tools
LICENSE
README.md
build.php
composer.json
test.php
test.sh

README.md

stdphp

Standard library for php.

php is not my primary language, but when I use it occasionally, I always miss a consistent standard library. Therefore I've created this one for my needs.

stdphp provides a set of basic classes and utility functions. It's mostly modeled after python, with some additions from javascript and ruby.

###Show Me What You Got

Some examples of what stdphp looks like.

#####Sort words in a string

print str('foo bar baz')->split()->map('strtoupper')->sort()->join(','); /// BAR,BAZ,FOO

#####Unicode fun

$str = str('Gänsefüßchen');
print count($str);           /// 12
print $str['5:8'];           /// 'füß'
print $str->upper();         /// 'GÄNSEFÜßCHEN'

#####Remove duplicates from a list

$dupes = [4,1,3,2,4,1,4,2,3,3,1,2];
print set($dupes); /// [4,1,3,2]

#####Sum every second number

$numbers = a(0,11,22,33,44,55,66,77,88,99);
print $numbers['::2']->reduce(operator('+')); /// 220

#####FizzBuzz

$x = lst(xrange(31));

$x['::3']  = repeat('Fizz');
$x['::5']  = repeat('Buzz');
$x['::15'] = repeat('FizzBuzz');

print $x['1:']; /// [1,2,"Fizz",4,"Buzz","Fizz",7,8,"Fizz","Buzz",11,"Fizz",13,14,"FizzBuzz",16,17,"Fizz",19,"Buzz","Fizz",22,23,"Fizz","Buzz",26,"Fizz",28,29,"FizzBuzz"]

#####Chunkify a list

If you know python, this is zip(*[iter(xs)]*n):

$a = [1,2,3,11,22,33,101,102,103];
print lst(zipargs(repeat(iter($a), 3))); /// [[1,2,3],[11,22,33],[101,102,103]]

###Usage

The whole library is one single php file, std.php:

include 'std.php';

$someList = lst("abc");

There's also a "local" version stdl.php, which keeps stdphp functions namespaced:

include 'stdl.php';

$someList = std\lst("abc");

stdphp requires php 5.4+

###Features

####Constructor functions

Objects, like strings or lists, are created using "constructor functions" rather than new + class name:

$someList   = lst([1,2,3]);
$someString = str("abc");

This has two advantages: conciseness and ability to override default classes with inherited ones:

class MyList extends std\Lst
{
    function myNewMethod() { return $this->join(' me '); }
}

std\_setclass('Lst', 'MyList');

// now, all library functions that return a list, will return MyList:

print str('foo bar')->split()->myNewMethod(); /// foo me bar

####Iterables and iterators

stdphp follows the pythonic concept of "iterables". Functions that iterate through their arguments don't enforce a particular type. Therefore you can pass any "iterable", including stdphp objects, native php arrays and strings, and generic Traversable objects:

$a = a(0,1,2,3);
$b = "abcd";
$c = array(9,8,7,6);

print lst(zip($a, $b, $c)); /// [[0,"a",9],[1,"b",8],[2,"c",7],[3,"d",6]]

There are several built-in iterator constructors for different purposes:

  • filter
  • map
  • repeat
  • xrange
  • zip

The following creates a "lazy" list of palindromic numbers. Since filter, map and xrange are iterators, this list uses constant memory:

$xs = filter(
    function($s) { return $s == $s['::-1']; },
    map('str',
        xrange(300000)));

Another example is an "endless" repeat iterator that plays nicely with zip:

print lst(zip('abcd', repeat('-'))); /// [["a","-"],["b","-"],["c","-"],["d","-"]]

####Mapping and higher-order functions

The higher-order function getter returns a closure that picks an item from a string or associative array.

// fetch the 2nd char from each string:

print a('ab','cd','ef')->map(getter(1)); /// ["b","d","f"]

getter (alias by) is especially useful with sort, which, like in python, uses a functional key argument to extract a comparison key.

$popularNames = [
     ['name' => 'Alfie'   ,'rank' => 7],
     ['name' => 'Charlie' ,'rank' => 4],
     ['name' => 'Harry'   ,'rank' => 1],
     ['name' => 'Jack'    ,'rank' => 3],
     ['name' => 'Jacob'   ,'rank' => 5],
     ['name' => 'Oliver'  ,'rank' => 2],
     ['name' => 'Riley'   ,'rank' => 8],
     ['name' => 'Thomas'  ,'rank' => 6],
     ['name' => 'William' ,'rank' => 9]
];

// print top 3 names by rank

print lst($popularNames)->sort(by('rank'))->map(getter('name'))->get(':3'); /// ["Harry","Oliver","Jack"]

Similarly, attr picks an attribute from an object argument:

class User {
    function __construct($name) {
        $this->name = $name;
    }
}

$a = [new User("Harry"), new User("Oliver"), new User("Jack")];
print lst($a)->map(attr('name'))->join(','); /// Harry,Oliver,Jack

method creates a closure that calls a specific method on the argument:

// call `String::reverse` on each element:

print s("Hello Foo Bar")->split()->map(method('reverse')); /// ["olleH","ooF","raB"]

###stdphp classes

Here's a brief overview, for a complete list of methods refer to the API documentation.

####List

Lists are created using constructors a() or lst() and provide the usual repertoire of methods:

print a('foo', 'bar', 'baz')->map('strtoupper')->join('-'); /// FOO-BAR-BAZ

Lists support python-alike slicing:

$a = a(0,1,2,3,4,5,6,7);
print $a[-3];     /// 5
print $a['1::3']; /// [1,4,7]

and slice assignments:

$a = a(0,1,2,3,4,5);
$a['2:4'] = 'abcd';
print $a; /// [0,1,"a","b","c","d",4,5]

####String

Strings are unicode-aware (source encoding is assumed to be utf8, unless specified otherwise):

$a = s('fuß');
print count($a); /// 3

$b = s("fu\xDF", 'latin1');
$a == $b; /// true

Slicing works too, but not slice assignments: strings are immutable! Note: mb extension is required for encoding and case conversions.

####Dict

Dicts are associative arrays. There are several dict constructors:

print d('a', 1, 'b', 2);            /// {"a":1,"b":2}
print dict(['a' => 1, 'b' => 2]);   /// {"a":1,"b":2}
print pairdict([['a',1], ['b',2]]); /// {"a":1,"b":2}
print keydict('abc', 42);           /// {"a":42,"b":42,"c":42}

In addition to standard pythonic methods, dicts can be also mapped and filtered:

$a = dict(['a'=>'foo', 'b'=>'bar']);
print $a->map('strtoupper'); /// {"a":"FOO","b":"BAR"}

####Set

Sets are just like python sets:

$a = set([1,2,3,4,5]);
print $a->intersection([5,3,9,1]); /// [1,3,5]

####Re

re creates a regular expression object. Unlike php, delimiters are not required, and flags can be passed as a second argument:

$r = re('[a-z]+', 'i');
print $r->sub('*', 'a1B2c3'); /// *1*2*3

find and findall return strings:

print re('[a-z]+')->findall('ab cd ef'); /// ["ab","cd","ef"]

match and matchall return "match objects":

print re('([a-z]+)(\d+)')->match('abc123')->group(2); /// 123

###Build system

std.php is generated from the src directory using small c-alike preprocessor CPP (in tools dir). doxytest runs tests which are embedded in the code and enclosed in @code...@endcode or @test...@endtest.

###Todos

  • wrappers for all php array/string functions
  • iterable files and streams, as in foreach (textfile('foo.txt', 'utf8')) as $line)...
  • itertools methods like product or combinations
You can’t perform that action at this time.