:: احصل علي ارخص رحلات الطيران والفنادق (آخر رد :فهد الشاعرى)       :: دورة الإحتراف في إدارة مخاطر المشاريع|دورات إدارة المشاريع مركزitr (آخر رد :ايمان محمد)       :: دورة الإحتراف في إدارة المشاريع وتطوير المهارات الإدارية والقيادية|دورات إدارة المشار (آخر رد :ايمان محمد)       :: دورة التحضير لشهادة مدير مشاريع معتمد وإكتساب المهارات|دورات إدارة المشاريع مركزitr (آخر رد :ايمان محمد)       :: دورة إستراتيجيات مكافحة غسل الأموال|دورات البنوك و المالية مركزitr (آخر رد :ايمان محمد)       :: دورة وسائل الدفع وآليات الضمان فى التجارة الخارجية وشروط البيوع الدولية incoterms 201 (آخر رد :ايمان محمد)       :: دورة تطبيقات الحوكمة فى القطاع المصرفى Governance|دورات البنوك و المالية مركزITR (آخر رد :ايمان محمد)       :: دورة التحكيم القضائي|دورات القانون والعقود مركزitr (آخر رد :ايمان محمد)       :: دورات تسويق مبيعات خدمة العملاء الاستثمار العقاري وفن البيع والتسويق (آخر رد :AHMEDBBMF)       :: دورة القانون الإداري وتطبيقاته فى منظومات الإدارة الحديثة|دورات القانون والعقود مركزi (آخر رد :ايمان محمد)      
اختر لونك:
وَقُلِ اعْمَلُوا فَسَيَرَى اللَّهُ عَمَلَكُمْ وَرَسُولُهُ وَالْمُؤْمِنُونَ ۖ وَسَتُرَدُّونَ إِلَىٰ عَالِمِ الْغَيْبِ وَالشَّهَادَةِ فَيُنَبِّئُكُم بِمَا كُنتُمْ تَعْمَلُونَ [ التوبة : ( 105 )] كلمة الإدارة

يرجى إختيار القسم المناسب قبل النشر وسيعاقب المخالف بإنذار أول مرة وسيتم حظره إذا تكرر ذلك كلمة الإدارة

يُمنع كتابة مواضيع السحر والشعوذة والروحانيات والابراج بكافة الأشكال والمخالف سيعاقب بحظر مؤقت وإذا تكرر سيكون حظر دائم تنبيه هام جداً



أضف رد جديد
 
LinkBack أدوات الموضوع انواع عرض الموضوع

قديم 23-02-2019, 04:49 PM   #1
تاريخ التسجيل: Feb 2019
المشاركات: 1,010
التقييم: 10
تاريخ التسجيل: Feb 2019
المشاركات: 1,010
التقييم: 10
افتراضي علاقات Eloquent والتحميل الحثيث في Laravel 5

علاقات Eloquent والتحميل الحثيث في Laravel 5


لقد وجدت أن جزءًا من النصّ البرمجي هو سبب تلك المشكلة. لقد كانت هناك ثلاث حلقات foreach تستعلم عن خاصيّة والخواص الفرعيّة التابعة لها. لقد كانت تعمل جيدًا إلى أن صار في قاعدة البيانات 5500 عنصرًا. وفيما يلي ما كان يحدث:

$main_object = MainObject::all();

foreach($main_object as $object) {
echo $object->some_property;
foreach($object->related_object as $related) {
echo $related->some_property;
echo $related->another_property;
}
foreach($object->another_related as $another) {
echo $another->some_property;
echo $another->another_property;
}
}
إذا كان الاستعلام ;()main_object = MainObject::all$ يعيد 5500 نتيجة، فستعيد حلقة foreach الأولى ذلك القدر أيضًا، وكذلك بالنسبة للثانية والثالثة. باستخدام ORM، كثيرًا ما يقع المبرمجون في فخّ كتابة استعلامات قواعد بيانات غير كفؤة، وتجعلها ORM أكثر صعوبة في الاكتشاف. تُسمّى هذه المشكلة بمشكلة N+1 (بالإنجليزيّة N+1 problem). وأظن المطور السابق لم يكن على علم بذلك. ولتفادي هذه المشكلة، نستخدم التحميل الحثيث (eager loading).

ما هو التحميل الحثيث؟
لتبسيط الأمر، التحميل الحثيث طريقة تُعنى بعمل كل شيء عند الطلب. وهذه الطريقة أيضًا على العكس تمامًا من التحميل الكسول (lazy loading) عندما ننفذ المهام عند الحاجة. يساعدنا التحميل الحثيث على تجنب مشكلات الأداء، كما رأيت في مثالي أعلاه. ستفهم الأمر أكثر من خلال مثال، لذا لنتخيل الوضع التالي:

pic1.thumb.png.94a71591d05847307fc3f46c8

لدينا نموذج علاقة هيئة محسّنة (بالإنجليزيّة: Enhanced Entity Relationship، واختصارًا EER)، بثلاث هيئات، كلّ منها مرتبطة بالأخرى. يمكنك أن تقرأ EER كما يلي: يمكن لكل عضو أن يملك العديد من المحلات، ولكن المحل الواحد ملك لعضو واحد فقط. يمكن للمحل الواحد أن يحوي العديد من المنتجات، ولكن المنتج الواحد لا يكون إلّا في محل واحد.

الخطوة التالية هي إنشاء نماذج Eloquent لهذه الهيئات:

العضو:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Member extends Model {
protected $fillable = ['username', 'email', 'first_name', 'last_name'];
public function stores() {
return $this->hasMany('App\\Store');
}
}
المحلّ:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Store extends Model {
protected $fillable = ['name', 'slug', 'site', 'member_id'];
public function member() {
return $this->belongsTo('App\\Member');
}
public function products() {
return $this->hasMany('App\\Product');
}
}
المُنتَج:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Product extends Model {
protected $fillable = ['name', 'short_desc', 'long_desc', 'price', 'store_id', 'member_id'];
public function store() {
return $this->belongsTo('App\\Store');
}
}
تخيّل أنك تبني تطبيقًا يسمح لمستخدميك أن يُنشئوا محالّهم التجاريّة الخاصّة. يمكن للمستخدمين –كما هو الحال بالنسبة للمحال الأخرى كلها طبعًا– أن يُنشئوا منتَجات عديدة. وأيضًا، يمكننا أن ننشئ صفحة واحدة تعرض كل المحلات وأفضل المنتجات لكل محلّ. شيء من قبيل هذا:

pic2.thumb.png.3d52edd250bc1561a13fdcd2d

يمكن أن ينتهي بك المطاف إلى الحصول على شيء كهذا في المتحكّم لديك:

<?php
namespace App\Http\Controllers;
use App\Repositories\StoreRepository;

class StoresController extends Controller {
protected $stores;
function __construct(StoreRepository $stores) {
$this->stores = $stores;
}
public function index() {
$stores = $this->stores->all();
return \View::make('stores.index')->with('stores', $stores);
}
}
وفي العرض الذي ستقدم فيه تلك البيانات:

@foreach($stores as $store)
<h1>{{ $store->name }}</h1>
<span>Owner: {{ $store->member->first_name . ' ' . $store->member->last_name }}</span><br>
<h2>Products:</h2>
@foreach($store->products as $product)
<h3>{{$product->name}}</h3>
<span>{{$product->short_desc}}</span><br/><br/>
<span>Price: {{$product->price}}</span><br/>
<?php Debugbar::info('Product displayed'); ?>
@endforeach
<br/>========================<br/>
@endforeach
والنتيجة كالتالي:

pic3.thumb.png.81f45d7561a7fe9028cc409f6

ومن اجل هذا المثال، زوّدت قاعدة البيانات بخمس مستخدمين، وثلاثة محالّ، وأربعة منتَجات. يقوم الاستعلام الأول باستدعاء كل المحال من قاعدة البيانات، وهذا هو الجزء +1 من مشكلة N+1. في هذا المثال تحديدًا، حرف N يمثّل عدد المحلات التي أرجعها لنا الاستعلام الأول، حيث أنها تمثل عدد المرات التي سنقوم فيها بالاستعلام select * from على جدولي products و members. وبما أن لدينا 3 محلات، فسنستعلم 3 مرات على جدول المستخدمين، وثلاث مرات على جدول المنتجات. وفي النهاية، قمنا بتنفيذ الاستعلامات بعدد مرات قدره 3+3+1.

تخيل الآن ما الذي يمكن أن يحدث لو كان لديك 5000 أو 10000 محل؟ سيكون لديك في تلك الحالة عشرة آلاف إلى عشرين ألف استعلام في كل مرة يقوم فيها أحد المستخدمين بزيارة الصفحة. وماذا لو كانت لديك عشرة آلاف أو مئة ألف زيارة كلّ أربع وعشرين ساعة؟ هذا كابوس! من الواضح الآن أن هذا التوجّه مدمّر للأداء. وبغض النظر عن نوع قاعدة البيانات التي تستخدمها، وعن مدى قوة الخادم الذي لديك، فستصل دائمًا إل تلك النقطة التي يقف فيها العتاد القوي لديك عاجزًا. يمكنك أن تحسّن الأداء بعمل cache لهذه الاستعلامات، باستخدام Redis على سبيل المثال. سيؤدي هذا الغرض، ولكن لبعض الوقت فقط. وبتلك الطريقة، أنت فقط تؤجل النهاية الحتميّة التي ستكلّفك الكثير من المال والوقت، وفي الغالب ستفقد بعض الزبائن، أو أنّ قاعدة بياناتك ستضعف كثيرًا.

وهنا يأتي التحميل الحثيث لينقذك من هذه الورطة. استخدام التحميل الحثيث في Laravel بسيط للغاية. العلاقات التي ترغب أن يتم تحميلها بشكل حثيث تحددها في طريقة with كما يلي:

$stores = Store::with('member','products')->get();
الآن، بدل استخدام 7 استعلامات، قلّلنا باستخدام التحميل الحثيث عدد الاستعلامات إلى 3 فقط:

pic4.thumb.png.6b36cfdc41ebbf5e138ee306e

وستكون ثلاثة استعلامات حتى ولو كانت لديك عشرة آلاف مدخلة في جدول المحلات. وكما ترى، فإن الاستخدام السليم للتحميل الحثيث يمكن أن يؤدي إلى تحسين أداء تطبيقك بقدر هائل. ولكي نحصل على تحسن للأداء بالفعل، فعلينا أن نوجد فهرسًا لحقل الهويّة id في جدولي members و products. ومع وجود كمّ هائل من السجلات، فإن تنفيذ (... ,'in( '1', '2 على حقل غير مفهرس سيأخذ وقتًا طويلًا.

وبعد هذه المقدمة عن التحميل الحثيث، هيا بنا نرى كيف يمكننا أن نستخدم العلاقات مع المستودعات.

تمديد فئة المستودع
سأريك طريقة واحدة يمكنك فيها أن تستخدم العلاقات في فئات مستودعات concrete. وهنا مثال عن النتيجة النهائيّة:

function __construct(StoreRepository $stores) {
$this->stores = $stores;
}

public function index() {
$stores = $this->stores->with('member', 'products')->all();
....
}
وكما ترى هنا، لدينا طريقة with يمكنك أن تسلسل فيها نموذج العلاقات. ستكون هذه الطريقة شبيهة بطريقة with في Laravel’s Query Builder.

public function with($relations) {
if (is_string($relations)) $relations = func_get_args();
$this->with = $relations;
return $this;
}
نحتاج الآن لأن نربط كلّ علاقة من العلاقات التي قمنا بتقديمها بالنموذج:

protected function eagerLoadRelations() {
if(!is_null($this->with)) {
foreach ($this->with as $relation) {
$this->model->with($relation);
}
}
return $this;
}
وها هو ذا، والشيء الوحيد الذي تبقّى هو أن نحدّث طريقة مستودع ()all (وأي شيء آخر ترغب بتحديثه) لاستخدام التحميل الحثيث:

public function all($columns = array('*')) {
$this->applyCriteria();
$this->newQuery()->eagerLoadRelations();
return $this->model->get($columns);
}
وكما سبق وذكرت، فيمكنك أن تضيف عدّة علاقات ضمن طريقة ()with. وفيما يلي مثال على StoresControler:

<?php
namespace App\Http\Controllers;
use App\Repositories\StoreRepository;

class StoresController extends Controller {
protected $stores;
function __construct(StoreRepository $stores) {
$this->stores = $stores;
}
public function index() {
$stores = $this->stores->with('member', 'products')->all();
return \View::make('stores.index')->with('stores', $stores);
}
}
وفي العرض يمكنك أن تعرض البيانات بالطريقة التي تريدها، ولغرض التجربة يكفي هذا:

@foreach($stores as $store)
<h1>{{ $store->name }}</h1>
<span>Owner: {{ $store->member->first_name . ' ' . $store->member->last_name }}</span><br>
<h2>Products:</h2>
@foreach($store->products as $product)
<h3>{{$product->name}}</h3>
<span>{{$product->short_desc}}</span><br/><br/>
<span>Price: {{$product->price}}</span><br/>
<?php Debugbar::info('Product displayed'); ?>
@endforeach
<br/>========================<br/>
@endforeach
وكما هو متوقع، لدينا الآن هذه الاستعلامات الثلاثة فقط:

pic5.thumb.png.61a6a34e29cafd231be676d20

الخلاصة
يمكنك باستخدام التحميل الحثيث أن تحسّن أداء تطبيقك. وأحيانًا، عندما يكبر التطبيق، حتى التحميل الحثيث ليس كافيًا للحفاظ على أعلى أداء. في الدرس التالي سأريك كيف يمكنك تجميل مستودعاتك لتقوم بعمل cache للاستعلامات من أجل أداء أفضل.

الفارس غير متواجد حالياً   اقتباس
قديم 27-07-2019, 10:44 AM   #2
الصورة الرمزية هديل الحرف
تاريخ التسجيل: Jul 2019
العمر: 30
المشاركات: 504
التقييم: 10
افتراضي

بارك الله فيك
إستمر ولك التوفيق بـإذن الله
تقديري وإحترامي
هديل الحرف غير متواجد حالياً   اقتباس
أضف رد جديد

الكلمات الدلالية (Tags)
منتديات رحيل, رحيل, شبكة رحيل, r7il, r7il.com


الذين يشاهدون محتوى الموضوع الآن : 1 ( الأعضاء 0 والزوار 1)
 

تعليمات المشاركة
لا تستطيع إضافة مواضيع جديدة
لا تستطيع الرد على المواضيع
لا تستطيع إرفاق ملفات
لا تستطيع تعديل مشاركاتك

BB code is متاحة
كود [IMG] متاحة
كود HTML معطلة
Trackbacks are متاحة
Pingbacks are متاحة
Refbacks are متاحة


المواضيع المتشابهه
الموضوع كاتب الموضوع المنتدى مشاركات آخر مشاركة
تثبيت Laravel 5 وإعداده على Windows وUbuntu الفارس قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 1 27-07-2019 10:40 AM
دليل مطوّري PHP للبدء في بناء تطبيقات Laravel - الجزء الثاني الفارس قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 1 26-07-2019 03:20 PM
المبادئ الأساسيّة لإطار العمل Eloquent ORM الفارس قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 1 26-07-2019 03:07 PM
كيف تستخدم منشئ الاستعلامات Query builder للتخاطب مع قاعدة البيانات في Laravel الفارس قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 1 26-07-2019 03:05 PM
إدارة علاقات الزوار vrm وتأثيرها على تجربة الاستخدام الفارس قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 0 02-03-2019 09:03 PM


الساعة الآن 01:21 AM

 


Content Relevant URLs by vBSEO ©2010, Crawlability, Inc.