doupao1978 2014-09-28 00:08
浏览 23
已采纳

结合功能

Trying to get my head around the logic for the following.

I have 3 images and two static functions. I believe it's possible to make one function but lack the knowledge of how to achieve this and putting the issue into words is hard, so google is of no help currently.

1 of the 3 images is outside of the foreach loop in the view, so in the model I created two public static functions. This is my issue, is there a better way to do this then use 2 functions?

Table in the database is "images" and consists of following:

  • id
  • image
  • page
  • list

Currently the Model looks like this:

class Images extends Eloquent {

public static function indexPageTL() 
  {
    $images = DB::table('images')
        ->where('page', 'index')
        ->whereBetween('list', array(0,1))
        ->orderBy('list', 'asc')
    ->get();

    return $images;
  }

  public static function indexPageMR() 
  {
    $images = DB::table('images')
        ->where('page', 'index')
        ->whereBetween('list', array(2,4))
        ->orderBy('list', 'asc')
    ->get();

    return $images;
  }
}

As you can see in the model I am using an array to select the items I need, so as to separate them (hence the two functions). I pass this to my services to better combine the data:

namespace Services;

use Images;

class IndexService
{
  public function indexData() 
  {
    $data = array(
      'images'  => Images::indexPageMR(),
      'imagesTL'  => Images::indexPageTL()
    );
    return $data;
  }
}

Then in my controller:

use Services\IndexService;

class IndexController extends BaseController
{

public function index() {
   return View::make('index', with(new IndexService())->indexData());
    }
}   

Finally in the view:

@foreach($imagesTL as $fetch)
 <img src="{{ $fetch->image }}" class="img-responsive">
 @endforeach 

//then further down the page I call the indexPageMR()

@foreach($imagesMR as $fetch)
 <img src="{{ $fetch->image }}" class="img-responsive">
 @endforeach 

Question is essentially, do I need 2 separate public static functions for this or can I combine them, if i can combine them how do I do it?

Apologies if this is unclear, as I said it's hard to put into words.

  • 写回答

1条回答 默认 最新

  • dongwu5801 2014-09-28 03:40
    关注

    There are two separate issues at play here: one is your question, can you combine your two image-gathering functions into one (i.e. simplifying the logic in your model); the other issue is the correct implementation of OOP principles, in order to make your code testable and flexible.

    (Disclaimer: I'm new to all this, too, so hopefully more experienced folks will chime in and correct any of my errors in the comments.)

    Before you delve into the OO way to deal with this, let's get your business logic itself to be a little simpler, more flexible, and more "Laravel-like".

    First, the model (which will ultimately change when you implement full OO principles):

    class Image extends Eloquent {
    
        public function scopeOnPage($query, $index)
        {
            return $query->wherePage($index);
        }
    
        public function scopeLocationBetween($query, $location)
        {
            return $query->whereBetween('list', $location);
        }
    
        public function getIndexPageImages($index, $location)
        {
            return $this->onPage($index)->locationBetween($location)->orderBy('list')->get();
        }
    
    }
    

    The changes here include:

    • Avoiding static functions; instead, the functions will act upon the Image object that we create elsewhere.
    • Making our primary method, getIndexPageImages, more flexible and reusable, rather than hardcoding in the values for location. Our model doesn't need to know about TL, MR, or what list values constitute those.
    • Taking advantage of Eloquent to make queries simpler and readable. I've used query scopes here, which will allow you to reuse that logic elsewhere in your model if needed.

    Now, from our controller, we can ask our Image model to give us exactly what we want (again, as with the model, this will change once you go full-OOP...but this is the starting point):

    class IndexController extends BaseController {
        public function showIndex($index)
        {
            $images = new Image;
            $data['images_TL'] = $images->getIndexPageImages($index, [0,1]);
            $data['images_MR'] = $images->getIndexPageImages($index, [2,4]); 
            return View::make('showIndex', with($data));
        }
    }
    

    ...and our route:

    Route::get('images/{index}', 'IndexController@showIndex');
    

    Our route passes along the index parameter to the controller. In the controller, we instantiate a new Image object, then ask it for the specific images we want, divided by TL and MR. (Since this logic is no longer hardcoded into our model, we have the flexibility to ask it for other groupings of images, if we wanted to, without having to go in and change our model.) We then pass that data to the view, where you would loop over $images_TL and $images_MR in foreach loops, as you are doing now.

    So now we have a 'thinner' model, a 'fat' controller (i.e. it contains logic that is best kept elsewhere), and while we are taking better advantage of the Eloquent object, we're still not fully-OO.

    Which leads to the second issue: how do you implement OOP correctly in a case like this, and, more generally, how to you learn how to do it?

    Our controller shouldn't have to gather data for the view, it should be given it (through dependency injection). And we need a layer of abstraction between our model and our controller, so that we're not so tightly coupled with the Eloquent ORM. The repository pattern would solve this, and take you to full-OOP nirvana.

    • The repository implements an interface, which sets out (as a 'contract') what methods the repository must have.
    • The repository communicates with the model to collect the data based on our 'business logic.'
    • Then, a service provider binds the interface and the repository together, so that we can inject the interface and Laravel will resolve the binding and serve up our repository.
    • Finally, inject the interface into the __construct method of the controller (or, in Laravel 5, you can inject it directly into a method, if the whole controller doesn't need it.)

    How you set these up depend in part on details of your application that aren't mentioned in your question. But here are a couple great, practical resources to help:

    Both of these books are well worth their price, for gaining a solid understanding of OOP and SOLID principles, and—more importantly—seeing them in action, applied to Laravel apps.

    Finally, subscribe to Laracasts and let Jeffrey Way teach you all of this like only he can.

    Good luck.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 数学建模,尽量用matlab回答,论文格式
  • ¥15 昨天挂载了一下u盘,然后拔了
  • ¥30 win from 窗口最大最小化,控件放大缩小,闪烁问题
  • ¥20 易康econgnition精度验证
  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能