title: Need Time-Efficient Method of Importing Large CSV File Via PHP Into Multiple MySQL Tables
body: <p>Okay, I'm having some serious issues here. I'm new to this site, and new to dealing with importing CSV data via PHP, but I'm not new to programming.</p>
  
  <p>Currently, I'm working on building a Customer Relationship Manager. I need to create a script to import a file that will populate the database with leads. The main issue here is that the Lead data consists of Companies and Employees of said Company. Also, a few other tables are split off, such as billing information, from the main tables.</p>
  
  <p>I have a working script that will allow users to map the imported data to specific rows and columns.</p>
  
  <pre><code>function mapData($file) {
      // Open the Text File
      $fd = fopen($file, "r");
  
      // Return FALSE if file not found
      if(!$fd) {
          return FALSE;
      }
  
      // Get the First Two Lines
      $first = 0;
      $data = array();
      while(!feof($fd)) {
          if($first == 0) {
              $cols = fgetcsv($fd, 4096);
              $data['cols'] = array();
              if(is_array($cols) &amp;&amp; count($cols)) {
                  foreach($cols as $col) {
                      if(!$col) {
                          continue;
                      }
                      $data['cols'][] = $col;
                  }
              }
              if(empty($data['cols'])) {
                  return array();
              }
              $first++;
              continue;
          }
          else {
              $data['first'] = fgetcsv($fd, 4096);
              break;
          }
      }
      fclose($fd);
  
      // Return Data
      return $data;
  }
  </code></pre>
  
  <p>The above script only activates after CodeIgniter moves the file to a working directory. I already know what the file name is by this point. The file goes in and returns the list of columns and the first row. Any empty columns are ignored.</p>
  
  <p>After this, process passes to a mapping script. Once mapping is done and "Import" is pressed, this piece of code loads.</p>
  
  <pre><code>function importLeads($file, $map) {
      // Open the Text File
      if(!file_exists($file)) {
          return false;
      }
      error_reporting(E_ALL);
      set_time_limit(240);
      ini_set("memory_limit", "512M");
      $fd = fopen($file, "r");
  
      // Return FALSE if file not found
      if(!$fd) {
          return FALSE;
      }
  
      // Traverse Each Line of the File
      $true = false;
      $first = 0;
      while(!feof($fd)) {
          if($first == 0) {
              $cols = fgetcsv($fd);
              $first++;
              continue;
          }
  
          // Get the columns of each line
          $row = fgetcsv($fd);
  
          // Traverse columns
          $group = array();
          $lead_status = array();
          $lead_type = array();
          $lead_source = array();
          $user = array();
          $user_cstm = array();
          $user_prof = array();
          $acct = array();
          $acct_cstm = array();
          $acct_prof = array();
          $acct_group = array();
          if(!$row) {
              continue;
          }
          foreach($row as $num =&gt; $val) {
              if(empty($map[$num])) {
                  continue;
              }
              $val = str_replace('"', "&amp;#34;", $val);
              $val = str_replace("'", "&amp;#39;", $val);
              switch($map[$num]) {
              // Company Account
              case "company_name":
                  $acct['company_name'] = $val;
                  break;
              case "lead_type":
                  $lead_type['name'] = $val;
                  break;
              case "lead_source":
                  $lead_source['name'] = $val;
                  break;
              case "lead_source_description":
                  $lead_source['name'] = $val;
                  break;
              case "campaign":
                  $campaign['name'] = $val;
                  break;
              case "mcn":
                  $acct['mcn'] = $val;
                  break;
              case "usdot":
                  $acct['usdot'] = $val;
                  break;
              case "sic_codes":
                  $acct_cstm['sic_codes'] = $val;
                  break;
              case "naics_codes":
                  $acct_cstm['naics_codes'] = $val;
                  break;
              case "agent_assigned":
                  $acct_cstm['agent_assigned'] = $val;
                  break;
              case "group_assigned":
                  $group['name'] = $val;
                  break;
              case "rating":
                  $acct_cstm['rating'] = $val;
                  break;
              case "main_phone":
                  $acct['phone'] = $val;
                  break;
              case "billing_phone":
                  $acct_cstm['billing_phone'] = $val;
                  break;
              case "company_fax":
                  $acct['fax'] = $val;
                  break;
              case "company_email":
                  $acct['email2'] = $val;
                  break;
  
              // Company Location
              case "primary_address":
                  $acct['address'] = $val;
                  break;
              case "primary_address2":
                  $acct['address2'] = $val;
                  break;
              case "primary_city":
                  $acct['city'] = $val;
                  break;
              case "primary_state":
                  $acct['state'] = $val;
                  break;
              case "primary_zip":
                  $acct['zip'] = $val;
                  break;
              case "primary_country":
                  $acct['country'] = $val;
                  break;
              case "billing_address":
                  $billing['address'] = $val;
                  break;
              case "billing_address2":
                  $billing['address2'] = $val;
                  break;
              case "billing_city":
                  $billing['city'] = $val;
                  break;
              case "billing_state":
                  $billing['state'] = $val;
                  break;
              case "billing_zip":
                  $billing['zip'] = $val;
                  break;
              case "billing_country":
                  $billing['country'] = $val;
                  break;
              case "company_website":
                  $acct_cstm['website'] = $val;
                  break;
              case "company_revenue":
                  $acct_cstm['revenue'] = $val;
                  break;
              case "company_about":
                  $acct_prof['aboutus'] = $val;
                  break;
  
              // Misc. Company Data
              case "bols_per_mo":
                  $acct_cstm['approx_bols_per_mo'] = $val;
                  break;
              case "no_employees":
                  $acct_cstm['no_employees'] = $val;
                  break;
              case "no_drivers":
                  $acct_prof['drivers'] = $val;
                  break;
              case "no_trucks":
                  $acct_prof['power_units'] = $val;
                  break;
              case "no_trailers":
                  $acct_cstm['no_trailers'] = $acct_prof['trailers'] = $val;
                  break;
              case "no_parcels_day":
                  $acct_cstm['no_parcels_day'] = $val;
                  break;
              case "no_shipping_locations":
                  $acct_cstm['no_shipping_locations'] = $val;
                  break;
              case "approves_inbound":
                  $acct_cstm['approves_inbound'] = $val;
                  break;
              case "what_erp_used":
                  $acct_cstm['what_erp_used'] = $val;
                  break;
              case "birddog":
                  $acct_cstm['birddog_referral'] = $val;
                  break;
              case "status_notes":
                  $acct_cstm['status_notes'] = $val;
                  break;
              case "notes":
                  $acct_cstm['notes'] = $val;
                  break;
              case "internal_notes":
                  $acct_cstm['notes_internal'] = $val;
                  break;
  
              // User Data
              case "salutation":
                  $user_cstm['salutation'] = $val;
                  break;
              case "first_name":
                  $user['first_name'] = $billing['first_name'] = $val;
                  break;
              case "last_name":
                  $user['last_name'] = $billing['last_name'] = $val;
                  break;
              case "user_title":
                  $user_prof['title'] = $val;
                  break;
              case "user_about":
                  $user_prof['about'] = $val;
                  break;
              case "user_email":
                  $user['email'] = $val;
                  break;
              case "home_phone":
                  $user_prof['phone'] = $val;
                  break;
              case "mobile_phone":
                  $user_cstm['mobile_phone'] = $val;
                  break;
              case "direct_phone":
                  $user_cstm['direct_phone'] = $val;
                  break;
              case "user_fax":
                  $user_prof['fax'] = $val;
                  break;
              case "user_locale":
                  $user['location'] = $val;
                  break;
              case "user_website":
                  $user_prof['website_url'] = $val;
                  break;
              case "user_facebook":
                  $user_prof['fb_url'] = $val;
                  break;
              case "user_twitter":
                  $user_prof['twitter_url'] = $val;
                  break;
              case "user_linkedin":
                  $user_prof['linkedin_url'] = $val;
                  break;
              }
          }
          if(empty($acct['company_name']) || empty($user['first_name']) || empty($user['last_name'])) {
              continue;
          }
          $this-&gt;db = $this-&gt;load-&gt;database('crm_db', TRUE);
          if(isset($lead_type['name']) &amp;&amp; ($name = $lead_type['name'])) {
              $count = $this-&gt;db-&gt;count_all("lead_types");
              $check = $this-&gt;db-&gt;get_where("lead_types", array("name" =&gt; $name));
              if($check-&gt;num_rows() &lt; 1) {
                  $this-&gt;db-&gt;insert("lead_types", array("name" =&gt; $name, "order" =&gt; $count));
                  $ltype = $this-&gt;db-&gt;insert_id();
                  $acct_cstm['lead_type'] = $acct['account_type'] = $user['company_type'] = $ltype;
              }
          }
          if(isset($lead_source['name']) &amp;&amp; ($name = $lead_source['name'])) {
              $count = $this-&gt;db-&gt;count_all("lead_sources");
              $check = $this-&gt;db-&gt;get_where("lead_sources", array("name" =&gt; $name));
              if($check-&gt;num_rows() &lt; 1) {
                  $this-&gt;db-&gt;insert("lead_sources", array("name" =&gt; $name, "order" =&gt; $count));
                  $acct_cstm['lead_source'] = $this-&gt;db-&gt;insert_id();
              }
          }
          if(isset($campaign['name']) &amp;&amp; ($name = $campaign['name'])) {
              $check = $this-&gt;db-&gt;get_where("campaigns", array("name" =&gt; $name));
              if($check-&gt;num_rows() &lt; 1) {
                  $campaign['id'] = $accounts_cstm['campaign'] = $this-&gt;Secure_m-&gt;generate_sugar_id();
                  $campaign['date_entered'] = time();
                  $campaign['date_modified'] = time();
                  $campaign['modified_user_id'] = $this-&gt;session-&gt;userdata('id');
                  $campaign['created_by'] = $this-&gt;session-&gt;userdata('id');
                  $this-&gt;db-&gt;insert("campaigns", $campaign);
              }
          }
          if(isset($group['name']) &amp;&amp; ($name = $group['name'])) {
              $order = $this-&gt;db-&gt;count_all("groups");
              $check = $this-&gt;db-&gt;get_where("groups", array("name" =&gt; $name));
              if($check-&gt;num_rows() &lt; 1) {
                  $this-&gt;db-&gt;insert("groups", array("name" =&gt; $name, "order" =&gt; $order));
                  $acct_group['id'] = $this-&gt;db-&gt;insert_id();
              }
          }
          $mem = new stdclass;
          $uid = 0;
          if(is_array($user) &amp;&amp; count($user)) {
              $where = "";
              if(!empty($user['phone'])) {
                  $where .= "prof.phone = '{$user['phone']}' OR ";
                  $where .= "cstm.mobile_phone = '{$user['phone']}' OR ";
                  $where .= "cstm.direct_phone = '{$user['phone']}'";
              }
              if(!empty($user['mobile_phone'])) {
                  if($where) {
                      $where .= " OR ";
                  }
                  $where .= "prof.phone = '{$user['mobile_phone']}' OR ";
                  $where .= "cstm.mobile_phone = '{$user['mobile_phone']}' OR ";
                  $where .= "cstm.direct_phone = '{$user['mobile_phone']}'";
              }
              if(!empty($user['direct_phone'])) {
                  if($where) {
                      $where .= " OR ";
                  }
                  $where .= "prof.phone = '{$user['direct_phone']}' OR ";
                  $where .= "cstm.mobile_phone = '{$user['direct_phone']}' OR ";
                  $where .= "cstm.direct_phone = '{$user['direct_phone']}'";
              }
              $query = $this-&gt;db-&gt;query($this-&gt;Account_m-&gt;userQuery($where));
              $mem = reset($query-&gt;result());
              if($where &amp;&amp; !empty($mem-&gt;id)) {
                  $uid = $mem-&gt;id;
                  $new = array();
                  foreach($user as $k =&gt; $v) {
                      if(!empty($mem-&gt;$k)) {
                          $new[$k] = $mem-&gt;$k;
                          unset($user[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("leads", $user, array("id" =&gt; $uid));
                  $user = $new;
              }
              else {
                  $user['uxtime'] = time();
                  $user['isclient'] = 0;
                  $user['flag'] = 0;
                  $user['activation_code'] = $this-&gt;Secure_m-&gt;generate_activate_id();
                  $uid = $this-&gt;Secure_m-&gt;generate_activate_id(10);
                  $query = $this-&gt;db-&gt;get_where("leads", array("id" =&gt; $uid), 1);
                  $data = reset($query-&gt;result());
                  while(!empty($data-&gt;id)) {
                      $uid = $this-&gt;Secure_m-&gt;generate_activate_id(10);
                      $query = $this-&gt;db-&gt;get_where("leads", array("id" =&gt; $uid), 1);
                      $data = reset($query-&gt;result());
                  }
                  $user['id'] = $uid;
                  $this-&gt;db-&gt;insert("leads", $user);
              }
          }
          if($uid &amp;&amp; is_array($user_prof) &amp;&amp; count($user_prof)) {
              if(!empty($mem-&gt;uid)) {
                  $new = array();
                  foreach($user_prof as $k =&gt; $v) {
                      if(!empty($mem-&gt;$k)) {
                          $new[$k] = $mem-&gt;$k;
                          unset($user_prof[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("mprofiles", $user_prof, array("uid" =&gt; $uid));
                  $user_prof = $new;
              }
              else {
                  $user_prof['uid'] = $uid;
                  $user_prof['flag'] = 0;
                  $this-&gt;db-&gt;insert("ldetails", $user_prof);
              }
          }
          if($uid &amp;&amp; is_array($user_cstm) &amp;&amp; count($user_cstm)) {
              $query = $this-&gt;db-&gt;get_where("leads_cstm", array("crm_id" =&gt; $cid), 1);
              $data = reset($query-&gt;result());
              if(!empty($data-&gt;crm_id)) {
                  $new = array();
                  foreach($user_cstm as $k =&gt; $v) {
                      if(!empty($mem-&gt;$k)) {
                          $new[$k] = $mem-&gt;$k;
                          unset($user_cstm[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("leads_cstm", $acct_prof, array("fa_user_id" =&gt; $cid));
                  $user_cstm = $new;
              }
              else {
                  $user_cstm['crm_id'] = $uid;
                  $user_cstm['date_entered'] = time();
                  $user_cstm['date_modified'] = time();
                  $user_cstm['created_by'] = $this-&gt;session-&gt;userdata('id');
                  $user_cstm['modified_user_id'] = $this-&gt;session-&gt;userdata('id');
                  $this-&gt;db-&gt;insert("leads_cstm", $user_cstm);
              }
          }
          $cmp = new stdclass;
          $cid = 0;
          if(is_array($acct) &amp;&amp; count($acct)) {
              $acct['uid'] = $uid;
              $acct['main_contact'] = "{$user['first_name']} {$user['last_name']}";
              if(!empty($user['email'])) {
                  $acct['email'] = $user['email'];
              }
              $acct['isprospect'] = 0;
              $acct['flag'] = 0;
              if(!empty($acct['mcn'])) {
                  $where .= "fms.mcn = '{$acct['mcn']}'";
              }
              if(!empty($acct['phone'])) {
                  if($where) {
                      $where .= " OR ";
                  }
                  $where .= "fms.phone = '{$acct['phone']}' OR ";
                  $where .= "crm.billing_phone = '{$acct['phone']}'";
              }
              if(!empty($acct['billing_phone'])) {
                  if($where) {
                      $where .= " OR ";
                  }
                  $where .= "fms.phone = '{$acct['billing_phone']}' OR ";
                  $where .= "crm.billing_phone = '{$acct['billing_phone']}'";
              }
              if(!empty($acct['company_name'])) {
                  if($where) {
                      $where .= " OR ";
                  }
                  $where .= "fms.company_name = '{$acct['company_name']}'";
              }
              $query = $this-&gt;db-&gt;query($this-&gt;Account_m-&gt;acctQuery($where));
              $cmp = reset($query-&gt;result());
              if($where &amp;&amp; !empty($cmp-&gt;id)) {
                  $cid = $cmp-&gt;id;
                  $new = array();
                  foreach($acct as $k =&gt; $v) {
                      if(!empty($cmp-&gt;$k)) {
                          $new[$k] = $cmp-&gt;$k;
                          unset($acct[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("accounts", $billing, array("cid" =&gt; $cid));
                  $acct = $new;
              }
              else {
                  $cid = $this-&gt;Secure_m-&gt;generate_activate_id(10);
                  $query = $this-&gt;db-&gt;get_where("leads", array("id" =&gt; $uid), 1);
                  $data = reset($query-&gt;result());
                  while(!empty($data-&gt;id)) {
                      $cid = $this-&gt;Secure_m-&gt;generate_activate_id(10);
                      $query = $this-&gt;db-&gt;get_where("accounts", array("id" =&gt; $cid), 1);
                      $data = reset($query-&gt;result());
                  }
                  $acct['id'] = $cid;
                  $this-&gt;db-&gt;insert("accounts", $acct);
              }
          }
          if($cid &amp;&amp; is_array($acct_group) &amp;&amp; count($acct_group)) {
              $grp = $this-&gt;db-&gt;get_where("accounts_groups", array("cid" =&gt; $cid, "gid" =&gt; $acct_group['id']));
              if(empty($cmp-&gt;id)) {
                  $acct_group['cid'] = $cid;
                  $this-&gt;db-&gt;insert("accounts_groups", $acct_group);
              }
          }
          if($cid &amp;&amp; is_array($acct_prof) &amp;&amp; count($acct_prof)) {
              if(!empty($cmp-&gt;id)) {
                  $new = array();
                  foreach($acct_prof as $k =&gt; $v) {
                      if(!empty($cmp-&gt;$k)) {
                          $new[$k] = $cmp-&gt;$k;
                          unset($acct_prof[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("cprofiles", $acct_prof, array("cid" =&gt; $cid));
                  $acct_prof = $new;
              }
              else {
                  $acct_prof['cid'] = $cid;
                  $acct_prof['flag'] = 0;
                  $this-&gt;db-&gt;insert("adetails", $acct_prof);
              }
          }
          if($cid &amp;&amp; is_array($billing) &amp;&amp; count($billing)) {
              $bill = $this-&gt;db-&gt;get_where("accounts_billing", array("cid" =&gt; $cid));
              if(!empty($bill-&gt;id)) {
                  $new = array();
                  foreach($acct_prof as $k =&gt; $v) {
                      if(!empty($cmp-&gt;$k)) {
                          $new[$k] = $cmp-&gt;$k;
                          unset($acct_prof[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("accounts_billing", $billing, array("cid" =&gt; $cid));
              }
              else {
                  $billing['cid'] = $cid;
                  $billing['flag'] = 0;
                  $this-&gt;db-&gt;insert("accounts_billing", $billing);
              }
          }
          if($cid &amp;&amp; $uid) {
              $this-&gt;db-&gt;update("leads", array("cid" =&gt; $cid), array("id" =&gt; $uid));
          }
          if($cid &amp;&amp; is_array($acct_cstm) &amp;&amp; count($acct_cstm)) {
              $query = $this-&gt;db-&gt;get_where("accounts_cstm", array("crm_id" =&gt; $cid), 1);
              $data = reset($query-&gt;result());
              if(!empty($data-&gt;crm_id)) {
                  $new = array();
                  foreach($acct_cstm as $k =&gt; $v) {
                      if(!empty($cmp-&gt;$k)) {
                          $new[$k] = $cmp-&gt;$k;
                          unset($acct_cstm[$k]);
                      }
                      else {
                          $new[$k] = $v;
                      }
                  }
                  //$this-&gt;db-&gt;update("accounts_cstm", $acct_cstm, array("crm_id" =&gt; $cid));
                  $acct_cstm = $new;
              }
              else {
                  $acct_cstm['crm_id'] = $cid;
                  $acct_cstm['date_entered'] = time();
                  $acct_cstm['date_modified'] = time();
                  $acct_cstm['created_by'] = $this-&gt;session-&gt;userdata('id');
                  $acct_cstm['modified_user_id'] = $this-&gt;session-&gt;userdata('id');
                  if(empty($acct_cstm['rating'])) {
                      $acct_cstm['rating'] = 1;
                  }
                  $this-&gt;db-&gt;insert("accounts_cstm", $acct_cstm);
              }
          }
          $true = TRUE;
      }
      fclose($fd);
  
      return $true;
  }
  </code></pre>
  
  <p>Now, as far as I can see, the script works perfectly fine. There's nothing wrong with the actual code itself. The problem is that after around 400-500 rows, the script just stops. I don't receive an error, but no further code is processed.</p>
  
  <p>I know this because I have code after this that is supposed to return a redirect page through AJAX. Nothing after my loop in the importLeads function ever loads, though.</p>
  
  <p>I'm not sure how to make this script more efficient... I'm positive it is timing out, but I don't know how to make it run more efficiently. I NEED this script to process all the information above separately. I have a variety of separate tables that all link together, and this import script has to set everything up in different ways.</p>
  
  <p>I've talked with my client about this project. This script works when I drop it to around 400 rows. He has some a lot of these CSV files that are around 75,000 rows. The one I am importing is a smaller one, only about 1,200 rows.</p>
  
  <p>I've tried looking into alternate methods, such as MySQL's import script, but I can't do that because this script must import data into separate tables, and it must check for existing data first. I'm also supposed to have all empty fields update with imported information, but that will make this even worse.</p>
  
  <p>If anyone knows of a more efficient method it would be much appreciated. I tried to be as detailed as I could. Of note, I will mention that I'm using CodeIgniter, but if there's a more efficient way that doesn't use CodeIgniter I'll take it (I can still put it into a CI model, though).</p>