如何使用CodeIgniter在Ajax中对数组进行切片以进行分页


How could I slice an array in Ajax with CodeIgniter for the pagination?

我在模块的视图页面中有一个foreach循环,它从控制器中检索图像网格(数量由"items_top"决定)。问题是同时加载所有项目,因为此时没有设置分页。

这是我的视图的代码:

<div class="row row-sm padder-lg ">
        <?php
        foreach ($top->tracks->track as $key => $value) 
        {
            if($key >= $this->config->item("items_top"))
                return false;
            $image = $value->image[3]->text;
                if($image == '')
            $image = $value->image[2]->text;
                if($image == '')
            $image = base_url()."assets/images/no-cover.png";
        ?>       
        <div class="col-xs-6 col-sm-4 col-md-3 col-lg-2">
            <div class="item">
                <div class="pos-rlt">
                <a href="#">
                    <div class="item-overlay opacity r r-2x bg-black">
                        <div class="center text-center m-t-n">
                        <i class="icon-control-play i-2x"></i>                    
                        </div>
                    </div>
                    <a href="#">
                        <div class="r r-2x img-full" style="background:url('<?php echo $image; ?>') no-repeat top center; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover;  background-size: cover;">
                            <div style="height:180px;overflow:hidden;"></div>
                        </div>
                    </a>
                </div>
                <div class="padder-v">
                    <a href="#" class="text-ellipsis"><?php echo $value->name; ?></a>
                    <a href="#" class="text-ellipsis text-xs text-muted"><?php echo $value->artist->name; ?></a>
                </div>
            </div>
        </div>
        <?php
        }
        ?>
    <script>
    $(".nav-sidebar li").removeClass("active");
    $("#topTrack").addClass('active');
    </script>
</div> 

这是我的功能助手

function _curl($url) {  
    $CI     =& get_instance();  
    $ch = curl_init(); 
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,15);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);    
    if(strtolower(parse_url($url, PHP_URL_SCHEME)) == 'https')
    {
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,1);
    }
    if($CI->config->item("proxy") != '')
    {       
        curl_setopt($ch, CURLOPT_PROXY, $CI->config->item("proxy"));
    }
    curl_setopt($ch, CURLOPT_URL, $url); 
    $data = curl_exec($ch);
    curl_close($ch); 
    return $data;
}
function getTopTracks($artist = false)
{
$CI     =& get_instance();  
$artist = econde($artist);  
$url    = "http://ws.audioscrobbler.com/2.0/?method=chart.gettoptracks&api_key=".$CI->config->item("lastfm")."&format=json&limit=60&page=3";    
$file_cache = 'cache/tracks_'.sha1("toptracks").".cache";
if($cache)
    {   
        $json = $cache;
        if (time()-filemtime($file_cache) > 24 * 3600) {
          // file older than 24 hours
            @unlink($file_cache);
        }
    }
    else
    {       
        $json   = _curl($url);  
        if($CI->config->item("use_cache") == "1")
            write_file($file_cache, $json);
    }   
if(!$artist)
    $json   = str_ireplace("toptracks","tracks",$json);
else
    $json   = remove_banned($json,true) ;
$json   = str_ireplace("#text","text",$json);
$json   = str_ireplace(":totalResults","",$json);
return remove_banned($json) ;
}

这是我的控制器

public function getTopTracks($return = false,$page = false)
{
    $data['page']   = $page;
    $data['top'] = json_decode(getTopTracks());
    if(count($data['top']->tracks->track) <=1)
            {                   
                $this->config->set_item("auto_country", '0');       
                $data['top'] = json_decode(getTopTracks());
            }
            return $this->load->view(getTemplate('topTracks'),$data,$return);   
 }

我需要对循环进行切片以对这些项进行分页,我希望能够在底部添加一个"加载更多"按钮,但问题是Ajax,我不能使用$page = (int)getFromExternalInput();,因为循环调用的是公共函数,而不是url。对这个循环进行切片的正确方法是什么?

我用询问的代码编辑了问题中的函数助手对于希望这能对答案有所帮助。感谢

好的,根据你的补充信息更新我的答案,我根据新信息创建了一个工作示例。我确实不得不为自己创建一个沙盒,它不会100%反映你的代码。我觉得你应该能够从这个答案中得到一些东西,并且你应该能够在自己的代码中实现它。

代码确实需要一些优化

我正在/application/cache/lastfm中保存缓存的文件

缓存可能是分页的一个问题,但我尽了最大努力想出了一个工作示例

application/config/lastfm.php

$config['url'] = 'http://ws.audioscrobbler.com/2.0/';
/**
 * 
 */
$config['API_KEY'] = '';
/**
 * 
 */
$config['limit'] = 12;
/**
 * 
 */
$config['cache_time'] = 24 * 3600;
/**
 * 
 */
$config['proxy'] = "";

application/librarys/curl.php

class Curl
{
    protected $handle;
    public function __construct()
    {
        $this->_init();
    }
    /**
     * 
     * @return type
     */
    protected function _init()
    {
        if(!in_array('curl', get_loaded_extensions())) 
            return log_message('error', 'curl extension is not loaded!');
        $this->handle = curl_init();
        if(!$this->handle) {
            return log_message('error', 'could not create curl handle!');
        } 
    }
    /**
     * 
     * @param type $url
     * @return type
     */
    public function fetch($url)
    {
        $this->setOptions($url);
        $response = curl_exec($this->handle);
        if($errno = curl_errno($this->handle)){
            log_message('error', 'Curl Response Error: ' .  curl_strerror($errno));
        }
        curl_close($this->handle);
        return ($errno === 0) ? $response : false;
    }
    /**
     * 
     * @param type $url
     * @return type
     */
    protected function setOptions($url)
    {
        if(strtolower(parse_url($url, PHP_URL_SCHEME)) == "https"){
            curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, 1);
            curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 1);
        }
        $proxy = $this->config->item('proxy', 'lastfm');
        if(!empty($proxy)){
            curl_setopt($this->handle, CURLOPT_PROXY, $proxy);
        }
        curl_setopt($this->handle,CURLOPT_FAILONERROR,true);
        curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->handle, CURLOPT_URL, $url);
        return;
    }
    /**
     * 
     * @param type $name
     * @return type
     */
    public function __get($name)
    {
        $instance =&get_instance();
        return $instance->$name;
    }
}

application/controllers/tracks.php

class Tracks extends App_Controller 
{
    public function __construct()
    {
        parent::__construct();
        $this->load->config('lastfm', true);
        $this->load->model('lastfm_model');
    }
    public function index()
    {
        $tracks = $this->lastfm_model->getTracks(1);
        $this->load->view($this->template, array(
            'content'  =>  'lastfm/tracks',
            'tracks_view'  =>  $this->load->view('lastfm/partials/tracks', array(
                'tracks'   =>   $tracks,
                'statistics'    => $tracks['data']->tracks->attr
            ), true)         
        ));
    }
    public function get($pageId=0)
    {
        $tracks = $this->lastfm_model->getTracks($pageId, true);
        if($pageId > $tracks['data']->tracks->attr->totalPages){
            return;
        }
        $this->load->view('lastfm/partials/tracks', array(
            'tracks'   =>   $tracks,
            'statistics'    => $tracks['data']->tracks->attr 
        ));
    }
}

application/models/lastfm_model.php

class LastFM_Model extends CI_Model
{
    /**
     *
     * @var type 
     */
    protected $options;
    /**
     *
     * @var type 
     */
    protected $cache;
    /**
     *
     * @var type 
     */
    protected $method;
    /**
     *
     * @var type 
     */
    protected $byPassCache = false;
    public function __construct()
    {
        parent::__construct();
        $this->options = $this->config->config['lastfm'];
    }

    /**
     * 
     * @param type $page
     */
    public function getTracks($page=0, $bypass_cache=false, $method='chart.gettoptracks')
    {
        $this->method = $method;
        $this->cache = $this->_getCachePath();
        $this->byPassCache = $bypass_cache;
        $url= $this->_buildUrl($page);
        if($bypass_cache){
            return array(
                'src'  =>  'curl',
                'data'  =>  $this->_parseContent($this->_fetch($url), false)
            );
        }
        if($cache = $this->_getCache()){
            return array(
                'src'  =>  'cache',
                'data'  =>  $this->_parseContent($cache)
            );
        }
        return array(
            'src'  =>  'curl',
            'data'  =>  $this->_parseContent($this->_fetch($url), false)
        );
    }
    /**
     * 
     * @param type $page
     * @return type
     */
    protected function _buildUrl($page=0)
    {
        $query_data = array(
            'method'    =>  $this->method,
            'format'    =>  'json',
            'page'      =>  $page,                     
            'limit'     =>  $this->options['limit'],
            'api_key'   =>  $this->options['API_KEY']
        );
        $query = http_build_query($query_data);
        return $this->options['url'] . '?' . $query;
    }
    /**
     * 
     * @param type $url
     * @return type
     */
    protected function _fetch($url)
    {
        $this->load->library('curl');
        $data = $this->curl->fetch($url);
        $data = str_ireplace(array('#text', '@attr'), array('text', 'attr'), $data);
        if(!$this->byPassCache){
            $this->_setCache($data);
        }

        return ($data) ? $data : false;
    }
    /**
     * 
     * @return type
     */
    protected function _getCachePath()
    {
        return APPPATH . "cache/lastfm/{$this->method}.cache";
    }
    /**
     * 
     * @param type $data
     * @return type
     */
    protected function _setCache($data)
    {
        if(file_exists($this->cache)){
            unlink($this->cache);
        }
        if(!empty($data)){
            return file_put_contents($this->cache, $data);
        }
    }
    /**
     * 
     * @return type
     */
    protected function _getCache()
    {
        return ( file_exists($this->cache) && ( time() - filemtime($this->cache) ) < $this->options['cache_time']  )
            ? $this->cache
            : false;
    }
    /**
     * 
     * @param type $content
     * @param type $cache
     * @return type
     */
    protected function _parseContent($content, $cache=true)
    {
        if($cache)
            $content = file_get_contents($content);
        return json_decode($content);
    }
}

application/views/lastfm/trats.php

<div id="track_list">
    <?php echo $tracks_view; ?>
</div>
<script>
var SITE_URL = "<?php echo site_url();?>"; 
</script>
<script>
/** LastFm **/
(function($){  
    var lastFm = {
        /**
         * 
         * @type type
         */
        options : {
            cache : false,
            url   : undefined,
            type  : "GET",
            dataType : "html",
            data : {}
        },
        /**
         * 
         * @returns {undefined}
         */
        init : function(){
            this.More = $("a#more");
            this.trackList = $("#track_list");
            this.trackList.on('click', this.More, $.proxy(this.handleEventClick, this));
        },
        /**
         * 
         * @param {type} event
         * @returns {undefined}
         */
        handleEventClick : function(event){
            event.preventDefault();
            var target, pageId;
            target = event.target;
            pageId = parseInt($(target).attr('data-pageId'));
            $(target).remove();
            this.pageID = pageId+1;
            this.fetch(this.pageID);
        },
        /**
         * 
         * @returns {undefined}
         */
        fetch : function(pageId){
            this.options.url = SITE_URL + "/tracks/get/"+pageId;
            this.dojax().then(
                $.proxy(this.handleResponse, this),
                $.proxy(this.handleErrors, this)
            );
        },
        /**
         * 
         * @returns {unresolved}
         */
        dojax : function(){
            return $.ajax(this.options).promise();
        },
        /**
         * 
         * @param {type} response
         * @returns {undefined}
         */
        handleResponse : function(response){
            this.More.remove();
            this.trackList.append(response);
            $("html, body").animate({
                scrollTop : $("[data-pageSlideId="+this.pageID+"]").filter(':last').offset().top
            });
        },
        /**
         * 
         * @param {type} error
         * @returns {undefined}
         */
        handleErrors : function(error){
        }
    };
    lastFm.init();
}(jQuery));
</script>

application/views/lastfm/partials/tracks.php

    <div id="page_<?php echo $statistics->page;?>">
    <?php 
    $columnsPerRow = 4;
    foreach(array_chunk($tracks['data']->tracks->track, $columnsPerRow) as $track): ?>
    <div class="row" data-pageSlideId="<?php echo $statistics->page;?>">
        <?php foreach($track as $trac):?>
            <?php $image = (!empty($trac->image[2]->text)) ? $trac->image[2]->text : false;?>
            <div class="large-3 medium-6 columns text-center" >
                <div class="panel" style="background: url('<?php echo $image;?>') no-repeat;background-size: cover;">
                    <h6><?php echo $trac->name;?></h6>
                    <h5><?php echo $trac->artist->name;?></h5>
                </div>
            </div>
        <?php endforeach;?>
    </div>
    <?php endforeach; ?>
    </div>

<div class="row">
    <div class="large-12 columns text-center">
        <a href="" class="button" id="more" data-pageId="<?php echo $statistics->page;?>">Load More...</a>
    </div>
</div>

我认为您需要做的是将代码分解为函数,而不是直接在视图中使用它。这个问题有点令人困惑,但让我们看看我能不能帮你。我将使用我在带有数据表的codeigniter中使用的分页列表代码。

<?php
#model fuction that take the list data from db
public function listSomething($listStart, $numberOfRows)
{
    $this->db->select('login, nome');
    $this->db->from('list');
    $this->db->limit($numberOfRows, $listStart);
    $queryUsuario = $this->db->get();
    return $queryUsuario->result();
}
#controller fuction
public function listSomething ()
{
    #pego as váriaveis do datatables via post.
    $numeroDeRegistros = intval($this->input->post('length'));
    $listStart = $this->input->post('start');
    #Carega o model de usuario.
    $this->load->model('UsuarioModel');
    #Cria uma váriavel para armazenar o resultado já no formato do DataTables.
    #Pega uma lista de usuário com parâmetros de paginação.
    $list = listSomething($listStart, $numberOfRows);
    #Conta os usuário registrados no banco.
    $listCount = count($list);
    #Pega o tamanho que a lista deve ter, passado pelo Datatables.
    $listLength = intval($this->input->post('length'));
    #Se o tamanho da lista for maior que a propria lista, o total é o tamanho.
    if ( $listLength > $listCount ) {
       $listLength = $listCount;
    }
    #Se o fim da lista é maior que o total da lista, então o fim da lista é o total.
    $listEnd = $listStart + $listLength;
    if ( $listEnd > $listCount ) {
       $listEnd = $listCount;
    }
    #Formata os dados antes de passar para json.
    for($i = 0; $i < $listEnd-$listStart; $i++) {
        foreach($list[$i] as $var => $value) {
            $list["data"][$i][] = $value;
        }
        $list["data"][$i][] =
        '
        <a href="javascript:;" class="btn btn-xs default blue" id="editaUsuarioBnt"><i class="fa fa-pencil"></i> Editar</a>
        <a href="javascript:;" class="btn default btn-xs red" id="excluiUsuario"><i class="fa fa-trash-o"></i> Excluir </a>
        <a href="javascript:;" class="btn btn-xs default yellow"><i class="fa fa-times"></i> Redefinir Senha</a>
        ';                
    }
    #Envia a lista para formatar em json.
    $this->jsonDataTables($list, $listCount);
}
#library function that append some datatables data and output json.
public function jsonDataTables (&$list, $totalDaLista) 
{
    #Gravo na variável o valor de quantas 
    $sEcho = intval($this->input->post('draw'));
    if ( $list != null ) {
        if (isset($_REQUEST["customActionType"]) && $_REQUEST["customActionType"] == "group_action") {
              $list["customActionStatus"] = "OK"; // pass custom message(useful for getting status of group actions)
              $list["customActionMessage"] = "Group action successfully has been completed. Well done!"; // pass custom message(useful for getting status of group actions)
        }
        $list["draw"] = $sEcho;
        $list["recordsTotal"] = $totalDaLista;
        $list["recordsFiltered"] = $totalDaLista;
        echo json_encode($list);
    }
    else {
        echo json_encode("");
    }
}

因此,您只需要创建一个数据表或将其调整为您自己的表。无论何时更新表,我都需要发布变量,这样代码点火器控制器就可以跟踪listStart、listLength等的变化。

因此,假设您知道DataTables是如何工作的,那么就不难理解代码的作用。正如你所说的关于数据,我假设我会有一个数组,作为来自外部源的结果,比如$list[0]$列表[$i]。

因此,在你的模型/任何功能列表中,你可能会有这样的东西,而不是从数据库中获取:

#model fuction that take the list data from db
public function listSomething($listStart, $numberOfRows)
{
    $list = getMyExternalImages();
    return array_slice($list, $listStart, $numberOfRows);
}
#I'll probably need this to count how many results you have
public function countExternalImages()
{
    $list = getMyExternalImages();
    return count($list);
}

如果你能阅读代码和解释,我认为你可以根据自己的需求进行调整。如果你有任何问题,直接问。