লারাভেল: অ্যাট্রিবিউট দ্বারা সংগ্রহ থেকে অবজেক্ট পান


91

লারাভেলে, আমি যদি কোনও জিজ্ঞাসা করি:

$foods = Food::where(...)->get();

... তারপর $foodsএকটি হল জ্বালান সংগ্রহ এর Foodমডেল বস্তু। (মূলত মডেলগুলির একটি অ্যারে))

তবে এই অ্যারের কীগুলি কেবল সহজ:

[0, 1, 2, 3, ...]

... সুতরাং যদি আমি 24 Foodটির সাথে একটি অবজেক্টটি পরিবর্তন করতে চাই, তবে idআমি এটি করতে পারি না:

$desired_object = $foods->get(24);
$desired_object->color = 'Green';
$desired_object->save();

... কারণ এটি কেবল অ্যারের মধ্যে 25 তম উপাদানকে পরিবর্তন করবে id, 24 এর একটি উপাদান দিয়ে নয় ।

আমি কোনও বৈশিষ্ট্য / কলামের সংগ্রহ (যেমন, তবে আইডি / রঙ / বয়স / ইত্যাদি সীমাবদ্ধ নয়) থেকে কীভাবে একটি একক (বা একাধিক) উপাদান (গুলি) পেতে পারি?

অবশ্যই, আমি এটি করতে পারি:

foreach ($foods as $food) {
    if ($food->id == 24) {
        $desired_object = $food;
        break;
    }
}
$desired_object->color = 'Green';
$desired_object->save();

... তবে, এটি কেবল স্থূল।

এবং, অবশ্যই, আমি এটি করতে পারি:

$desired_object = Food::find(24);
$desired_object->color = 'Green';
$desired_object->save();

... তবে এটি আরও বেশি স্থূল , কারণ আমার কাছে ইতিমধ্যে $foodsসংগ্রহটিতে পছন্দসই অবজেক্ট থাকা অবস্থায় এটি একটি অতিরিক্ত অপ্রয়োজনীয় ক্যোয়ারি সম্পাদন করে ।

কোন গাইডেন্সের জন্য আগাম ধন্যবাদ।

সম্পাদনা:

স্পষ্টতই, আপনি অন্য জিজ্ঞাসা তৈরি না করেই আলোকসজ্জা সংগ্রহ করতে কল করতে পারেন->find() , তবে এটি কেবলমাত্র প্রাথমিক আইডি গ্রহণ করে। এই ক্ষেত্রে:

$foods = Food::all();
$desired_food = $foods->find(21);  // Grab the food with an ID of 21

যাইহোক, এখনও সংগ্রহের কোনও বৈশিষ্ট্য দ্বারা কোনও উপাদান (গুলি) ধরার কোনও পরিষ্কার (নন-লুপিং, অ-কোয়েরি) উপায় নেই:

$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This won't work.  :(

উত্তর:


126

আপনি filterযেমন ব্যবহার করতে পারেন :

$desired_object = $food->filter(function($item) {
    return $item->id == 24;
})->first();

filterএকটি ফিরে আসবে Collection, কিন্তু যেহেতু আপনি জানেন শুধুমাত্র এক হবে, আপনি কল করতে পারেন firstযে Collection

আপনার আর ফিল্টার লাগবে না (বা সম্ভবত কখনও, আমি জানি না এটি প্রায় 4 বছরের পুরানো)। আপনি কেবল ব্যবহার করতে পারেন first:

$desired_object = $food->first(function($item) {
    return $item->id == 24;
});

7
হেই ধন্যবাদ! আমি মনে করি আমি এটি নিয়ে বাঁচতে পারি। তবুও আমার মতামত অস্বাভাবিকভাবে ভারবস করে যা সাধারণত এই জাতীয় 'বুদ্ধিমান' কাঠামো হাহা হয়। তবে এটি এখনও পর্যন্ত বিকল্পগুলির তুলনায় অনেক পরিষ্কার, তাই আমি এটি গ্রহণ করব।
দৈর্ঘ্য

যেমন @ স্প্যারেস্টেস্ট অন্য উত্তরে ইঙ্গিত করছে, আপনার বন্ধের ভিতরে আপনি একটি দায়িত্ব তৈরি করছেন এবং তুলনা করছেন না (যেমন আপনার উচিত == এবং না =)
এলিমেন্টালস্টোরম

24
প্রকৃতপক্ষে এমনকি filter()->first()আপনি কেবল কল করতে কল করতেও প্রয়োজনীয় নয়first(function(...))
লুকাশজিটার

লারাভেল সংগ্রহ ডকুমেন্টেশন থেকে। লারাভেল.com collect([1, 2, 3, 4])->first(function ($value, $key) { return $value == 2; });
শিরো

4
ফাংশন যেখানে আপনি একই জিনিস করতে পারেন। $desired_object = $food->where('id', 24)->first();
ভাভিন থুমার

111

লারাভেল নামক একটি পদ্ধতি সরবরাহ করে keyByযা মডেলটিতে প্রদত্ত কী দ্বারা কীগুলি সেট করতে দেয়।

$collection = $collection->keyBy('id');

সংগ্রহটি ফিরিয়ে আনবে তবে কীগুলি idকোনও মডেলের বৈশিষ্ট্যের মান হিসাবে থাকবে ।

তারপরে আপনি বলতে পারেন:

$desired_food = $foods->get(21); // Grab the food with an ID of 21

এবং এটি কোনও ফিল্টার ফাংশন ব্যবহার না করায় সঠিক আইটেমটি দখল করবে।


4
সত্যই কার্যকর, বিশেষত পারফরম্যান্সের জন্য -> একাধিকবার বলা হলে প্রথম () প্রথমে () অগ্রণী হয়ে যায় (পূর্বে অগ্রণী ...) যাতে আপনি আপনার সংগ্রহটিকে "সূচক" করতে পারেন: $exceptions->keyBy(function ($exception) { return $exception->category_id . ' ' . $exception->manufacturer_id;এবং ->get($category->id . ' ' . $manufacturer->id)পরে ব্যবহার করুন !
ফ্রান্সোইস ব্রেটন

যখন নতুন আইটেম সংগ্রহে যুক্ত করা হয় তখন কী কী ব্যবহার করা অবিরত থাকে? অথবা প্রতিবারই কোনও নতুন অবজেক্ট বা অ্যারে সংগ্রহের দিকে ঠেলে কি কীবি () ব্যবহার করতে হবে?
জেসন

keyByআমার মনে আছে যা থেকে নতুন সংগ্রহ ফিরে আসে সম্ভবত আপনাকে আবার কল করতে হবে, যদিও নিশ্চিত নয়, আপনি Illuminate/Support/Collectionএটি অনুসন্ধান করতে পারেন। (লারাভেলে বেশ কিছুদিন কাজ করছেন না যাতে কেউ আমাকে সংশোধন করতে পারে)।
ম্যাকসেম সিয়ার্জনিয়াক

এটি আমার পক্ষে কাজ করে নি, এটি অন্য আইটেমটি ফিরিয়ে দিয়েছে, পরের আইটেমটি, যদি আমি (1) পেতে টাইপ করি তবে এটি আইটেম হিসাবে 2 নম্বর থাকা আইটেমটি ফিরিয়ে দেবে।
জ্যাকলিন

ব্যাচটি একটি টেবিল লোড করছে এবং এতে একদিন লেগেছে। এই সমাধানটি ব্যবহার করে এবং এটি কয়েক মিনিট সময় নেয়।
জেড লিঞ্চ


7

যেহেতু আমার পুরো সংগ্রহটি লুপ করার দরকার নেই, তাই আমি মনে করি এর মতো সহায়ক কাজ করা ভাল

/**
 * Check if there is a item in a collection by given key and value
 * @param Illuminate\Support\Collection $collection collection in which search is to be made
 * @param string $key name of key to be checked
 * @param string $value value of key to be checkied
 * @return boolean|object false if not found, object if it is found
 */
function findInCollection(Illuminate\Support\Collection $collection, $key, $value) {
    foreach ($collection as $item) {
        if (isset($item->$key) && $item->$key == $value) {
            return $item;
        }
    }
    return FALSE;
}

7

বিল্ট ইন কালেকশন পদ্ধতিগুলিতে অন্তর্ভুক্ত এবং সন্ধান করুন যা প্রাথমিক আইডির সাহায্যে অনুসন্ধান করা হবে (অ্যারের কীগুলির পরিবর্তে)। উদাহরণ:

if ($model->collection->contains($primaryId)) {
    var_dump($model->collection->find($primaryId);
}

() প্রকৃতপক্ষে কেবলমাত্র কল (() অনুসন্ধান করে এবং নাল পরীক্ষা করে থাকে, যাতে আপনি এটি সংক্ষিপ্ত করে দেখতে পারেন:

if ($myModel = $model->collection->find($primaryId)) {
    var_dump($myModel);
}

আমরা বুঝতে পারি যে সন্ধান () একটি প্রাথমিক আইডি গ্রহণ করে। আমরা যা চাই তা হ'ল একটি পদ্ধতি যা "রঙ" বা "বয়স" এর মতো কোনও বৈশিষ্ট্য গ্রহণ করে । এখনও অবধি, ক্যালির পদ্ধতিটি কেবলমাত্র কোনও বৈশিষ্ট্যের জন্য কাজ করে।
লেং

5

আমি জানি এই প্রশ্নটি মূলত লারাভেল 5.0 প্রকাশের আগে জিজ্ঞাসা করা হয়েছিল, তবে লারাভেল 5.0 হিসাবে সংগ্রহগুলি where()এই উদ্দেশ্যে পদ্ধতিটিকে সমর্থন করে ।

লারাভেল 5.0, 5.1, এবং 5.2 এর জন্য, উইলের where()উপর থাকা পদ্ধতিটি Collectionকেবল একটি সমান তুলনা করবে। এছাড়াও, এটি ===ডিফল্ট হিসাবে একটি কঠোর সমান তুলনা করে ( ) করে। শিথিল তুলনা ( ==) করতে, আপনি হয় falseতৃতীয় প্যারামিটার হিসাবে পাস করতে পারেন বা whereLoose()পদ্ধতিটি ব্যবহার করতে পারেন ।

লারাভেল ৫.৩ হিসাবে, ক্যোয়ারী নির্মাতার পক্ষে পদ্ধতিটির where()মতো আরও কাজ করার জন্য পদ্ধতিটি প্রসারিত করা হয়েছিল where(), যা অপারেটরটিকে দ্বিতীয় প্যারামিটার হিসাবে গ্রহণ করে। এছাড়াও ক্যোয়ারী নির্মাতার মতো, অপারেটর ডিফল্ট হবে যদি কোনও সরবরাহ না করা হয় তবে সমান তুলনা করতে হবে। ডিফল্ট তুলনাটি ডিফল্ট দ্বারা কড়া থেকে ডিফল্টরূপে আলগা হয়ে যায়। সুতরাং, আপনি যদি কোনও কঠোর তুলনা করতে চান তবে আপনি ব্যবহার করতে পারেন whereStrict()বা কেবল ===অপারেটর হিসাবে ব্যবহার করতে পারেন where()

সুতরাং, লারাভেল ৫.০ হিসাবে, প্রশ্নের শেষ কোড উদাহরণটি ঠিক যেমন কাজ করবে ঠিক তেমন কাজ করবে:

$foods = Food::all();
$green_foods = $foods->where('color', 'green'); // This will work.  :)

// This will only work in Laravel 5.3+
$cheap_foods = $foods->where('price', '<', 5);

// Assuming "quantity" is an integer...
// This will not match any records in 5.0, 5.1, 5.2 due to the default strict comparison.
// This will match records just fine in 5.3+ due to the default loose comparison.
$dozen_foods = $foods->where('quantity', '12');

3

আমাকে উল্লেখ করতে হবে যে ক্যালির উত্তরে একটি ছোট্ট কিন্তু একেবারে ক্রিটিকাল ত্রুটি রয়েছে। উপলব্ধি করার আগে আমি কয়েক ঘন্টা এর সাথে লড়াই করেছি:

ফাংশনের অভ্যন্তরে, আপনি কী ফিরিয়ে দিচ্ছেন তা একটি তুলনা এবং এই জাতীয় কিছু আরও সঠিক হবে:

$desired_object = $food->filter(function($item) {
    return ($item->id **==** 24);
})->first();

4
হ্যাঁ, এটি নির্দেশ করার জন্য ধন্যবাদ। এটিও লক্ষ করা গুরুত্বপূর্ণ যে ফিল্টার ফাংশনটি আমার foreach()উদাহরণ পারফরম্যান্স অনুসারে আলাদা নয়, কারণ এটি ঠিক একই ধরণের লুপটি করে ... আসলে, আমার foreach()উদাহরণটি আরও ভাল পারফর্ম করা কারণ এটি সঠিক মডেলটি আবিষ্কার করার পরে ভেঙে যায়। এছাড়াও ... {Collection}->find(24)প্রাথমিক কী দ্বারা দখল করবে, যা এটিকে এখানে সেরা বিকল্প হিসাবে তৈরি করে। কলি প্রস্তাবিত ফিল্টারটি আসলে অভিন্ন $desired_object = $foods->find(24);
দৈর্ঘ্য

4
**==**অপারেটরটি কখনও দেখেনি , এটি কী করে?
কিরাদোটি

@ কিরাদোটি আমি মনে করি যে ওপি কেবলমাত্র দ্বিগুণ সমান তুলনা অপারেটরকে ( == ) জোর দেওয়ার চেষ্টা করছিল । মূল উত্তরটি কেবল একটি সমান চিহ্ন ব্যবহার করেছে, সুতরাং এটি তুলনার পরিবর্তে একটি কার্য সম্পাদন করছিল। ওপি দুটি সমান লক্ষণ থাকা উচিত জোর দেওয়ার চেষ্টা করছিল।
প্যাট্রিকাস


0

উপরের প্রশ্ন হিসাবে আপনি যখন যেখানে ক্লজটি ব্যবহার করছেন তখন আপনাকে ফলাফলটি পেতে get বা প্রথম পদ্ধতিটি ব্যবহার করা দরকার।

/**
*Get all food
*
*/

$foods = Food::all();

/**
*Get green food 
*
*/

$green_foods = Food::where('color', 'green')->get();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.