Да, это очень плохо. Предлагаю два решения:
1. Как ваше, только использовать функцию strtr:
strtr($tpl, array('{$val}' => $val));
2. Рендер производить с помощью require обёрнутым в ob_start(); и ob_end(); Переменные из массива извлечь с помощью extract() а в файле шаблона уже работать с чистыми переменными. К примеру:
$data = ['var1' => 1, 'var2' => 2];
View::render('index', $data);
View::render:
extract($data);
require($viewFile);
Файл view:
<div class="container">
<?php echo $var1; ?>
<?=$var2 ?>
</div>
Собственно, второй метод используется в Yii framework, так что если требуется шустрый шаблонизатор, то лучше заморочиться, но если нужно пару раз прогнать, первый вариант может подойти