collection های لاراول :‌ آرایه‌های php

گردآوری و تالیف : عرفان کاکایی
تاریخ انتشار : 13 مرداد 1397
دسته بندی ها : لاراول

مجموعه‌های لاراول (Laravel Collections) یکی از قدرتمند‌ترین مقررات فریم‌وورک لاراول هستند. این مجموعه‌ها، همان چیزی که آرایه‌های PHP باید باشند، و حتی بهتر هستند.

در این آموزش، برخی تکنیک‌ها که می‌توانند در هنگام کار با مجموعه‌های لاراول کاربردی باشند را بررسی خواهیم کرد.

جدول محتویات:

  1. کلاس Collection
  2. ایجاد یک مجموعه جدید
  3. مجموعه‌های ORM
  4. ساخت نمونه مجموعه خود
  5. یافتن داده‌ها
  6. فیلتر کردن داده‌ها
  7. چینش / مرتب کردن داده‌ها
  8. گروه‌بندی داده‌ها
  9. دریافت زیر مجموعه‌ای از داده‌ها
  10. تکرار داده‌ها
  11. استفاده از یک مجموعه به عنوان یک Set
  12. نتیجه گیری

کلاس Collection

کلاس  Illuminate\Support\Collection یک جمع‌کننده قابل قبول برای کار با آرایه‌ها را فراهم کرده است.

کلاس Collection برخی رابط‌های PHP و Laravel مانند موارد زیر را پیاده‌سازی می‌کند:

  • ArrayAccess - رابطی برای فراهم کردن قابلیت دسترسی به آبجکت‌های آرایه.
  • IteratorAggregate - رابطی برای ایجاد یک Iterator.
  • JsonSerializable

ایجاد یک مجموعه جدید

یک مجموعه می‌تواند با استفاده از متد collect() یا با استفاده از کلاس Illuminate\Support\Collection از یک آرایه ساخته شود.

یک مثال ساده برای استفاده از متد collect():

$newCollection = collect([1, 2, 3, 4, 5]);

و یک مورد پیچیده‌تر:

<?php

namespace app\Http\Controllers;

use Illuminate\Support\Collection;

class TestController extends Controller

{

    /**

     * با استفاده از متد مورد نظر، یک مجموعه جدید بسازید.

     */

    public function helperCollection()

    {

        $newCollection = collect([1, 2, 3, 4, 5]);

        dd($newCollection);

    }

    /**

     * با استفاده از نمونه کلاس مجموعه، یک مجموعه جدید بسازید.

     */

    public function classCollection()

    {

        $newCollection = new Collection([1, 2, 3, 4, 5]);

        dd($newCollection);

    }

}

روش متد collect() بسیار آسان‌تر است.

من همچنین متد dd() را برای نمایش این مجموعه در مرورگر اضافه کردم. این مورد پس از اجرا، باید چنین ظاهری داشته باشد:

مجموعه‌های ORM

Laravel Eloquent ORM نیز داده‌ها را به عنوان مجموعه بر می‌گرداند.

برای نمایش چنین بازخوردی، یک دیتابیس SQLite را راه‌اندازی خواهم کرد.

سپس یک جدول کاربر با تنظیمات پیشفرض که در لاراول وجود دارد می‌سازیم و ۱۰ رکورد را در آن وارد می‌کنیم.

/**

     * دریافت لیستی از کاربران، از مجموعه مربوطه.

     */

    public function getUsers()

    {

        $users = User::all();

        dd($users);

    }

متد کنترلر زیر، یک مجموعه لاراول با لیستی از تمام کاربران را نمایش می‌دهد.

سپس می‌توانید به سادگی و با استفاده از نشانه‌گذاری با پیکان‌ها، به یک صفت مجموعه دسترسی داشته باشید. برای مثال، برای دریافت نام کوچک کاربر از مجموعه $users، می‌توانیم به این صورت عمل کنیم:

/**

     * دریافت نام اولین کاربر

     */

    public function firstUser()

    {

        $user = User::first();

        dd($user->name);

    }

ساخت نمونه مجموعه خود:

برای بخش‌های بعدی، از این داده‌های موجود در جدول کاربران، و برخی مجموعه‌های سفارشی برای اهداف نمایشی، استفاده خواهم کرد. در حالیکه که ما این اطلاعات را به صورت دستی می‌سازیم، می‌توانیم با استفاده از Model Factory در لاراول نیز آن‌ها را بسازیم.

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Chasity Tillman
            [email] => qleuschke@example.org
            [age] => 51
            [created_at] => 2016-06-07 15:50:50
            [updated_at] => 2016-06-07 15:50:50

        )
    ...
)

یافتن داده‌ها

تعدادی راه برای یافتن داده‌ها در یک مجموعه وجود دارند.

contains

متد contains() یک مقدار تکی، یک جفت مقدار کلیدی از پارامترها یا یک تابع را می‌گیرد، و یک مقدار Boolean را درباره وجود یا عدم وجود آن مقدار، بر می‌گرداند.

/**

     * بررسی این که ایا یک مجموعه شامل جفت مقدار کلیدی داده شده است یا نه.

     * value or callback parameter

     *

     * @return true or false

     */

    public function contains()

    {

        $users = User::all();

        $users->contains('name', 'Chasity Tillman');

        //true

        $collection = collect(['name' => 'John', 'age' => 23]);

        $collection->contains('Jane');

        //false

        $collection = collect([1, 2, 3, 4, 5]);

        $collection->contains(function ($key, $value) {

            return $value <= 5;

            //true

        });

    }

where

می‌توانید از متد where برای جستجو در یک مجموعه به وسیله یک کلید، یا یک جفت مقدار استفاده کنید.

 public function where()
    {
        $users = User::all();
        $user = $users->where('id', 2);

        //Collection of user with an ID of 2
        $user = $users->where('id', 1)
                      ->where('age', '51')
                      ->where('name', 'Chasity Tillman');

        //مجموعه کاربران با آیدی ۱ و سن ۵۱
    }

برخی متدهای دیگر شبیه به where نیز وجود دارند، که به آن‌ها وارد نخواهم شد. اما بهتر است این سه مورد را به یاد داشته باشید:

  • whereIn() - یک جفت مقدار کلیدی را برای جستجو می‌گیرد، اما یک آرایه را نیز قبول می‌کند.
  • search() - به دنبال یک مقدار در یک مجموعه می‌گردد، اگر مقدار وجود داشته باشد همان ورودی را بر می‌گرداند، و در غیر این صورت false را بر می‌گرداند.
  • has() - یک مقدار Boolean درباره وجود یا عدم وجود مقدار مورد نظر بر می‌گرداند.

فیلتر کردن داده‌ها

احتمالا تا به اینجا حدث زده‌اید که فیلتر کردن در مجموعه‌ها با استفاده از متد filter() انجام می‌شود.

/**

     * استفاده از متد فیلتر برای دریافت لیستی ار کاربران با سن کمتر از 35

     */

    public function filter()

    {

        $users = User::all();

        $youngsters = $users->filter(function ($value, $key) {

            return $value->age < 35;

        });

        $youngsters->all();

        //لیست تمام کاربران یه سنی کمتر از ۳۵ دارند.

    }

متد filter یک کلید و یک مقدار را به عنوان پارامتر در یک تابع می‌گیرد.

همچنین متد all() را نیز نشان دادم که آرایه زیرین را از یک مجموعه نمایش می‌دهد.

چینش / مرتب کردن داده‌ها

مجموعه‌ها ما را قادر می‌سازند تا با استفاده از ۲ متد ساده، داده‌های خود را بچینیم:

  • sortBy() - بر حسب یک شاخص، داده‌ها را به صورت صعودی می‌چیند.
  • sortByDesc() - بر حسب یک شاخص، داده‌ها را به صورت نزولی می‌چیند.

متدهای sort یک کلید یا یک تابع را به عنوان پارامتر خود می‌گیرد، که برای چینش مجموعه‌ها استفاده می‌شود.

    public function sortData()
    {
        $users  = User::all();
        $youngestToOldest = $users->sortBy('age');
        $youngestToOldest->all();

        //list of all users from youngest to oldest

        $movies = collect([

            [
                'name' => 'Back To The Future',
                'releases' => [1985, 1989, 1990]
            ],
            [
                'name' => 'Fast and Furious',
                'releases' => [2001, 2003, 2006, 2009, 2011, 2013, 2015, 2017]
            ],
            [
                'name' => 'Speed',
                'releases' => [1994]
            ]

        ]);

        $mostReleases = $movies->sortByDesc(function ($movie, $key) {
            return count($movie['releases']);
        });

        $mostReleases->toArray();
        dd($mostReleases->values()->toArray());

    }

متدهای چینش، شامل کلیدهایی برای هر مقدار می‌شوند. درحالیکه این می‌تواند برای برنامه شما مهم باشد، می‌توانید با استفاده از متد values()، آن‌ها را به مقدار افزایشی پیشفرض بازنشانی کنید.

گروه‌بندی داده‌ها

groupBy

گروه‌بندی یک مجموعه، شما را قادر می‌سازد تا داده‌های خود را منطقی‌تر کنید. متد groupBy یک کلید، و یا یک تابع را می‌گیرد و یک مجموعه گروه‌بندی شده را بر پایه آن مقدار کلیدی یا تابع بر می‌گرداند.

    public function grouping()

    {

        $movies = collect([

            ['name' => 'Back To the Future', 'genre' => 'scifi', 'rating' => 8],

            ['name' => 'The Matrix',  'genre' => 'fantasy', 'rating' => 9],

            ['name' => 'The Croods',  'genre' => 'animation', 'rating' => 8],

            ['name' => 'Zootopia',  'genre' => 'animation', 'rating' => 4],

            ['name' => 'The Jungle Book',  'genre' => 'fantasy', 'rating' => 5],

        ]);

        $genre = $movies->groupBy('genre');

        /*

        [

             "scifi" => [

               ["name" => "Back To the Future", "genre" => "scifi", "rating" => 8,],

             ],

             "fantasy" => [

               ["name" => "The Matrix", "genre" => "fantasy", "rating" => 9,],

               ["name" => "The Jungle Book", "genre" => "fantasy", "rating" => 5, ],

             ],

             "animation" => [

               ["name" => "The Croods", "genre" => "animation", "rating" => 8,],

               ["name" => "Zootopia", "genre" => "animation", "rating" => 4, ],

             ],

        ]

        */

        $rating = $movies->groupBy(function ($movie, $key) {

            return $movie['rating'];

        });

        /*

        [

           8 => [

             ["name" => "Back To the Future", "genre" => "scifi", "rating" => 8,],

             ["name" => "The Croods", "genre" => "animation", "rating" => 8,],

           ],

           9 => [

             ["name" => "The Matrix", "genre" => "fantasy", "rating" => 9,],

           ],

           4 => [

             ["name" => "Zootopia","genre" => "animation", "rating" => 4,],

           ],

           5 => [

             ["name" => "The Jungle Book","genre" => "fantasy","rating" => 5,],

           ],

        ]

       */

    }

دریافت زیر مجموعه‌ای از داده‌ها

با توجه به آرایه‌ای از داده‌ها، یا متقاربا یک مجموعه، شاید بخواهید بخشی از آن را به دست بیاورید. این بخش می‌تواند موارد زیر باشد:

  • دو رکورد اول
  • دو رکورد آخر
  • تمام رکوردها، اما در گرو‌ه‌های دو تایی

مجموعه‌ها دارای برخی متدها برای انجام این کارها هستند.

take

متد take یک مقدار integer را می‌گیرد و تعداد مشخص شده آیتم‌ها را بر می‌گرداند. اگر به آن یک مقدار منفی بدهید نیز،‌ تعداد مشخص شده آیتم‌ها را از آخر مجموعه بر می‌گرداند.

    public function takeMe()

    {

        $list = collect([

            'Albert', 'Ben', 'Charles', 'Dan', 'Eric', 'Xavier', 'Yuri', 'Zane'

        ]);

        //دریافت دو نام اول

        $firstTwo = $list->take(2);

        //['Albert', 'Ben']

        //دریافت دو نام آخر

        $lastTwo = $list->take(-2);

        //['Yuri', 'Zane']

    }

chunk

متد chunk، مجموعه مورد نظر را به تکه‌های کوچک‌تر در اندازه «n» تقسیم می‌کند.

    public function chunkMe()

    {

        $list = collect([

            'Albert', 'Ben', 'Charles', 'Dan', 'Eric', 'Xavier', 'Yuri', 'Zane'

        ]);

        $chunks = $list->chunk(3);

        $chunks->toArray();

        /*

        [

            ["Albert", "Ben", "Charles",],

            [3 => "Dan", 4 => "Eric", 5 => "Xavier",],

            [6 => "Yuri", 7 => "Zane",],

        ]

        */

    }

موارد زیادی وجود دارند که این ممکن است کاربری باشد.

وقتی که داده‌ها را به یک blade view منتقل می‌کنید، می‌توانید آن‌ها را به n ردیف در هر بار تقسیم کنید. مثلا به صورتی که هر ۳ نام در یک ردیف جا شوند.

@foreach($list->chunk(3) as $names)

    <div class="row">

        @foreach($names as $name)

            {{ $name }}

        @endforeach

    </div>

@endforeach

همچنین می‌تواند برعکس chink() را انجام دهید، و با استفاده از متد collapse() تکه‌های کوچک را به یک مجموعه بزرگتر تبدیل کنید.

تکرار داده‌ها

map

تابع map در یک مجموعه به صورت حلقه‌وار می‌چرخد و هر مقدار را در معرض یک تابع قرار می‌دهد.

ما مجموعه‌ای از نام مردم می‌سازیم و مجموعه‌ای از طول هر نام را بر می‌گردانیم.

public function mapMe()
{

        $names = collect([
            'Albert', 'Ben', 'Charles', 'Dan', 'Eric', 'Xavier', 'Yuri', 'Zane'
        ]);

        $lengths = $names->map(function ($name, $key) {
            return strlen($name);
        });
        $lengths->toArray();

        //[6, 3, 7, 3, 4, 6, 4, 4,]

}

transform

در حالیکه متد map یک مجموعه جدید می‌سازد، بعضی وقت‌ها شاید بخواهید مجموعه مورد نظر را ویرایش کنید. متد transform یک متد را می‌گیرد و یک action را بر روی همان مجموعه انجام می‌دهد.

از آنجایی که transform کردن یک مجموعه جدید را نمی‌سازد، نیازی نیست که آن را به یک مقدار جدید اختصای دهید.

    public function transformMe()

    {

        $names = collect([

            'Albert', 'Ben', 'Charles', 'Dan', 'Eric', 'Xavier', 'Yuri', 'Zane'

        ]);

        $names->transform(function ($name, $key) {

            return strlen($name);

        });

        $names->toArray();

        //[6, 3, 7, 3, 4, 6, 4, 4,]

    }

reduce

برخلاف متدهای map و transform، متد reduce یک مقدار تکی را بر می‌گرداند. این متد، نتیجه هر تکرار را به تکرار بعدی منتقل می‌کند.

برای نمونه، برای دریافت مجموعه مقدارهای integer در یک مجموعه، reduce مجموعه اعداد متعاقب را بر می‌گرداند و به صورت حلقه‌وار، نتیجه را به عدد بعدی اضافه می‌کند.

/**

     * دریافت مجموعه اعداد در یک مجموعه

     */

    public function reduceMe()

    {

        $numbers = collect([

            1, 2, 3, 4, 5, 6, 7, 8, 9, 10

        ]);

        $sum = $numbers->reduce(function ($sum, $number) {

            return $sum + $number;

        });

        //55

    }

each

متد each هر آیتم را از طریق یک تابع منتقل می‌کند.

جالب‌ترین بخش درباره متد each این است که به سادگی می‌توانید به برگرداندن مقدار false در تابع، از حلقه خارج شوید.

/**

     * دریافت لیستی از اعداد که معادل یا کوچک‌تر از5 هستند

     */

    public function eachMethod()

    {

        $numbers = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

        $smallNumbers = $numbers->each(function ($num, $key) {

            if ($num > 5) {

                return false;

            }

            echo $num .", ";

        });

        //1, 2, 3, 4, 5,

    }

every

متد every مجموعه‌ای جدید می‌سازد، که از هر عنصر nام در یک مجموعه ساخته شده است.

استفاده از یک مجموعه به عنوان یک Set

کلاس Collection همچنین متدهایی برای کمک در کار با داده‌ها به عنوان setها فراهم کرده است. این به این معنی است که می‌توانیم دو دیتاست را مقایسه کنیم و بر پایه آن‌، کارهایی را انجام دهیم.

union

متد union() برای اضافه کردن مقادیر به یک مجموعه، از یک آرایه استفاده می‌شود. اگر مقداری از قبل در مجموعه وجود داشته باشد، آن مقدار نادیده گرفته می‌شود.

/**

     * اضافه کردن مقادیر آرایه به یک مجموعه

     */

    public function union()

    {

        $coolPeople = collect([

            1 => 'John', 2 => 'James', 3 => 'Jack'

        ]);

        $allCoolPeople = $coolPeople->union([

            4 => 'Sarah', 1 => 'Susan', 5 =>'Seyi'

        ]);

        $allCoolPeople->all();

        /*

        [

            1 => "John", 2 => "James", 3 => "Jack", 4 => "Sarah", 5 => "Seyi",

       ]

       */

    }

intersect

متد intersect() عناصر موجود در یک مجموعه که در یک مجموعه یا آرایه منتقل شده وجود ندارند را حذف می‌کند.

public function intersect()
{
        $coolPeople = collect([
            1 => 'John', 2 => 'James', 3 => 'Jack'
        ]);

        $veryCoolPeople = $coolPeople->intersect(['Sarah', 'John', 'James']);
        $veryCoolPeople->toArray();
        //[1 => "John" 2 => "James"]

}

دقت کنید که متد intersect کلیدهایی برای مقادیر برگردانده شده را نگه می‌دارد.

نتیجه گیری

در این مقاله سعی کردم که تمام متدهای مجموعه‌ای که ممکن است بخواهید استفاده کنید را پوشش دهم، اما همچنان متدهای بیشتری باقی هستند که می‌توانید یاد بگیرید. مهم‌تر از همه، این موارد را رد کردم:

  • متدهای ریاضی رایج مانند sum و avg.
  • متدهایی که شامل بروزرسانی یک مجموعه می‌شوند. مانند splice، prepend، push و pop.

امیدوارم این که آموزش برای شما کاربردی بوده باشد.

منبع

مقالات پیشنهادی

10 متد Collections کمتر شناخته شده ( اما بسیار جالب ) لاراول

به نظر من Eloquent لاراول یک ابزار عالی در لاراوله - احتمالا نیازی به تاکیید کردن من روی این مسئله نیست چون همه این مسئله رو میدونن . امروز میخوام لیس...

چند نکته کاربردی درباره Collection ها در لاراول

کالکشن ها یکی از بهترین ویژگی های کاربردی لاراول هست. اینجا می خواهیم به چند نکته ی ساده و مهم برای استفاده از کالکشن ها اشاره کنیم. 

بهترین پکیج های لاراولی – سری اول

پکیج ها قابلیت عملیاتی لاراول را افزایش می‌دهند و عملکرد آنرا بهبود می‌بخشند. پکیج ها میتوانند یک راه مناسب برای کار با تاریخ در پروژه باشد مثل پکیج C...

کمکی های جدید لاراول در نسخه 5.4 و 5.5

کمکی های جدید String دارند راهشون رو به سمت لاراول از طریق ریلیز بزرگ 5.5 پیدا می کنند. که قراره در حین Laracon EU 2017 منتشر بشه.