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

Ändra bildbehållare på serversidan i WordPress

27

Närhelst du bygger anpassade lösningar för andra människor kan du behöva ta itu med nyanserade fall av hur WordPress renderar innehållet.

Detta beror vanligtvis på temat, åtminstone en plugin eller kombinationen av båda. Och om du behöver arbeta med bilder individuellt, då kan det vara lite av en utmaning. Problemet med att ens försöka skriva ett sånt här inlägg är att det är svårt att ens beskriva en situation där du kan behöva något liknande.

Ändå ska jag göra så gott jag kan. Det vill säga, jag vill dela med mig av hur man modifierar bildbehållare på serversidan innan jag renderar dem på klientsidan och gör det med PHP:s DOMDocument-bibliotek.

Låter det mycket? Förhoppningsvis kan jag bryta ner detta enkelt nog.

Innan du går in i koden, låt oss säga att du har en dem som återger bilder i ett enda styckeelement (eller någon typ av element på blocknivå) och att du måste slå in varje element i någon typ av klass så att du kan komma åt det via CSS eller JavaScript.

Där vi är

Så, till att börja med, låt oss säga att bilderna återges så här:

Och du måste återge dem så här:

Ändra bildbehållare på serversidan i WordPress

Nu kanske du behöver utrymme mellan dem eller inte. Det spelar egentligen ingen roll eftersom du har kontroll över detta via CSS. Men du har kontroll över hur detta skickas över tråden till klientsidan.

För att göra detta behöver du några saker:

  • Tillgång till PHP:s DOMDocument-bibliotek,
  • Förståelse för hur man manipulerar innehåll via WordPress’ the_content- hook,
  • En strategi för hur du vill slå in bilderna.

Jag ska gå igenom var och en av dessa i koden men det räcker med att säga att jag kommer att slå in varje bild i ett styckeelement. Du kan självklart välja att göra vad du vill.

Hur man gör det

Se först till att du har deklarerat att du använder innehållet i DOM-dokumentet ovanför din klass :

<?php

namespace Acme;

use DOMDocument;

class AcmeContentSubscriber
{
  // ...
}

Gå sedan vidare och skapa en krok till the_content. Hur du gör detta beror på hur du har organiserat din kod (oavsett om det är OOP eller inte). För det här exemplet ska jag visa ett mycket enkelt exempel på hur man gör det :

<?php

public function contentSubscriber()
{
  add_action( 'the_content', [$this, 'addImageAttributes']);
}

Efter det måste du göra lite arbete (som allt är nedan men utanför ramen för detta inlägg). Detta inkluderar:

  • konvertera kodningen av HTML-entiteterna,
  • skapa en instans av DOM-dokumentet,
  • ladda inläggets HTML från det inkommande innehållet

I koden ska det se ut så här :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    // ...
}

Därefter måste du iterera genom img- elementen och se till att du ställer in ett korrekt attribut. Du kan välja att använda en klass, du kan välja att använda ett dataattribut eller så kan du välja att använda något annat. Den här delen spelar ingen roll.

Observera att du för en given bild vill kontrollera att nästa element inte är ett styckeelement eftersom det är det jag väljer att slå in bilden. Med andra ord, om nästa element inte är ett stycke, kommer vi att slå in elementet i ett styckeelement.

För att göra detta bör skelettet för huvudfunktionen se ut så här :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    $images = $document->getElementsByTagName('img');
    foreach ($images as $image) {
        $image->setAttribute('class', 'acme-iamge');
        if ($image->nextSibling->tagName !== 'p') {
            $this->wrapImage($document, $image);
        }
    }

    // ...
}

Då ska funktionen som är ansvarig för att faktiskt linda elementet i ett styckeelement se ut så här :

<?php

/**
 * This function is used to wrap individual images in a paragraph element.
 *
 * @param $document The DOM Document which is to be rendered.
 * @param $image    The image to wrap with the new paragraph element.
 */
private function wrapImage($document, $image)
{
    if (null === $image) {
        return;
    }
    $wrapper = $document->createElement('p');
    $wrapper->setAttribute('class', 'acme-image');

    $image->parentNode->replaceChild($wrapper, $image);
    if (null !== $image) {
        $wrapper->appendChild($image);
    }
}

Se till att läsa kodens DocBlock för att förstå hur funktionen fungerar. Enkelt uttryckt:

  • den accepterar en instans av dokumentet och bildelementet,
  • skapar ett styckeelement,
  • lägger till ett klassattribut
  • ersätter det ursprungliga bildelementet med stycket,
  • och lägger till bilden som ett underordnat element

Och eftersom vi har baserat dokumentobjektet i metoden behöver vi inte returnera något.

Den slutliga versionen av den ursprungliga funktionen bör se ut så här :

<?php

public function addImageAttributes($content)
{

    $content  = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    $document = new DOMDocument();

    libxml_use_internal_errors(true);
    $document->loadHTML(utf8_decode($content));

    $images = $document->getElementsByTagName('img');
    foreach ($images as $image) {
        $image->setAttribute('class', 'acme-image');
        if ($image->nextSibling->tagName !== 'p') {
            $this->wrapImage($document, $image);
        }
    }

  return $document->saveHTML();
}

Och din utdata ska se ut som bilden ovan. Kom dock ihåg; du måste returnera resultaten av dokumentinstansen till WordPress, så att den återger HTML-koden ordentligt. Och det är vad saveHTML- funktionen gör i koden ovan.

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