लारवेल में अनुमति के लिए फ़िल्टर करते समय प्रदर्शन के लिए सबसे अच्छा तरीका


9

मैं एक ऐसे एप्लिकेशन पर काम कर रहा हूं, जहां एक उपयोगकर्ता के पास कई अलग-अलग परिदृश्यों के माध्यम से कई रूपों तक पहुंच हो सकती है। मैं उपयोगकर्ता के लिए प्रपत्रों के सूचकांक को वापस करते समय सर्वश्रेष्ठ प्रदर्शन के साथ दृष्टिकोण का निर्माण करने की कोशिश कर रहा हूं।

एक उपयोगकर्ता के पास निम्न परिदृश्यों के माध्यम से फ़ॉर्म तक पहुँच हो सकती है:

  • मालिक का रूप
  • टीम फॉर्म का मालिक है
  • किसी ऐसे समूह के पास अनुमति है जो फ़ॉर्म का मालिक है
  • एक टीम के पास अनुमति है जो एक फॉर्म का मालिक है
  • एक फॉर्म की अनुमति है

जैसा कि आप देख सकते हैं कि 5 संभावित तरीके हैं जिनसे उपयोगकर्ता किसी फॉर्म तक पहुंच सकता है। मेरी समस्या यह है कि मैं कैसे सबसे कुशलता से उपयोगकर्ता के लिए सुलभ रूपों की एक सरणी लौटा सकता हूं।

फार्म नीति:

मैंने मॉडल से सभी फ़ॉर्म प्राप्त करने का प्रयास किया है और फिर फ़ॉर्म नीति द्वारा प्रपत्रों को फ़िल्टर किया है। ऐसा लगता है कि प्रदर्शन फ़िल्टर के रूप में प्रत्येक फ़िल्टर पुनरावृत्ति पर प्रपत्र किसी समाहित () सुवक्ता विधि से 5 बार गुजरता है जैसा कि नीचे दिखाया गया है। डेटाबेस में अधिक रूपों का अर्थ है कि यह धीमा हो जाता है।

FormController@index

public function index(Request $request)
{
   $forms = Form::all()
      ->filter(function($form) use ($request) {
         return $request->user()->can('view',$form);
   });
}
FormPolicy@view

public function view(User $user, Form $form)
{
   return $user->forms->contains($form) ||
      $user->team->forms->contains($form) ||
      $user->permissible->groups->forms($contains);
}

हालांकि उपरोक्त विधि काम करती है यह एक प्रदर्शन बोतल गर्दन है।

मैं अपने निम्नलिखित विकल्पों में से क्या देख सकता हूं:

  • फॉर्मपॉली फिल्टर (वर्तमान दृष्टिकोण)
  • सभी अनुमतियों को छोड़ें (5) और एकल संग्रह में विलय करें
  • सभी अनुमतियों (5) के लिए सभी पहचानकर्ताओं को क्वेरी करें, फिर पहचानकर्ताओं का उपयोग करके IN () विवरण में फॉर्म मॉडल को क्वेरी करें

मेरा प्रश्न:

कौन सी विधि सबसे अच्छा प्रदर्शन प्रदान करेगी और क्या कोई अन्य विकल्प है जो बेहतर प्रदर्शन प्रदान करेगा?


अगर आप उपयोगकर्ता फार्म का उपयोग कर सकते हैं तो लिंक करने के लिए कई टू-वे कई दृष्टिकोण भी बना सकते हैं
कोड के लिए धन

उपयोगकर्ता प्रपत्र अनुमतियों को क्वेरी करने के लिए विशेष रूप से एक तालिका बनाने के बारे में क्या? user_form_permissionसिर्फ युक्त तालिका user_idऔर form_id। यह रीडिंग अनुमतियों को एक हवा बना देगा, हालांकि अपडेट करने की अनुमति कठिन होगी।
PtrTon

User_form_permissions टेबल के साथ समस्या यह है कि हम अन्य संस्थाओं के लिए अनुमतियों का विस्तार करना चाहते हैं, जिसके लिए प्रत्येक इकाई के लिए एक अलग तालिका की आवश्यकता होगी।
टिम

1
@ समय पर लेकिन अभी भी 5 प्रश्न हैं। यदि यह एक संरक्षित सदस्य के क्षेत्र के अंदर है, तो मुद्दा नहीं हो सकता है। लेकिन अगर यह एक सार्वजनिक सामना करने वाले URL पर है, जो प्रति सेकंड बहुत सारे अनुरोध प्राप्त कर सकता है, तो मुझे लगता है कि आप इसे थोड़ा अनुकूलित करना चाहते हैं। प्रदर्शन के कारण, मैं हर बार एक फॉर्म या टीम के सदस्य को मॉडल पर्यवेक्षकों के माध्यम से जोड़ा जाता है या हटा दिया जाता है, एक अलग तालिका (जिसे मैं कैश कर सकता हूं) बनाए रखूंगा। फिर, हर अनुरोध पर, मुझे लगता है कि कैश से मिलेगा। मुझे यह सवाल और समस्या बहुत दिलचस्प लगती है और यह जानना अच्छा लगेगा कि दूसरे भी क्या सोचते हैं। इस सवाल के अधिक वोट और जवाब के लायक है, एक इनाम शुरू किया :)
राउल

1
आप एक भौतिक दृष्टिकोण पर विचार कर सकते हैं जिसे आप एक निर्धारित कार्य के रूप में ताज़ा कर सकते हैं। इस तरह आप हमेशा अपेक्षाकृत जल्दी से परिणाम प्राप्त कर सकते हैं।
एपोक्रीफोस

जवाबों:


2

मैं एक एसक्यूएल क्वेरी करना चाहूंगा क्योंकि यह php से बहुत बेहतर प्रदर्शन करने वाला है

कुछ इस तरह:

User::where('id', $request->user()->id)
    ->join('group_users', 'user.id', 'group_users.user_id')
    ->join('team_users', 'user.id', 'team_users.user_id',)
    ->join('form_owners as user_form_owners', function ($join) {
        $join->on('users.id', 'form_owners.owner_id')
            ->where('form_owners.owner_type', User::class);
    })
    ->join('form_owners as group_form_owners', function ($join) {
        $join->on('group_users.group_id', 'form_owners.owner_id')
            ->where('form_owners.owner_type', Group::class);
    })
    ->join('form_owners as team_form_owners', function ($join) {
        $join->on('team_users.team_id', 'form_owners.owner_id')
           ->where('form_owners.owner_type', Team::class);
    })
    ->join('forms', function($join) {
        $join->on('forms.id', 'user_form_owners.form_id')
            ->orOn('forms.id', 'group_form_owners.form_id')
            ->orOn('forms.id', 'team_form_owners.form_id');
    })
    ->selectRaw('forms.*')
    ->get();

मेरे सिर के ऊपर से और बिना छपे हुए आपको उपयोगकर्ता, उसके समूह और इस टीम के स्वामित्व वाले सभी रूपों को प्राप्त करना चाहिए।

हालांकि यह समूहों और टीमों में उपयोगकर्ता दृश्य रूपों की अनुमतियों को नहीं देखता है।

मुझे यकीन नहीं है कि आपके पास इसके लिए अपना विशेषाधिकार कैसे निर्धारित किया गया है और इसलिए आपको इसके लिए क्वेरी को संशोधित करने की आवश्यकता है और आपके DB संरचना में कोई अंतर है।


जवाब के लिए धन्यवाद। हालाँकि, समस्या यह नहीं थी कि डेटाबेस से डेटा कैसे प्राप्त किया जाए। समस्या यह है कि इसे हर बार, हर अनुरोध पर कुशलतापूर्वक कैसे प्राप्त किया जाए, जब ऐप में हज़ारों रूपों और टीमों और सदस्यों के सैकड़ों रूप हैं। आपके जोड़ों में ORक्लॉस होते हैं, जो मुझे लगता है कि धीमे होने वाले हैं। तो हर अनुरोध पर इसे मारना पागल हो जाएगा मुझे विश्वास है।
राउल

आप कच्ची MySQL क्वेरी के साथ बेहतर गति प्राप्त करने में सक्षम हो सकते हैं या किसी चीज़ जैसे विचार या प्रक्रिया का उपयोग कर सकते हैं, लेकिन आपको हर बार इस तरह से कॉल करने होंगे जो आपको डेटा चाहिए। परिणामों की कैशिंग भी यहाँ मदद कर सकती है।
जोश

जबकि मुझे लगता है कि इस प्रदर्शन को बनाने का एकमात्र तरीका कैशिंग है, जो हर बार इस नक्शे को बनाए रखने की लागत पर आता है जब भी कोई बदलाव किया जाता है। मुझे लगता है कि मैं एक नया रूप बनाता हूं, जो, अगर एक टीम को मेरे खाते में सौंपा जाता है, तो इसका मतलब है कि हजारों उपयोगकर्ता इसे प्राप्त कर सकते हैं। आगे क्या होगा? कुछ हजार सदस्यों की नीति को फिर से कैश करें?
राउल

जीवनकाल के साथ कैश समाधान हैं (जैसे लार्वा का कैश एब्स्ट्रक्शन), और आप किसी भी बदलाव के तुरंत बाद कैश इंफ़ेक्शंस को भी हटा सकते हैं। यदि आप इसे सही तरीके से उपयोग करते हैं तो कैश एक वास्तविक गेम-चेंजर है। कैश को कैसे कॉन्फ़िगर करें यह डेटा की रीड और अपडेट पर निर्भर करता है।
गोंजालो

2

संक्षिप्त जवाब

तीसरा विकल्प: Query all identifiers for all permissions (5), then query the Form model using the identifiers in an IN() statement

$teamMorphType  = Relation::getMorphedModel('team');
$groupMorphType = Relation::getMorphedModel('group');
$formMorphType  = Relation::getMorphedModel('form');

$permissible = [
    $teamMorphType  => [$user->team_id],
    $groupMorphType => [],
    $formMorphType  => [],
];

foreach ($user->permissible as $permissible) {
    switch ($permissible->permissible_type) {
        case $teamMorphType:
        case $groupMorphType:
        case $formMorphType:
            $permissible[$permissible->permissible_type][] = $permissible->permissible_id;
            break;
    }
}

$forms = Form::query()
             ->where('user_id', '=', $user->id)
             ->orWhereIn('id', $permissible[$fromMorphType])
             ->orWhereIn('team_id', $permissible[$teamMorphType])
             ->orWhereIn('group_id', $permissible[$groupMorphType])
             ->get();

लंबा जवाब

एक तरफ, (लगभग) वह सब कुछ जो आप कोड में कर सकते हैं, बेहतर प्रदर्शन-वार है, जो प्रश्नों में है।

दूसरी ओर, डेटाबेस से आवश्यकता से अधिक डेटा प्राप्त करना पहले से ही बहुत अधिक डेटा होगा (रैम उपयोग और इसी तरह)।

मेरे दृष्टिकोण से, आपको बीच में कुछ चाहिए, और केवल आपको पता होगा कि संख्याओं के आधार पर शेष राशि कहां होगी।

मैं कई प्रश्नों को चलाने का सुझाव दूंगा, जो अंतिम विकल्प आपने प्रस्तावित किया है ( Query all identifiers for all permissions (5), then query the Form model using the identifiers in an IN() statement):

  1. सभी अनुमतियों के लिए सभी पहचानकर्ताओं से पूछताछ करें (5 प्रश्न)
  2. स्मृति में सभी रूपों को मिलाएं, और अद्वितीय मूल्य प्राप्त करें array_unique($ids)
  3. एक () कथन में पहचानकर्ताओं का उपयोग करके फ़ॉर्म मॉडल को छोड़ें।

आप कई बार क्वेरी को चलाने के लिए कुछ टूल का उपयोग करके आपके द्वारा प्रस्तावित तीन विकल्पों को आज़मा सकते हैं और प्रदर्शन की निगरानी कर सकते हैं, लेकिन मुझे 99% यकीन है कि अंतिम आपको सबसे अच्छा प्रदर्शन देगा।

यह बहुत कुछ बदल सकता है, इस पर निर्भर करता है कि आप किस डेटाबेस का उपयोग कर रहे हैं, लेकिन अगर हम MySQL के बारे में बात कर रहे हैं, उदाहरण के लिए; एक बहुत बड़ी क्वेरी में अधिक डेटाबेस संसाधनों का उपयोग किया जाएगा, जो न केवल सरल प्रश्नों की तुलना में अधिक समय बिताएगा, बल्कि लिखने से तालिका को लॉक करेगा, और यह गतिरोध त्रुटियों का उत्पादन कर सकता है (जब तक कि आप एक दास सर्वर का उपयोग नहीं करते हैं)।

दूसरी तरफ, यदि फॉर्म आईडी की संख्या बहुत बड़ी है, तो आपके पास बहुत अधिक प्लेसहोल्डर्स के लिए त्रुटियां हो सकती हैं, इसलिए आप समूहों के प्रश्नों को चुन सकते हैं, मान लीजिए कि 500 ​​आईडी (यह बहुत कुछ निर्भर करता है, सीमा के रूप में) आकार में है, बाइंडिंग की संख्या में नहीं है), और परिणाम को स्मृति में मर्ज करें। यहां तक ​​कि अगर आपको डेटाबेस त्रुटि नहीं मिलती है, तो भी आपको प्रदर्शन में बड़ा अंतर दिखाई दे सकता है (मैं अभी भी MySQL के बारे में बात कर रहा हूं)।


कार्यान्वयन

मैं मानूंगा कि यह डेटाबेस योजना है:

users
  - id
  - team_id

forms
  - id
  - user_id
  - team_id
  - group_id

permissible
  - user_id
  - permissible_id
  - permissible_type

तो अनुमेय पहले से ही कॉन्फ़िगर पॉलीमोर्फिक संबंध होगा

इसलिए, संबंध होंगे:

  • मालिक का रूप: users.id <-> form.user_id
  • टीम फॉर्म का मालिक है: users.team_id <-> form.team_id
  • किसी ऐसे समूह के पास अनुमति है जो फ़ॉर्म का मालिक है: permissible.user_id <-> users.id && permissible.permissible_type = 'App\Team'
  • फॉर्म के मालिक वाली टीम के लिए अनुमति है: permissible.user_id <-> users.id && permissible.permissible_type = 'App\Group'
  • फॉर्म की अनुमति है: permissible.user_id <-> users.id && permissible.permissible_type = 'App\From'

सरल संस्करण:

$teamMorphType  = Relation::getMorphedModel('team');
$groupMorphType = Relation::getMorphedModel('group');
$formMorphType  = Relation::getMorphedModel('form');

$permissible = [
    $teamMorphType  => [$user->team_id],
    $groupMorphType => [],
    $formMorphType  => [],
];

foreach ($user->permissible as $permissible) {
    switch ($permissible->permissible_type) {
        case $teamMorphType:
        case $groupMorphType:
        case $formMorphType:
            $permissible[$permissible->permissible_type][] = $permissible->permissible_id;
            break;
    }
}

$forms = Form::query()
             ->where('user_id', '=', $user->id)
             ->orWhereIn('id', $permissible[$fromMorphType])
             ->orWhereIn('team_id', $permissible[$teamMorphType])
             ->orWhereIn('group_id', $permissible[$groupMorphType])
             ->get();

विस्तृत संस्करण:

// Owns Form
// users.id <-> forms.user_id
$userId = $user->id;

// Team owns Form
// users.team_id <-> forms.team_id
// Initialise the array with a first value.
// The permissions polymorphic relationship will have other teams ids to look at
$teamIds = [$user->team_id];

// Groups owns Form was not mention, so I assume there is not such a relation in user.
// Just initialise the array without a first value.
$groupIds = [];

// Also initialise forms for permissions:
$formIds = [];

// Has permissions to a group that owns a Form
// permissible.user_id <-> users.id && permissible.permissible_type = 'App\Team'
$teamMorphType = Relation::getMorphedModel('team');
// Has permissions to a team that owns a Form
// permissible.user_id <-> users.id && permissible.permissible_type = 'App\Group'
$groupMorphType = Relation::getMorphedModel('group');
// Has permission to a Form
// permissible.user_id <-> users.id && permissible.permissible_type = 'App\Form'
$formMorphType = Relation::getMorphedModel('form');

// Get permissions
$permissibles = $user->permissible()->whereIn(
    'permissible_type',
    [$teamMorphType, $groupMorphType, $formMorphType]
)->get();

// If you don't have more permissible types other than those, then you can just:
// $permissibles = $user->permissible;

// Group the ids per type
foreach ($permissibles as $permissible) {
    switch ($permissible->permissible_type) {
        case $teamMorphType:
            $teamIds[] = $permissible->permissible_id;
            break;
        case $groupMorphType:
            $groupIds[] = $permissible->permissible_id;
            break;
        case $formMorphType:
            $formIds[] = $permissible->permissible_id;
            break;
    }
}

// In case the user and the team ids are repeated:
$teamIds = array_values(array_unique($teamIds));
// We assume that the rest of the values will not be repeated.

$forms = Form::query()
             ->where('user_id', '=', $userId)
             ->orWhereIn('id', $formIds)
             ->orWhereIn('team_id', $teamIds)
             ->orWhereIn('group_id', $groupIds)
             ->get();

उपयोग किए गए संसाधन:

डेटाबेस प्रदर्शन:

  • डेटाबेस को क्वेरी (उपयोगकर्ता को छोड़कर): 2 ; एक को अनुमेय और दूसरे को रूपों को प्राप्त करना।
  • कोई जुड़ता नहीं !!
  • संभव न्यूनतम ओ आर ( user_id = ? OR id IN (?..) OR team_id IN (?...) OR group_id IN (?...)

PHP, मेमोरी, प्रदर्शन में:

  • एक स्विच के साथ अनुमेय फाड़नेवाला foreach अंदर।
  • array_values(array_unique()) आईडी दोहराने से बचने के लिए।
  • स्मृति में, आईडी के 3 सरणियों ( $teamIds, $groupIds, $formIds)
  • स्मृति में, प्रासंगिक अनुमतियाँ वाक्पटु संग्रह (इसे अनुकूलित किया जा सकता है, यदि आवश्यक हो)।

फायदा और नुकसान

पेशेवरों:

  • समय : एकल प्रश्नों के समय का योग जोड़ और OR के साथ एक बड़ी क्वेरी के समय से कम है।
  • DB संसाधन : MySQL संसाधन जो किसी क्वेरी से जुड़ने और या कथन के लिए उपयोग किया जाता है, उसके अलग-अलग प्रश्नों के योग से उपयोग किए जाने से बड़ा होता है।
  • धन : कम डेटाबेस संसाधन (प्रोसेसर, रैम, डिस्क रीड, आदि), जो PHP संसाधनों से अधिक महंगे हैं।
  • ताले : यदि आप किसी रीड-ओनली स्लेव सर्वर को क्वैरी नहीं कर रहे हैं, तो आपके क्वेश्चंस कम पंक्तियों को रीड रीड बना देंगे (रीड लॉक MySQL में शेयर किया गया है, इसलिए यह किसी अन्य रीड को लॉक नहीं करेगा, लेकिन यह किसी भी राइट को ब्लॉक कर देगा)।
  • स्केलेबल : यह दृष्टिकोण आपको अधिक प्रदर्शन अनुकूलन करने की अनुमति देता है जैसे कि प्रश्नों को काट देना।

कान्स:

  • कोड संसाधन : डेटाबेस के बजाय कोड में गणना करना, जाहिर तौर पर कोड उदाहरण में अधिक संसाधनों का उपभोग करेगा, लेकिन विशेष रूप से रैम में, मध्य सूचना को संग्रहीत करता है। हमारे मामले में, यह सिर्फ आईडी की एक सरणी होगी, जो वास्तव में एक समस्या नहीं होनी चाहिए।
  • रखरखाव : यदि आप लारवेल के गुणों और विधियों का उपयोग करते हैं, और आप डेटाबेस में कोई बदलाव करते हैं, तो कोड में अपडेट करना आसान होगा, यदि आप अधिक स्पष्ट प्रश्न और प्रसंस्करण करते हैं।
  • Overkilling? : कुछ मामलों में, यदि डेटा उतना बड़ा नहीं है, तो प्रदर्शन को अनुकूलित करना अधिक भारी हो सकता है।

प्रदर्शन को कैसे मापें

प्रदर्शन को मापने के तरीके के बारे में कुछ सुराग?

  1. धीमी क्वेरी लॉग
  2. विश्लेषण तालिका
  3. शोभित स्टेटस लाइक
  4. एक्सक्लूसिव ; विस्तारित प्रदर्शन आउटपुट स्वरूप ; समझाने का उपयोग करना ; आउटपुट समझाएं
  5. दिखाएँ चेतावनी

कुछ दिलचस्प रूपरेखा उपकरण:


वह पहली पंक्ति क्या है? क्वेरी का उपयोग करना लगभग हमेशा बेहतर प्रदर्शन बुद्धिमान होता है, क्योंकि PHP में विभिन्न लूप या सरणी हेरफेर को धीमा करना होता है।
ज्वाला

यदि आपके पास एक छोटा डेटाबेस है या आपकी डेटाबेस मशीन आपके कोड उदाहरण की तुलना में अधिक शक्तिशाली है, या डेटाबेस विलंबता बहुत खराब है, तो हाँ, MySQL तेज है, लेकिन यह आमतौर पर ऐसा नहीं है।
गोंजालो

जब आप एक डेटाबेस क्वेरी का अनुकूलन करते हैं, तो आपको निष्पादन समय पर विचार करने की आवश्यकता होती है, पंक्तियों की संख्या वापस आ जाती है, और सबसे महत्वपूर्ण बात यह है कि पंक्तियों की संख्या की जांच की जाती है। यदि टिम कह रहा है कि क्वेरी धीमी हो रही हैं, तो मैं मानता हूं कि डेटा बढ़ रहा है, और इसलिए जांच की गई पंक्तियों की संख्या। इसके अलावा, डेटाबेस प्रोग्रामिंग भाषा के रूप में प्रसंस्करण के लिए अनुकूलित नहीं है।
गोंजालो

लेकिन आपको मुझ पर भरोसा करने की आवश्यकता नहीं है, आप अपने समाधान के लिए EXPLAIN चला सकते हैं, फिर आप इसे मेरे सरल प्रश्नों के समाधान के लिए चला सकते हैं, और अंतर देख सकते हैं, और फिर सोच सकते हैं कि क्या एक सरल array_merge()और array_unique()आईडी का एक गुच्छा, वास्तव में अपनी प्रक्रिया को धीमा।
गोंजालो

10 में से 9 मामलों में mysql डेटाबेस उसी मशीन पर चलता है जो कोड चलाता है। डेटा परत का उपयोग डेटा पुनर्प्राप्ति के लिए किया जाता है और इसे बड़े सेटों से डेटा के टुकड़ों को चुनने के लिए अनुकूलित किया जाता है। मैंने अभी तक ऐसी स्थिति देखी है जहाँ array_unique()a GROUP BY/ SELECT DISTINCTकथन से अधिक तेज़ है ।
ज्वाला

0

क्यों नहीं आप कर सकते हैं बस आप की जरूरत है Form::all()और उसके filter()बाद एक समारोह का पीछा करने के बजाय फार्म की क्वेरी ?

इस तरह:

public function index() {
    $forms = $user->forms->merge($user->team->forms)->merge($user->permissible->groups->forms);
}

तो हाँ, यह कुछ प्रश्न करता है:

  • के लिए एक क्वेरी $user
  • एक के लिए $user->team
  • एक के लिए $user->team->forms
  • एक के लिए $user->permissible
  • एक के लिए $user->permissible->groups
  • एक के लिए $user->permissible->groups->forms

हालांकि, समर्थक पक्ष यह है कि अब आपको पॉलिसी का उपयोग करने की आवश्यकता नहीं है , क्योंकि आप जानते $formsहैं कि उपयोगकर्ता के लिए पैरामीटर के सभी रूपों की अनुमति है।

तो यह समाधान डेटाबेस में आपके पास जितने भी फॉर्म हैं, उनके लिए काम करेगा।

उपयोग करने पर एक नोट merge()

merge()संग्रह को मर्ज करता है, और डुप्लिकेट फॉर्म आईडी को छोड़ देगा जो इसे पहले ही मिल चुका है। इसलिए यदि किसी कारण से teamसंबंध से एक रूप भी प्रत्यक्ष संबंध है user, तो यह केवल एक बार मर्ज किए गए संग्रह में दिखाई देगा।

ऐसा इसलिए है क्योंकि यह वास्तव में एक Illuminate\Database\Eloquent\Collectionअपना स्वयं का merge()फ़ंक्शन है जो एलोक्वेंट मॉडल आईडी के लिए जांच करता है। तो आप वास्तव में इस ट्रिक का उपयोग नहीं कर सकते हैं , जैसे कि 2 अलग-अलग संग्रह सामग्री को मर्ज करना Postsऔर Users, क्योंकि आईडी 3और आईडी वाला एक पोस्ट 3इस मामले में संघर्ष करेगा, और केवल बाद वाला (पोस्ट) मर्ज किए गए संग्रह में मिलेगा।


यदि आप चाहते हैं कि यह और भी तेज़ हो, तो आपको डीबी मुखौटा का उपयोग करके एक कस्टम क्वेरी बनानी चाहिए, कुछ इस तरह से:

// Select forms based on a subquery that returns a list of id's.
$forms = Form::whereIn(
    'id',
    DB::select('id')->from('users')->where('users.id', $user->id)
        ->join('teams', 'users.id', '=', 'teams.user_id')
        ...
)->get();

आपके वास्तविक संबंध बहुत बड़े हैं क्योंकि आपके बहुत सारे संबंध हैं।

यहां मुख्य प्रदर्शन में सुधार इस तथ्य से आता है कि भारी काम (उपश्रेणी) पूरी तरह से एलोकेंट मॉडल तर्क को दरकिनार कर देता है। फिर वह सब करने के लिए छोड़ दिया जाता है जो whereInआपकी सूची को पुनः प्राप्त करने के लिए फ़ंक्शन में आईडी की सूची को पास करने के लिए है Form


0

मेरा मानना ​​है कि आप उस (लारवेल 6.x) के लिए लेजी कलेक्शंस का उपयोग कर सकते हैं और उन तक पहुँचने से पहले संबंधों को उत्सुकता से लोड कर सकते हैं।

public function index(Request $request)
{
   // Eager Load relationships
   $request->user()->load(['forms', 'team.forms', 'permissible.group']);
   // Use cursor instead of all to return a LazyCollection instance
   $forms = Form::cursor()->filter(function($form) use ($request) {
         return $request->user()->can('view', $form);
   });
}
public function view(User $user, Form $form)
{
   return $user->forms->contains($form) ||
      $user->team->forms->contains($form) ||
      // $user->permissible->groups->forms($contains); // Assuming this line is a typo
      $user->permissible->groups->contains($form);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.