【问题标题】:Laravel application architecture issue. Model being called between Controller & View?Laravel 应用程序架构问题。在控制器和视图之间调用模型?
【发布时间】:2014-10-17 22:31:44
【问题描述】:

我遇到的问题似乎暗示我不了解 Laravel 中的架构如何正常工作。我是 Laravel 的新手,但我以为我知道这一点。当客户端请求一个页面时,会调用一个控制器,它从模型中提取数据并将其传递给视图。如果前面的说法是正确的,那么为什么会出现这个问题:

在我的JourneyController

public function journey($id) {

    // Find the journey and the images that are part of the journey from the db
    $journey = Journey::find($id);
    $imagesInJourney = Journey::find($id)->images->keyBy('id');

    // Perform some manipulation on the article. THE ERROR OCCURS HERE. 
    $journey->article = str_replace('[[ ' . $image . ' ]]', $html, $journey->article);

    return View::make('journey', array(
        'journey' => $journey,
        'title' => $journey->name,
        'bodyClass' => 'article'
    ));
}

这个控制器被调用,并从我的Journey 模型(如下)中提取数据。特别是,我有一个属性,我称之为article,在发送到我的控制器之前我正在对其进行操作:

class Journey extends Eloquent {

    protected $table = 'journeys';
    protected $primaryKey = 'id';
    public $timestamps = false;

    // Database relationship
    public function images() {
        return $this->hasMany('Image');
    }

    // THIS IS THE PROBLEMATIC METHOD
    public function getArticleAttribute($value) {
        return file_get_contents($value);
    }

}

如您所见,我正在编辑 article 字段,它只是一个文件链接,并使用 PHP 的 file_get_contents() 函数将其替换为实际文件内容。所以我的理解是,当它返回到上面的控制器时,$journey->article 将包含 文章本身,而不是 它的 URL

然而,出于某种原因,我的控制器中的这个语句(我用图像替换了部分文章文本)导致了问题:

 $journey->article = str_replace('[[ ' . $image . ' ]]', $html, $journey->article);

journey.blade.php 的视图中,我尝试输出$journey->article,期望它是添加图像的文章文本,但我收到错误:

ErrorException (E_UNKNOWN) file_get_contents(*entire article content here*): failed to open stream:     Invalid argument (View: app/views/journey.blade.php)

为什么当我尝试调用str_replace() 时会发生这种情况?如果我将其注释掉,它会完美运行。

【问题讨论】:

    标签: php laravel eloquent file-get-contents


    【解决方案1】:

    由于您的 getArticleAttribute 方法在您第一次获取/回显此属性时被调用,所以没有问题(这是 str_replace 函数执行的地方)但是当您尝试再次获取文章属性时(这是您在视图页面中回显)您已经更改了属性的值,因此您的函数尝试再次执行 file_get_contents。

    解决方案是在旅程类中设置一个标志,并在执行 file_get_contents 时将其设置为 true,并为其他调用返回属性本身。

    喜欢;

    class Journey extends Eloquent {
    
        protected $table = 'journeys';
        protected $primaryKey = 'id';
        public $timestamps = false;
        private $article_updated = false;
    
        // Database relationship
        public function images() {
            return $this->hasMany('Image');
        }
    
        // THIS IS THE PROBLEMATIC METHOD
        public function getArticleAttribute($value) {
            if($this->article_updated){
                return $value;
            }
            else {
                $this->article_updated = true;
                return file_get_contents($value);
            }
    
        }
    
    }
    

    【讨论】:

    • 这似乎与 MVC 应该做的完全相反。有没有关于这个“功能”的文档?
    • 实际上这是关于 OOP,ORM 使用魔术 __get 函数作为模型属性,当您定义访问器时,它会调用您的访问器函数 (github.com/illuminate/database/blob/master/Eloquent/…) 在您的情况下,您的旅程模型具有一个文章属性,(在“受保护的”属性数组中定义的所有属性)并且每次您编写$journey->article ORM 的 __get 函数都会被调用,因此它是您的 get 访问器。您可以为此检查“封装”。
    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    相关资源
    最近更新 更多