MVC (Laravel) tempat menambahkan logika

137

Katakanlah setiap kali saya melakukan operasi CRUD atau memodifikasi hubungan dengan cara tertentu saya juga ingin melakukan sesuatu yang lain. Misalnya, setiap kali seseorang menerbitkan posting saya juga ingin menyimpan sesuatu ke meja untuk analitik. Mungkin bukan contoh terbaik tetapi secara umum ada banyak fungsi "dikelompokkan" ini.

Biasanya saya melihat tipe logika ini dimasukkan ke dalam controller. Itu semua bagus dan keren sampai Anda ingin mereproduksi fungsi ini di banyak tempat. Ketika Anda mulai masuk ke sebagian, membuat API dan menghasilkan konten dummy itu menjadi masalah dengan menjaga hal-hal KERING.

Cara yang saya lihat untuk mengelola ini adalah peristiwa, repositori, perpustakaan, dan menambah model. Inilah pemahaman saya masing-masing:

Layanan: Di sinilah kebanyakan orang mungkin akan meletakkan kode ini. Masalah utama saya dengan layanan adalah bahwa kadang-kadang sulit untuk menemukan fungsionalitas spesifik di dalamnya dan saya merasa mereka dilupakan ketika orang-orang fokus menggunakan Eloquent. Bagaimana saya tahu saya perlu memanggil metode publishPost()di perpustakaan ketika saya bisa melakukannya $post->is_published = 1?

Satu-satunya syarat saya melihat ini berfungsi dengan baik adalah jika Anda HANYA menggunakan layanan (dan idealnya membuat Eloquent tidak dapat diakses entah bagaimana dari pengontrol secara bersamaan).

Pada akhirnya sepertinya ini hanya akan membuat banyak file tambahan yang tidak perlu jika permintaan Anda umumnya mengikuti struktur model Anda.

Repositori: Dari apa yang saya pahami ini pada dasarnya seperti layanan tetapi ada antarmuka sehingga Anda dapat beralih di antara ORM, yang tidak saya butuhkan.

Kejadian: Saya melihat ini sebagai sistem yang paling elegan karena Anda tahu acara model Anda akan selalu dipanggil dengan metode Eloquent, sehingga Anda dapat menulis pengendali seperti yang biasa Anda lakukan. Saya bisa melihat ini semakin berantakan dan jika ada yang punya contoh proyek besar menggunakan acara untuk kopling kritis saya ingin melihatnya.

Model: Secara tradisional saya memiliki kelas yang melakukan CRUD dan juga menangani coupling kritis. Ini sebenarnya membuat segalanya mudah karena Anda tahu semua fungsi di sekitar CRUD + apa pun yang harus dilakukan dengan itu ada di sana.

Sederhana, tetapi dalam arsitektur MVC ini biasanya tidak seperti yang saya lihat selesai. Dalam arti tertentu saya lebih suka ini daripada layanan karena sedikit lebih mudah ditemukan, dan ada sedikit file untuk melacak. Itu bisa agak berantakan meskipun. Saya ingin mendengar kejatuhan metode ini dan mengapa kebanyakan orang tampaknya tidak melakukannya.

Apa kelebihan / kekurangan masing-masing metode? Apakah saya melewatkan sesuatu?

Sabrina Leggett
sumber
3
Bisakah Anda meminimalkan pertanyaan Anda?
The Alpha
3
Anda juga dapat memeriksa ini .
The Alpha
1
"Bagaimana saya tahu saya perlu memanggil metode publishPost () di perpustakaan ketika saya bisa melakukan $ post-> is_published = 1?" Dokumentasi?
ceejayoz
salah satu keindahan tentang fasih dan ORMS adalah lebih mudah untuk bekerja dengan mereka tanpa banyak dokumen?
Sabrina Leggett
1
Terima kasih telah memposting ini. Saya kesulitan dengan masalah yang sama dan menemukan posting dan jawaban Anda sangat membantu. Pada akhirnya saya telah memutuskan bahwa Laravel tidak menyediakan arsitektur yang baik untuk apa pun yang melampaui situs web Ruby-on-Rails yang cepat dan kotor. Trates di mana-mana, kesulitan menemukan fungsi-fungsi kelas dan banyak sampah sihir otomatis di mana-mana. ORM tidak pernah berfungsi dan jika Anda menggunakannya, Anda mungkin harus menggunakan NoSQL.
Alex Barker

Jawaban:

171

Saya pikir semua pola / arsitektur yang Anda sajikan sangat berguna selama Anda mengikuti prinsip-prinsip SOLID .

Untuk tempat menambahkan logika, saya pikir penting untuk merujuk pada Prinsip Tanggung Jawab Tunggal . Juga, jawaban saya menganggap Anda sedang mengerjakan proyek menengah / besar. Jika ini adalah proyek throw-something-on-a-page , lupakan jawaban ini dan tambahkan semuanya ke pengontrol atau model.

Jawaban singkatnya adalah: Di mana masuk akal bagi Anda (dengan layanan) .

Jawaban panjangnya:

Controllers : Apa tanggung jawab Controllers? Tentu, Anda dapat menempatkan semua logika Anda di controller, tetapi apakah itu tanggung jawab controller? Saya kira tidak.

Bagi saya, controller harus menerima permintaan dan mengembalikan data dan ini bukan tempat untuk meletakkan validasi, memanggil metode db, dll.

Model : Apakah ini tempat yang baik untuk menambahkan logika seperti mengirim email selamat datang ketika pengguna mendaftar atau memperbarui penghitungan suara suatu posting? Bagaimana jika Anda perlu mengirim email yang sama dari tempat lain dalam kode Anda? Apakah Anda membuat metode statis? Bagaimana jika email itu membutuhkan informasi dari model lain?

Saya pikir model harus mewakili suatu entitas. Dengan LARAVEL, saya hanya menggunakan kelas model untuk menambahkan hal-hal seperti fillable, guarded, tabledan hubungan (ini karena saya menggunakan Pola Repository, jika model ini juga akan memiliki save, update, findmetode, dll).

Repositori (Pola Repositori) : Pada awalnya saya sangat bingung dengan ini. Dan, seperti Anda, saya pikir "baiklah, saya menggunakan MySQL dan hanya itu."

Namun, saya telah menyeimbangkan pro dan kontra menggunakan Pola Repositori dan sekarang saya menggunakannya. Saya pikir sekarang , pada saat ini, saya hanya perlu menggunakan MySQL. Tetapi, jika tiga tahun dari sekarang saya perlu mengubah ke sesuatu seperti MongoDB sebagian besar pekerjaan dilakukan. Semua dengan mengorbankan satu antarmuka tambahan dan a $app->bind(«interface», «repository»).

Acara ( Pola Pengamat ): Acara berguna untuk hal-hal yang dapat dilemparkan ke kelas mana saja kapan saja. Pikirkan, misalnya, mengirim pemberitahuan ke pengguna. Ketika Anda membutuhkan, Anda memecat acara untuk mengirim pemberitahuan di kelas aplikasi Anda. Kemudian, Anda dapat memiliki kelas seperti UserNotificationEventsitu yang menangani semua acara yang dipecat untuk pemberitahuan pengguna.

Layanan : Sampai sekarang, Anda memiliki pilihan untuk menambahkan logika ke pengontrol atau model. Bagi saya, masuk akal untuk menambahkan logika di dalam Layanan . Mari kita hadapi itu, Layanan adalah nama mewah untuk kelas. Dan Anda dapat memiliki kelas sebanyak yang masuk akal untuk Anda dalam aplikasi Anda.

Ambil contoh ini: Beberapa waktu yang lalu, saya mengembangkan sesuatu seperti Formulir Google. Saya mulai dengan CustomFormServicedan berakhir dengan CustomFormService, CustomFormRender, CustomFieldService, CustomFieldRender, CustomAnswerServicedan CustomAnswerRender. Mengapa? Karena itu masuk akal bagi saya. Jika Anda bekerja dengan tim, Anda harus menempatkan logika Anda di tempat yang masuk akal bagi tim.

Keuntungan menggunakan Layanan vs Pengontrol / Model adalah bahwa Anda tidak dibatasi oleh Pengontrol tunggal atau Model tunggal. Anda dapat membuat sebanyak mungkin layanan sesuai kebutuhan berdasarkan desain dan kebutuhan aplikasi Anda. Tambahkan juga keuntungan memanggil Layanan dalam kelas apa pun dari aplikasi Anda.

Ini berlangsung lama, tetapi saya ingin menunjukkan kepada Anda bagaimana saya menyusun aplikasi saya:

app/
    controllers/
    MyCompany/
        Composers/
        Exceptions/
        Models/
        Observers/
        Sanitizers/
        ServiceProviders/
        Services/
        Validators/
    views
    (...)

Saya menggunakan setiap folder untuk fungsi tertentu. Misalnya Validatorsdirektori berisi BaseValidatorkelas yang bertanggung jawab untuk memproses validasi, berdasarkan pada $rulesdan$messages validator tertentu (biasanya satu untuk setiap model). Saya dapat dengan mudah memasukkan kode ini ke dalam Layanan, tetapi masuk akal bagi saya untuk memiliki folder khusus untuk ini bahkan jika hanya digunakan dalam layanan (untuk saat ini).

Saya sarankan Anda untuk membaca artikel berikut, karena mereka mungkin menjelaskan hal-hal yang sedikit lebih baik kepada Anda:

Breaking the Mold oleh Dayle Rees (penulis CodeBright): Di sinilah saya menggabungkan semuanya, meskipun saya mengubah beberapa hal agar sesuai dengan kebutuhan saya.

Memisahkan kode Anda di Laravel menggunakan Repositori dan Layanan oleh Chris Goosey: Posting ini menjelaskan dengan baik apa itu Layanan dan Pola Repositori dan bagaimana mereka cocok bersama.

Laracasts juga memiliki Repositori yang Disederhanakan dan Tanggung Jawab Tunggal yang merupakan sumber daya yang bagus dengan contoh-contoh praktis (walaupun Anda harus membayar).

Luís Cruz
sumber
3
penjelasan yang bagus Di sinilah saya berdiri saat ini - dalam proyek saat ini saya meletakkan logika bisnis saya dalam model dan itu sebenarnya bekerja dengan sangat baik. Kita pasti perlu sedikit fudge SOLID, tapi, itu belum benar-benar membuat kita kesulitan. Cepat, agak kotor, tapi sejauh ini proyek kami sangat mudah dikelola karena sangat KERING. Saya benar-benar baik-baik saja dengan tetap berpegang pada mereka saat ini karena mereka menyelesaikan pekerjaan, tetapi dalam proyek masa depan saya mungkin hanya akan pergi dengan apa pun yang standar, yang kedengarannya seperti repositori.
Sabrina Leggett
2
Saya senang Anda menemukan cara yang masuk akal bagi Anda. Berhati-hatilah dengan asumsi yang Anda buat hari ini . Saya telah mengerjakan sebuah proyek selama 3+ tahun dan berakhir dengan pengontrol dan model dengan lebih dari 5000 baris kode. Semoga berhasil dengan proyek Anda.
Luís Cruz
juga agak kotor tapi saya berpikir tentang menggunakan ciri-ciri untuk menghindari model menjadi besar. Dengan begitu saya bisa memisahkan mereka sedikit
Sabrina Leggett
Artikel ini mengartikulasikan dengan baik KAPAN masuk akal untuk menggunakan layanan. Dalam Contoh formulir Anda, memang masuk akal untuk menggunakan layanan, tetapi ia menjelaskan bagaimana ia melakukannya, yaitu ketika logika terkait langsung dengan model yang ia masukkan ke dalam model itu. justinweiss.com/articles/where-do-you-put-your-code
Sabrina Leggett
Saya sangat suka penjelasannya. Ada satu pertanyaan yang saya miliki: Anda menyebutkan untuk tidak meletakkan validasi di controller, jadi di mana menurut Anda di mana tempat terbaik untuk melakukan validasi? Banyak yang menyarankan untuk memasukkannya ke dalam kelas Permintaan yang diperluas (dan juga apa yang saat ini kami lakukan), tetapi bagaimana jika saya tidak hanya ingin memvalidasi permintaan http, tetapi juga pada perintah tukang, dll, apakah ini benar-benar tempat yang bagus?
kingshark
24

Saya ingin mengirim jawaban untuk pertanyaan saya sendiri. Saya bisa membicarakan hal ini selama berhari-hari, tetapi saya akan mencoba untuk memposting ini dengan cepat untuk memastikan saya bangun.

Saya akhirnya menggunakan struktur yang ada yang disediakan Laravel, artinya saya menyimpan file saya terutama sebagai Model, View, dan Controller. Saya juga memiliki folder Perpustakaan untuk komponen yang dapat digunakan kembali yang sebenarnya bukan model.

SAYA TIDAK MENGAMBIL MODEL SAYA DALAM LAYANAN / PERPUSTAKAAN . Semua alasan yang diberikan tidak 100% meyakinkan saya tentang manfaat menggunakan layanan. Walaupun saya mungkin salah, sejauh yang saya bisa lihat mereka hanya menghasilkan banyak file kosong yang hampir saya butuhkan untuk membuat dan beralih antara ketika bekerja dengan model dan juga benar-benar mengurangi manfaat menggunakan fasih (terutama ketika datang ke model RETRIEVING , misalnya, menggunakan pagination, cakupan, dll).

Saya menempatkan logika bisnis DI MODEL dan akses fasih langsung dari pengendali saya. Saya menggunakan sejumlah pendekatan untuk memastikan bahwa logika bisnis tidak dilewati:

  • Pengakses dan mutator: Laravel memiliki pengakses dan mutator yang hebat. Jika saya ingin melakukan tindakan setiap kali posting dipindahkan dari konsep ke diterbitkan saya bisa menyebutnya dengan membuat fungsi setIsPublishedAttribute dan termasuk logika di sana
  • Mengesampingkan Buat / Perbarui dll: Anda selalu dapat mengganti metode Eloquent dalam model Anda untuk menyertakan fungsionalitas khusus. Dengan begitu Anda dapat memanggil fungsionalitas pada operasi CRUD apa pun. Sunting: Saya pikir ada bug dengan mengesampingkan buat di versi Laravel yang lebih baru (jadi saya menggunakan acara yang sekarang terdaftar di boot)
  • Validasi: Saya menghubungkan validasi saya dengan cara yang sama, misalnya, saya akan menjalankan validasi dengan mengesampingkan fungsi CRUD dan juga accessor / mutators jika diperlukan. Lihat Esensi atau dwightwatson / validasi untuk informasi lebih lanjut.
  • Metode Ajaib: Saya menggunakan metode set __get dan __ dari model saya untuk menghubungkan ke fungsionalitas yang sesuai
  • Memperluas Eloquent: Jika ada tindakan yang ingin Anda lakukan pada semua pembaruan / pembuatan, Anda bahkan dapat memperluas fasih dan menerapkannya ke beberapa model.
  • Acara: Ini adalah langkah maju dan umumnya disepakati untuk melakukan ini juga. Kelemahan terbesar dengan peristiwa yang saya pikir adalah pengecualian sulit untuk dilacak (mungkin bukan kasus baru dengan sistem acara baru Laravel). Saya juga suka mengelompokkan acara saya berdasarkan apa yang mereka lakukan alih-alih ketika mereka dipanggil ... misalnya, memiliki pelanggan MailSender yang mendengarkan acara yang mengirim surat.
  • Menambahkan Peristiwa Pivot / BelongToMany: Salah satu hal yang saya perjuangkan paling lama adalah bagaimana melampirkan perilaku pada modifikasi hubungan milikTomany. Misalnya, melakukan tindakan setiap kali pengguna bergabung dengan grup. Saya hampir selesai memoles perpustakaan khusus untuk ini. Saya belum menerbitkannya tetapi ini fungsional! Akan mencoba memposting tautan segera. EDIT Saya akhirnya membuat semua poros saya menjadi model normal dan hidup saya menjadi jauh lebih mudah ...

Mengatasi masalah orang dengan menggunakan model:

  • Organisasi: Ya jika Anda memasukkan lebih banyak logika ke dalam model, mereka bisa lebih lama, tetapi secara umum saya menemukan 75% dari model saya masih cukup kecil. Jika saya memilih untuk mengatur yang lebih besar saya dapat melakukannya dengan menggunakan ciri-ciri (misalnya, buat folder untuk model dengan beberapa file seperti PostScopes, PostAccessors, PostValidation, dll sesuai kebutuhan). Saya tahu ini belum tentu untuk apa sifatnya tetapi sistem ini berfungsi tanpa masalah.

Catatan tambahan: Saya merasa seperti membungkus model Anda dalam layanan seperti memiliki pisau tentara swiss, dengan banyak alat, dan membangun pisau lain di sekitarnya yang pada dasarnya melakukan hal yang sama? Ya, kadang-kadang Anda mungkin ingin melepas pisau atau memastikan dua bilah digunakan bersama-sama ... tetapi biasanya ada cara lain untuk melakukannya ...

KAPAN MENGGUNAKAN LAYANAN : Artikel ini mengartikulasikan dengan sangat baik contoh HEBAT untuk kapan menggunakan layanan ( petunjuk: itu tidak terlalu sering ). Dia mengatakan pada dasarnya ketika objek Anda menggunakan banyak model atau model di bagian aneh siklus hidupnya, itu masuk akal. http://www.justinweiss.com/articles/where-do-you-put-your-code/

Sabrina Leggett
sumber
2
Pikiran yang menarik dan valid. Tapi saya ingin tahu - bagaimana Anda menguji logika bisnis Anda jika dikaitkan dengan model yang terkait dengan Eloquent, yang terkait dengan basis data?
JustAMartin
code.tutsplus.com/tutorials/… atau Anda dapat menggunakan acara seperti saya katakan jika Anda ingin memecahnya lebih lanjut
Sabrina Leggett
1
@JustAMartin Anda yakin tidak bisa hanya menggunakan database dalam pengujian unit Anda? Apa alasannya untuk tidak melakukannya? Banyak orang setuju bahwa sering tidak apa-apa menggunakan database dalam unit test. (termasuk Martin Fowler, martinfowler.com/bliki/UnitTest.html : "Saya tidak memperlakukan menggunakan ganda untuk sumber daya eksternal sebagai aturan mutlak. Jika berbicara dengan sumber daya stabil dan cukup cepat untuk Anda, maka tidak ada alasan untuk tidak melakukan dalam tes unit Anda ")
Alex P.
@ AlexP11223 Ya, itu masuk akal. Saya mencoba mengintegrasikan SQLite sebagai basis data pengujian saya dan secara umum berjalan dengan baik, meskipun SQLite memiliki beberapa batasan serius yang harus diperhitungkan dalam migrasi Laravel dan kueri khusus (jika ada). Tentu saja, yang kemudian bukan semata-mata unit test tetapi tes fungsional, tetapi bahkan lebih efisien seperti itu. Namun, jika Anda ingin menguji model Anda dalam isolasi lengkap (sebagai tes unit ketat), mungkin memerlukan sejumlah kode tambahan yang terlihat (mengejek dll.).
JustAMartin
22

Apa yang saya gunakan untuk membuat logika antara pengontrol dan model adalah membuat lapisan layanan . Pada dasarnya, ini adalah alur saya untuk setiap tindakan dalam aplikasi saya:

  1. Kontroler mendapatkan tindakan yang diminta pengguna dan mengirim parameter dan mendelegasikan semuanya ke kelas layanan.
  2. Kelas layanan melakukan semua logika yang terkait dengan operasi: validasi input, pencatatan peristiwa, operasi basis data, dll ...
  3. Model menyimpan informasi bidang, transformasi data, dan definisi validasi atribut.

Beginilah cara saya melakukannya:

Ini metode pengontrol untuk membuat sesuatu:

public function processCreateCongregation()
{
    // Get input data.
    $congregation                 = new Congregation;
    $congregation->name           = Input::get('name');
    $congregation->address        = Input::get('address');
    $congregation->pm_day_of_week = Input::get('pm_day_of_week');
    $pmHours                      = Input::get('pm_datetime_hours');
    $pmMinutes                    = Input::get('pm_datetime_minutes');
    $congregation->pm_datetime    = Carbon::createFromTime($pmHours, $pmMinutes, 0);

    // Delegates actual operation to service.
    try
    {
        CongregationService::createCongregation($congregation);
        $this->success(trans('messages.congregationCreated'));
        return Redirect::route('congregations.list');
    }
    catch (ValidationException $e)
    {
        // Catch validation errors thrown by service operation.
        return Redirect::route('congregations.create')
            ->withInput(Input::all())
            ->withErrors($e->getValidator());
    }
    catch (Exception $e)
    {
        // Catch any unexpected exception.
        return $this->unexpected($e);
    }
}

Ini adalah kelas layanan yang melakukan logika terkait dengan operasi:

public static function createCongregation(Congregation $congregation)
{
    // Log the operation.
    Log::info('Create congregation.', compact('congregation'));

    // Validate data.
    $validator = $congregation->getValidator();

    if ($validator->fails())
    {
        throw new ValidationException($validator);
    }

    // Save to the database.
    $congregation->created_by = Auth::user()->id;
    $congregation->updated_by = Auth::user()->id;

    $congregation->save();
}

Dan ini adalah model saya:

class Congregation extends Eloquent
{
    protected $table = 'congregations';

    public function getValidator()
    {
        $data = array(
            'name' => $this->name,
            'address' => $this->address,
            'pm_day_of_week' => $this->pm_day_of_week,
            'pm_datetime' => $this->pm_datetime,
        );

        $rules = array(
            'name' => ['required', 'unique:congregations'],
            'address' => ['required'],
            'pm_day_of_week' => ['required', 'integer', 'between:0,6'],
            'pm_datetime' => ['required', 'regex:/([01]?[0-9]|2[0-3]):[0-5]?[0-9]:[0-5][0-9]/'],
        );

        return Validator::make($data, $rules);
    }

    public function getDates()
    {
        return array_merge_recursive(parent::getDates(), array(
            'pm_datetime',
            'cbs_datetime',
        ));
    }
}

Untuk informasi lebih lanjut tentang cara ini saya gunakan untuk mengatur kode saya untuk aplikasi Laravel: https://github.com/rmariuzzo/Pitimi

Rubens Mariuzzo
sumber
Sepertinya layanan adalah apa yang saya sebut perpustakaan di pos saya. Saya pikir ini lebih baik daripada repositori jika Anda tidak perlu menggunakan beberapa ORMS, tetapi masalahnya adalah Anda harus memigrasikan seluruh proyek Anda (yang tidak harus Anda lakukan dengan peristiwa), dan sepertinya itu agak hanya berakhir mencerminkan struktur Model sehingga Anda baru saja mendapatkan semua file tambahan ini. Mengapa tidak memasukkannya ke dalam model? Setidaknya dengan begitu Anda tidak memiliki file tambahan.
Sabrina Leggett
Itu pertanyaan menarik @SabrinaGelbart, saya telah diajarkan untuk membiarkan model mewakili entitas basis data dan untuk tidak memegang logika apa pun. Itulah alasan mengapa saya membuat file-file tambahan yang dinamai sebagai layanan: untuk menampung semua logika dan operasi tambahan. Saya tidak yakin apa arti seluruh peristiwa yang Anda gambarkan sebelumnya, tapi saya pikir dengan layanan dan menggunakan acara Laravel, kami dapat membuat semua metode layanan untuk memecat acara di awal dan akhir. Dengan cara ini peristiwa apa pun dapat sepenuhnya dipisahkan dari logika. Bagaimana menurut anda?
Rubens Mariuzzo
Saya diajarkan bahwa terlalu tentang model ... akan menyenangkan untuk mendapatkan penjelasan yang baik untuk alasan (mungkin masalah ketergantungan)?
Sabrina Leggett
Saya suka pendekatan ini! Saya telah mencari di internet untuk mendapatkan ide tentang bagaimana saya seharusnya menangani logika model, memeriksa Repositori tetapi sepertinya terlalu rumit dan tidak berguna untuk sedikit penggunaan. Layanan adalah ide yang bagus. Pertanyaan saya adalah setelah membuat folder Layanan di folder aplikasi, apakah Anda harus memasukkannya di bootstrap / start.php atau di mana saja untuk mem-boot karena saya melihat-lihat git Anda tidak dapat menemukannya? @RubensMariuzzo. Apakah itu secara otomatis menjadi tersedia selama aplikasi? jadi kita bisa menggunakan CongregationService :: getCongregations (); ??
Oguzhan
1
Jika semua yang Anda lakukan adalah $congregation->save();mungkin Anda tidak perlu Repositori. Namun, Anda mungkin melihat kebutuhan akses data Anda meningkat seiring waktu. Anda mungkin mulai memiliki kebutuhan untuk $congregation->destroyByUser()atau $congregationUsers->findByName($arrayOfSelectedFields);dan sebagainya. Mengapa tidak membatalkan layanan Anda dari kebutuhan akses data. Biarkan sisa aplikasi Anda bekerja dengan objek / array yang dikembalikan dari repo, dan hanya menangani manipulasi / pemformatan / dll ... Repo Anda akan tumbuh (tetapi membaginya menjadi file yang berbeda, pada akhirnya kompleksitas proyek harus berada di suatu tempat).
prograhammer
12

Menurut pendapat saya, Laravel sudah memiliki banyak pilihan bagi Anda untuk menyimpan logika bisnis Anda.

Jawaban singkat:

  • Gunakan laravel's Request untuk memvalidasi input Anda secara otomatis, dan kemudian bertahan data dalam permintaan (buat model). Karena semua input pengguna langsung tersedia dalam permintaan, saya yakin masuk akal untuk melakukan ini di sini.
  • Gunakan objek laravel Jobuntuk melakukan tugas-tugas yang memerlukan komponen individual, lalu kirimkan saja. kupikirJob mencakup kelas layanan. Mereka melakukan tugas, seperti logika bisnis.

Panjang (er) jawaban:

Gunakan Respositoris Ketika Diperlukan: Repositori pasti akan terlalu banyak digunakan, dan sebagian besar waktu, hanya digunakan sebagai accessormodel. Saya merasa mereka pasti memiliki beberapa kegunaan, tetapi kecuali Anda sedang mengembangkan aplikasi besar yang membutuhkan sejumlah fleksibilitas bagi Anda untuk dapat membuang laravel sepenuhnya, tinggal jauh dari repositori. Anda akan berterima kasih kepada diri sendiri nanti dan kode Anda akan jauh lebih jelas.

Tanyakan pada diri Anda apakah ada kemungkinan Anda akan mengubah kerangka kerja PHP atau ke tipe database yang tidak didukung laravel.

Jika jawaban Anda adalah "Mungkin tidak", maka jangan menerapkan pola repositori.

Selain di atas, jangan menampar pola di atas ORM hebat seperti Eloquent. Anda hanya menambahkan kompleksitas yang tidak diperlukan dan sama sekali tidak menguntungkan Anda.

Manfaatkan Layanan dengan hemat: Kelas layanan bagi saya, hanyalah tempat untuk menyimpan logika bisnis untuk melakukan tugas tertentu dengan dependensi yang diberikan. Laravel memiliki ini di luar kotak, yang disebut 'Pekerjaan', dan mereka memiliki lebih banyak fleksibilitas daripada kelas Layanan kustom.

Saya merasa seperti Laravel memiliki solusi menyeluruh untuk MVC masalah logika. Itu hanya masalah atau organisasi.

Contoh:

Minta :

namespace App\Http\Requests;

use App\Post;
use App\Jobs\PostNotifier;
use App\Events\PostWasCreated;
use App\Http\Requests\Request;

class PostRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title'       => 'required',
            'description' => 'required'
        ];
    }

    /**
     * Save the post.
     *
     * @param Post $post
     *
     * @return bool
     */
    public function persist(Post $post)
    {
        if (!$post->exists) {
            // If the post doesn't exist, we'll assign the
            // post as created by the current user.
            $post->user_id = auth()->id();
        }

        $post->title = $this->title;
        $post->description = $this->description;

        // Perform other tasks, maybe fire an event, dispatch a job.

        if ($post->save()) {
            // Maybe we'll fire an event here that we can catch somewhere else that
            // needs to know when a post was created.
            event(new PostWasCreated($post));

            // Maybe we'll notify some users of the new post as well.
            dispatch(new PostNotifier($post));

            return true;
        }

        return false;
    }
}

Pengendali :

namespace App\Http\Controllers;

use App\Post;
use App\Http\Requests\PostRequest;

class PostController extends Controller
{

   /**
    * Creates a new post.
    *
    * @return string
    */
    public function store(PostRequest $request)
    {
        if ($request->persist(new Post())) {
            flash()->success('Successfully created new post!');
        } else {
            flash()->error('There was an issue creating a post. Please try again.');
        }

        return redirect()->back();
    }

   /**
    * Updates a post.
    *
    * @return string
    */
    public function update(PostRequest $request, $id)
    {
        $post = Post::findOrFail($id);

        if ($request->persist($post)) {
            flash()->success('Successfully updated post!');
        } else {
            flash()->error('There was an issue updating this post. Please try again.');
        }

        return redirect()->back();
    }
}

Pada contoh di atas, input permintaan secara otomatis divalidasi, dan yang perlu kita lakukan hanyalah memanggil metode persistence dan mengirimkan Post baru. Saya pikir keterbacaan dan pemeliharaan harus selalu truf pola desain yang kompleks dan tidak dibutuhkan.

Anda kemudian dapat menggunakan metode bertahan yang sama persis untuk memperbarui posting juga, karena kami dapat memeriksa apakah posting sudah ada dan melakukan logika alternatif jika diperlukan.

Steve Bauman
sumber
tetapi - bukankah pekerjaan "seharusnya" harus antri? Kadang-kadang kita mungkin ingin antrian tetapi tidak setiap saat. Mengapa tidak menggunakan perintah saja? Bagaimana jika Anda ingin menulis beberapa logika bisnis yang dapat dieksekusi sebagai perintah atau acara atau antri?
Sabrina Leggett
1
Pekerjaan tidak perlu antri. Anda menentukan itu dengan mengimplementasikan antarmuka pada pekerjaan ShouldQueueyang disediakan Laravel. Jika Anda ingin menulis logika Bisnis dalam perintah atau acara, jalankan saja pekerjaan di dalam acara / perintah tersebut. Pekerjaan Laravels sangat fleksibel, tetapi pada akhirnya mereka hanya kelas layanan biasa.
Steve Bauman