Php ZF2 ldap分页

Php ZF2 ldap分页,php,zend-framework2,Php,Zend Framework2,我对LDAP库和Active Directory有一些问题。由于AD的限制,如果参数返回的结果超过1000个,我就无法使用LDAP库进行搜索。此外,似乎也没有办法使用ZF2 LDAP库对结果进行分页。我知道如何分页,但如果存在ZF2内置方法,我宁愿使用它 我是否缺少什么,或者我是否必须创建自己的方法来实现这一点 另外,我已经看过了手册和代码,但我看不到任何实现这一点的方法。查看Zend LDAP库:Zend\LDAP\LDAP.php /** * A global LDAP search ro

我对LDAP库和Active Directory有一些问题。由于AD的限制,如果参数返回的结果超过1000个,我就无法使用LDAP库进行搜索。此外,似乎也没有办法使用ZF2 LDAP库对结果进行分页。我知道如何分页,但如果存在ZF2
内置方法,我宁愿使用它

我是否缺少什么,或者我是否必须创建自己的方法来实现这一点


另外,我已经看过了手册和代码,但我看不到任何实现这一点的方法。

查看Zend LDAP库:Zend\LDAP\LDAP.php

/**
 * A global LDAP search routine for finding information.
 *
 * Options can be either passed as single parameters according to the
 * method signature or as an array with one or more of the following keys
 * - filter
 * - baseDn
 * - scope
 * - attributes
 * - sort
 * - collectionClass
 * - sizelimit
 * - timelimit
 *
 * @param  string|Filter\AbstractFilter|array $filter
 * @param  string|Dn|null                     $basedn
 * @param  integer                            $scope
 * @param  array                              $attributes
 * @param  string|null                        $sort
 * @param  string|null                        $collectionClass
 * @param  integer                            $sizelimit
 * @param  integer                            $timelimit
 * @return Collection
 * @throws Exception\LdapException
 */
public function search($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB, array $attributes = array(),
                       $sort = null, $collectionClass = null, $sizelimit = 0, $timelimit = 0
)
{
     // ..
}
您可以从签名中看到,您可以传入一个参数来限制resultset

此方法的一个非常简单的包装器:

/**
 * Search for entries.
 * 
 * @parram  string
 * @param   string
 * @param   int
 * @param   int
 * @return  array
 */
public function search($filter, $basedn = null, $scope = \Zend\Ldap\Ldap::SEARCH_SCOPE_SUB, $sizelimit = 0)
{
    $attributes = array(); 
    $sort = null;
    $collectionClass = null;

    $result = $this->_getLdap()
        ->search($filter, $basedn, $scope, $attributes, $sort, $collectionClass, $sizelimit)
    ;

    return $result;
}
查找用户的简单示例如下:

/**
 * Get all Users..
 * 
 * @param   string
 * @return  \Zend\Ldap\Collection
 */
public function getUsers($baseDn, $sizelimit = 0)
{
    return $this->search('(objectCategory=user)', $baseDn, $sizelimit);
}
然后,您可以将迭代器适配器与Paginator一起使用,以使其正常工作:

use Zend\Paginator\Adapter\Iterator as IteratorAdapter;
// ..
$users = $this->_getMyLdapService()->getUsers();
$paginator = new Paginator(new IteratorAdapter($users));

这就是我为了回避这个问题所做的

/**
 * An LDAP search routine for finding information and returning paginated results
 *
 * Options can be either passed as single parameters according to the
 * method signature or as an array with one or more of the following keys
 * - filter
 * - baseDn
 * - scope
 * - attributes
 * - sort
 * - collectionClass
 * - sizelimit
 * - timelimit
 *
 * @param  string|Filter\AbstractFilter|array $filter
 * @param  string|Dn|null                     $basedn
 * @param  array                              $attributes
 * @param  string|null                        $sort
 * @param  string|null                        $collectionClass
 * @param  integer                            $timelimit
 * @param  integer                            $pageSize
 * @return Array
 * @throws Exception\LdapException
 */
public function multiPageSearch(
    $filter, $basedn = null, array $attributes = array(), $sort = null,
    $collectionClass = null, $timelimit = 0, $pageSize = 1000
)
{
    if (is_array($filter)) {
        $options = array_change_key_case($filter, CASE_LOWER);
        foreach ($options as $key => $value) {
            switch ($key) {
                case 'filter':
                case 'basedn':
                case 'scope':
                case 'sort':
                    $$key = $value;
                    break;
                case 'attributes':
                    if (is_array($value)) {
                        $attributes = $value;
                    }
                    break;
                case 'collectionclass':
                    $collectionClass = $value;
                    break;
                case 'sizelimit':
                case 'timelimit':
                    $$key = (int) $value;
                    break;
            }
        }
    }

    if ($basedn === null) {
        $basedn = $this->getBaseDn();
    } elseif ($basedn instanceof Dn) {
        $basedn = $basedn->toString();
    }

    if ($filter instanceof Filter\AbstractFilter) {
        $filter = $filter->toString();
    }

    $resource = $this->getResource();

    $results = new \ArrayIterator;

    Stdlib\ErrorHandler::start(E_WARNING);
    $cookie = '';
    do {
        ldap_control_paged_result($resource, $pageSize, true, $cookie);

        $result  = ldap_search($resource, $basedn, $filter, $attributes, 0, $pageSize, $timelimit);

        if ($sort !== null && is_string($sort)) {
            $isSorted = ldap_sort($resource, $result, $sort);

            if ($isSorted === false) {
                throw new Exception\LdapException($this, 'sorting: ' . $sort);
            }
        }

        $entries = new \ArrayIterator(ldap_get_entries($resource, $result));

        foreach ($entries as $e) {
            $results[] = $e;
        }

        ldap_control_paged_result_response($resource, $result, $cookie);
    } while($cookie !== null && $cookie != '');
    Stdlib\ErrorHandler::stop();

    if ($results->count() == 0) {
        throw new Exception\LdapException($this, 'searching: ' . $filter);
    }

    return $results;
}

此类/方法用于扩展Zend\Ldap\Ldap类,它将允许返回1000多个结果,但不会以与Ldap::search方法相同的格式返回结果。

感谢您的回复。。。我认为如果你有超过1000个结果,这是行不通的,因为我已经做了一些非常类似的事情,但事实并非如此。问题在于Active Directory,因为它在任何一个查询中最多只能返回1000个结果。如果查询需要返回10000行,那么90%的数据将丢失。或者也许我遗漏了一些你可以解释的东西?这确实不适用于结果>服务器限制。所以,投反对票