22

I am writing an application in CodeIgniter where I specify the <title> meta-tag on every page in every controller which I have managed to send to my header template. However, now I have created an application that fetch credit cards and their titles from the database, through an CodeIgniter model. I would like to automatically fetch and use the credit card's name in <title> so that i don't need to change it manually, but I'm a little stuck on how to proceed.

This is my code as of now:

Controller

public function show($card = NULL)
{

    $data['query'] = $this->Listing_model->get_card($card);

    $header["page_title"] = from the model

    $this->load->view('includes/header',$header);
    $this->load->view('listings/listing_card',$data);
    $this->load->view('includes/footer');
}

Model

function get_card($card = FALSE)
{
    $query = $this->db->get_where('creditcards', array('slug' => $card), 0,1);
    return $query->result();
}

I have been following the official CodeIgniter documentation when creating this application, but so far no luck. Any solutions?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
kanarifugl
  • 9,887
  • 5
  • 29
  • 39
  • What does the 0, 1 mean at end of array? –  Jan 03 '16 at 23:20
  • @wolfgang1983 is limit for results! Can you please var_dump($data['query']); – Valor_ Jan 04 '16 at 18:32
  • @Valor_ its not my question I am just asking What does the 0, 1 mean at end of array? –  Jan 04 '16 at 21:03
  • I think your get_where is wrong . $query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset); your limit is 0 – lumos0815 Jan 05 '16 at 11:17
  • We can't tell if the problem is in the model, the controller or the view. What does $data['query'] return ? does it return any value ? Can you post the portion in 'includes/header' which calls $header["page_title"] plz ? – mariek Jan 06 '16 at 14:53

14 Answers14

14

Try this

  1. Model is changed
  2. Controller is changed.

In Model

function get_card($card)
{
    $query = $this->db->query("SELECT * FROM table_name WHERE creditcards = '$card' ");
    $result = $query->result_array();
    $count = count($result); # New

    if(empty($count)){ # New
        return FALSE;
    }
    elseif($count > 1){ # New
        return 0;
    }
    else{
        return $result;
    }
}

In Controller

public function show($card)
{
    $result = $this->Listing_model->get_card($card); # Changed

    if($result == FALSE){ # New
        echo "No Data Found";
    }
    elseif($result == 0){ # New
        echo "Multiple Data Found";
    }
    else{
        $data["page_title"] = $result[0]['field_name']; # Changed

        $this->load->view('includes/header',$data); # Changed
        $this->load->view('listings/listing_card',$data);
        $this->load->view('includes/footer');
    }

}

In View

<?php echo (!empty($page_title)) ? $page_title : ''; ?> # Changed 
Abdulla Nilam
  • 36,589
  • 17
  • 64
  • 85
  • The query in the model is insecure, unstable, and is not making use of CI's active record helper methods. Why make trip to the model at all if the `$card` is `null`? `empty()` is inappropriate when a variable is guaranteed to be declared. I would be unconditionally returning the `result_array()` from the model so that that model method has the best chance of being called from elsewhere in the application. – mickmackusa Aug 28 '21 at 11:50
  • Those loose checks in the controller are problematic https://3v4l.org/9Jjnu Too many researchers have been learning bad techniques here. – mickmackusa Aug 28 '21 at 11:56
4

A simple example:

Controller

$query = $this->Listing_model->get_card($card);
$query = $query->row();

$header["page_title"] = $query->title;

View

<title><?php echo (!isset($page_title) ? '' : $page_title) ?></title>
Peter
  • 192
  • 1
  • 10
4

Create a base controller. The default location for this is application/core/MY_Controller.php => this can be changed via the config. By using $this->site_data you can add variables in your base class and use them in every controlle/view

class MY_Controller extends CI_Controller
{
    function __construct()
    {
        parent::__construct();


        $this->load->database();

        $this->load->model('your model');

        $result = $this->Listing_model->get_card($card);
        $this->site_data['query']=$result;

       $this->site_data_header["page_title"] = $result['get the property you want'];//this is possible, as get_card returns 1 result 


    }
}


class YourClass extends MY_Controller
{
    function __construct()
    {
        parent::__construct();
    }

    public function show($card = NULL)
    {
        //you don't need to split the variables 
        //for header and the rest 

        $this->load->view('includes/header',$this->site_data_header);
        $this->load->view('listings/listing_card',$this->site_data);
        $this->load->view('includes/footer');
    }
}

And I think your get_where is wrong:

$query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);

your limit is 0

function get_card($card = FALSE)
{
    $query = $this->db->get_where('creditcards', array('slug' => $card), 1,0);//limit 1 offset 0
    return $query->result();
}

access the data in your view

<title><?php echo (!isset($page_title) ? '' : $page_title) ?></title>
Tom Fuller
  • 5,291
  • 7
  • 33
  • 42
lumos0815
  • 3,908
  • 2
  • 25
  • 25
4

You can create a Base Controller and Extends all you other controller to that base controller.

Like this

<?php
class MY_Controller extends CI_Controller {

public $data = array();
    function __construct() {

        parent::__construct();

        $this->data['errors'] = array();

        $this->data['site_name'] = config_item('site_name');


    }
}       

Then In Your Controller

class Test extends MY_Controller
{
  function __construct() {

        parent::__construct();
         $this->data['meta_title'] = 'Your Title';

 }

}

And in you views access the page title like this:

echo("<title>.$site_name.</title>");
Rajan
  • 2,427
  • 10
  • 51
  • 111
3

You may need to create some routes for your show function. Codeigniter URI Routing

$route['your_controller_name/show/(:any)'] = 'your_controller_name/show/$1';

I am not sure if you have set up a htaccess for your main directory so you could remove the index.php from your url.

Try this code below

Model:

<?php 

class Listing_model extends CI_Model {

function get_card_title($card) {
    $this->db->where('slug', $card);
    $query = $this->db->get($this->db->dbprefix . 'creditcards');
    if ($query->num_rows() > 0) {
        $row = $quer->row();
        return $row->title;
    } else {
        return false;
    }
}

}

Controller: Your_controller_name.php

<?php

class Your_controller_name extends CI_Controller {

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

    public function show($card) {
        $data['title'] = $this->listing_model->get_card_title($card);

        $this->load->view('includes/header', $data);
        $this->load->view('listings/listing_card', $data);
        $this->load->view('includes/footer');
    }
}

View:

<head>
<title><?php echo $title;?></title>
</head>
Tom Fuller
  • 5,291
  • 7
  • 33
  • 42
3

Controller

 $card_data= $this->Listing_model->get_card($card); //Your model returns an array of objects


 $header["page_title"]  = $card_data[0]->title; //grab value of 'title' property of first object returned from model.


 $this->load->view('includes/header',$header);

View

<title><?php echo (!isset($page_title) ? '' : $page_title) ?></title>
Bishnu Paudel
  • 2,083
  • 1
  • 21
  • 39
3

Try this:

function get_card($card = FALSE)
{
    $data = $this->db->get_where('creditcards', array('slug' => $card), 0,1)->result();
    $data->title = $data[0]->title;
    return $data;
}
Stefan Ferstl
  • 5,135
  • 3
  • 33
  • 41
synan54
  • 658
  • 6
  • 16
3

Controller

$query = $this->Listing_model->get_card($card);
var_dump($query);
//Your $query may be some data got from db;
$card_name = "";
if(!empty($query)){
$card_name = $query[0]->name;  //You must verify the name attribute and it should in the $query result;
}

$header["page_title"] = $card_name;

View

<title><?php echo (!isset($page_title) ? '' : $page_title) ?></title>
mbo
  • 164
  • 8
1

In your listing card view, do this:

foreach ($query  as  $rec){
    <title><?php echo $rec->title ?></title>
}

replace 'title' with the name of the column on your database that keeps the title of the credit card...so you are passing the results of the query you ran in your controller to this view, and then using a foreach loop to display data of the specific credit card

1

You can use template library for robustness and use as follows:

Controller

$this->template->title('Home :: ' . $this->data['metadata']['site_name'])
            ->set_layout('home_layout')
            ->build('listing_card', $this->data);

Views

    <title><?php echo $template['title']; ?></title>
    <?php echo $template['metadata']; ?>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Reference: https://github.com/philsturgeon/codeigniter-template

Crestamr
  • 57
  • 8
1

Controller :

$data["page_title"] = $result[0]['title_field'];

view: and You just need to write in your header file like :

<title><?php echo $page_title; ?></title>
1

In your model - don't return $query->result(), just return $query:

function get_card($card = FALSE)
{
    $query = $this->db->get_where('creditcards', array('slug' => $card), 0,1);
    return $query;
}

Controller:

public function show($card = NULL)
{
    // verify that you got something back from the database
    // or show an error 
    if( ! $query = $this->Listing_model->get_card($card) )
    {
        $this->_showNoResultsFor($card) ; 
    } 
    else
    {

        // get one record from the query using row()
        $onecard = $query->row() ; 

        // assign the title using whatever your field name is called 
        $header["page_title"] = $onecard->thetitle ; 

        // Now assign the query result() to data 
        $data['query'] = $query->result() ; 

        $this->load->view('includes/header',$header);
        $this->load->view('listings/listing_card',$data);
        $this->load->view('includes/footer');

    }    

}
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
cartalot
  • 3,147
  • 1
  • 16
  • 14
1

Just to add another, there's no reason this shouldn't work:

$data['query'] = $this->Listing_model->get_card($card);
$this->load->view('header', array('page_title' => $data['query'][0]->column_name)); 
//Will there only be one result? Consider returning $query->row(). Multiple,      
//loop through and set one title

In your view:

<title><?=isset($page_title) ? $page_title : "";?></title>

If this doesn't work your query isn't returning what you think it is.

Kisaragi
  • 2,198
  • 3
  • 16
  • 28
0
  • I call the parent constructor as I extend new controllers from CI_Controller and MY_Controller so that I can enjoy higher variable declarations that are shared throughout the project.
  • I recommend creating general use model methods so that they have greater utility and can be re-used by many controllers in your project.
  • To make it easier to load header data into all controllers in your project, I recommend declaring some default header data in MY_Controller then within lower level controllers, you can amend that data and pass it to the view(s).

ci/application/core/MY_Controller.php

<?php
/**
 * @property Listing_model ListingModel
 * @property CI_DB_query_builder|CI_DB_postgre_driver $db
 * @property CI_Loader                                $load
 * @property CI_Config                                $config
 */
class MY_Controller extends CI_Controller
{
    protected $headerData;

    public function __construct()
    {
        parent::__construct();
        $this->headerData['title'] = 'Some Default Title';
        $this->headerData['js'] = [
            'loaded_unconditionally.js',
        ];
        $this->headerData['css'] = [
            'loaded_unconditionally1.css',
            'loaded_unconditionally2.css',
        ];
    }
}

ci/application/controllers/Listing.php

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Listings extends CI_Controller
{    
    public function __construct()
    {
        parent::__construct();
        $this->load->model('Listings_model', 'ListingsModel');
    }

    public function show(string $card): void
    {
        $listing = $this->ListingModel->getByCard($card);

        $this->headerData['title'] = $listing->name ?? 'Invalid Card Provided';

        $this->load->view('layout/header', $this->headerData);
        $this->load->view('listings/listing_card', ['listing' => $listing]);
        $this->load->view('layout/footer');
    }
}

ci/application/models/Listings_model.php

// returns object or null
function getByCard(string $card): ?object
{
    // it is assumed that the slug column will be UNIQUE
    return $this->db->get_where('creditcards', ['slug' => $card])->row();
}

// returns empty array or array of objects
function get(?int $limit, int $offset = 0): array
{
    $args = ['creditcards'];
    if ($limit !== null) {
        array_push($args, $limit, $offset);
    }
    return $this->db->get_where(...$args)->result();
}

ci/application/views/layout/header.php

<!DOCTYPE html>
<html lang="en">
<head>
    <title><?php echo $title; ?></title>
    <?php foreach ($css as $filepath) { ?>
        <link rel="stylesheet" href="<?php echo base_url("assets/css/$filepath"); ?>" />
    <?php } ?>
    <?php foreach ($js as $filepath) { ?>
        <script src="<?php echo base_url("assets/js/$filepath"); ?>" />
    <?php } ?>
</head>

ci/application/views/listings/listing_card.php

<?php
/**
 * @var object|null $listing
 */

// start crafting your html markup and reference $listing as needed
if (!empty($listing->name)) {
    echo "<p>Hello $listing->name</p>";
} else {
    echo "<p>Um, who are you again?</p>";
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136