LDAP filters
What are LDAP filters?
LDAP filters are defined in RFC 2254 and can be compared to the WHERE clause in SQL select statements - they filter the data returned from some search request - in this case the entries returned from the directory server. With Net_LDAP, you may use plain strings as filters, or preferably, the Net_LDAP_Filter class which mostly releases you of the burden to escape yourself and to remember all the various special characters needed for constructing and combining filters.
Where and how to use filters is described in chapter Search.
Some LDIF filter basics
Although you should preferably use the Net_LDAP_Filter class to construct your LDAP filters, some theory may be interesting and helpful in understanding how to construct LDAP filters and what they are capable of.
Basic LDAP filters are composed of an "[attribute][operator][value]" pair enclosed by round brackets. There are several comparison operators available: "=" (equal), ">" (greater), "<" (less), ">=" (greater or equal), "<=" (less or equal) and "=~" (phonetical similar). The exact match behavior is defined by the attribute syntax of the attribute to which the filter should apply.
Some basic string filters
<?php
// Filter entries whose first name is 'Benedikt':
$filter = '(givenName=Benedikt)';
// Filter entries which have an employeenumber higher or equal than 1424:
$filter = '(employeeNumber>=1424)';
// Filter entries whose first name sounds similar to "Stephane"
// This should also find "Stephen" and "Stefan" (depending on implementation)
$filter = '(givenName=~Stephane)';
?>
The value part of the basic filter construct could also include a special character: "*". The star acts as placeholder for none, one or several characters at that position. "V*lue" would therefore match against "Value", "Vlue", "VaaAaAalue" and so on. There are some special named combinations using the star, but they work exactly the same way:
Name | Filter | Description |
---|---|---|
present | (attr=*) | Also refered to as "any". Finds any entry containing any (unless empty) value for the named attribute. |
begins | (attr=value*) | value starts with some fixed string |
ends | (attr=*value) | value ends with some fixed string |
contains | (attr=*value*) | value contains some fixed string |
Combining string filters
Basic filters can be combined using the three logical operators "&" (and), "|" (or) and "!" (not). Note, that the smallest filter component, the basic filter enclosed in round brackets, remains isolated: instead of just adding another "[attribute][operator][value]" pair into the brackets, a new bracket level is introduced that contains all filter components that should be combined. Note also, that the logical operator does stand in front of all filter components, not between them as common in programming languages.
Combining string filters
<?php
// Search all 'Benedikt's with phone number 1234567890
$filter = '(&(givenName=Benedikt)(telephoneNumber=1234567890))';
// Search the same, but exclude person "Benedikt Foobar"
// Note that the "not" is a logical operator and thus needs its own
// surrounding bracket. This explains nicely, that each bracket level
// is evaluated independently from surrounding brackets.
$filter = '(&(givenName=Benedikt)(telephoneNumber=1234567890)(!(sureName=Foobar)))';
?>
The Net_LDAP_Filter class
As you will read below, there are some special characters inside the LDAP filter definition and thus must be escaped. These are mainly the special characters used directly by the filter syntax like braces and the logical operators. Despite those, there are some other cases which need special threatment. Nearly all of this cases are hidden through the Net_LDAP_Filter class so you should only consider using string filters if you need to or you know what you are doing. If you need a filter string, you may also use Net_LDAP_Filters toString() function after building the filter.
The filter class has two different usage models: one for constructing basic filters and another to combine them logically. This has to do with the syntax of LDAP filters you may read below.
Creating filters
For creating basic filter components, you need to use the create() factory method.
There, you combine three items: an attribute to filter for, a matching rule for comparison and a value
that is beeing compared with the servers entries.
The given value is automatically escaped, so you need take care if you want to use the star placeholder.
In this case, you need to pass FALSE
as fourth parameter to create()
which causes value
to be threaten as-is. This of course also means, that you need to
escape the parts of the value that may contain restricted characters yourself using
Net_LDAP_Util::escape_filter_value(). To learn what characters
are restricted, refer to RFC 2254 or the documentation of
Net_LDAP_Util::escape_filter_value(); otherwise its safe to always escape.
The matching rules partly follow the basic filter matching rules described above, but are enhanced to make your life easier:
Rule | Description |
---|---|
equals | One of attribute s values is exactly value . Please note that case sensitiviness depends on the matching rule defined in the attributes schema syntax. |
begins | One of attribute s values must begin with value |
ends | One of attribute s values must end with value |
contains | One of attribute s values must contain value |
present | any | The attribute can contain any value but must be existent |
greater | The attribute s value is greater than value |
less | The attribute s value is less than value |
greaterOrEqual | The attribute s value is greater or equal than value |
lessOrEqual | The attribute s value is less or equal than value |
approx | One of attribute s values sounds similar to value . The matching behavior depends on the server implementation. |
Creating LDAP filters
<?php
// Filter entries whose first name is 'Benedikt':
$filter = Net_LDAP_Filter::create('givenName', 'equals', 'Benedikt');
// Filter entries whose first name starts with 'Steph':
$filter = Net_LDAP_Filter::create('givenName', 'begins', 'Steph');
// Filter entries containing 'Lone*'; matching the star character.
// The automatic escaping of $value will conveniently escape the star for us.
$filter = Net_LDAP_Filter::create('givenName', 'contains', 'Lone*');
// Filter entries containing 'Foo[something]Bar'; not matching the star character.
// For this to work, we need to disable automatic escaping of $value by passing
// false as fourth parameter. This however implies, that we take care of
// proper escaping, which is showed in the example.
$escaped_values = Net_LDAP_Util::escape_filter_value(array('Foo', 'Bar'));
$foo =& $escaped_values[0];
$bar =& $escaped_values[1];
$filter = Net_LDAP_Filter::create('givenName', 'contains', "$foo*$bar", false);
// Filter entries whose first name sounds similar to "Stephane"
// This should also find "Stephen" and "Stefan" (depending on implementation)
$filter = '(givenName=~Stephane)';
?>
Combining filters
Although the filters can be used stand alone, they can be combined to match sophisticated
search requiremets. This is done by using the combine() to combine
several present Net_LDAP_Filter objects using a logical operator.
The execption is the not
operator since it only allows one filter
object to be negated.
Rule | Description |
---|---|
and | All filter components must evaluate to true for the combined filter to be true |
or | At least one filter component must evaluate to true for the combined filter to be true |
not | The result of the filter component is inversed (true becomes false and vice versa).
Note that this operator only accepts one filter object. |
Combining LDAP filters
<?php
// Create some test filters
$filter_benedikt = Net_LDAP_Filter::create('givenName', 'equals', 'Benedikt');
$filter_steph = Net_LDAP_Filter::create('givenName', 'begins', 'Steph');
$filter_foobar = Net_LDAP_Filter::create('sureName', 'equals', 'Foobar');
$filter_height = Net_LDAP_Filter::create('personHeight', 'greater', '175');
// Negate 'foobar' filter.
// This filters every entry whose sure name is not 'Foobar'
$filter_not_foobar = Net_LDAP_Filter::combine('not', $filter_foobar);
// Build a 'and' combination to be able to search for people whose
// first names start with 'Steph' and who are are taller than 175
// except those whose surname is 'Foobar'
$filter_stephs_tall = Net_LDAP_Filter::combine('and',
array($filter_steph, $filter_height, $filter_not_foobar));
// In any case, add every person whose first name is
// 'Benedikt' to the search result.
$filter_add_benedikt = Net_LDAP_Filter::combine('or', array($filter_benedikt, $filter_stephs_tall));
?>
Advanced features
You may need some advanced functionality if you have to deal with string representation of filters.
Method | Description |
---|---|
parse() | Takes an filter string and parses it into a Net_LDAP_Filter object. It also verifies, that the filter syntax is correct. |
printMe() | In PERLs interface, this method is called "print" but due to language constraints, we cannot use that name. Prints the string representation of this filter object to standard output or to an optional filehandle passed as parameter. |
toString() | Returns the string representation of the filter object. |