✅ WEB- och WordPress -nyheter, teman, plugins. Här delar vi tips och bästa webbplatslösningar.

WordPress-frågor med IN-klausuler (vem visste)?

21

För lite över ett år sedan skrev jag ett inlägg om hur man använder WP_Meta_Query när du har en uppsättning nycklar som du vill använda för att hjälpa till att dra tillbaka information från databasen.

Men hur är det med fallet när du har ett antal olika nycklar som skulle resultera i att skapa en riktigt lång array för klassen WP_Meta_Query? Till exempel, vad händer om du var tvungen att gå igenom en samling data innan du ens ställer in frågan?

På någon nivå kan det kännas som att det naturliga är att:

  1. iterera genom samlingen av nycklar,
  2. dynamiskt bygga upp resultaten,
  3. kombinera dem till en enda resultatuppsättning,
  4. arbeta sedan med vad du än får.

Men låter inte det lite krångligt (låt vara långsamt)?

När det kommer till att använda WordPress API gör jag vad jag kan för att hålla mig till det innan jag pratar, säg direkt till databasen, men det finns också tillfällen då det är vettigt att skriva en rå fråga än att skriva någon typ av smart kod bara för att få WordPress API att fungera.

Innan jag går in på motiveringen till varför jag har gjort de saker jag har, vill jag förklara problemet och tillvägagångssättet. Detta kommer sannolikt att rädda någon från att hoppa in i kommentarerna i förtid.

Den här skärmdumpen har inget med frågan att göra. Bara en bild av IDE för skojs skull.

Så här kommer:

  • Jag har en standarduppsättning av värden som så småningom används för att hjälpa till att ta metadata och skapa en anpassad inläggstyp från dem (eftersom de har importerats från en tredjepartskälla).
  • Jag är en stor förespråkare för att parametrera frågor (och därmed använda prepare) för att säkerställa att data blir korrekt frågade mot databasen. Tyvärr hände detta inte när du försökte köra den här frågan. Jag ska förklara varför senare i detta inlägg.
  • Så, ta arrayen och konvertera den till en sträng är till hjälp, men det löser fortfarande inte problemet med att den vanliga prepareringsfunktionen inte fungerade.

Med det sagt ska jag förklara några saker:

  1. varför jag valde att använda en array för att lagra metadatavärden,
  2. varför jag har använt implode för att konvertera dem till en sträng,
  3. varför jag inte använder förbered för att hantera frågan.

Om metadatavärden

Anledningen till att metadata behålls i en array som en egenskap för klassen är att denna array kan förändras över tiden.

Det vill säga, vi kan behöva importera ytterligare data från tredje part, skulle behöva ta bort data från tredje part, eller så kan vi behöva göra vissa ändringar av vad som än finns.

När dessa data förvaras på ett enda ställe gör det det mycket lättare att hantera för framtida versioner av koden.

Imploding The Array

Närhelst du kör en fråga mot databasen och du måste arbeta med en array av data, kan du använda WP_Meta_Query och använda varje nyckel som delar av argumentarrayen.

Men om du har en relativt stor uppsättning data måste du först gå igenom allt, sedan måste du skapa frågan, sedan måste du bearbeta den.

Och när du väl har gjort allt detta är jag inte övertygad om att koden som har skrivits inte har kommit på bekostnad av prestanda. Det är därför jag ibland väljer att använda wpdb.

Använder inte Prepare

Nu, när jag gränsar direkt med databasen, försöker jag se till:

  1. Jag har en bra anledning att göra det,
  2. Jag använder parametriserade frågor.

Men jag har arbetat med denna specifika uppsättning data ett tag och försökt använda varje permutation av WordPress-utveckling som jag är medveten om (inklusive att prata med flera kamrater om det) för att försöka få det här att fungera på bästa möjliga sätt.

Det hände dock inte. Och det var då jag snubblade över följande sida i Codex :

I 99% av fallen kan du använda $wpdb->prepare() istället, och det är den rekommenderade metoden. Denna funktion är endast för användning i de sällsynta fall där du inte enkelt kan använda $wpdb->prepare(). Ett exempel är att förbereda en array för användning i en IN-sats.

Och det var precis det jag försökte göra: jag letade efter att söka i post-metatabellen där meta-nyckelvärdena fanns i en array.

Så här är hur jag löste allt detta.

Först skapade jag en array för att hålla de olika meta-nycklarna som jag vet att jag så småningom kommer att behöva kartlägga (även om värdet på nycklarna inte spelar någon roll för detta inläggs syfte):

<?php

// This is used to maintain a map of data should we need to add more.
$data_types = [
    'data_item_one',
    'data_item_two',
    '...'
    'data_item_ten,
];

Sedan konverterade jag dem till en MySQL-klar sträng. Visst, detta är inte användarinmatning och det används i en IN – klausul, så det kan inte användas i en prepare- sats:

<?php

/**
 * Converts the incoming array into a comma-delimited string with
 * quotes wrapped around each key.
 *
 * @access private
 *
 * @param  array $arr The array to convert to a string.
 * @return string     The string representation of the array delimited by quotes and commas.
 */
private function convert_to_sql_ready_string( $arr) {
  return '"'. implode( $arr, '","' ). '"';
}

Till slut skapade jag frågan och hämtade resultaten:

<?php

public function get_data_values() {

  global $wpdb;
  $query = "
    SELECT post_id, meta_key, meta_value 
    FROM $wpdb->postmeta WHERE
    meta_key in ($this->data_types) AND 
    meta_value <> '';
  ";

  $results = $wpdb->get_results( $query );

  return $results;
}

Och det var så det slutade med att jag arbetade med arrayerna, klassegenskapen och satte upp min fråga.

Är detta det bästa sättet att arbeta med WordPress-frågor med IN-klausuler? Jag är inte säker, men med tanke på min erfarenhet, vad jag har läst och hur det fungerar är jag nöjd med slutresultatet.

Inspelningskälla: tommcfarlin.com

Denna webbplats använder cookies för att förbättra din upplevelse. Vi antar att du är ok med detta, men du kan välja bort det om du vill. Jag accepterar Fler detaljer