I was trying to retrieve data from the "user_app" table into my table form in the view page.
Here's my Controller(method):
public function getUserApps($email) {
$userAppsModel = new UserApps($this->pdo);
$apps = $userAppsModel->get($email);
return $this->view('user/dashboard', ['apps' => $apps]);
}
Here's the method I used to get the data:
public function get($email) {
$sql = "SELECT * FROM $this->table WHERE email = :email";
$stmt = $this->pdo->prepare($sql);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
return $user;
}
and here's my View Page (dashboard.php) Line 107:
<h1>User List</h1>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
**Line 107:** <?php foreach ((array) $apps as $app) : ?>
<tr>
<td><?= $app['app_name'] ?></td>
<td><?= $app['app_desc'] ?></td>
<td><?= $app['app_cat'] ?></td>
</tr>
<?php endforeach; ?>
</table>
My view() method:
protected function view($filename, $data = []) {
if (file_exists('../view/' . $filename . '.php')) {
require_once '../view/' . $filename . '.php';
}
}
Error Getting: Warning : Undefined variable $apps in C:\xampp\htdocs\xxxxxx\view\user\dashboard.php on line 107
Your view()
method is not extract()
ing the $data
argument, so $data['apps']
is not being made available to your view.
Prior to require
ing your view file, you need to use extract($data)
.
NOTE: extract()
is a dangerous method and should NEVER be used with untrusted data (such as from $_GET
or $_POST
), because extract
makes array keys available as variables.
Solution:
Here is a rewritten version of your view()
method using extract:
protected function view($filename, $data = []) {
if (file_exists('../view/' . $filename . '.php')) {
extract($data); // $data['apps'] is now exposed as $apps variable
require_once '../view/' . $filename . '.php';
}
}
THOUGH, your use of require_once
could cause you problems. If a view is to be displayed twice on the same request, only the first call to view()
will do anything. I'd replace require_once
with require
Unrelated Suggestion: I'm personally fond of early returns, instead of nesting meaningful code inside if blocks. I also like explicit pathing and types. You can ignore this suggestion, but I personally would write the method more like this:
protected function view(string $filename, array $data = []) {
$file_path = __DIR__.'/../view/'.$filename.'.php';
if (!file_exists($file_path))return;
extract($data); // expose each array key as a variable.
require $file_path;
}