Core functions and classes
The core module contains all basic routines offered by Anewt.
This module is loaded by default upon when Anewt is initialized.
Most functions are related to strings and arrays. The widely used
AnewtContainer object is in the
core module as well. Additionally, some other useful functions are
provided. This chapter only covers the basic functionality offered
by the core module; see the API documentation and the source code
(quite readable and pretty well documented, really) for a full
reference.
PHP itself offers a lot of string utility functions, but some
commonly used string logic routines are not
implemented as simple, separarate functions. Often, this leads to
duplication of (often simple but boring) micro-routines. A good
example of this is the
str_contains()
function that checks whether a string contains a given substring.
Of course you could also have used
strpos()
directly, but since this function can return both integers and
boolean false, some care has to be taken every
time you need this functionality. That's why Anewt provides you
with a str_contains() function that hides
these tiny details from view, so that you can concentrate on the
meaning of your own code, instead of fiddling with PHP internals.
A second example of this is
str_is_whitespace().
Of course you could've used (strlen(trim($str)) == 0),
but once again: using meaningful functions keeps your code
maintainable.
Several functions are provided to deal with string
prefixes and suffixes. The names speak for
themselves: str_has_prefix(),
str_has_whitespace_prefix(),
str_has_suffix(),
str_has_whitespace_suffix(),
str_strip_suffix(), and
str_strip_prefix(). See the API reference for
more information.
A useful string truncation routine,
str_truncate(), is provided to cut off
strings at a given length. This is very useful if you want to
display overview pages with only a certain number of characters
instead of the whole bunch of text.
Some other functions let you deal with arrays of strings
easily:
str_first_non_white() and
str_all_non_white(). Once again, the names
speak for themselves.
The array functions offered by Anewt are written in the same spirit as the string functions outlined in the previous section. PHP itself has a lot of array related functions. Anewt tries to fill in the missing pieces to make arrays a pleasure to deal with.
PHP makes no difference between lists and hashes. Lists are
simply lists of values (called numerical arrays in PHP), while
hashes (also known as dictionaries or hash tables, called
associative arrays in PHP) contain key/value pairs. Lists in PHP
are implemented as hashes with numerical keys, while hashes use
string keys. The values can be of any type. The built-in
is_array() cannot be used to differentiate
between these types. Anewt offers
is_numeric_array() and
is_assoc_array() functions to do this for
you.
PHP allows you to mix lists and hashes by using both integer and string keys in the same array. You are strongly discouraged to do this. It makes your code a mess!
The function
array_get_default() is
useful to get a value from an array, providing a default value if
the given key was not present in the array. Use this function to
to get values from arrays with optional configuration data (e.g.
config files). This saves you from a lot of checking code, as the
example below shows:
Example 1: Retrieving data (providing default values) from arrays
// Sample array data, included from a configuration file: $user_data = array( 'firstname' => 'John', 'lastname' => 'Doe', 'age' => 34); // Now assume that the 'firstname' and age fields in the // above data are optional and should default to an empty // string and the number 0 if omitted. // Look at this ugly piece of code: $firstname = ''; if (array_key_exists('firstname', $user_data)) { $firstname = $user_data['firstname']; } $age = 0; if (array_key_exists('age', $user_data)) { $age = $user_data['age']; } // This is a bit shorter, but still really ugly: $firstname = array_key_exists('firstname', $user_data) ? $user_data['firstname'] : ''; $age = array_key_exists('age', $user_data) ? $user_data['age'] : 0; // Things get so much better with Anewt: $firstname = array_get_default($user_data, 'firstname', ''); $age = array_get_default($user_data, 'age', 0);
The function
array_set_default() is
similar to
array_get_default(), setting
values in arrays if no value was set before:
Example 2: Setting default values in arrays
// If you want to augment the $user_data array by providing // defaults for missing values, this piece of code suffices: array_set_default($user_data, 'firstname', ''); array_set_default($user_data, 'age', 0); // Now you are sure all keys can be safely accessed (without // generating PHP warnings): do_something_useful($user_data['firstname'], $user_data['lastname'], $user_data['age']);
Anewt also provides a method to nicely format an array as a
string: array_format(). Other routines allow
you to retrieve certain data types from arrays:
array_get_int() and
array_get_bool(). Several other methods are
provided, but not described in this section. See the API reference
for more information.
The AnewtContainer class is one
of the most useful classes provided by Anewt. It allows you to
implement flexible and extensible data objects. The
AnewtContainer class is intended to
be extended by your own classes implementing your application logic.
Your objects get the data handling functionality offered by the base
AnewtContainer class for free.
The AnewtContainer object is
basically a wrapper around a hash (associative
array) and can hold any data you provide, while adding the
possibility to add very fine-grained control over which data can be
kept in the object. This way you can easily start coding a fully
functional class and add the necessary validation and output logic
later. As long as you use your object in a standard way, calling
code won't need any changes in case you decide to change the
internal workings of your data object.
The AnewtContainer object can be
used to create clever (or nasty) hacks to manipulate data. Many
other Anewt modules (such as the the page and forms modules) heavily
use the AnewtContainer
functionality.
You can implement getter and setter methods to
control which data can be retrieved from your object and which
data can be stored in it. Note that you don't need to write getter
and setter methods for each variable you want to store in the
object: that's what the
AnewtContainer class does for
you. The
AnewtContainer::get() and
AnewtContainer::set()
functions accept any key/value pair, but call into your own
functions if you have implemented those. Getter functions should
be named get_foo, where foo is the key
provided to the
AnewtContainer::get()
function. The same idea goes for setter functions. Instead of
calling the methods directly, you can also get and set the values
by accessing those as instance properties. The example below shows
some basic AnewtContainer
usage:
Example 3: Basic container object usage with getter and setter methods
// The class used in the examples below: class Person extends AnewtContainer { function get_fullname() { /* format the name correctly */ return sprintf('%s %s', $this->get('firstname'), $this->get('lastname')); } function set_age($age) { /* input checking */ assert('is_int($age)'); if (($age > 100) || ($age < 0)) return; /* everything seems to be ok */ $this->_set('age', $age); } } /* Create a new Person instance and store some data in it */ $p = new Person(); $person->set('firstname', 'John'); $person->set('lastname', 'Doe'); /* We can also use object properties instead of methods */ $person->age = 23; /* Storing several values at once is easy (e.g. rows from a * database) */ $values = array( 'firstname' => 'John', 'lastname' => 'Doe', 'age' => 23); $person->seed($values); /* Now you can get data from the object */ $age_next_decennium = $person->get('age') + 10; /* This will invoke the get_fullname() method */ $fullname = $person->get('fullname'); /* These lines throw errors or don't have any effect */ $person->set('age', 'invalid'); $person->set('age', 800);
As you can see from the example, the
AnewtContainer class allows you
to retrieve dynamically generated data from your objects, e.g. by
performing some calculations with other data in the object. The
setter method makes sure no invalid data can be set on your
object.
For your convenience, a
AnewtContainer::seed()
function is provided to fill the
AnewtContainer with data from an
associative array. This is very useful to store the results of a
database query: $obj->seed($row_data) is all you need
to do.
All magic methods offered by the
AnewtContainer class have
non-magic equivalents with the same name starting
with an underscore, e.g.
AnewtContainer::_get(),
AnewtContainer::set(), and
AnewtContainer::_seed().
These methods do not do any magic, but just store or retrieve data
on the object without calling into getter and setter methods. This
is considerably faster, but does not offer you as much
flexibility.
If your getter methods do computationally expensive operations,
like querying data from a database or doing some heavy
calculations, each $obj->get('foo') call will cause a
lot of overhead. In some cases it might be worth using a
simple caching mechanism: the dynamically
generated value is stored in the container and used on subsequent
$obj->get('foo') calls. To use caching, you append an
underscore to your getter method's name, so that it becomes
get_foo_() instead of get_foo(). See
also the example below:
Example 4: Using simple caching in data objects
class Foo extends AnewtContainer { function get_foo_() { // computationally expensive stuff is done here // ... return $result; } } $obj = new Foo(); // This triggers the get_foo_() method... print $obj->get('foo'); // expensive (only the first time) // ... while subsequent calls just return the cached value: print $obj->get('foo'); // cheap print $obj->get('foo'); // cheap
The AnewtRequest class provides
several static methods to retrieve information about the current
request. The relative and canonical (full) URL's for the current
request can be retrieved using the
AnewtRequest::relative_url()
and
AnewtRequest::canonical_url()
methods. Furthermore, the request type can easily be determined by
calling the
AnewtRequest::method(),
AnewtRequest::is_get() and
AnewtRequest::is_post()
methods. In addition, several methods to extract GET, POST or cookie
data (with type-safety) are available.
Example 5: Retrieving request information
// Get the url of the current request. The shorter // AnewtRequest::url() method does exactly the same as // AnewtRequest::relative_url(), but saves you a bit of typing. // Example result: /path/to/page $url = AnewtRequest::url(); $url = AnewtRequest::relative_url(); // This yields the canonical url. Example: // http://example.com/path/to/page $url = AnewtRequest::canonical_url(); // Find out the request method: $method = AnewtRequest::method(); // "GET" or "POST" $somevar = AnewtRequest::is_get(); // true or false $somevar = AnewtRequest::is_post(); // true or false
TODO: redirect()
TODO: constants
TODO: mkenum
This module provides the following classes: