2
\$\begingroup\$

How can I pass data from database to my HTML template without putting PHP code in my HTML file.

Thanks.

This is my controller

public function index($aRequest)
{
    $oModel = new todoModel();
    $aTodoList = $oModel->getTodoList();
    return array('type' => 'view', 'view' => 'view/index.tpl', 'data' => 
    array('aTodoList' => $aTodoList));
}

my Model

public function getTodoList()
{
    $aTodoList = [];
    $this->oConnection->setAttribute(PDO::ATTR_ERRMODE, 
    PDO::ERRMODE_EXCEPTION);

    $sQuery = 'SELECT * FROM t_todolist';
    foreach ($this->oConnection->query($sQuery) as $aTodo) {
        array_push($aTodoList, array(
            'sequence'    => $aTodo['sequence'],
            'todo'     => $aTodo['todo']                
        ));
    }
    print_r($aTodoList);
    return $aTodoList;
}

my tpl -(this is working but it has php code inside)

<div id="todo_list">
<ul id="todo_list_ul">
<?php
foreach ($aTodoList as $aTodo) {
?>
    <!-- list here -->
    <li><?php echo $aTodo['todo'];?>  <a href="" 
class="todo_update">update</a> <a class="todo_delete" href="">delete</a></li>
<?php
}
?>
</ul>
<button id="todo_create">create</button>
</div>
\$\endgroup\$
1
  • \$\begingroup\$ What is the acrual problem with PHP code inside? \$\endgroup\$ May 8, 2019 at 7:49

1 Answer 1

3
\$\begingroup\$

First, let me review some of of the code you have

public function getTodoList()
{
    return $this->oConnection->query('SELECT * FROM t_todolist')->fetchAll();
}

This is actually all the code you need for this task. Just one line. Thanks PDO being not an ordinary database driver like mysqli. You can check other PDO wonders in my article

There is also one important issue that should be fixed in the controller

public function index($aRequest)
{
    $connection = new Database; // whatever you have to supply a database connection
    $oModel = new todoModel($connection);
    $aTodoList = $oModel->getTodoList();
    return ['type' => 'view', 'view' => 'view/index.tpl', 'data' => 
    ['aTodoList' => $aTodoList]];
}

You may check the above article in order to learn why it is very important to create a database connection only once instead of making each model to create its own.

Now, to the template.

First off, there is absolutely nothing wrong with having some PHP code in a template. PHP is a template language after all, and a good one. All you need is to keep an eye on your template and make sure that all PHP code does in it is actually related to the output only. You can only make it a bit prettier and safer

<ul id="todo_list_ul">
<?php foreach ($aTodoList as $aTodo): ?>
    <!-- list here -->
    <li>
       <?= htmlspecialchars($aTodo['todo']) ?>
       <a href="" class="todo_update">update</a> <a class="todo_delete">
         delete
       </a>
    </li>
<?php endforeach ?>
</ul>

However, to answer your question literally, you will need a dedicated template engine, like Twig. Twig has many good features compared to raw PHP. One of them is autoescaping. There is one critical flaw in your current template, namely

<li><?php echo $aTodo['todo'];?>

The moment a malicious user will put some bad Javascript in the todo description, your site will be hacked. So you have to escape HTML when echoing a variable.

Unlike PHP, Twig escapes your values automatically, so a code

<ul id="todo_list_ul">
{% for aTodo in aTodoList %}
    <li>
        {{ aTodo.todo }}
        <a href="" class="todo_update">update</a> <a class="todo_delete">
          delete
        </a>
    </li>
{% endfor %}
</ul>

will be automatically protected from XSS

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.