News section

In the last section, we went over some basic concepts of the frameworkby writing a class that references static pages. We cleaned up the URI byadding custom routing rules. Now it’s time to introduce dynamic contentand start using a database.

Create a database to work with

The CodeIgniter installation assumes that you have set up an appropriatedatabase, as outlined in the requirements.In this tutorial, we provide SQL code for a MySQL database, andwe also assume that you have a suitable client for issuing databasecommands (mysql, MySQL Workbench, or phpMyAdmin).

You need to create a database that can be used for this tutorial,and then configure CodeIgniter to use it.

Using your database client, connect to your database and run the SQL command below (MySQL).Also, add some seed records. For now, we’ll just show you the SQL statements neededto create the table, but you should be aware that this can be done programmaticallyonce you are more familiar with CodeIgniter; you can read about Migrationsand Seeds to create more useful database setups later.

  1. CREATE TABLE news (
  2. id int(11) NOT NULL AUTO_INCREMENT,
  3. title varchar(128) NOT NULL,
  4. slug varchar(128) NOT NULL,
  5. body text NOT NULL,
  6. PRIMARY KEY (id),
  7. KEY slug (slug)
  8. );

A note of interest: a “slug”, in the context of web publishing, is auser- and SEO-friendly short text used in a URL to identify and describe a resource.

The seed records might be something like::

  1. INSERT INTO news VALUES
  2. (1,'Elvis sighted','elvis-sighted','Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app.'),
  3. (2,'Say it isn\'t so!','say-it-isnt-so','Scientists conclude that some programmers have a sense of humor.'),
  4. (3,'Caffeination, Yes!','caffeination-yes','World\'s largest coffee shop open onsite nested coffee shop for staff only.');

Connect to your database

The local configuration file, .env, that you created when you installedCodeIgniter, should have the database property settings uncommented andset appropriately for the database you want to use.:

  1. database.default.hostname = localhost
  2. database.default.database = ci4tutorial
  3. database.default.username = root
  4. database.default.password = root
  5. database.default.DBDriver = MySQLi

Setting up your model

Instead of writing database operations right in the controller, queriesshould be placed in a model, so they can easily be reused later. Modelsare the place where you retrieve, insert, and update information in yourdatabase or other data stores. They provide access to your data.

Open up the app/Models/ directory and create a new file calledNewsModel.php and add the following code. Make sure you’ve configuredyour database properly as described here.

  1. <?php namespace App\Models;
  2.  
  3. use CodeIgniter\Model;
  4.  
  5. class NewsModel extends Model
  6. {
  7. protected $table = 'news';
  8. }

This code looks similar to the controller code that was used earlier. Itcreates a new model by extending CodeIgniter\Model and loads the databaselibrary. This will make the database class available through the$this->db object.

Now that the database and a model have been set up, you’ll need a methodto get all of our posts from our database. To do this, the databaseabstraction layer that is included with CodeIgniter —Query Builder — is used. This makes itpossible to write your ‘queries’ once and make them work on allsupported database systems. The Model classalso allows you to easily work with the Query Builder and providessome additional tools to make working with data simpler. Add thefollowing code to your model.

  1. public function getNews($slug = false)
  2. {
  3. if ($slug === false)
  4. {
  5. return $this->findAll();
  6. }
  7.  
  8. return $this->asArray()
  9. ->where(['slug' => $slug])
  10. ->first();
  11. }

With this code, you can perform two different queries. You can get allnews records, or get a news item by its slug. You might havenoticed that the $slug variable wasn’t sanitized before running thequery; Query Builder does this for you.

The two methods used here, findAll() and first(), are providedby the Model class. They already know the table to use based on the $tableproperty we set in NewsModel class, earlier. They are helper methodsthat use the Query Builder to run their commands on the current table, andreturning an array of results in the format of your choice. In this example,findAll() returns an array of objects.

Display the news

Now that the queries are written, the model should be tied to the viewsthat are going to display the news items to the user. This could be donein our Pages controller created earlier, but for the sake of clarity,a new News controller is defined. Create the new controller atapp/Controllers/News.php.

  1. <?php namespace App\Controllers;
  2. use App\Models\NewsModel;
  3. use CodeIgniter\Controller;
  4.  
  5. class News extends Controller
  6. {
  7. public function index()
  8. {
  9. $model = new NewsModel();
  10.  
  11. $data['news'] = $model->getNews();
  12. }
  13.  
  14. public function view($slug = null)
  15. {
  16. $model = new NewsModel();
  17.  
  18. $data['news'] = $model->getNews($slug);
  19. }
  20. }

Looking at the code, you may see some similarity with the files wecreated earlier. First, it extends a core CodeIgniter class, Controller,which provides a couple of helper methods, and makes sure that you haveaccess to the current Request and Response objects, as well as theLogger class, for saving information to disk.

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

Now the data is retrieved by the controller through our model, butnothing is displayed yet. The next thing to do is, passing this data tothe views. Modify the index() method to look like this:

  1. public function index()
  2. {
  3. $model = new NewsModel();
  4.  
  5. $data = [
  6. 'news' => $model->getNews(),
  7. 'title' => 'News archive',
  8. ];
  9.  
  10. echo view('templates/header', $data);
  11. echo view('news/overview', $data);
  12. echo view('templates/footer');
  13. }

The code above gets all news records from the model and assigns it to avariable. 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 aview to render the news items. Create app/Views/news/overview.phpand add the next piece of code.

  1. <h2><?= $title ?></h2>
  2.  
  3. <?php if (! empty($news) && is_array($news)) : ?>
  4.  
  5. <?php foreach ($news as $news_item): ?>
  6.  
  7. <h3><?= $news_item['title'] ?></h3>
  8.  
  9. <div class="main">
  10. <?= $news_item['body'] ?>
  11. </div>
  12. <p><a href="<?= '/news/'.$news_item['slug'] ?>">View article</a></p>
  13.  
  14. <?php endforeach; ?>
  15.  
  16. <?php else : ?>
  17.  
  18. <h3>No News</h3>
  19.  
  20. <p>Unable to find any news for you.</p>
  21.  
  22. <?php endif ?>

Here, each news item is looped and displayed to the user. You can see wewrote our template in PHP mixed with HTML. If you prefer to use a templatelanguage, you can use CodeIgniter’s ViewParser or a third party parser.

The news overview page is now done, but a page to display individualnews items is still absent. The model created earlier is made in sucha way that it can easily be used for this functionality. You only need toadd some code to the controller and create a new view. Go back to theNews controller and update the view() method with the following:

  1. public function view($slug = NULL)
  2. {
  3. $model = new NewsModel();
  4.  
  5. $data['news'] = $model->getNews($slug);
  6.  
  7. if (empty($data['news']))
  8. {
  9. throw new \CodeIgniter\Exceptions\PageNotFoundException('Cannot find the news item: '. $slug);
  10. }
  11.  
  12. $data['title'] = $data['news']['title'];
  13.  
  14. echo view('templates/header', $data);
  15. echo view('news/view', $data);
  16. echo view('templates/footer');
  17. }

Instead of calling the getNews() method without a parameter, the$slug variable is passed, so it will return the specific news item.The only thing left to do is create the corresponding view atapp/Views/news/view.php. Put the following code in this file.

  1. <?php
  2. echo '<h2>'.$news['title'].'</h2>';
  3. echo $news['body'];

Routing

Because of the wildcard routing rule created earlier, you need an extraroute to view the controller that you just made. Modify your routing file(app/config/routes.php) so it looks as follows.This makes sure the requests reach the News controller instead ofgoing directly to the Pages controller. The first line routes URI’swith a slug to the view() method in the News controller.

  1. $routes->get('news/(:segment)', 'News::view/$1');
  2. $routes->get('news', 'News::index');
  3. $routes->get('(:any)', 'Pages::showme/$1');

Point your browser to your “news” page, i.e. localhost:8080/news,you should see a list of the news items, each of which has a linkto display just the one article.../_images/tutorial2.png