PHP 不在对象上下文中时使用 $this 的 fat free 框架?
PHP fat free framework using $this when not in object context?
我正在使用 fat free PHP framework 开发一个项目。在文档中,他们说你可以为项目构建自己的框架,所以我的项目目录如下:
- 资产
- css
- js
- 控制器
- Controller.php
- 主页_Controller.php
- lib(有框架的东西)
- 型号
- Model.php
- Model_Home.php
- 观看次数
- 家
- main.html
- index.php
在 index.php 中,我正在调用框架(控制器和模型,包括数据库连接)并且我的路由如下:
// Kickstart the framework
$f3=require($_SERVER['DOCUMENT_ROOT'] . '/project_name/lib/base.php');
$f3->set('AUTOLOAD',''.$_SERVER['DOCUMENT_ROOT'] . '/project_name/controllers/; '.$_SERVER['DOCUMENT_ROOT'] . '/project_name/models/');
$f3->set('DEBUG',3);
if ((float)PCRE_VERSION<7.9){
trigger_error('PCRE version is out of date');
}
if (!($f3->get('DEBUG')))
{
$f3->set('ONERROR',
function($f3) {
$f3->reroute('/');
}
);
}
/****************** Start Routing the URLs ******************/
/****** Home Controller ******/
$f3->route('GET|HEAD /',
function($f3) {
$f3->reroute('/home');
}
);
$f3->route('GET|HEAD /index',
function($f3) {
$f3->reroute('/home');
}
);
$f3->route('GET /home','Controller_Home->main');
$f3->run();
在 Model.php 中,我有一个成功连接到数据库的函数,如下所示:
class Model
{
public $f3, $db;
public function connect()
{
global $db;
$username = 'username';
$password = 'password';
$hostname = 'hostname';
$dbname = 'dbname';
try{
$db = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo $e->getMessage();
}
print_r($db); // this will give PDO Object ( )
$this->db = $db;
}
}
// if you try to execute query here, it will work.
现在,在 Controller.php 中,我在结构内部 Model.php 中调用 connect() 函数,如下所示:
class Controller extends Model
{
public $f3, $db;
public function __construct($f3)
{
$this->f3 = $f3;
$this->connect();
}
}
Model_Home.php 具有如下查询数据库的函数:
class Model_Home extends Model
{
public $f3, $db;
public static function getUsers()
{
$query = "SELECT * FROM users";
$result = $this->db->query($query);
$output = '';
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$output.= '<tr>
<td>'.$row['attrib1'].'</td>
<td>'.$row['attrib2'].'</td>
<td>'.$row['attrib3'].'</td>
<td>'.$row['attrib4'].'</td>
<td>'.$row['attrib5'].'</td>
</tr>';
}
return $output;
}
}
和Controller_Home.php会静态调用前面的函数,然后调用右视图渲染结果如下:
class Controller_Home extends Controller
{
public $f3, $db;
public function main($output = '')
{
//setting up the variables
$this->f3->set('getUsersTable', Model_Home::getUsers());
// getUsersTable is a variable that will be passed to the view to reder
//calling the view
$this->f3->set('main','views/home/main.html');
}
}
最后是main.html页面,如下所示:
<h1>All Users</h1></br>
<?php echo htmlspecialchars_decode($getUsersTable); ?>
当我运行代码时,它会给我一条错误信息说:
致命错误:不在对象上下文中时使用 $this
project_name/models/Model_Home.php:8
指的是Model_Home.php
中的下一行
$result = $this->db->query($query);
我必须使用的 php 版本是 5.4(相当旧)。任何想法,请!
谢谢大家!
您已将 Model_Home::getUsers 定义为静态方法。这意味着它是 class 而不是实例化对象的方法,这反过来意味着您无法访问对象属性,只能访问 class 定义为 "static" 的属性和方法。 $db 未定义为 "static" 因此它是对象的 属性 而不是 class.
如果您想将 getUsers 保持为静态:
您可以将 $db 定义为 "static"(这将需要对引用它的任何代码进行其他代码更改),或者使用单例模式,从而将对象的实例存储为静态 class 变量,供其他 class 方法访问。例如:
class myClass
{
protected static $db = null;
public static function getDb()
{
if(empty(self::$db))
self::$db = new Database();
return self::$db;
}
}
如果您不关心保持 getUsers 静态:
只需从其声明中删除 "static" 关键字,您还必须更新此方法调用:
$this->f3->set('getUsersTable', Model_Home::getUsers());
至:
$modelHome = new Model_Home;
$this->f3->set('getUsersTable', $modelHome->getUsers());
首先,在尝试创建这种骨架之前,先熟悉一下 f3。您发布的代码似乎表明您可以充分利用一些您可能不熟悉的关键概念。
使用模板 使用 echo \Template::instance()->render('templates/controller_index.htm');
从控制器调用模板
使用 F3 ORM 尽管与 Eloquent 等其他 ORM 相比,F3 ORM 确实加快了处理数据库的速度。在这里阅读:http://fatfreeframework.com/databases
$user=new DB\SQL\Mapper($db,'users');
$user->load(array('userID=? AND password=?','cheetah','ch1mp')); // load one user
$allusers = $user->find(); // get all users
根据您拥有的模型代码,我想说您完全可以不使用任何模型,使用 Mapper class 可以带您走很长一段路。
将配置存储在配置文件中。这会将配置信息与逻辑分开。
$f3->config("config.ini");
在那里定义的任何值都可以像全局一样访问
[globals]
DEBUG=0
CACHE=true
; Database
db.host=localhost
db.port=3306
db.user=root
db.pass=
db.name=phproject
; Session lifetime
; Also set session.gc_maxlifetime in php.ini
JAR.expire=604800
像这样...
// Connect to database
$f3->set("db.instance", new DB\SQL(
"mysql:host=" . $f3->get("db.host") . ";port=" . $f3->get("db.port") . ";dbname=" . $f3->get("db.name"),
$f3->get("db.user"),
$f3->get("db.pass")
));
如果在调用任何控制器之前将该代码放入索引文件中,则可以轻松调用数据库连接。使用 $f3->set("db.instance",...)
创建并设置连接
// get reference to instance and initialize mapper
$user = new DB\SQL\Mapper($f3->get("db.instance"),'users');
// get all records (same as SELECT * FROM $tablename) and put them inside all_users var
$f3->set('all_users', $user->find());
如果您随后在模板文件中使用此信息,您将执行类似这样的操作
<table>
<repeat group="{{ @all_users }}" value="{{ @user }}">
<tr>
<td>{{ @user.attrib1 }}</td>
<td>{{ @user.attrib2 }}</td>
<td>{{ @user.attrib3 }}</td>
</tr>
</repeat>
</table>
我正在使用 fat free PHP framework 开发一个项目。在文档中,他们说你可以为项目构建自己的框架,所以我的项目目录如下:
- 资产
- css
- js
- 控制器
- Controller.php
- 主页_Controller.php
- lib(有框架的东西)
- 型号
- Model.php
- Model_Home.php
- 观看次数
- 家
- main.html
- 家
- index.php
在 index.php 中,我正在调用框架(控制器和模型,包括数据库连接)并且我的路由如下:
// Kickstart the framework
$f3=require($_SERVER['DOCUMENT_ROOT'] . '/project_name/lib/base.php');
$f3->set('AUTOLOAD',''.$_SERVER['DOCUMENT_ROOT'] . '/project_name/controllers/; '.$_SERVER['DOCUMENT_ROOT'] . '/project_name/models/');
$f3->set('DEBUG',3);
if ((float)PCRE_VERSION<7.9){
trigger_error('PCRE version is out of date');
}
if (!($f3->get('DEBUG')))
{
$f3->set('ONERROR',
function($f3) {
$f3->reroute('/');
}
);
}
/****************** Start Routing the URLs ******************/
/****** Home Controller ******/
$f3->route('GET|HEAD /',
function($f3) {
$f3->reroute('/home');
}
);
$f3->route('GET|HEAD /index',
function($f3) {
$f3->reroute('/home');
}
);
$f3->route('GET /home','Controller_Home->main');
$f3->run();
在 Model.php 中,我有一个成功连接到数据库的函数,如下所示:
class Model
{
public $f3, $db;
public function connect()
{
global $db;
$username = 'username';
$password = 'password';
$hostname = 'hostname';
$dbname = 'dbname';
try{
$db = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo $e->getMessage();
}
print_r($db); // this will give PDO Object ( )
$this->db = $db;
}
}
// if you try to execute query here, it will work.
现在,在 Controller.php 中,我在结构内部 Model.php 中调用 connect() 函数,如下所示:
class Controller extends Model
{
public $f3, $db;
public function __construct($f3)
{
$this->f3 = $f3;
$this->connect();
}
}
Model_Home.php 具有如下查询数据库的函数:
class Model_Home extends Model
{
public $f3, $db;
public static function getUsers()
{
$query = "SELECT * FROM users";
$result = $this->db->query($query);
$output = '';
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
$output.= '<tr>
<td>'.$row['attrib1'].'</td>
<td>'.$row['attrib2'].'</td>
<td>'.$row['attrib3'].'</td>
<td>'.$row['attrib4'].'</td>
<td>'.$row['attrib5'].'</td>
</tr>';
}
return $output;
}
}
和Controller_Home.php会静态调用前面的函数,然后调用右视图渲染结果如下:
class Controller_Home extends Controller
{
public $f3, $db;
public function main($output = '')
{
//setting up the variables
$this->f3->set('getUsersTable', Model_Home::getUsers());
// getUsersTable is a variable that will be passed to the view to reder
//calling the view
$this->f3->set('main','views/home/main.html');
}
}
最后是main.html页面,如下所示:
<h1>All Users</h1></br>
<?php echo htmlspecialchars_decode($getUsersTable); ?>
当我运行代码时,它会给我一条错误信息说: 致命错误:不在对象上下文中时使用 $this
project_name/models/Model_Home.php:8
指的是Model_Home.php
中的下一行$result = $this->db->query($query);
我必须使用的 php 版本是 5.4(相当旧)。任何想法,请!
谢谢大家!
您已将 Model_Home::getUsers 定义为静态方法。这意味着它是 class 而不是实例化对象的方法,这反过来意味着您无法访问对象属性,只能访问 class 定义为 "static" 的属性和方法。 $db 未定义为 "static" 因此它是对象的 属性 而不是 class.
如果您想将 getUsers 保持为静态:
您可以将 $db 定义为 "static"(这将需要对引用它的任何代码进行其他代码更改),或者使用单例模式,从而将对象的实例存储为静态 class 变量,供其他 class 方法访问。例如:
class myClass
{
protected static $db = null;
public static function getDb()
{
if(empty(self::$db))
self::$db = new Database();
return self::$db;
}
}
如果您不关心保持 getUsers 静态:
只需从其声明中删除 "static" 关键字,您还必须更新此方法调用:
$this->f3->set('getUsersTable', Model_Home::getUsers());
至:
$modelHome = new Model_Home;
$this->f3->set('getUsersTable', $modelHome->getUsers());
首先,在尝试创建这种骨架之前,先熟悉一下 f3。您发布的代码似乎表明您可以充分利用一些您可能不熟悉的关键概念。
使用模板 使用 echo \Template::instance()->render('templates/controller_index.htm');
使用 F3 ORM 尽管与 Eloquent 等其他 ORM 相比,F3 ORM 确实加快了处理数据库的速度。在这里阅读:http://fatfreeframework.com/databases
$user=new DB\SQL\Mapper($db,'users');
$user->load(array('userID=? AND password=?','cheetah','ch1mp')); // load one user
$allusers = $user->find(); // get all users
根据您拥有的模型代码,我想说您完全可以不使用任何模型,使用 Mapper class 可以带您走很长一段路。
将配置存储在配置文件中。这会将配置信息与逻辑分开。
$f3->config("config.ini");
在那里定义的任何值都可以像全局一样访问
[globals]
DEBUG=0
CACHE=true
; Database
db.host=localhost
db.port=3306
db.user=root
db.pass=
db.name=phproject
; Session lifetime
; Also set session.gc_maxlifetime in php.ini
JAR.expire=604800
像这样...
// Connect to database
$f3->set("db.instance", new DB\SQL(
"mysql:host=" . $f3->get("db.host") . ";port=" . $f3->get("db.port") . ";dbname=" . $f3->get("db.name"),
$f3->get("db.user"),
$f3->get("db.pass")
));
如果在调用任何控制器之前将该代码放入索引文件中,则可以轻松调用数据库连接。使用 $f3->set("db.instance",...)
创建并设置连接
// get reference to instance and initialize mapper
$user = new DB\SQL\Mapper($f3->get("db.instance"),'users');
// get all records (same as SELECT * FROM $tablename) and put them inside all_users var
$f3->set('all_users', $user->find());
如果您随后在模板文件中使用此信息,您将执行类似这样的操作
<table>
<repeat group="{{ @all_users }}" value="{{ @user }}">
<tr>
<td>{{ @user.attrib1 }}</td>
<td>{{ @user.attrib2 }}</td>
<td>{{ @user.attrib3 }}</td>
</tr>
</repeat>
</table>