基于CodeIgniter实现单张漫画图片分页的技术求助
Hey there! Let's work through your CodeIgniter comic pagination and Google Drive image loading problems together. I'll break this down into actionable fixes that align with your teacher's requirement to use CodeIgniter's features, plus solve those image loading glitches.
First: Fix the Core Pagination with CodeIgniter's Built-in Library
Your current frontend-only pagination can get slow with lots of images, and it doesn't leverage CodeIgniter's tools. Let's shift the pagination logic to the backend:
1. Update Your Model
First, modify the model to split the semicolon-separated images into a clean array, and add Google Drive link conversion (this fixes most loading failures):
public function getComicById($comic_id) { // Return a single row instead of the query object for easier use return $this->db->get_where('comic', ["comic_id" => $comic_id])->row(); } public function getChapterImagesArray($chapter_id) { $chapter = $this->db->get_where('chapter', ["chapter_id" => $chapter_id])->row(); if (!$chapter) return []; // Split and clean up image links $raw_images = explode(";", $chapter->content); $clean_images = array_filter($raw_images, function($img) { return trim($img) !== ''; }); // Convert Google Drive links to embeddable URLs return array_map([$this, 'convertDriveLink'], $clean_images); } // Helper to fix Google Drive image links private function convertDriveLink($link) { // Extract the unique file ID from Drive links preg_match('/[-\w]{25,}/', $link, $matches); if (isset($matches[0])) { return "https://drive.google.com/uc?export=view&id={$matches[0]}"; } return $link; // Return original if not a Drive link }
2. Rewrite the Controller with Pagination
Load CodeIgniter's pagination library and handle page routing:
public function pbp($chapter_id = NULL, $comic_id = NULL) { // Fix session view tracking (cleaner key naming) if ($comic_id) { $session_key = "views_{$comic_id}"; if (!$this->session->userdata($session_key)) { $this->read_model->viewer($comic_id); $this->session->set_userdata($session_key, true); } } // Load and configure pagination $this->load->library('pagination'); $all_images = $this->read_model->getChapterImagesArray($chapter_id); $total_pages = count($all_images); $config = [ 'base_url' => base_url("your-controller-name/pbp/{$chapter_id}/{$comic_id}"), // Replace with your controller name 'total_rows' => $total_pages, 'per_page' => 1, // Show 1 image per page 'uri_segment' => 5, // Matches the page number position in your URL 'full_tag_open' => '<div class="btn-group mt-1 flex-wrap" role="group" aria-label="Basic example">', 'full_tag_close' => '</div>', 'prev_link' => '<i class="feather icon-arrow-left mr-1"></i>Prev', 'prev_tag_open' => '<button type="button" class="btn btn-sm btn-outline-primary text-bold-600">', 'prev_tag_close' => '</button>', 'next_link' => 'Next<i class="feather icon-arrow-right ml-1"></i>', 'next_tag_open' => '<button type="button" class="btn btn-sm btn-outline-primary text-bold-600">', 'next_tag_close' => '</button>', 'cur_tag_open' => '<button type="button" class="btn btn-sm btn-primary btn-icon">', 'cur_tag_close' => '</button>' ]; $this->pagination->initialize($config); // Get current page and image $current_page = $this->uri->segment(5, 0); $current_image = isset($all_images[$current_page]) ? $all_images[$current_page] : ''; // Pass data to view $data['comic'] = $this->read_model->getComicById($comic_id); $data['current_image'] = $current_image; $data['pagination_links'] = $this->pagination->create_links(); $data['current_page_num'] = $current_page + 1; $data['total_pages'] = $total_pages; $this->load->view('read-pbp', $data); }
3. Simplify the View
Now the view only needs to show the current image and generated pagination links:
<div class="card-body p-0" id="top-page"> <div class="img-list d-flex justify-content-center"> <?php if ($current_image): ?> <img src="<?php echo $current_image ?>" class="img-fluid" alt="Page <?php echo $current_page_num ?>" onerror="this.src='path/to/your/placeholder-image.jpg';"> <!-- Add a placeholder for failed loads --> <?php else: ?> <p>No image found for this page.</p> <?php endif; ?> </div> </div> <div class="card-body d-flex justify-content-center"> <?php echo $pagination_links; ?> </div>
Optional: Keep Keyboard Navigation
If you want to retain arrow key navigation, add this simple JS to your view:
$(document).ready(function(){ $(document).keyup(function(event) { if (event.keyCode === 39) { $('.btn-group .btn-outline-primary:contains("Next")').click(); } else if (event.keyCode === 37) { $('.btn-group .btn-outline-primary:contains("Prev")').click(); } }); });
Quick Fix for Your Original Frontend Pagination (If You Prefer It)
If you need to stick with frontend pagination for now, fix the variable conflict and JS logic bugs:
Fixed View
<div class="card-body p-0" id="top-page"> <div class="img-list d-flex justify-content-center"> <?php foreach ($images as $row) : $chapter_images = $row->content; // Rename to avoid overwriting $images $img_array = explode(";", $chapter_images); $img_array = array_filter($img_array, function($img) { return trim($img) !== ''; }); $i = 1; foreach ($img_array as $page) { ?> <img src="<?php echo $this->read_model->convertDriveLink($page) ?>" <!-- Use the Drive conversion helper --> class="img-fluid" alt="<?php echo $i++ ?>" onerror="this.src='path/to/placeholder.jpg';"> <?php } endforeach; ?> </div> </div> <!-- Keep your original button group here -->
Fixed JavaScript
$(document).ready(function(){ const perPage = 1; const totalImages = $('.img-list img').length; let currentPage = 0; // Initialize: hide all, show first page $('.img-list img').hide(); showPage(currentPage); // Button handlers $('#prevb').click(e => { e.preventDefault(); if (currentPage > 0) { currentPage--; showPage(currentPage); scrollToTop(); } }); $('#nextb').click(e => { e.preventDefault(); if (currentPage < Math.floor(totalImages / perPage)) { currentPage++; showPage(currentPage); scrollToTop(); } }); // Keyboard navigation $(document).keyup(event => { event.keyCode === 39 ? $('#nextb').click() : event.keyCode === 37 ? $('#prevb').click() : null; }); // Helper functions function showPage(pageNum) { const start = pageNum * perPage; const end = start + perPage; $('.img-list img').hide().slice(start, end).show(); } function scrollToTop() { $('html, body').animate({scrollTop: $("#top-page").offset().top}, 200); } });
内容的提问来源于stack exchange,提问作者Rantasa

