Verifica della presenza di email duplicate nei dati di risposta api
Sto lavorando a una piccola app interna che funziona con un'API esterna a scopo di provisioning.
Il codice è essenzialmente costituito da una serie di moduli in cui l'utente inserisce i dati, questi dati vengono quindi inviati all'API per registrare nuovi clienti.
Questo è un processo piuttosto lineare che cercherò di spiegare:
- Creazione contatto: informazioni di base del cliente (e-mail, indirizzo ...).
- Creazione del cliente: informazioni più avanzate, per creare un cliente deve esserci
contactId
un'appartenenza a questo cliente. - Creazione abbonato: informazioni che collegano il cliente al servizio acquisito. Il passaggio precedente deve essere completato e
customerId
deve esistere. - Creazione servizio: ultimi bit di informazioni avanzate sul servizio. Ancora una volta,
suscriberId
deve esistere per collegare il servizio.
Ho gestito un processo più o meno veloce con alcune modifiche qua e là, ma il primo passaggio (Contatto) ha un metodo che non riesco a migliorare, che a sua volta fa sì che questo processo richieda fino a un minuto intero !
Come l'intero processo descritto in precedenza, anche la creazione di ciascuno di questi è molto lineare.
La documentazione API afferma che i risultati di qualsiasi GET devono essere impaginati fino a un massimo di 10 voci, ma in seguito a ciò aumenta ulteriormente il tempo nel minuto. Gli esperimenti manuali hanno mostrato che il rapporto migliore è di circa 500 voci per pagina o, in alcuni casi, anche l'intero numero di voci si è rivelato il modo più veloce piuttosto che 10 per 10.
Poiché l'email di contatto non può essere duplicata, una delle prime cose da fare è controllare l'email fornita nel modulo e confrontarla con tutte le email già esistenti archiviate.
Per fornire il $page
e $entries
alla chiamata API, devo prima recuperare il numero totale di contatti. Questo numero viene visualizzato quando si chiama l'API per ottenere i contatti. Quindi il primo metodo che uso è:
function fetchTotalContacts($uri, $auth){
$ch = curl_init(); $options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_URL => $uri.'?page=1&rows=1', CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: $auth')
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$response = json_decode($response, true);
$totalContacts = $response['total_count'];
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code != 200) { echo "Error en fetchTotalContacts() - Código: $http_code | ";
}
curl_close($ch); return $totalContacts;
}
Ora $totalContacts
, posso procedere e cercare se l'e-mail è già stata registrata, e questo è il passaggio che sospetto sia responsabile dell'elevato tempo di esecuzione. Questo metodo ricerca i contatti e le loro email, se non trova coincidenza, procede alla creazione del contatto con i dati forniti.
function checkDuplicatedEmail($uri, $totalContacts, $contactEmailArray, $auth, $contactEmail, $dataContact){ $ch = curl_init();
$options = array( CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_URL => $uri.'?page=1&rows='.$totalContacts, CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: $auth')
);
curl_setopt_array($ch, $options);
$customers = curl_exec($ch);
$customers = json_decode($customers, true);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code != 200) { echo "Error en checkDuplicatedEmail() - Código: $http_code | ";
}
curl_close($ch); /* foreach ($customers['_embedded']['ngcp:customercontacts'] as $customer) { $email = $customer['email']; array_push($contactEmailArray, $email); } if (in_array($contactEmail, $contactEmailArray)) { echo('El email utilizado ya ha sido registrado en la base de datos'); die(); }else{ $contactCreated = createContact($uri, $dataContact);
return $contactCreated; } */ $repeated = 0;
for ($i=0; $i < $totalContacts ; $i++) {
if ($contactEmail == $customer["_embedded"]["ngcp:customercontacts"][$i]["email"]) { $repeated += 1;
}
}
if ($repeated > 0) { die(echo('El email utilizado ya ha sido registrado en la base de datos')); }else{ $contactCreated = createContact($uri, $dataContact, $auth); return $contactCreated;
}
}
Come puoi vedere, queste sono le opzioni più veloci che ho trovato, entrambe fanno sì che l'intero processo richieda 40 secondi, il che è ancora troppo.
La risposta per è un codice di successo (400, 201 ..), quindi quando voglio andare al passaggio successivo devo, ancora una volta, cercare tutti i contatti per trovare quello che ho appena creato e ottenere l'id. Fortunatamente, qui posso semplicemente saltare agli ultimi 20 contatti (non l'ultimo direttamente in modo che possa essere utilizzato contemporaneamente senza problemi) e cercare lì, questo lo rende davvero veloce, ma per l'email non c'è un tale salto, tutte le voci deve essere analizzato.createContact($uri, $dataContact, $auth);
Non so come far cadere il tempo qui, il resto del codice consiste nel recuperare contactId
e creare il cliente in modo che non ci sia molto da fare lì come lo è ora.
Se qualcuno di voi riterrà necessario vedere il resto della pagina aggiornerò il post.
Come promemoria finale, ho provato manualmente con diverse configurazioni di pagine e voci e per questa pagina, il più veloce è stato 1 page - All entries
. Ho anche provato a prendere il ciclo for / each al di fuori del metodo, senza alcun risultato.
Risposte
Il for
loop non sarà il collo di bottiglia nel tuo loop, ma ciò che mi sembra ovvio è che non trai vantaggio dal conteggio più alto di $repeated = 1
. Ciò significa che non è necessaria una variabile contatore, in realtà è necessario un evento di interruzione del ciclo, in questo caso die()
. Per tua informazione, die()
stamperà il testo nel suo primo parametro, quindi l'utilizzo echo
è ridondante.
for ($i=0; $i < $totalContacts; ++$i) { if ($contactEmail == $customer["_embedded"]["ngcp:customercontacts"][$i]["email"]) {
die('El email utilizado ya ha sido registrado en la base de datos');
}
}
return createContact($uri, $dataContact, $auth);
O un altro modo, che presumo sarà più lento (perché array_column()
raccoglierà tutte le email) è questo design funzionale:
if (in_array($contactEmail, array_column($customer["_embedded"]["ngcp:customercontacts"], "email"))) { die('El email utilizado ya ha sido registrado en la base de datos'); } return createContact($uri, $dataContact, $auth);