Objednat. Zrychlení databázových dotazů pomocí PDO a iterátorů Možnosti návrhu překladu pro fyzické

Mám problémy s parametry v klauzuli ORDER BY mého SQL. Nevydává žádná varování, ale nezobrazuje nic.

$objednávka = "název sloupce"; $direction = "ASC"; $stmt = $db->prepare("VYBRAT pole z tabulky WHERE sloupec = :my_param ORDER BY:order:direction"); $stmt->bindParam(":my_param", $is_live, PDO::PARAM_STR); $stmt->bindParam(":objednávka", $objednávka, PDO::PARAM_STR); $stmt->bindParam(":direction", $direction, PDO::PARAM_STR); $stmt->execute();

The:my_param funguje, ale ne:order nebo:direction . Je to vnitřní únik? Mohu to vložit přímo do SQL? Takhle:

$objednávka = "název sloupce"; $direction = "ASC"; $stmt = $db->prepare("SELECT * z tabulky WHERE sloupec = :my_param ORDER BY $order $direction");

Existuje konstanta PDO::PARAM_COLUMN_NAME nebo nějaký ekvivalent?

Díky!

To vyvolává otázku, že široce oblíbená připravená prohlášení nejsou žádná stříbrná kulka, hehe :)

Ano, vkládáte to přímo do SQL, samozřejmě s určitými opatřeními. Každý operátor/identifikátor musí být ve vašem skriptu pevně zakódován, například:

$orders=array("název","price","množství"); $key=array_search($_GET["sort"],$objednavky); $objednávka=$objednávky[$klíč]; $query="SELECT * z tabulky WHERE is_live = :is_live ORDER BY $order"; - $orders=array("name","price","qty"); $key=array_search($_GET["sort"],$objednavky); $objednávka=$objednávky[$klíč]; $query="SELECT * z tabulky WHERE is_live = :is_live ORDER BY $order";

Totéž pro směr.

Všimněte si, že bindParam neunikne, protože není vyžadováno žádné escapování. je to závazné.

Nemyslím si, že můžete:

  • Použijte zástupné symboly v pořadí podle
  • Svázat názvy sloupců: Můžete svázat pouze hodnoty – nebo proměnné – a zadat jejich hodnotu do připraveného příkazu.

Je možné použít připravené výpisy v klauzuli ORDER BY, bohužel je potřeba předat pořadí sloupce s názvem a je potřeba nastavit PDO_PARAM_INT s typem.

V MySQL můžete získat pořadí sloupců pomocí tohoto dotazu:

SELECT název_sloupce, pořadová_pozice FROM informační_schéma.sloupce WHERE název_tabulky = "tabulka" a schéma_tabulky = "databáze"

$objednávka = 2; $stmt = $db->prepare("VYBRAT pole z tabulky WHERE sloupec = :param ORDER BY:order DESC"); $stmt->bindParam(":param", $is_live, PDO::PARAM_STR); $stmt->bindParam(":objednávka", $objednávka, PDO::PARAM_INT); $stmt->execute();

Nemyslím si, že můžete získat ASC/DESC jako součást připraveného výpisu, ale sloupec ano.

Seřadit podle případu: pořadí, když "colFoo" potom colFoo když "colBar" potom colBar else colDefault end $direction

Protože ASC/DESC jsou pouze dvě možné hodnoty, můžete je snadno otestovat a vybrat si mezi nimi jako pevně zakódované hodnoty.

Můžete k tomu také použít funkce ELT (FIELD(,),), ale pak bude řazení vždy provedeno jako řetězec, i když se jedná o číselný sloupec.

Bohužel si nemyslím, že byste to mohli udělat s připravenými prohlášeními. Tím by se stal necachovatelným, protože různé sloupce mohou mít hodnoty, které lze třídit pomocí speciálních strategií řazení.

Vytvořte dotaz pomocí standardních obrazovek a spusťte jej přímo.

Je to možné. V klauzuli „pořadí podle“ můžete místo názvu pole použít číslo. Toto je číslo začínající 1 a mající pořadí názvů polí v dotazu. A řetězec můžete zřetězit na ASC nebo DESC. Například "Select col1, col2, col3 from tab1 order on?" + StrDesc + „limit 10,5“. strDesc = "ASC" / "DESC".

Pokud se nepletu, Pascal má pravdu.
Jediná možná vazba v PDO je vazba hodnoty, jako jste to udělali s parametrem ":my_param".
Na tom však není žádná škoda:

$stmt = $db->prepare("SELECT pole z tabulky WHERE sloupec = :my_param ORDER BY ".$order ." ".$direction); $stmt->bindParam(":my_param", $is_live, PDO::PARAM_STR); $stmt->execute();

Jediná věc, na kterou je třeba dávat pozor, je správně projít $ order a $direction, ale protože je nastavujete ručně a nenastavujete je pomocí uživatelského vstupu, myslím, že je vše připraveno.

Vytvořte podmínku if-other.
If (ascCondion) pak svažte hodnoty, ale pevný kód ORDER BY columnName ASC
více
Svázat hodnoty, ale pevný kód ORDER BY COlumnName DESC

Stránka návrhu pluginu woocommerce má určitou strukturu a funkčnost. Ale tato struktura není úplně vhodná. Dokončíme registrační stránku a rozdělíme ji na logické bloky: Objednávka, Dodání, Způsob platby, Informace o zákazníkovi atd.

Pokladna (základní struktura)

Šablona form-checkout.php
název formuláře = "pokladna"

woocommerce_checkout_billing (informace o zákazníkovi)
woocommerce_checkout_shipping (informace o dodávce)

h3 Objednávka /h3
div id=”order_review” Objednávka-recenze /div

Template review-order.php (Order-review)
stůl
položky položky k nákupu
celkový
doprava (cart-shipping.php, ajax závislost na informacích zadaných v woocommerce_checkout_billing, více o dopravě)
/stůl

div id=”payment” Platební formulář /div (propojený s háčkem)

Tlačítko pro zadání objednávky

Připravil jsem vizuálnější schéma, která oblast designu je zodpovědná za kterou šablonu Woocommerce

Blok „Výběr způsobu doručení“

Šablona, ​​která je zodpovědná za zobrazení bloku s výběrem možností doručení, je (z nějakého důvodu) zde: cart/cart-shipping.php.

Nápis Delivery, který je tam původně přítomen, se zobrazí s tímto řádkem:

Echo wp_kses_post($název_balíčku);

Záhlaví “Vyberte způsob doručení” a celkovou hmotnost objednávky můžete přidat přímo do bloku doručení pomocí háčku

Funkce action_woocommerce_review_order_before_shipping() ( echo "Vyberte způsob dopravy"; globální $woocommerce; echo "Celková hmotnost: "; $total_weight = $woocommerce->cart->cart_contents_weight; $total_weight .= " ".get_option("nit");echo_weight_u $celkova_vaha ""); add_action("woocommerce_review_order_before_shipping", "action_woocommerce_review_order_before_shipping", "action_woocommerce_review_order_before_shipping", 10, 0);

Dokončení prvků

Pokud nepoužíváme funkcionalitu pro výpočet doručení a uplatnění kuponů, můžeme aktualizaci ajaxu zakázat. Pokud nepotřebujete deaktivovat ajax, existuje metoda níže, aniž byste ji deaktivovali.

// Zakáže Ajax na stránce pokladny jQuery(document.body).on("update_checkout", function(e)( //e.preventDefault(); //e.stopPropagation(); e.stopImmediatePropagation(); // konzole .log(e);

Přesunout blok platebních formulářů

Remove_action("woocommerce_checkout_order_review", "woocommerce_checkout_payment", 20); add_action("woocommerce_after_order_notes", "woocommerce_checkout_payment", 20); nebo připojit k vlastnímu háku

Deaktivace výpočtů dodávky

Pokud je dodávka poměrně složitá a nelze ji automaticky zaregistrovat (například: pokud opravdu nemůžeme spočítat, která gazela je potřeba), pak výpočet dodávky deaktivujeme: jednoduše ponecháme v dodávce Vyzvednutí a doručení (s cenou 0) metody. Zároveň z formuláře s informacemi o zákazníkovi odebereme pole související s dodávkou a naopak z doručovacího formuláře odebereme pole související se zákazníkem. A vytvoříme skript, když kliknete na položku Doručení, čímž se zobrazí dodací formulář.

ID pole s položkou Delivery

$(document).ready(function() ( if($("#shipping_method_0_flat_rate-6 ").is(':checked')) ( $('.shipping_address').show(); ) $('.shipping_method ').click(function())( if($("#shipping_method_0_flat_rate-6 ").is(':checked')) ( $('.shipping_address').show(); $('.shipping_address') .html('

informace o doručení

‘); ) else ( $(‘.shipping_address’).html(‘

‘); $('.dodací_adresa').hide(); ))); ));

Tato možnost implementace není úplným řešením, protože má řadu nevýhod a je založen na dosti primitivním přístupu

Vztah mezi možností doručení a poli

Způsob pro 2 možnosti doručení (není vhodné pro 3 a více)

Pokud máme možnosti doručení a vyzvednutí, pak by bylo hezké synchronizovat možnost doručení a pole nabízená k vyplnění. Při vyzvednutí je nutné, aby pole doručení byla skryta, ale aby se zobrazila při výběru možnosti doručení.

Problém woocommerce spočívá v tom, že formulář Podrobnosti o doručení se rozbalí, když klepnete na záhlaví Odeslání na jinou adresu. (#ship-to-different-address) a spolu se skrytím pole je zakázáno ověřování doručovacích polí. Se dvěma možnostmi doručení (Pickup a Delivery) můžete při jejich přepínání nastavit událost (click) na id ship-to-different-address pomocí jquery. V tomto případě je nutné zajistit, aby jedno z polí bylo zpočátku aktivní, podle potřeby.

$("#shipping_method_0_flat_rate-2").attr("checked",true); $("vstup:radio").on("změnit", funkce () ( $("#zaškrtávací políčko-dodat-na-jinou-adresu").click(); ));

Aby byla pole pro doručení zpočátku otevřená, musíte nastavit nastavení doručení v možnostech woocommerce
Cíl doručení > Výchozí pro doručovací adresu zákazníka

V poli města můžete ve výchozím nastavení provést automatické nahrazování
$("#shipping_city")val("Rostov na Donu");

Způsob pro 3 nebo více možností doručení

Zpočátku provádíme doručení (jedna z možností) a pole doručení jsou aktivní. Další magie jquery

$("input:radio").on("change", function () ( if($("#shipping_method_0_local_pickup-2").is(":checked")) ( if($("#ship-to-) different-address-checkbox").is(":checked")) ( $("#ship-to-ifferent-checkbox").click(); ) else ( ) ) else ( if($("#) ship-to-different-address-checkbox").is(":checked")) ( ) else ( $("#ship-to-different-address-checkbox").click(); ) ) ));

V tomto případě zkontrolujeme, zda je aktivní pole Vyzvednutí (#shipping_method_0_local_pickup-2) a v závislosti na tom zaškrtneme skryté (skrývám) zaškrtávací políčko (Doručit na jinou adresu? #ship-to-different-address) .

Bez deaktivace ajaxu

Ajax na stránce pokladny je potřeba tak či onak (pro stejné kupóny). Pojďme se proto trochu změnit (změny se dotkly prvního řádku, protože prvky DOM ještě nebyly vytvořeny) na univerzální skript pro deaktivaci doručovacích polí. #shipping_method_0_local_pickup-3 — ID pole vyzvednutí.

$("body").on("change", "input:radio", function(e) ( if($("#shipping_method_0_local_pickup-3").is(":checked")) ( if($(" #ship-to-different-address-checkbox").is(":checked")) ( $("#ship-to-different-address-checkbox").click(); ) else ( ) ) else ( if ($("#ship-to-different-address-checkbox").is(":checked")) ( ) else ( $("#ship-to-different-address-checkbox").click(); ) )));

A pro každý případ uvádíme počáteční volbu pro jakoukoli dodávku

$("#shipping_method_0_flat_rate-4").attr("checked",true);

Připomenutí: V nastavení doručení musí být u doručovací adresy zákazníka zvoleno Cíl doručení - Výchozí

Možnosti designu pro jednotlivce osoby a právnické osoby tváře

Úkolem je udělat 2 možnosti zadání objednávky pro jednotlivce. osoby a právnické osoby tváře. Vytvoření této funkcionality je popsáno v článku

Když se probíráte mílemi kódu, můžete se divit: "Proč se všechno dělá tak, jak je?" Osobně si všímám zejména věcí, které mohou a měly by se zlepšit, pokud jde o těžké databázové dotazy.

Vývoj bez rámce

Při práci s frameworkem jsou již v zásadě pro vývojáře optimalizovány dotazy v databázi a abstrahována komplexní logika, což zlepšuje a optimalizuje získávání a další využití dat. Stává se ale, že vývojáři potřebují něco kódovat bez použití frameworku. Hlavní vlastnosti PHP přitom často nejsou využívány nejoptimálněji.

$pdo = new \PDO($config["db"]["dsn"], $config["db"]["username"], $config["db"]["heslo"]); $sql = "VYBRAT * Z `gen_contact` ORDER BY `contact_modified` DESC"; $stmt = $pdo->prepare($sql); $stmt->execute(); $data = $stmt->fetchAll(\PDO::FETCH_OBJ); echo "Získání kontaktů, které se za poslední 3 měsíce změnily" . PHP_EOL; foreach ($data as $row) ( $dt = new \DateTime("2015-04-01 00:00:00"); if ($dt->format("Y-m-d") . "00:00:00"< $row->contact_modified) ( echo sprintf("%s (%s)| upraveno %s", $row->contact_name, $row->contact_email, $row->contact_modified) . PHP_EOL; ) )

Výše je uveden příklad kódu, který se nejčastěji používá k načítání dat. Na první pohled vypadá tento kód hezky a čistě, ale když se podíváte blíže, uvidíte několik příležitostí ke zlepšení.

  • Kód není znovu použitelný. Pokud potřebujete použít podobnou funkci, budete muset duplikovat existující kód.
  • I když použijete $stmt->fetchAll(\PDO::FETCH_OBJ); stále máš problém, protože... Výstupem bude pole objektů. S velkým vzorkem to spotřebuje moře paměti.
  • Filtrování se provádí pomocí funkce. To znamená, že pokud jsou vyžadovány jiné podmínky filtrování, budete muset upravit současnou logiku, což z hlediska snadnosti údržby a rozšíření funkčnosti příliš nepřidá.
Iterátory

Většina moderních frameworků používá k načítání dat iterátory, protože jsou rychlé a opakovaně použitelné. Umožňují také použít jiné iterátory k filtrování a úpravě vrácených výsledků. Můžete je ale používat i bez frameworku, protože... Iterátory jsou součástí PHP od verze 5.0.0 Beta 2.

Představme si tedy, že budete nadále používat PDO k načítání dat. Máme na výběr:

  • Použijte PDOStatement::fetchAll() k načtení všech dat v jednom průchodu.
  • Pomocí PDOSTatement::fetch() načtěte jeden řádek na iteraci.

I když se vám první možnost zdá velmi lákavá, preferuji a doporučuji využít možnost číslo dvě. Umožňuje mi vytvořit jediný iterátor pro načítání dat, aniž bych byl omezován podmínkami dotazu (aby byl znovu použitelný pro jakékoli načítání).