2017-01-16 19 views
0

У меня есть ряд функций, которые используются большинством моих моделей
, поэтому имеет смысл хранить их централизованно, а не повторять код.Laravel - где хранить общие функции модели и как получить к ним доступ от контроллеров?

Например, у меня есть функция, которая находит случайную строку из какой таблицы мне нужно:

function getRandomRow() { 
    $rowCount = DB::connection('mydatabasename') 
       ->table('my_table_name') 
       ->selectRaw("FLOOR(RAND() * COUNT(*)) AS offset") 
       ->first(); 

    $offset = $rowCount->offset; 

    $randomRow = DB::connection('mydatabasename') 
        ->table('my_table_name') 
        ->select() 
        ->offset($offset) 
        ->limit(1) 
        ->first(); 

    return $randomRow; 
} 

Я смотрел на inheritance (распространяется) и traits - а также docs on polymorphic relations - но это не так который наиболее эффективен и как получить доступ к имени таблицы (связанной с используемой моделью) в рамках общей функции.

Мои вопросы:
- где я могу поместить эту функцию, чтобы она могла использоваться всеми моделями?
- как написать код, чтобы 'my_table_name' использовал правильную таблицу моделей?

+0

ли вы найти решение? Я отправил свое решение ниже – Gayan

ответ

0

Простым решением, которое я нашел, является создание родительской модели/класса - как указано в this answer на другой вопрос - для текущего примера назовем его BaseModel.

Для Laravel это хранится вместе с другими моделями, непосредственно в App каталоге

... в моем случае родительская модель/класс может быть abstract как это не нужно иметь свой собственный стол (также означая BaseModel функции могут быть доступны только через дочернюю модель):

namespace App; 

use Illuminate\Database\Eloquent\Model; 

abstract class BaseModel extends Model 
{ 
    // ...put common model functions here 
} 

трюк, чтобы получить эту работу (где BaseModel функции нужно будет получить доступ к таблице на правах ребенка модели) заключается в следующем:
- у каждого детская модель/класс extendBaseModel класса
- убедитесь, что $table определяется во всех дочерних моделях - как отмечено here:

class MyFunkyModel extends BaseModel 
{ 
    protected $table = 'funktown'; 

    // ...put child specific functions here 

} 

что означает $this->table может быть использован в BaseModel абстрактного родительского класса для ссылки на назначенном $table ребенка модель/класс:

namespace App; 

use Illuminate\Database\Eloquent\Model; 
use Illuminate\Support\Facades\DB; 

abstract class BaseModel extends Model 
{ 
    function getRandomRow() { 
     $rowCount = DB::connection('mydatabasename') 
         ->table($this->table) 
         ->selectRaw("FLOOR(RAND() * COUNT(*)) AS offset") 
         ->first(); 

     $offset = $rowCount->offset; 

     $profileRow = DB::connection('mydatabasename') 
         ->table($this->table) 
         ->select() 
         ->offset($offset) 
         ->limit(1) 
         ->first(); 

     return $profileRow; 
    } 
} 

Теперь от контроллера вы можете получить доступ к любой функции, хранящейся в BaseModel просто с помощью модели (ы) ребенка:

namespace App\Http\Controllers; 

use App\MyFunkyModel; 
use App\MySeriousModel; 
use App\MyHappyModel; 

class MyController extends Controller 
{ 
    public function getRandomName($type){ 
     switch ($type) { 
      case 'funky': 
       $modelFunky = new MyFunkyModel; 
       $funkyRow = $modelFunky->getRandomRow(); 
       $randomName = $funkyRow->funky_name_column; 
       break; 
      case 'serious': 
       $modelSerious = new MySeriousModel; 
       $seriousRow = $modelSerious->getRandomRow(); 
       $randomName = $seriousRow->serious_name_column; 
       break; 
      case 'happy': 
       $modelHappy = new MyHappyModel; 
       $happyRow = $modelHappy->getRandomRow(); 
       $randomName = $happyRow->happy_name_column; 
       break; 
     return $randomName; 
    } 
} 
2

Вы можете использовать оба inheritance и trait для этого. Но настоятельно рекомендуем использовать модели Eloquent, а не DB::table(). Причина в том, что если каким-то образом имя таблицы изменилось, вы должны изменить ее повсюду. С Eloquent вам нужно только указать название таблицы один раз в вашей модели.

protected $table = 'new_table_name' 

наследованием

структуру, которую вы BaseModel и class следующим образом.

class BaseModel extends Model { 
    public static function getRandomRow() 
    { 
     $rowCount = self::selectRaw("FLOOR(RAND() * COUNT(*)) AS offset") 
      ->first(); 

     $offset = $rowCount->offset; 

     $randomRow = self::select() 
      ->offset($offset) 
      ->limit(1) 
      ->first(); 

     return $randomRow; 
    } 
} 

class YourModel extends BaseModel { 
    // getRandomRow() available here 
} 

используя Черту

структуру вашей trait и class следующим образом.

trait BaseTrait { 
    public static function getRandomRow() 
    { 
     $rowCount = self::selectRaw("FLOOR(RAND() * COUNT(*)) AS offset") 
      ->first(); 

     $offset = $rowCount->offset; 

     $randomRow = self::select() 
      ->offset($offset) 
      ->limit(1) 
      ->first(); 

     return $randomRow; 
    } 
} 

class YourClass { 
    use BaseTrait; 
    // getRandomRow() available here 
} 

В любом случае вы можете получить доступ к методу, как

class yourController { 
    public function youMethod() 
    { 
     $rows = YourModel::getRandomRow(); 
    } 
} 
+0

Спасибо за ответ. Есть ли какая-то причина использовать статические функции - очевидно, необходимые с помощью «Черты и помощники» - с наследованием типа BaseModel? Хотя это технически возможно, он создает некорректный код в некотором смысле - половина ваших функций в модели будет вызвана 'MyModel-> modelFunction()' и наполовину с помощью 'MyModel :: modelFunction()' - это еще один speedhump в (помня, какие функции находятся в 'MyModel', и которые находятся в' BaseModel'). – goredwards

+0

также спасибо за совет по Eloquent vs Query Builder - мы нашли Eloquent слишком строгим для сложных запросов, поэтому мы используем только Query Builder. Кроме того, вы можете использовать '$ this-> table' в QB, чтобы избежать повторения имени таблицы, что делает его таким же, как Eloquent для этой цели. Наши имена таблиц меняются очень редко, и большинство IDE имеют достаточно компетентные функции поиска/замены в наши дни, поэтому я не уверен, что это прерыватель транзакций. – goredwards