LeviZoesch
LeviZoesch

Reputation: 1621

Laravel Collection() vs collect()

I have a series of database tables that store estimating information. I am trying to return all data from all database tables when certain perimeters are set.

Collection

        $estimateItems = new Collection();
    $estimateItems = $estimateItems->merge( $this->getBoxVent() );
    $estimateItems = $estimateItems->merge( $this->getCoatings() );
    $estimateItems = $estimateItems->merge( $this->getCounterFlashing() );
    $estimateItems = $estimateItems->merge( $this->getDripEdge() );
    $estimateItems = $estimateItems->merge( $this->getFasteners() );
    $estimateItems = $estimateItems->merge( $this->getHeadwallFlashing() );
    $estimateItems = $estimateItems->merge( $this->getHipcap() );
    $estimateItems = $estimateItems->merge( $this->getIceShield() );
    $estimateItems = $estimateItems->merge( $this->getPipeFlashing() );
    $estimateItems = $estimateItems->merge( $this->getRidgecap() );
    $estimateItems = $estimateItems->merge( $this->getRidgeVentilation() );
    $estimateItems = $estimateItems->merge( $this->getSheathing() );
    $estimateItems = $estimateItems->merge( $this->getShingles() );
    $estimateItems = $estimateItems->merge( $this->getSidewallFlashing() );
    $estimateItems = $estimateItems->merge( $this->getSkylights() );
    $estimateItems = $estimateItems->merge( $this->getStarterShingle() );
    $estimateItems = $estimateItems->merge( $this->getTearOff() );
    $estimateItems = $estimateItems->merge( $this->getUnderlayment() );
    $estimateItems = $estimateItems->merge( $this->getValleyMetal() );

enter image description here

and Collect()

$collectedItems = collect([
        $this->getBoxVent(),
        $this->getCoatings(),
        $this->getCounterFlashing(),
        $this->getDripEdge(),
        $this->getFasteners(),
        $this->getHeadwallFlashing(),
        $this->getHipcap(),
        $this->getIceShield(),
        $this->getPipeFlashing(),
        $this->getRidgecap(),
        $this->getRidgeVentilation(),
        $this->getSheathing(),
        $this->getShingles(),
        $this->getSidewallFlashing(),
        $this->getSkylights(),
        $this->getStarterShingle(),
        $this->getTearOff(),
        $this->getUnderlayment(),
        $this->getValleyMetal(),
    ]);

enter image description here

There are only 4 database tables that have data pertaining to this "estimate" for this example. Ideally there would be 1 or all have data.

Why does Collection only return a maximum of 3, where as collect returns them all even if they're empty?

Am i doing something wrong to have the $estimateItems = new Collection(); only return 3, when theres 4 or more in database?

Here are the queries I am using.

    private function getBoxVent() {
    return ProposalBoxVent::where('proposalRecordID', $this->getProposalAPI())->get();
}

private function getCoatings() {
    return ProposalCoatings::where('proposalRecordID', $this->getProposalAPI())->get();
}

If I use concat instead of merge I get the desired results. enter image description here

Upvotes: 3

Views: 16755

Answers (2)

lagbox
lagbox

Reputation: 50491

What you pass to collect() is the array you want as the 'items' of the Collection. You are saying you want a Collection containing 18 items; it just happens to be that most of them are empty, but that doesn't matter to the array or Collection.

When you are merging you are actually merging the current items of the Collection with a new set of items. When merging it is possible that something is overwriting something else instead of adding to the Collection. Similar to how array_merge works as that is what is happening internally. Eloquent Collections get keyed by 'id'.

It is possible to also try to use values to reset the keys before merging:

$collection->merge($this->getValleyMetal()->values());

Upvotes: 1

mrhn
mrhn

Reputation: 18926

I would believe you are having problems with the merge method in Laravel, merge will work differently if it is an associative array or an indexed array. If it's indexed, it should work as concat. Thou if it's associtive array it will try to merge it by key value base. Therefor i believe one of your underlying methods return something wrongfully.

With that said, if you are working with indexed arrays concat is better and quicker since it don't have to check. If you want to merge ['apple' => 'green'] with ['banana' => 'yellow'] into ['apple' => 'green', 'banana' => 'yellow'] you should use merge.

In regards to your question use concat instead, if you are working with indexed arrays. Merge can also have bad performance in big sets.

$estimateItems = $estimateItems->concat($this->getBoxVent());

Upvotes: 2

Related Questions