summaryrefslogtreecommitdiffstats
path: root/user_guide_src/source/tutorial/news_section.rst
blob: fe8e416075a0567ec9f8763e99cf5bd1d9caf403 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
############
News section
############

In the last section, we went over some basic concepts of the framework
by writing a class that includes static pages. We cleaned up the URI by
adding custom routing rules. Now it's time to introduce dynamic content
and start using a database.

Setting up your model
---------------------

Instead of writing database operations right in the controller, queries
should be placed in a model, so they can easily be reused later. Models
are the place where you retrieve, insert, and update information in your
database or other data stores. They represent your data.

Open up the application/models directory and create a new file called
news_model.php and add the following code. Make sure you've configured
your database properly as described
`here <../database/configuration.html>`_.

::

    <?php
    class News_model extends CI_Model {

        public function __construct()
        {
            $this->load->database();
        }
    }

This code looks similar to the controller code that was used earlier. It
creates a new model by extending CI\_Model and loads the database
library. This will make the database class available through the
$this->db object.

Before querying the database, a database schema has to be created.
Connect to your database and run the SQL command below. Also add some
seed records.

::

    CREATE TABLE news (
        id int(11) NOT NULL AUTO_INCREMENT,
        title varchar(128) NOT NULL,
        slug varchar(128) NOT NULL,
        text text NOT NULL,
        PRIMARY KEY (id),
        KEY slug (slug)
    );

Now that the database and a model have been set up, you'll need a method
to get all of our posts from our database. To do this, the database
abstraction layer that is included with CodeIgniter — `Active
Record <../database/active_record.html>`_ — is used. This makes it
possible to write your 'queries' once and make them work on `all
supported database systems <../general/requirements.html>`_. Add the
following code to your model.

::

    public function get_news($slug = FALSE)
    {
        if ($slug === FALSE)
        {
            $query = $this->db->get('news');
            return $query->result_array();
        }
        
        $query = $this->db->get_where('news', array('slug' => $slug));
        return $query->row_array();
    }

With this code you can perform two different queries. You can get all
news records, or get a news item by its `slug <#>`_. You might have
noticed that the $slug variable wasn't sanitized before running the
query; Active Record does this for you.

Display the news
----------------

Now that the queries are written, the model should be tied to the views
that are going to display the news items to the user. This could be done
in our pages controller created earlier, but for the sake of clarity, a
new "news" controller is defined. Create the new controller at
application/controllers/news.php.

::

    <?php
    class News extends CI_Controller {

        public function __construct()
        {
            parent::__construct();
            $this->load->model('news_model');
        }

        public function index()
        {
            $data['news'] = $this->news_model->get_news();
        }

        public function view($slug)
        {
            $data['news'] = $this->news_model->get_news($slug);
        }
    }

Looking at the code, you may see some similarity with the files we
created earlier. First, the "\_\_construct" method: it calls the
constructor of its parent class (CI\_Controller) and loads the model, so
it can be used in all other methods in this controller.

Next, there are two methods to view all news items and one for a
specific news item. You can see that the $slug variable is passed to the
model's method in the second method. The model is using this slug to
identify the news item to be returned.

Now the data is retrieved by the controller through our model, but
nothing is displayed yet. The next thing to do is passing this data to
the views.

::

    public function index()
    {
        $data['news'] = $this->news_model->get_news();
        $data['title'] = 'News archive';

        $this->load->view('templates/header', $data);
        $this->load->view('news/index', $data);
        $this->load->view('templates/footer');
    }

The code above gets all news records from the model and assigns it to a
variable. The value for the title is also assigned to the $data['title']
element and all data is passed to the views. You now need to create a
view to render the news items. Create application/views/news/index.php
and add the next piece of code.

::

    <?php foreach ($news as $news_item): ?>

        <h2><?php echo $news_item['title'] ?></h2>
        <div id="main">
            <?php echo $news_item['text'] ?>
        </div>
        <p><a href="news/<?php echo $news_item['slug'] ?>">View article</a></p>

    <?php endforeach ?>

Here, each news item is looped and displayed to the user. You can see we
wrote our template in PHP mixed with HTML. If you prefer to use a
template language, you can use CodeIgniter's `Template
Parser <../libraries/parser.html>`_ class or a third party parser.

The news overview page is now done, but a page to display individual
news items is still absent. The model created earlier is made in such
way that it can easily be used for this functionality. You only need to
add some code to the controller and create a new view. Go back to the
news controller and add the following lines to the file.

::

    public function view($slug)
    {
        $data['news_item'] = $this->news_model->get_news($slug);

        if (empty($data['news_item']))
        {
            show_404();
        }

        $data['title'] = $data['news_item']['title'];

        $this->load->view('templates/header', $data);
        $this->load->view('news/view', $data);
        $this->load->view('templates/footer');
    }

Instead of calling the get\_news() method without a parameter, the $slug
variable is passed, so it will return the specific news item. The only
things left to do is create the corresponding view at
application/views/news/view.php. Put the following code in this file.

::

    <?php
    echo '<h2>'.$news_item['title'].'</h2>';
    echo $news_item['text'];

Routing
-------

Because of the wildcard routing rule created earlier, you need need an
extra route to view the controller that you just made. Modify your
routing file (application/config/routes.php) so it looks as follows.
This makes sure the requests reaches the news controller instead of
going directly to the pages controller. The first line routes URI's with
a slug to the view method in the news controller.

::

    $route['news/(:any)'] = 'news/view/$1';
    $route['news'] = 'news';
    $route['(:any)'] = 'pages/view/$1';
    $route['default_controller'] = 'pages/view';

Point your browser to your document root, followed by index.php/news and
watch your news page.