【问题标题】:Models/Controller variables - Laravel模型/控制器变量 - Laravel
【发布时间】:2014-04-18 09:06:36
【问题描述】:

我一直在我的控制器中使用查询生成器,但是想开始使用 eloquent 和查询生成器。我想知道在两者之间传递变量的最佳实践。我已经阅读了文档,但仍然遇到问题。

这是我在控制器中的操作方式:

public function getRetailers($city) {    
    $locations = DB::table('retailers_listings')
        ->orderBy('country', 'asc')
        ->Where('city', $city)
        ->get();

        $this->layout->header = $city;
    $content = View::make('retailers.stores')
        ->with('header', $this->layout->header)
        ->with('store_listings', $locations)

        if (Request::header('X-PJAX')) {
        return $content;
        } else { 
            $this->layout->content = $content; 
        } 
    }

我将如何在 eloquent 和模型中执行上述操作?我如何将变量 $city 从视图中传递给模型。比文档给我的更深入的建议会很棒。

【问题讨论】:

    标签: php laravel-4 eloquent


    【解决方案1】:

    将您的模型作为依赖项注入到您的控制器中。

    在此示例中,为了简单起见,我指的是列表模型。

    class HomeController extends BaseController {
    
        protected $listing;
    
        // Type hint your model. This is laravels automatic resolution
    
        // It will automatically inject this dependency for you
    
        public function __construct(Listing $listing) 
        {
            $this->listing= $listing;
        }
    
        public function index()
        {
            $listings = $this->listing->whereTitle(Input::get['title'])->get();
    
            return View::make('listing' , compact($listings));
        }
    
    }
    

    更好的方法是使用可让您交换存储实现的存储库。

    查看this post 中的答案以获取更多信息。

    事实上,您可以在控制器中使用列表模型,而无需像这样的依赖注入

    Listing::all();
    

    但上述方法使它更清晰一些。

    更新

    我不确切知道您的应用程序的结构,所以我会尝试模仿。您可以更改文件和类名称以匹配您的实现。

    准备步骤

    1. 在您的应用文件夹下创建一个名为 Acme 的新文件夹(或任何您喜欢的文件夹)。此文件夹与控制器、模型、视图等位于同一级别。
    2. 在 Acme 文件夹中创建另一个名为 Repositories 的文件夹
    3. 在 Repositories 文件夹中创建一个名为 RetailerRepository.php 的新文件
    4. 编辑根目录中的 composer.json 文件并添加一个 prs-0 部分,以便自动加载我们的新闻类

      "autoload": {
      "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/tests/TestCase.php" ], "psr-0": { Acme": "app/Acme" } }

    5. 在您的控制台中运行 composer dumpautoload -o 即可完成

    现在让我们编写一些代码

    我假设你的 ORM 是

    class Retailer extends Eloquent{}
    

    编辑您的 Acme/Repositories/RetailerRepository.php 使其如下所示:

    <?php namespace Acme/Repositories
    
    use Retailer;
    
    class RetailerRepository {
    
      public function getLocations($city) {
    
        return Retailer::whereCity($city)->orderBy(‘country’, ‘asc’)->get();
    
      }    
    }
    

    编辑您的控制器,使其看起来像这样。我使用通用名称,但您可以切换到自己的名称。

    <?php
    
    use Acme/Repositories/RetailerRepository;
    
    class RetailersController extends BaseController {
    
      protected $repo;
    
      public function __construct(RetailerReposiroty $repo) {
    
        $this->repo = $repo;
      }
    
      public function index($city) {
    
        // I assume that the route is 
    
        // Route::get('retailers/{city}','RetailersController@index')
    
        $locations = $this->repo->getLocations($city);
    
        // I keep it simple here but you can do whatever you want
    
        return View::make('retailers.stores')->with('stores', $locations);
      }
    
    }
    

    正如您现在所看到的,您的控制器不知道数据来自哪里,但它知道如何访问它。它不必知道您的数据在 MySQL 中是否可用。知道在某处可用就很好了。此外,通过以这种方式构建您的应用程序,现在您可以使用您喜欢的任何控制器的存储库功能,只需将存储库作为构造函数中的依赖项注入即可。在一个复杂的应用程序中,您可能会使用一个 RetailerRepositoryInterface 和多个具体的实现,但让我们在这里保持简单。

    现在,您的应用程序是否需要提供例如?计费能力。在 Acme 下创建一个名为 Services 的新文件夹,并在那里定义您的服务提供者。不要用业务逻辑来膨胀你的控制器。根据您的需要构建您的 Acme 文件夹。这是你的应用程序!

    有一个常见的误解,即模型只是一个类(例如,在我们的例子中扩展了 Eloquent 的 Retailer 类)。这种误解,连同“胖模型瘦控制器”的说法,导致许多人认为他们必须将所有业务逻辑从控制器中取出(这绝对正确)并将其放在一个简单的类中(这绝对错误)。

    您的模型(MVC 中的 M)不仅仅是一个类。它是一个包含领域实体、数据抽象、服务提供者等的层。

    希望我能帮上忙。

    【讨论】:

    • 这篇文章帮助我更好地理解了,但是你能用我上面的代码给我一个例子吗?
    猜你喜欢
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2011-05-30
    • 2013-09-24
    相关资源
    最近更新 更多