Я работаю над онлайн-газета / приложение для ведения блога с CodeIgniter 3.1.8 и Веточка.
Приложение предназначено для того, чтобы предложить разработчикам и дизайнерам возможность очень легко превратить свои HTML-шаблоны в веб-сайты на базе баз данных. Для этого я использовал Веточка шаблонизатор для внешнего интерфейса.
Я заинтересован в улучшении той части приложения, которая связана с отображением сообщений.
В Сообщения контроллер:
class Posts extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
private function _initPagination($path, $totalRows, $query_string_segment="page")
{
//load and configure pagination
$this->load->library('pagination');
$config['base_url'] = base_url($path);
$config['query_string_segment'] = $query_string_segment;
$config['enable_query_strings'] = TRUE;
$config['reuse_query_string'] = TRUE;
$config['total_rows'] = $totalRows;
$config['per_page'] = 12;
if (!isset($_GET[$config['query_string_segment']]) || $_GET[$config['query_string_segment']] < 1) {
$_GET[$config['query_string_segment']] = 1;
}
$this->pagination->initialize($config);
$limit = $config['per_page'];
$offset = ($this->input->get($config['query_string_segment']) - 1) * $limit;
return array(
'limit' => $limit,
'offset' => $offset
);
}
public function index()
{
//call initialization method
$config = $this->_initPagination("/", $this->Posts_model->get_num_rows());
$data = $this->Static_model->get_static_data();
$data['base_url'] = base_url("/");
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
$data['search_errors'] = validation_errors();
//use limit and offset returned by _initPaginator method
$data['posts'] = $this->Posts_model->get_posts($config['limit'], $config['offset']);
$this->twig->addGlobal('pagination', $this->pagination->create_links());
// featured posts
if ($data['is_featured']) {
$data['featured'] = $this->Posts_model->featured_posts();
$this->twig->addGlobal('featuredPosts', "themes/{$data['theme_directory']}/partials/hero.twig");
}
$this->twig->display("themes/{$data['theme_directory']}/layout", $data);
}
public function search()
{
// Force validation since the form's method is GET
$this->form_validation->set_data($this->input->get());
$this->form_validation->set_rules('search', 'search term', 'required|trim|min_length[3]', array(
'min_length' => 'The search term must be at least 3 characters long.'
));
$this->form_validation->set_error_delimiters('<p class = "error search-error">', '</p>');
// If search fails
if ($this->form_validation->run() === FALSE) {
$data['search_errors'] = validation_errors();
return $this->index();
} else {
$expression = $this->input->get('search');
$posts_count = $this->Posts_model->search_count($expression);
$query_string_segment="page";
$config = $this->_initPagination("/posts/search", $posts_count, $query_string_segment);
$data = $this->Static_model->get_static_data();
$data['base_url'] = base_url("/");
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
//use limit and offset returned by _initPaginator method
$data['posts'] = $this->Posts_model->search($expression, $config['limit'], $config['offset']);
$data['expression'] = $expression;
$data['posts_count'] = $posts_count;
$this->twig->addGlobal('pagination', $this->pagination->create_links());
$this->twig->display("themes/{$data['theme_directory']}/layout", $data);
}
}
public function byauthor($authorid)
{
//load and configure pagination
$this->load->library('pagination');
$config['base_url'] = base_url('/posts/byauthor/' . $authorid);
$config['query_string_segment'] = 'page';
$config['total_rows'] = $this->Posts_model->posts_by_author_count($authorid);
$config['per_page'] = 12;
if (!isset($_GET[$config['query_string_segment']]) || $_GET[$config['query_string_segment']] < 1) {
$_GET[$config['query_string_segment']] = 1;
}
$limit = $config['per_page'];
$offset = ($this->input->get($config['query_string_segment']) - 1) * $limit;
$this->pagination->initialize($config);
$data = $this->Static_model->get_static_data();
$data['base_url'] = base_url("/");
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
$data['posts'] = $this->Posts_model->get_posts_by_author($authorid, $limit, $offset);
$data['posts_count'] = $this->Posts_model->posts_by_author_count($authorid);
$data['posts_author'] = $this->Posts_model->posts_author($authorid);
$data['tagline'] = "Posts by " . $data['posts_author']->first_name . " " . $data['posts_author']->last_name;
$this->twig->addGlobal('pagination', $this->pagination->create_links());
$this->twig->display("themes/{$data['theme_directory']}/layout", $data);
}
public function post($slug)
{
$data = $this->Static_model->get_static_data();
$data['base_url'] = base_url("/");
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
$data['authors'] = $this->Usermodel->getAuthors();
$data['posts'] = $this->Posts_model->sidebar_posts($limit = 5, $offset = 0);
$data['post'] = $this->Posts_model->get_post($slug);
$data['next_post'] = $this->Posts_model->get_next_post($slug);
$data['prev_post'] = $this->Posts_model->get_prev_post($slug);
$data['author_image'] = isset($data['post']->avatar) && $data['post']->avatar !== '' ? $data['post']->avatar : 'default-avatar.png';
if ($data['categories']) {
foreach ($data['categories'] as &$category) {
$category->posts_count = $this->Posts_model->count_posts_in_category($category->id);
}
}
if (!empty($data['post'])) {
// Overwrite the default tagline with the post title
$data['tagline'] = $data['post']->title;
// Get post comments
$post_id = $data['post']->id;
$data['comments'] = $this->Comments_model->get_comments($post_id);
$this->twig->addGlobal('singlePost', "themes/{$data['theme_directory']}/templates/singlepost.twig");
} else {
$data['tagline'] = "Page not found";
$this->twig->addGlobal('notFound', "themes/{$data['theme_directory']}/templates/404.twig");
}
$this->twig->display("themes/{$data['theme_directory']}/layout", $data);
}
}
В Posts_model модель:
class Posts_model extends CI_Model {
public function get_num_rows() {
$query = $this->db->get('posts');
return $query->num_rows();
}
public function get_posts($limit, $offset) {
$this->db->select('posts.*, categories.name as post_category, authors.first_name as author_fname, authors.last_name as author_lname');
$this->db->order_by('posts.id', 'DESC');
$this->db->join('categories', 'posts.cat_id = categories.id', 'inner');
$this->db->join('authors', 'posts.author_id = authors.id', 'inner');
$query = $this->db->get('posts', $limit, $offset);
return $query->result();
}
public function featured_posts() {
$this->db->select('posts.*, categories.name as post_category, authors.first_name as author_fname, authors.last_name as author_lname');
$this->db->order_by('posts.id', 'DESC');
$this->db->join('categories', 'posts.cat_id = categories.id', 'inner');
$this->db->join('authors', 'posts.author_id = authors.id', 'inner');
$query = $this->db->get_where('posts', array('featured' => 1));
return $query->result();
}
public function search_count($expression) {
$query = $this->db->like('title', $expression)
->or_like('description', $expression)
->or_like('content', $expression);
$query = $this->db->get('posts');
return $query->num_rows();
}
public function search($expression, $limit, $offset) {
$query = $this->db->like('title', $expression)
->or_like('description', $expression)
->or_like('content', $expression);
$this->db->select('posts.*,categories.name as post_category');
$this->db->order_by('posts.id', 'DESC');
$this->db->join('categories', 'posts.cat_id = categories.id', 'inner');
$query = $this->db->get('posts', $limit, $offset);
return $query->result();
}
public function sidebar_posts($limit, $offset) {
$this->db->order_by('id', 'DESC');
$query = $this->db->get('posts', $limit, $offset);
return $query->result();
}
public function get_num_rows_by_category($category_id) {
$query = $this->db->get_where('posts', array('cat_id' => $category_id));
return $query->num_rows();
}
public function get_posts_by_category($category_id, $limit, $offset) {
$this->db->select('posts.*, categories.name as post_category, authors.first_name as author_fname, authors.last_name as author_lname');
$this->db->order_by('posts.id', 'DESC');
$this->db->limit($limit, $offset);
$this->db->join('categories', 'posts.cat_id = categories.id', 'inner');
$this->db->join('authors', 'posts.author_id = authors.id', 'inner');
$query = $this->db->get_where('posts', array('cat_id' => $category_id));
return $query->result();
}
public function count_posts_in_category($category_id) {
return $this->db
->where('cat_id', $category_id)
->count_all_results('posts');
}
public function get_posts_by_author($authorid, $limit, $offset) {
$this->db->select('posts.*, categories.name as post_category, authors.first_name as author_fname, authors.last_name as author_lname');
$this->db->order_by('posts.id', 'DESC');
$this->db->limit($limit, $offset);
$this->db->join('categories', 'posts.cat_id = categories.id', 'inner');
$this->db->join('authors', 'posts.author_id = authors.id', 'inner');
$query = $this->db->get_where('posts', array('posts.author_id' => $authorid));
return $query->result();
}
public function posts_by_author_count($authorid) {
$query = $this->db->get_where('posts', array('posts.author_id' => $authorid));
return $query->num_rows();
}
public function posts_author($authorid) {
$this->db->select('authors.first_name,last_name');
$query = $this->db->get_where('authors', array('id' => $authorid));
return $query->row();
}
/* Single post */
public function get_post($slug) {
$query = $this->db->get_where('posts', array('slug' => $slug));
if ($query->num_rows() > 0) {
$data = $query->row();
// run separate query for author name
$author_query = $this->db->get_where('authors', array('id' => $data->author_id));
if ($author_query->num_rows() == 1) {
$author = $author_query->row();
$data->first_name = $author->first_name;
$data->last_name = $author->last_name;
$data->avatar = $author->avatar;
} else {
$data->first_name="Unknown";
$data->last_name="";
$data->avatar="";
}
$category_query = $this->db->get_where('categories', array('id' => $data->cat_id));
if ($category_query->num_rows() == 1) {
$category = $category_query->row();
$data->category_name = $category->name;
}
return $data;
}
}
public function get_next_post($slug) {
$this->db->where('id >', $this->get_post($slug)->id);
$this->db->limit(1);
return $this->db->get('posts')->row_array();
}
public function get_prev_post($slug) {
$this->db->where('id <', $this->get_post($slug)->id);
$this->db->order_by('id', 'desc');
$this->db->limit(1);
return $this->db->get('posts')->row_array();
}
public function slug_count($slug, $id){
$this->db->select('count(*) as slugcount');
$this->db->from('posts');
$this->db->where('slug', $slug);
// if its an update
if ($id != null) {
$this->db->where('id !=', $id);
}
$query = $this->db->get();
return $query->row(0)->slugcount;
}
// Create, post
public function create_post($post_image, $slug, $featured) {
$data = [
'title' => $this->input->post('title'),
'slug' => $slug,
'description' => $this->input->post('desc'),
'content' => $this->input->post('body'),
'post_image' => $post_image,
'featured' => $featured,
'author_id' => $this->session->userdata('user_id'),
'cat_id' => $this->input->post('category'),
'created_at' => date('Y-m-d H:i:s')
];
return $this->db->insert('posts', $data);
}
// Update post
public function update_post($id, $post_image, $slug, $featured) {
$data = [
'title' => $this->input->post('title'),
'slug' => $slug,
'description' => $this->input->post('desc'),
'content' => $this->input->post('body'),
'post_image' => $post_image,
'featured' => $featured,
'cat_id' => $this->input->post('category'),
'updated_at' => date('Y-m-d H:i:s')
];
$this->db->where('id', $id);
return $this->db->update('posts', $data);
}
//Delete post
public function delete_post($slug) {
$this->db->where('slug', $slug);
$this->db->delete('posts');
return true;
}
public function delete_post_image($id) {
$this->db->update('posts', array('post_image'=>'default.jpg'), ['id'=>$id]);
}
}
Представление layout.php:
<!DOCTYPE html>
<html>
<head>
<title>{{site_title}} | {{tagline}}</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="{{base_url}}themes/{{theme_directory}}/assets/css/main.css">
</head>
<body>
<!-- Header -->
<header id="header">
<div class="logo"><a href="{{base_url}}">{{site_title}}</a></div>
</header>
<section id="main">
<div class="inner">
{% if singlePost is defined %}
{{include(singlePost)}}
{% elseif pageTemplate is defined %}
{{include(pageTemplate)}}
{% elseif contactForm is defined %}
{{include(contactForm)}}
{% elseif notFound is defined %}
{{include(notFound)}}
{% else %}
{{ include('themes/' ~ theme_directory ~ '/templates/posts.twig') }}
{% endif %}
</div>
</section>
<!-- Footer -->
<footer id="footer">
<div class="container">
<ul class="icons">
<li><a href="{{twitter}}" target="_blank" class="icon fa-twitter"><span class="label">Twitter</span></a></li>
<li><a href="{{facebook}}" target="_blank" class="icon fa-facebook"><span class="label">Facebook</span></a></li>
<li><a href="{{instagram}}" target="_blank" class="icon fa-instagram"><span class="label">Instagram</span></a></li>
<li><a href="mailto:{{company_email}}" class="icon fa-envelope-o"><span class="label">Email</span></a></li>
</ul>
{% if pages %}
<ul class="footer-links">
{% for page in pages %}
<li><a href="{{base_url}}/pages/page/{{page.id}}">{{page.title}}</a></li>
{% endfor %}
<li><a class="nav-link" href="{{base_url}}contact">Contact</a></li>
</ul>
{% endif %}
</div>
<div class="copyright">
© {{company_name}}. All rights reserved. Design by <a href="https://templated.co" target="_blank">TEMPLATED</a>
</div>
</footer>
<script src="{{base_url}}/assets/js/jquery.min.js"></script>
</body>
</html>
Меня больше всего беспокоит то, является ли код (разумно) СУХИМ или нет. и является ли приложение безопасным.
Но любая конструктивная критика будет оценена.