J'essaie d'interroger mon jos_rsform_submission_values
table pour FieldValue
données en lignes avec un FieldName
de Container#
qui partage un SubmissionId
avec une autre ligne où FieldValue
est "en attente" et FieldName
est "Status #" et le #
après "Statut" = le #
après "Conteneur".
Voici quelques exemples de données de table, afin que je puisse mieux exprimer ce que je recherche:
CREATE TABLE `jos_rsform_submission_values` (
`SubmissionValueId` int(11) NOT NULL,
`FormId` int(11) NOT NULL,
`SubmissionId` int(11) NOT NULL DEFAULT '0',
`FieldName` text NOT NULL,
`FieldValue` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `jos_rsform_submission_values` (`SubmissionValueId`, `FormId`, `SubmissionId`, `FieldName`, `FieldValue`) VALUES
(129862, 28, 548, 'creationdate', '27-08-2018 10:30 AM'),
(129863, 28, 548, 'CustomerAccount', 'TEST'),
(129864, 28, 548, 'otheraccount', ''),
(129865, 28, 548, 'salesorderno', 'SO-00006296'),
(129866, 28, 548, 'DocumentUpload', '-'),
(129867, 28, 548, 'numberofbayan', '1'),
(129868, 28, 548, 'BayanNo', '189426'),
(129869, 28, 548, 'portofloading', 'Seaport'),
(129870, 28, 548, 'containers', '3'),
(129871, 28, 548, 'Container1', 'TTNU8517512'),
(129872, 28, 548, 'CargoDescription1', 'Chocolate'),
(129873, 28, 548, 'containertype1', 'Reefer'),
(129874, 28, 548, 'purchaseorder1', ''),
(129875, 28, 548, 'Location1', 'Jeddah'),
(129876, 28, 548, 'Status1', 'Return Empty'),
(129877, 28, 548, 'requesteddate1', '18-08-2018 07:00 AM'),
(129878, 28, 548, 'Container2', 'TCLU1256192'),
(129879, 28, 548, 'CargoDescription2', 'Chocolate'),
(129880, 28, 548, 'containertype2', 'Reefer'),
(129881, 28, 548, 'purchaseorder2', ''),
(129882, 28, 548, 'Location2', 'Jeddah'),
(129883, 28, 548, 'Status2', 'Return Empty'),
(129884, 28, 548, 'requesteddate2', '18-08-2018 07:00 AM'),
(129885, 28, 548, 'Container3', 'KKFU6780793'),
(129886, 28, 548, 'CargoDescription3', 'Chocolate'),
(129887, 28, 548, 'containertype3', 'Reefer'),
(129888, 28, 548, 'purchaseorder3', ''),
(129889, 28, 548, 'Location3', 'Jeddah'),
(129890, 28, 548, 'Status3', 'Pending'),
(129891, 28, 548, 'requesteddate3', '18-08-2018 07:00 AM'),
(129892, 28, 548, 'Container4', ''),
(129893, 28, 548, 'CargoDescription4', ''),
(129894, 28, 548, 'containertype4', ' '),
(129895, 28, 548, 'purchaseorder4', ''),
(129896, 28, 548, 'Location4', '-'),
(129897, 28, 548, 'Status4', ' '),
(129898, 28, 548, 'requesteddate4', ''),
(129899, 28, 548, 'Container5', ''),
(129900, 28, 548, 'CargoDescription5', ''),
(129901, 28, 548, 'containertype5', ' '),
(129902, 28, 548, 'purchaseorder5', ''),
(129903, 28, 548, 'Location5', '-'),
(129904, 28, 548, 'Status5', ' '),
(129905, 28, 548, 'requesteddate5', '')
ALTER TABLE `jos_rsform_submission_values`
ADD PRIMARY KEY (`SubmissionValueId`),
ADD KEY `FormId` (`FormId`),
ADD KEY `SubmissionId` (`SubmissionId`),
ADD KEY `SubmissionId_2` (`SubmissionId`),
ADD KEY `SubmissionId_3` (`SubmissionId`);
ALTER TABLE `jos_rsform_submission_values`
MODIFY `SubmissionValueId` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=133092;
De ce qui précède, seul SubmissionId
548 a une valeur Status de en attente.
## SubmissionId FieldName FieldValue
## -----------------------------------------
## 548 Status1 Return Empty
## 548 Status2 Return Empty
## 548 Status3 Pending
## 548 Status4
## 548 Status5
J'ai besoin de trouver la valeur Container # correspondante:
## SubmissionId FieldName FieldValue
## ----------------------------------------
## 548 Container3 KKFU6780793
En ce qui concerne les données que j'ai soumises, les valeurs FieldName
commencent par l'une des cinq chaînes suivantes: "Status", "Container", "ContainerType", "ExpDate" et "Commodity", suivies d'un nombre commençant par 1
mais peut atteindre 10
.
<?php
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('FieldName')));
$query->from($db->quoteName('#__rsform_submission_values'));
$query->where($db->quoteName('FieldName') . ' IN ("Status1","Status2","Status3","Status4" ,"Status5")');
$query->where($db->quoteName('FieldValue') . ' = "Pending"');
$db->setQuery($query);
$result = $db->loadColumn();
foreach($result as $value) {
foreach($value as $key => $data) {
$cut = substr($data, 6);
$cut = "Container".$cut;
}
}
?>
Vous remarquerez que j'ai utilisé substr pour supprimer les 6 premières lettres (Status) de chaque résultat. Cela permet d’obtenir uniquement le nombre restant (1, 2, 3, 4, etc., en fonction du statut "En attente"). J'ai aussi ajouté ensuite "Container" au début de chacun des nombres restants, puisque la "FieldValue" que je cherche est "Container1 à Container10" (selon le champ choisi). Rappelez-vous qu’il n’affiche que le statut "En attente", il peut donc s'agir d’un résultat ou de 10 résultats récupérés.
J'ai donc pensé que le moyen le plus simple consistait simplement à ajouter le préfixe requis à chaque élément du tableau; Ensuite, je sélectionne la valeur "FieldValue" dans la colonne "SubmissionValue", la valeur "FieldValue" étant égale à "FieldName" de l'un des résultats obtenus dans la requête précédente.
Voici le code pour ceci:
<?php
$query = $db->getQuery(true);
$query->select($db->quoteName(array('FieldValue')));
$query->from($db->quoteName('#__rsform_submission_values'));
$query->where($db->quoteName('FieldName') . ' IN ' . '(' . implode(',', $cut) . ')');
$db->setQuery($query);
$results = $db->loadObjectList();
foreach($results as $value) {
foreach($value as $key => $data) {
echo $data."<br />";
}
}
?>
J'ai essayé d'utiliser "loadRow, loadColumn, loadResult", etc., et aucun d'entre eux ne fonctionne. Cela signifie que j'ai une erreur de syntaxe (1064) lorsque je charge la page.
Je ne suis pas sûr s'il s'agit d'un problème de "SubmissionId". Cependant, je ne sais pas comment incorporer le SubmissionId dans cette requête, car substr le supprimera simplement dans la première requête, puis ajoutera le préfixe devant lui, ce qu’il ne devrait pas faire.
En d'autres termes:
Il est recommandé de minimiser le nombre d'appels à la base de données.
Votre logique dans vos deux requêtes peut être fusionnée en une comme celle-ci:
try {
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select("a.FieldName, a.FieldValue")
->from("#__rsform_submission_values a")
->innerJoin("#__rsform_submission_values b ON a.SubmissionId = b.SubmissionId AND a.FieldName = REPLACE(b.FieldName, 'Status', 'Container')")
->where(["b.FieldValue = 'Pending'", "b.FieldName LIKE 'Status%'"]);
$db->setQuery($query);
echo $query->dump(); // never show to public
if (!$result = $db->loadAssocList()) {
echo "No rows found";
} else {
echo "<pre>";
var_export($result);
echo "</pre>";
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // never show to public
}
Sortie:
SELECT a.FieldName, a.FieldValue
FROM jos_rsform_submission_values a
INNER JOIN jos_rsform_submission_values b ON a.SubmissionId = b.SubmissionId AND a.FieldName = REPLACE(b.FieldName, 'Status', 'Container')
WHERE b.FieldValue = 'Pending' AND b.FieldName LIKE 'Status%'
array (
0 =>
array (
'FieldName' => 'Container3',
'FieldValue' => 'KKFU6780793',
),
)
En joignant la table à elle-même et en stipulant que vous n'êtes intéressé que par les données SubmissionId
associées à "Statut # = 'En attente'", vous pouvez éviter deux accès à la base de données.
En ce qui concerne vos extraits originaux ... (que je ne vous recommande pas d'essayer de sauver)
Vous écrasiez votre $cut
variable dans la boucle (ne pas insérer d’éléments dans un $cut
tableau. Cela aurait dû être quelque chose comme:
foreach($result as $value) {
$cut[] = "Container" . substr($value, 6);
}
Ensuite, dans la requête suivante, vous devez utiliser un guillemet simple pour envelopper vos éléments dans IN
.
"... IN ('" . implode("','", $cut) . "')"
En ce qui concerne les performances, il existe différentes façons d’écrire la requête qui donnera le résultat souhaité, mais je ne sais pas combien de lignes vous avez dans votre projet pour démarrer un test d’analyse comparative précis. (et je n'ai pas le temps d'offrir ce service de toute façon)
Voici une autre requête qui devrait bien fonctionner:
SELECT a.SubmissionId, a.FieldName AS ContainerName, a.FieldValue AS ContainerValue
FROM jos_rsform_submission_values a
INNER JOIN (
SELECT SubmissionId, SUBSTRING(FieldName, 7) AS StatusNum
FROM jos_rsform_submission_values
WHERE FieldValue = 'Pending'
AND FieldName LIKE 'Status%'
) b ON a.SubmissionId = b.SubmissionId AND a.FieldName = CONCAT('Container', b.StatusNum)
En supposant que ceci soit le code complet et que le deuxième extrait de code aille juste après le premier:
$db->loadColumn()
renvoie un tableau simple mais vous exécutez des boucles imbriquées foreach
qui, si le rapport d'erreurs strict était activé, générerait un avertissement:
Warning: Invalid argument supplied for foreach()
Pour cette raison, la variable $cut
Est NULL
. Vous devez également échapper des chaînes avec $db->quote()
.
Dans votre premier extrait, remplacez les boucles foreach
par ceci:
foreach($result as $key => $value) {
$result[$key] = $db->quote('Container' . substr($value, 6));
}
Et passez ensuite $result
Au lieu de $cut
À implode()
dans le deuxième extrait.