Codeigniter. Модель для рейтинга, часть 2

2015, 24 сентября

И так в прошлой статье мы создали модель для нашего рейтинга, но стандартный способ вызова модели в codeigniter не очень нам подходит, так как не позволяет работать с моделью, как с объектом создавая множество объектов данного типа. Что бы было понятней, в дальнейшем понадобится возвращать внутри объекта каталог, объект оценку и вот тут стандартный способ работы с моделью станет не возможен. При стандартной работе с моделью

$this->load->model(‘rating’);

Создается один объект и последующие вызовы возвращают указатель на этот объект.
В новой версии можно делать так:

$rating = new Rating();
$rating2 = new Rating();

И так изменённая модель Rating

Class Rating {

    /**
     * Ид оценки
     * @var int
     */
    public $rating_id = <span style="caps">NULL</span>;

    /**
     * Общая оценка
     * @var float
     */
    public $rate = <span style="caps">NULL</span>;

    /**
     * Кол-во проголосовавших
     * @var int
     */
    public $voted = <span style="caps">NULL</span>;

    /**
     * Активна оценка или нет
     * @var bool
     */
    public $active = <span style="caps">NULL</span>;

    /**
     * Имя нашей таблицы в бд
     * @var string
     */
    private $_table_name;

    /**
     * Максимально возможная оценка
     * @var int
     */
    private $_max_rate = 5;

    private $_CI;

    public function __construct() {
        $this->_CI = & get_instance();
        $this->_CI->config->load(‘rating’);
        if (($this->_table_name = $this->_CI->config->item(‘table_name’, ‘rating_config’)) === <span style="caps">FALSE</span>) {
            //Если не получил имя таблицы, то выводим окно ошибки
            show_error(‘Не удалось получить имя таблицы в базе данных для системы оценок’);
        }
        $this->_max_rate = $this->_CI->config->item(‘max_rate’, ‘rating_config’);
    }

    /**
     * Создаем оценку
     * param float $rate - Оценка, по умолчанию 0
     * param int $voted – Кол-во проголосовавших
     * param bool $active - Активировать оценку
     * return bool – результат создания объекта
     */
    public function create($rate = 0, $voted = 0, $active = true) {
        $sql =<span style="caps">INSERT</span> <span style="caps">INTO</span>. $this->_table_name .(rate,voted,active) <span style="caps">VALUES</span>;;
        $this->_CI->db->query($sql, array($rate, $voted, $active));
        if ($this->_CI->db->affected_rows() > 0) {
            $this->rating_id = $this->_CI->db->insert_id();
            $this->rate = $rate;
            $this->voted = $voted;
            $this->active = $active;
            return <span style="caps">TRUE</span>;
        } else {
            $this->_clear_rate();
            return <span style="caps">FALSE</span>;
        }
    }

    /**
     * Удаляем оценку
     * param type $id - ид оценки, если не указан ид, то пытается удалить текущий объект
     * return boolean – результат удаления
     */
    public function delete($id = false) {
        if ($id !== false) {
            $this->_CI->db->delete($this->_table_name, array(‘rating_id’ => $id));
        } else {
            if (is_numeric($this->rating_id)) {
                $this->_CI->db->delete($this->_table_name, array(‘rating_id’ => $this->rating_id));
            } else {
                return <span style="caps">FALSE</span>;
            }
        }
        if ($this->_CI->db->affected_rows() > 0) {
            if (($id = false) || ($id  $this->rating_id)) {
                $this->_clear_rate();
            }
            return <span style="caps">TRUE</span>;
        } else {
            return <span style="caps">FALSE</span>;
        }
    }

    /**
     * Клас ищет оценку по ид
     * param type $id - ид оценки
     * param type $active – искать только активные
     * @return boolean – true если нашел, ну или false
     */
    public function find_by_id($id, $active = true) {
        $sql =<span style="caps">SELECT</span> rating_id,rate,voted,active <span style="caps">FROM</span>. $this->_table_name .<span style="caps">WHERE</span> rating_id=?;
        $result = null;
        if ($active) {
            $sql .=<span style="caps">AND</span> active=?;
            $result = $this->_CI->db->query($sql, array($id, $active));
        } else {
            $result = $this->_CI->db->query($sql, array($id));
        }
        if ($result->num_rows() > 0) {
            $tmp = $result->row();
            $this->rating_id = $tmp->rating_id;
            $this->rate = $tmp->rate;
            $this->voted = $tmp->voted;
            $this->active = $tmp->active;
            return <span style="caps">TRUE</span>;
        } else {
            $this->_clear_rate();
            return <span style="caps">FALSE</span>;
        }
    }

    /**
     * Редактируем данные
     * @return boolean результат обновления
     */
    public function edit() {
        if (is_numeric($this->rating_id)) {
            $sql =<span style="caps">UPDATE</span>. $this->_table_name .<span style="caps">SET</span> rate=?,voted=?,active=? <span style="caps">WHERE</span> rating_id=?;
            $this->_CI->db->query($sql, array($this->rate, $this->voted, $this->active, $this->rating_id));
            if ($this->_CI->db->affected_rows() > 0) {
                return <span style="caps">TRUE</span>;
            } else {
                return <span style="caps">FALSE</span>;
            }
        } else {
            return <span style="caps">FALSE</span>;
        }
    }

    /**
     * Добаляем оценку
     * param type $rate - оценка проголосовавшего
     * param type $id – ид оценки, если не указывать, то попытается использховать текущий объект
     * param type $ret - возращать обновленный объект или нет
     * return boolean если $ret=true, то вернет объект с новыми данными, если $ret=false, то просто вернет true
     */
    public function add_rate($rate, $id = <span style="caps">FALSE</span>, $ret = <span style="caps">TRUE</span>) {
        $sql =<span style="caps">UPDATE</span>. $this->_table_name .<span style="caps">SET</span> voted = voted+1, rate = <span style="caps">ROUND</span>)+?)/voted,1)  <span style="caps">WHERE</span> rating_id=?;
        if ($rate > $this->_max_rate)
            $rate = $this->_max_rate;

        if ($id !== <span style="caps">FALSE</span>) {
            $this->_CI->db->query($sql, array($rate, $id));
        } else {
            if (is_numeric($this->rating_id)) {
                $this->_CI->db->query($sql, array($rate, $this->rating_id));
                $id = $this->rating_id;
            } else {
                return <span style="caps">FALSE</span>;
            }
        }

        if ($this->_CI->db->affected_rows() > 0) {
            if ($ret) {
                return $this->find_by_id($id);
            }
            return <span style="caps">TRUE</span>;
        } else {
            return <span style="caps">FALSE</span>;
        }
    }

    /**
     * Возвращает максимальную оценку
     * @return int
     */
    public function get_max_rate() {
        return $this->_max_rate;
    }

    /**
     * Удаляем значения
     */
    private function _clear_rate() {
        $this->rating_id = <span style="caps">NULL</span>;
        $this->rate = <span style="caps">NULL</span>;
        $this->voted = <span style="caps">NULL</span>;
        $this->active = <span style="caps">NULL</span>;
    }

}

?>

Теперь в папке application/controllers создадим два контроллера
ajax.php – для обработка ajax запросов
rate.php – для тестирования работы код ajax.php

BASEPATH))
    exit(‘No direct script access allowed’);

class Ajax extends CI_Controller {

    public function __construct() {
        parent::__construct();
    }

    /**
     * Возращает результат добаления оценки
     * param type $id - id оценки
     * param type $rate – rate оценка
     */
    public function rate($id = false, $rate = false) {
        if ($id !== false) {
            require_once <span style="caps">APPPATH</span> . ‘models/Rating.php’;
            $this->load->helper(‘rating’);
            $rating = new Rating();
            $id = preg_replace(/[^0-9]/, ‘’, $id);
            if ($rate !== false) {
                $rate = preg_replace(/[^0-9]/, ‘’, $rate);
                $rating->add_rate($rate, $id);
                set_rating_cookie(1);
                $data[‘rating’] = $rating;
                $this->load->view(‘rate/result’, $data);
            }
        }
    }

}

?>

код rate.php

BASEPATH))
    exit(‘No direct script access allowed’);

class Rate extends CI_Controller {

    private $rating;

    public function __construct() {
        parent::__construct();
        require_once <span style="caps">APPPATH</span> . ‘models/Rating.php’;
    }

    /**
     *
     * @param type $id – ид оценки
     */
    public function view($id = false) {
        if($id!== false) {
            $id = preg_replace(/[^0-9]/, ‘’, $id);//оставляем только цифры
            $this->rating = new Rating();
             if ($this->rating->find_by_id($id)) {
                $this->load->view(‘head’);
                $data[‘rating’] = $this->rating;
                $this->load->helper(‘rating’);
                $this->load->view(‘rate/result’, $data);
                if(!exist_rating_cookie($this->rating->rating_id)) {
                    $this->load->view(‘rate/voted’, $data);
                }
                $this->load->view(‘foot’);
            }

        } else {
            $this->load->view(‘head’);
            echo '

# No id rate

';
            $this->load->view(‘foot’);
        }

    }
}  
?>

Теперь создадим хелпер для работы с куками в папке application/helpers создаем rating_helper.php

BASEPATH))
    exit(‘No direct script access allowed’);

/**
 * Проверяет и устанавливает куки
 * param type $rating_id - ид оценки
 * return boolean – результат добавления
 */  
function set_rating_cookie($rating_id) {
    $CI = & get_instance();

    $rating = $CI->input->cookie(‘rating’, <span style="caps">TRUE</span>);
    if ($rating !== false) {
        $rating = unserialize($rating);
        if (is_array($rating)) {
            if (array_search($rating_id, $rating) === false) {
                $rating[] = $rating_id;
            } else {
                return <span style="caps">FALSE</span>;
            }
        } else {
            $rating = array($rating_id);
        }
    } else {
        $rating = array($rating_id);
    }
    $cookie = array(
        ‘name’ => ‘rating’,
        ‘value’ => serialize($rating),
        ‘expire’ =>86500, //24 часа
        ‘secure’ => false
    );
    $CI->input->set_cookie($cookie);
    return <span style="caps">TRUE</span>;
}

/**
 * Функция проверяет существует ли заданая кука для оценки
 * param type $rating_id - ид оценки
 * return boolean – результат существования
 */  
function exist_rating_cookie($rating_id) {
    $CI = & get_instance();
    $rating = $CI->input->cookie(‘rating’, <span style="caps">TRUE</span>);
    if ($rating !== false) {
        $rating = unserialize($rating);
        if (is_array($rating)) {
            if (array_search($rating_id, $rating) !== false) {
                return <span style="caps">TRUE</span>;
            } else {
                return <span style="caps">FALSE</span>;
            }
        } else {
            return <span style="caps">FALSE</span>;
        }
    } else {
        return <span style="caps">FALSE</span>;
    }  
}

?>

В контроллере rate у нас идет вызов 4 представлений
1. head – шапка сайта
2. rate/result – форма вывода результатов голосования
3. rate/voted – форма для голосования
4. foot – подвал сайт Теперь создадим их в папке application/view создаем файл head.php

<br>
            function add_rate(id,rate) {<br>
                $.ajax({<br>
                    url:/turcat/ajax/rate/<ins>id</ins>/+rate, <br>
                    success: function (data) { <br>
                        $(#rate).html(data);<br>
                        $(#action_rate).html(’<p>Ваш голос принят</p>’);<br>
                    } ,        <br>
                    error: function () { <br>
                        $(#action_rate).html(’<p>Произошла ошибка.</p>’);<br>
                    }         <br>
                });     <br>
            } <br>

Там же foot.php

Теперь создадим папку rate и в ней 2 файла result.php и voted.php result.php

**Оценка: ** rate; ?>  

  

  
    **Всего проголосовало: ** voted; ?>

voted.php

**Оцените:**   
        
        $max = $rating->get_max_rate();  
        for ($i = 1; $i <= $max; $i++) {  
            echo[rating_id .,. $i .);>. $i .](#) ‘;  
        }  
        ?>

Теперь если мы создадим тестовый рейтинг выполнив запрос к базе:
INSERT INTO rating (rate,voted,active) VALUES(0,0,TRUE); И обратимся к нашему сайту http://ip-addres/путь-к-codeigniter/rate/view/1 Страница Увидим следующую страницу, теперь проголосовав, нажав на одну из оценок, наша система обновит страницу по средствам ajax запроса Результат После чего в куках появится id оценки и на 24 часа вы не сможете больше голосовать.