Skip to content

Instantly share code, notes, and snippets.

@LasseRafn
Last active June 9, 2017 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LasseRafn/5b3b945eddb7ff6193fb18dd1ed16cfb to your computer and use it in GitHub Desktop.
Save LasseRafn/5b3b945eddb7ff6193fb18dd1ed16cfb to your computer and use it in GitHub Desktop.
<?php
/*
* Various of other things going on up here. I slimmed down the code for readability,
* and focus. $companies is an array of .. companies .. gathered from an external API.
*/
$companiesToCreate = collect([]);
foreach ( $companies as $company )
{
$companiesToCreate->push( [...] ); /* Pushing some data from $company here */
foreach( $company->contacts()->all() as $contact)
{
/*
* I need to fetch contacts from $company and add that to the createMany below.
* Basically the best would be if I could just add it to the above push statement,
* with a array-key with the name of the hasMany-relation-method in the class.
* But I dont assume thats an option. With the current setup, I'll likely have to
* Create each company in the foreach, and append contacts to them in the loop too.
* Which is not really optimal, considering some companies might have 50.000 contacts,
* and that theres easily 5.000 companies in a single array. Likely more.
*/
}
}
$this->companies()->createMany( $companiesToCreate->toArray() );
@billmn
Copy link

billmn commented Dec 6, 2016

@LasseRafn I hope that I have correctly understood your case.

I have used insert() because createMany() execute a query for each employee.
Obviously this require to associate the company ID before.

This example cares only to insert new companies and new employees.
If you need a complete sync (create/update/delete) we can change it to fit your needs.

<?php

use App\Company;
use App\Employe;
use App\Business;

Route::get('/', function ()
{
    // Business contains manny companies
    $business = Business::first();

    // Collection of companies from the API
    $extCompanies = collect([
        ['code' => 'company-1', 'name' => 'Company 1'],
        ['code' => 'company-2', 'name' => 'Company 2'],
        ['code' => 'company-3', 'name' => 'Company 3'],
        ['code' => 'company-4', 'name' => 'Company 4'],
        ['code' => 'company-5', 'name' => 'Company 5'],
    ])->keyBy('code');

    // Collection of employees from the API
    $extEmployees = collect([
        ['company' => 'company-1', 'code' => 'empl_1', 'name' => 'Taylor'],
        ['company' => 'company-1', 'code' => 'empl_2', 'name' => 'Jeffrey'],
        ['company' => 'company-2', 'code' => 'empl_7', 'name' => 'Matt'],
        ['company' => 'company-3', 'code' => 'empl_3', 'name' => 'Adam'],
        ['company' => 'company-4', 'code' => 'empl_4', 'name' => 'Lasse'],
        ['company' => 'company-4', 'code' => 'empl_5', 'name' => 'Davide'],
        ['company' => 'company-4', 'code' => 'empl_6', 'name' => 'John'],
        ['company' => 'company-5', 'code' => 'empl_8', 'name' => 'Steve'],
    ]);

    // In this example I would create only new companies ignoring existing ones
    $intCompanies = $business->companies()->select('code')->pluck('code', 'code');
    $newCompanies = $extCompanies->diffKeys($intCompanies);

    foreach ($newCompanies as $code => $extCompany) {
        // For optimization I can run a single "insert" outside the loop and execute
        // a new query with a "whereIn('code', ...)" condition
        $company = $business->companies()->create($extCompany);

        // "Company code" doesn't exists on employees table, then remove it
        $newEmployees = $extEmployees->where('company', $code)->map(function($item) use ($company) {
            $item['company_id'] = $company->id;
            unset($item['company']);

            return $item;
        });

        // Insert all company's employees with a single query
        if ($newEmployees->isEmpty() === false) {
            $company->employees()->insert($newEmployees->toArray());
        }
    }

    return 'Done.';
});

using "createMany"

schermata 2016-12-06 alle 11 40 57

Using "insert"

schermata 2016-12-06 alle 11 42 54

@LasseRafn
Copy link
Author

Didn't even reply to the comment. Went back to this (at random) and remembered that your solution fixed this. Thanks so much!! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment