【问题标题】:PHP fat free framework using $this when not in object context?不在对象上下文中使用 $this 的 PHP 无脂肪框架?
【发布时间】:2016-05-29 00:02:09
【问题描述】:

我正在使用fat free PHP framework 开发一个项目。在文档中,他们说你可以为项目构建自己的骨架,所以我的项目目录如下:

  • 资产
    • CSS
    • js
  • 控制器
    • Controller.php
    • Home_Controller.php
  • lib(有框架的东西)
  • 型号
    • 模型.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(相当旧)。有什么想法,请!

谢谢大家!

【问题讨论】:

  • “无脂肪”框架的好处在于它允许您按照自己的方式做事,而无需强加严格的规则。我建议从模型中取出数据库访问凭据,并使用 config(.ini) 文件来存储这些凭据。此外,不要让模型在每次调用其构造函数时都调用一个连接函数,而应该只连接一次并重用相同的连接。如果您对更多细节感兴趣,可以查看这个项目github.com/Alanaktion/phproject,我相信它的设置非常好
  • 你说得对,我曾尝试在代码的构造函数中建立一次连接,但没有成功。现在,每次我想执行查询时,我都会调用连接函数。你能帮我用我的骨架解决这个问题吗?谢谢丹尼尔!

标签: php model-view-controller pdo fat-free-framework


【解决方案1】:

首先,在尝试创建这种骨架之前,先对 f3 稍微熟悉一点。您发布的代码似乎表明您可以充分利用您可能不熟悉的几个关键概念。

使用模板使用echo \Template::instance()-&gt;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 类可以带您走很长一段路。

将配置存储在配置文件中。这会将配置信息与逻辑分开。

$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-&gt;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>

【讨论】:

  • 非常感谢丹尼尔的好例子。我会看看它并让你知道
【解决方案2】:

您已将 Model_Home::getUsers 定义为静态方法。这意味着它是类的方法而不是实例化的对象,这反过来意味着您无法访问对象属性,只能访问定义为“静态”的类属性和方法。 $db 未定义为“静态”,因此它是对象的属性,而不是类的属性。

如果您想让 getUsers 保持静态:

您可以将 $db 定义为“静态”(这将需要对任何引用它的代码进行其他代码更改),或者使用单例模式,将对象的实例存储为静态类变量以供其他人访问类方法。例如:

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());

【讨论】:

  • 好的,所以你说的是创建一个静态调用数据库的函数并将该函数放在 Model.php 中
  • 或者我刚刚添加的第二个选项
  • 您是否从函数声明中删除了“静态”?
  • 对不起,上传到服务器不起作用,所以它没有更改错误消息。现在错误消息是致命错误:调用非成员函数查询()对象
  • 调用 $this->connect();在任何数据库操作之前
猜你喜欢
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多