Skip to main content

Command Palette

Search for a command to run...

Laravelda ma'lumotlar bazasi bilan ishlashda hisobga olishingiz kerak bo'lgan - 8 ta foydali maslahat

Updated
7 min read
Laravelda ma'lumotlar bazasi bilan ishlashda hisobga olishingiz kerak bo'lgan -  8 ta foydali maslahat

Laravel da loyihalarini yaratish qulay va o'zining yuqori intuitivligi (tushunarli) bilan mashhur hisoblanadi. Laravel fraymvorkida dasturchilar ishni yengilashtiruvchi juda ko'plab qulayliklar mavjud. Albatta ma'lumotlar bazasi bilan ishlaganizda ham bu qulaylik va funksionallardan foydalana olasiz. Bunda sizga eng katta yordamchi sifatida Laravel documentatsiyasi keltirilgan havoliani ko'rsatishimiz mumkin.Shunga qaramay, quyida men dokumentatsiyada to'liqroq keltirilmagan misollar bilan bir nechta maslahatlarni keltirib o'taman. Bu ma'lumotlarni ishingizda hisobga olsangiz loyihalaringiz mustahkam bo'lib, tunlari behavotir uxlashingiz mumkin.

Ma'lumotlar bazasi bilan bog'lanish

Laravelda yangi loyiha uchun ko'pincha ma''lumotlar bazasi bilan bog'lanishingiz kerak buladi va MB ga kerakli konfiguratsiyalarni kiritishingiz zarur. Bu konfiguratsiyalarni kiritish laravelda juda qulay ko'rinishda keltirilgan. Loyihaning asosiy papkasida joylashgan .env fayl mavjud bo'lib unda quyidagi konfiguratsiyalar keltirilgan qatorini topib kerakli parametrlarni kiritib chiqasiz:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_db_name
DB_USERNAME=your_db_user
DB_PASSWORD=your_db_pass

Loyiha uchun sizda ma'lumotlar bazasi(MySQL,PostgreSQL) serverlaridan foydalanishingiz mumkin. Ba'zi paytda ayniqsa kichik loyihalarda SQLiteni ishlatishingiz ham mumkin. Buning uchun siz database/database.sqlite faylini yaratib .env faylda quyidagi qatorni kiritasiz:

DB_CONNECTION=sqlite

Ma'lumotlar bazasi ulanishni yakunlaganingizdan so'ng u bilan ishlashingiz optimizatsiya qilishingiz mumkin.

1. DB::transaction()

MB tranzaksiyalari bilan ishlash uchun loyihalarimizda uchraydigan zadachalar(task, topshiriq) asosida misol ko'rib chiqarmiz. Aytaylik sizning loyihangizdagi foydalalanuvchilar to'lov qilgandan so'ng pullik funksionallarni ruxsat berishingiz yoki aytaylik foydalanuvchi statusini "cheklangan" dan "premium" statusga o'zgartirishingz kerak. Buni amalga oshirishda quyidagi misoldan foydalanishingiz mumkin. Laravel controlleringiz quyidagicha ko'rinishi mumkin:

public function store()
{
    Payment::where(['user_id' => auth()->user()->id])->update(['payment_success' => 1]);
    UserPoint::create([
        'user_id' => auth()->user()->id,
        'points' => 1000,
    ]);
    UserStatus::where(['user_id' => auth()->user()->id])->update(['status' => 'premium']);
}

Yuqoridagi kod ishlasada, agarda kodda bazaga jo'natilayotgan ikkita so'rovdan birortasi xatolik berib ishlamay qolsa ham foydalanuvchining status o'zgarishi yoki aksincha yuqoridagi ikkita so'rov ishlab foydalanuvchi statusi o'zgarmasdan qolish ehtimoli bor.

DB::transaction() metodi bu kabi muammolarni hal qilishda yordam beradi. Agar yuqoridagi holatda ma'lumotlar bazaga kiritilmasa yoki o'zgarish qila olamasa ya'ni error beradigan bo'lsa sizning bundan oldingi ma'lumotlaringiz bazadan o'chib ketmaydi olindingi holatiga qaytadi :

{
    DB::beginTransaction();

    try {
        Payment::where(['user_id' => auth()->user()->id])->update(['payment_success' => 1]);
        UserPoint::create([
            'user_id' => auth()->user()->id,
            'points' => 1000,
        ]);
        UserStatus::where(['user_id' => auth()->user()->id])->update(['status' => 'premium']);

        DB::commit();
    } catch (\Exception $e) {
        DB::rollBack();
    }
}

2. MB ga so'rov jo'naitshda if shartini when sharti bilan almashtirish

Odatda biz bazadan ma'lumotlarni olishda ma'lum bir shartlardan foydalanamiz. Misol uchun MB dan barcha foydalanuvchilar yoki statusiga qiymatiga qarab foydalanuvchilarni chiqarish (Bravzerdan kelayotgan so'rovda active parametrni mavjud bo'lsa foydalanvuchilar jadvalidagi status ustuni request dagi active qiymatiga teng bo'lishi kerak).

public function index()
{
    $users = User::orderBy('name', 'ASC');

    if (request()->has('active')) {
        $users->where('active', \request('active'));
    }

    $users->get();
}

Yuqoridagi kodni if shart operatorini ishlatmasdan Eloquent metodi yordamida realizatsiya qilishimiz mumkin:

public function index()
{
    $users = User::orderBy('name', 'ASC')
        ->when(request()->has('active'), function ($query) {
            $query->where('active', request('active'));
        })
        ->get();
}

3. Modelda ma'lumotlar o'zgartirish

Faraz qilaylik siz mahsulotlar haqidagi ma'lumotlarni MBda products jadvalida saqlaysiz. Ba'zida mahsulot narxini saqlashda valyuta sifatida so'm emas tiyin tanlashingiz mumkin ammo foydalanuvchilarga chiqarishda siz so'mda chiqarasiz. Shu sababli , mahsulot narxi 2000 so'm MB da 200 000 tiyin ko'rinishida saqlanishi mumkin. Siz foydalanuvchiga narxni chiqarishda siz so'm dan foydalansiz va interfeysga chiqarishda tiyindan so'mga o'tishingiz lozim. Bu operatsiyani siz Eloquent da accessor metodlari yordamida realizatsiya qilishingiz mumkin. Bu haqida Laravel dokumentatsiyasida to'liq ma'lumot berilgan.

Agarda siz narxlar (prices) attributida barcha valyutadagi kurslarni ham qo'shib chiqarmoqchi bo'lsangiz u holatda siz getPricesAttribute metodini modelda yaratib unda kerakli valyuta bo'yicha kerakli kurslarni hisob kitoblarni qaytarishingiz va $appends nomli model o'zgaruvchisini qo'shasiz:

class Product extends Model
{
    protected $appends = ['prices'];

    public function getPricesAttribute()
    {
        return [
            'UZS' => $this->price, 
            'USD' => $this->price, // Bu joyda siz narxni $ konvertatsiya qilishingiz mumkin.
            'EUR' => $this->price, // Bu joyda siz narxni EURO konvertatsiya qilishingiz mumkin.
        ];
    }
}

4. O'zaro bog'langan jadvallar orasidagi bog'liq ma'lumotlarni avtomatik o'chirish

Jadvallar orasidagi eng ko'p uchraydigan bog'lanish turlaridan biri bu birga ko'p bog'lanish. Dasturchi programma yozayotganda bu programma kamida 2-3 yil ishlatilishi hisobga olib ketadi. Aytaylik sizda foydalanuvchilar haqida ma'lumotni saqlovchi users jadvali mavjud va foydalanuvchilar kontakt ma'lumotlarni saqlash uchun alohida contacts jadvali bor. Ushbu dastur ko'proq yillar xizmat qilishini maqsad qilgan bo'lsangiz foydalanuvchi haqida ma'lumotlar users jadvalidan o'chirilganda contacts jadvalidan ham ushbu foydalanuvchiga bog'liq kontaktlarni o'chirib tashlashingiz kerak bo'ladi. Aks holatda, ma'lumotlar bazangizdagi contacts jadvalingiz yillar o'tib keraksiz ma'lumotlarga ya'ni foydalanuvchisi nomalum bo'lgan kontakt ma'lumotlariga to'lib ketadi.

Bu holatda siz bir nechta yechimlarni qo'llashinshingiz mumkin,tavsiya qilinadigan usullardan biri bu migratsiya vaqtini buni hisobga olib ketishdir.

Dastlabki holatda contacts jadvali migratsiyas faylli quyidagi ko'rinishga ega bo'ladi deb hisoblasak:

public function up()
{
    Schema::create('contacts', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('user_id');
        $table->string('fist_name');
        $table->string('last_name');
        $table->string('address');
        $table->string('email');
        $table->timestamps();
    });
}

user_id ustuni o'ylaganingizdek users jadvalidagi mos foydalanuvchi id sini o'zida saqlaydi. Shu sababli, siz o'zaro bog'lanishni contacts migratsiyasida qayt etishingiz va agar users jadvalida ma'lumot o'chirilsa contacts javdalida ma'lumotlarni o'chirish ni yozib ketishingiz mumkin.

public function up()
{
    Schema::create('contacts', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('user_id');
        $table->string('first_name');
        $table->string('last_name');
        $table->string('address');
        $table->string('email');
        $table->timestamps();

        $table->foreign('user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');
    });
}

5. foreach o'rniga map() ishlatish

Yuqoriroqdagi keltirilgan misollarda bazadan olingan ma'lumotlarni ekranga chiqarishdan oldin ma'lum bir o'zgartirishlarni kiritishimiz mumkin . Albatta buning uchun siz foreach sikl operatorini ishlatishingiz mumkin:

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::all();

        foreach ($products as $product) {
            $product->price = $product->price / 100;
            $product->currency = 'EUR';
        }
    }
}

Biroq, odatdagidek Laravel bu holat uchun yaxshiroq yechimni taklif qilgan. Siz foreach o'rniga map() funksiyasini ishlatishingiz mumkin:

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::query()->get()->map(function (Product $product) {
            $product->price = $product->price / 100;
            $product->currency = 'EUR';

            return $product;
        });
    }
}

6. Sana bo'yicha qidirishning qulayroq usuli

Laravel dokumentatsiyasiga ko'ra sana formati Y-m-d H:i:s ko'rinishda keladi . Bu formatdan foydalanib siz ma'lumot vaqt oralig'idagi ma'lumotlarni whereDate, whereMonth, whereDay, whereYear or whereTime methodlaridan foydalanib chiqarishingiz mumkin. Quyida misollar keltirilgan:

$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', ’14:13:58')->get();

7. N+1 problem

Ikkita jadval o'rtasida o'zaro bog'lanish o'rnatish Laravel super oson va sodda. Laravel fraymevorkida foydalaniladigan yechim juda ko'p ustunlari bo'lishi bilan birga ba'zi kamchiliklar ham bor. Yuqoridagi bir ko'p bog'lanishda keltirilgan foydalanuvchilar va ularning kontaktlari misoliga qaytaylik. O'zaro bog'lanish quyidagicha keltirilgan:

class User extends Authenticatable
{
    public function contacts()
    {
        return $this->hasMany(Contact::class);
    }
}

Aytaylik, barcha foydalanuvchilar va ularning kontakt ma'lumotlari bilan ekranga chiqarmoqchi bo'lsangiz:

public function index()
{
    $users = User::all();

    foreach ($users as $user) {
        echo $user->name;

        foreach ($user->contacts as $contact) {
            echo $contact->last_name;
        }
    }
}

Baxtga qarshi, ishingizni yenglashtirib berayotgan Eloquent funksionallari ishlatish orqali berilgan topshiriqni tez bajarish mumkin ammo siz bu kod aslida qanday ishlashini ko'ra olmasligingiz mumkin. Baxtingizga bu holatda sizga Laravelning yana bitta instrumenti Telescope yordam beradi. Bu instrument yordamida siz bazaga yuborayotgan so'rovlaringiz statistikasi va sql formatini ko'rishingiz mumkin:

Checking what exactly the Laravel database query looks like using Telescope tool

Rasmdagi ko'rganingizdek, laravel dastlab barcha foydalanuvchilar bazadan yuklab olib keyin alohida har bitta foydalanuvchi kontakt ma'lumotlarni yuklab olyapdi. Bu dastur ishlashiga yomon tasir qiluvchi kamchiliklardan biri. Agar foydalanuvchilar soni ko'p bo'lsa, yuqoridagi yechimda siz juda ko'p bazaga ortiqcha so'rovlar jo'natishingizga to'gri keladi. Bu muammoning yechimda aslida juda oson. Siz all() metodi o'rniga with() metodidan foydalanishingiz va so'rov vaqtida contacts bog'lanishlarni birga yuklab olishingiz kerak bo'ladi.

public function index()
{
    $users = User::with('contacts')->get();

    foreach ($users as $user) {
        echo $user->name;

        foreach ($user->contacts as $contact) {
            echo $contact->last_name;
        }
    }
}

8. Relationship orqali bog'langan ma'lumotlarni saralash

Aytaylik sizda yuqoridagi kod misolida foydalanuvchi kontaktlarini alifbo bo'yicha saralab chiqish masalasi qo'yildi. Quyidagi misolda siz buni amalga oshirishingiz mumkin:

$users = User::with(['contacts' => function ($query) {
    $query->orderBy('last_name', 'ASC');
}])->get();

Albatta agar siz har safar bir xil parametr orqali saralashingiz kerak bo'lsa u holda User modelda contacts metodi ichida bog'lanishni kiritib ketishingiz mumkin. Masalan User va Contact modellari o'rtasida quyidagicha bog'lanish o'rnatilgan bo'lsin:

public function contacts()
{
    return $this->hasMany(Contact::class);
}

orderBy metodi yordamida natijalarni istalgan ko'rinishda saralab olishingiz mumkin:

public function contacts()
{
    return $this->hasMany(Contact::class)
        ->orderBy('last_name' ,'ASC');
}

Laravel yangiliklaridan doim xabardor bo'ling.

Laravel doim dasturlashda qulay yechimlar taklif qilib yangilanib boradi. Shuning uchun ham siz bilimlaringizni yangilab turishingiz yangiliklarni o'rganib borishingiz lozim. Laravelning yangi versiyalari har yili tizimli ravishda o'zgarishlar va zamoniy yangiliklar qo'shilib turadi.

More from this blog

Rashidov Nuriddin

34 posts