以递归方式合并PHP数组

时间:2013-11-08 14:13:11

标签: php arrays zend-framework merge

我正在研究zend Framework中的一个项目,我试图将我的SQL查询结果合并为一个数组$result 这是我的疑问:

public function getOpen()
{
    $query = $this->select()
          ->setIntegrityCheck(false)
          ->from(array('e' => 'emails'), array(
               'isp' => new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"),
               'count' => new Zend_Db_Expr('COUNT( * )')))
          ->join(array('to' => 'track_open'), 'e.email_id = to.email_id', array(''))
          ->where('e.email_id = to.email_id')
          //->where('DATE( open_date ) = ? ', $date )
          ->group(new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;
}

public function getUnsubscribe()
{
    $query = $this->select()
          ->setIntegrityCheck(false)
          ->from(array('e' => 'emails'), array(
              'isp' => new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"),
              'count' => new Zend_Db_Expr('COUNT( * )')))
          ->join(array('tu' => 'track_unsubscribe'), 'e.email_id = tu.email_id', array(''))
          ->where('e.email_id = tu.email_id')
          //->where('DATE( unsubscribe_date ) = ? ', $date )
          ->group(new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;
}

public function getClick()
{
    $query = $this->select()
          ->setIntegrityCheck(false)
          ->from(array('e' => 'emails'), array(
              'isp' => new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"),
              'count' => new Zend_Db_Expr('COUNT( * )'),
              'tc.click_date',))
          ->join(array('tc' => 'track_click'), 'e.email_id = tc.email_id', array(''))
          ->where('e.email_id = tc.email_id')
          //->where('DATE( click_date )= ? ', $date )
          ->group(new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;
}


public function getlogs()
{
    $query = $this->select()
            ->setIntegrityCheck(false)
            ->from(array('ee' => 'email_errors'),
                    array(  'isp' => new Zend_Db_Expr('ee.FAI'),
                            'sent' => new Zend_Db_Expr("SUM( ee.STATUS =0 )"),
                            'deferred' => new Zend_Db_Expr("SUM( ee.STATUS =1 )"),
                            'bounced' => new Zend_Db_Expr("SUM( ee.STATUS =2 )")))
            ->group(new Zend_Db_Expr("FAI"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;

}

public function getSB()
{
    $query = $this->select()
          ->setIntegrityCheck(false)
          ->from(array('e' => 'emails'), array(
              'isp' => new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"),
              'count' => new Zend_Db_Expr('COUNT( * )')))
          ->join(array('tb' => 'track_bounce'), 'e.email_id = tb.email_id', array(''))
          ->where('e.email_id = tb.email_id')
          //->where('DATE( bounce_date ) = ? ', $date )
          ->where('tb.bounce_type = ?', "soft")
          ->group(new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;
}

public function getHB()
{
    $query = $this->select()
          ->setIntegrityCheck(false)
          ->from(array('e' => 'emails'), array(
              'isp' => new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"),
              'count' => new Zend_Db_Expr('COUNT( * )')))
          ->join(array('tb' => 'track_bounce'), 'e.email_id = tb.email_id')
          ->where('e.email_id = tb.email_id')
          //->where('DATE( bounce_date ) = ? ', $date )
          ->where('tb.bounce_type = ?', "hard")
          ->group(new Zend_Db_Expr("SUBSTRING_INDEX( e.email_value,  '@', -1 )"));

    $result = $this->fetchAll($query);

    if($result)
    {
        return $result->toArray();
    }

    return false;
}

并且这是我在合并时所做的功能:

function array_merge_rec($arrays) 
{
    $result = array();

    $keys = array('logs','open', 'click', 'unsubscribe', 'soft', 'hard', );

    foreach ($arrays as $key => $value) {
        if (is_array($value)) {
            foreach ($value as $item) {
                $result[$item['isp']][$key] = $item['count'];
            }
        }
    }

    $results = array();

    foreach($result as $key => $value)
    {
        foreach($keys as $k)
        {
            if(!isset($result[$key][$k])) $result[$key][$k] = 0;
        }
    }

    return $result;
}

如果需要,这是我的Action控制器:

public function logsAction()
{   

    $log_review = new Dashboard_Model_DbTable_logs();


        $open = $log_review->getOpen();
        $click = $log_review->getClick();
        $unsubscribe = $log_review->getUnsubscribe();
        $logs = $log_review->getlogs();
        $SB = $log_review->getSB();
        $HB = $log_review->getHB();

    $result = $this->array_merge_rec(array('logs'=>$logs,'open' => $open, 'click' => $click, 'unsubscribe' => $unsubscribe, 'hard' => $HB, 'soft' => $SB));

    $this->view->data = $result; 
}

正如我所说,我想要做的是将所有查询结果合并到一个基于ISP的数组“$ result”中。当我在没有getlogs查询的情况下合并所有查询时,该函数正常工作,但是当我将getlogs查询添加到函数参数时,它不起作用,这是正常的。所以我需要帮助才能知道如何修改我的合并函数以获取一个数组,该数组包含所有查询的公共ISP列上合并的所有列

1 个答案:

答案 0 :(得分:1)

检查Kohana_Arr类,特别是两种方法:

................

    /**
     * Merges one or more arrays recursively and preserves all keys.
     * Note that this does not work the same as [array_merge_recursive](http://php.net/array_merge_recursive)!
     *
     *     $john = array('name' => 'john', 'children' => array('fred', 'paul', 'sally', 'jane'));
     *     $mary = array('name' => 'mary', 'children' => array('jane'));
     *
     *     // John and Mary are married, merge them together
     *     $john = Arr::merge($john, $mary);
     *
     *     // The output of $john will now be:
     *     array('name' => 'mary', 'children' => array('fred', 'paul', 'sally', 'jane'))
     *
     * @param   array  initial array
     * @param   array  array to merge
     * @param   array  ...
     * @return  array
     */
    public static function merge(array $a1, array $a2)
    {
        $result = array();
        for ($i = 0, $total = func_num_args(); $i < $total; $i++)
        {
            // Get the next array
            $arr = func_get_arg($i);

            // Is the array associative?
            $assoc = Arr::is_assoc($arr);

            foreach ($arr as $key => $val)
            {
                if (isset($result[$key]))
                {
                    if (is_array($val) AND is_array($result[$key]))
                    {
                        if (Arr::is_assoc($val))
                        {
                            // Associative arrays are merged recursively
                            $result[$key] = Arr::merge($result[$key], $val);
                        }
                        else
                        {
                            // Find the values that are not already present
                            $diff = array_diff($val, $result[$key]);

                            // Indexed arrays are merged to prevent duplicates
                            $result[$key] = array_merge($result[$key], $diff);
                        }
                    }
                    else
                    {
                        if ($assoc)
                        {
                            // Associative values are replaced
                            $result[$key] = $val;
                        }
                        elseif ( ! in_array($val, $result, TRUE))
                        {
                            // Indexed values are added only if they do not yet exist
                            $result[] = $val;
                        }
                    }
                }
                else
                {
                    // New values are added
                    $result[$key] = $val;
                }
            }
        }

        return $result;
    }

    /**
     * Overwrites an array with values from input arrays.
     * Keys that do not exist in the first array will not be added!
     *
     *     $a1 = array('name' => 'john', 'mood' => 'happy', 'food' => 'bacon');
     *     $a2 = array('name' => 'jack', 'food' => 'tacos', 'drink' => 'beer');
     *
     *     // Overwrite the values of $a1 with $a2
     *     $array = Arr::overwrite($a1, $a2);
     *
     *     // The output of $array will now be:
     *     array('name' => 'jack', 'mood' => 'happy', 'food' => 'tacos')
     *
     * @param   array   master array
     * @param   array   input arrays that will overwrite existing values
     * @return  array
     */
    public static function overwrite($array1, $array2)
    {
        foreach (array_intersect_key($array2, $array1) as $key => $value)
        {
            $array1[$key] = $value;
        }

        if (func_num_args() > 2)
        {
            foreach (array_slice(func_get_args(), 2) as $array2)
            {
                foreach (array_intersect_key($array2, $array1) as $key => $value)
                {
                    $array1[$key] = $value;
                }
            }
        }

        return $array1;
    } 

.........

/**
 * Tests if an array is associative or not.
 *
 *     // Returns TRUE
 *     Arr::is_assoc(array('username' => 'john.doe'));
 *
 *     // Returns FALSE
 *     Arr::is_assoc('foo', 'bar');
 *
 * @param   array   array to check
 * @return  boolean
 */
public static function is_assoc(array $array)
{
    // Keys of the array
    $keys = array_keys($array);

    // If the array keys of the keys match the keys, then the array must
    // not be associative (e.g. the keys array looked like {0:0, 1:1...}).
    return array_keys($keys) !== $keys;
}

/**
 * Test if a value is an array with an additional check for array-like objects.
 *
 *     // Returns TRUE
 *     Arr::is_array(array());
 *     Arr::is_array(new ArrayObject);
 *
 *     // Returns FALSE
 *     Arr::is_array(FALSE);
 *     Arr::is_array('not an array!');
 *     Arr::is_array(Database::instance());
 *
 * @param   mixed    value to check
 * @return  boolean
 */
public static function is_array($value)
{
    if (is_array($value))
    {
        // Definitely an array
        return TRUE;
    }
    else
    {
        // Possibly a Traversable object, functionally the same as an array
        return (is_object($value) AND $value instanceof Traversable);
    }
}