[WP] Denk mee: Scannen content, automatisch taggen keywords

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Asitis
  • Registratie: Augustus 2008
  • Laatst online: 28-08 13:11
Ik hou een WordPress installatie als een soort catalogus voor mijn muziekcollectie en tegelijkertijd als web-speeltuin om mezelf dingen te leren, uit te proberen en steeds te optimaliseren.

De zwart-wit situatie is nu (dus) alsvolgt; ik heb een custom post type met x-aantal custom taxonomies en geschreven content in alle posts. In die berg van posts zitten talloze verwijzingen naar die taxonomies en ik zou ze allemaal automagisch scannen en linken waar dat mogelijk is.

Dus, wat is het plan?
De bedoeling is om de content van nu ~200 posts te scannen en te vergelijken met alle mogelijke taxonomies. Wanneer dan de taxonomy voor een label "Sony Records" bestaat, en een stuk content bevat bv. "Deze opname is in 2001 op Sony Records uitgebracht", dat het keyword van de taxonomy wordt vervangen door
code:
1
<a href="http://site/label/sony-records">Sony Records</a>
waar 'label' de slug van de taxonomy is, en 'sony-records' vanzelf de slug van de betreffende tag.

Hoe pak je dat het beste aan?
Ik ben best bedreven in de WordPress markup en kan aardig overweg met PHP en database queries, maar nog niet goed genoeg om deze code uit de losse pols te schrijven. Mijn vraag is dus of jullie met me mee willen denken over de beste oplossing en/of manier om dit überhaupt aan te pakken (en is het misschien interessant voor andere juniors).

Het makkelijkst lijkt me om een plugin te maken met een script dat via een cronjob gedraaid wordt. Dat script gaat in basis alle content van de posts door;

- Haal gekoppelde taxonomies op van post-type
- Maak een array van alle keywords uit de taxonomy (ID, slug en titel)
- Loop met die array alle posts uit de taxonomy door
- Vervang alle resultaten ("Term") door links ("<a href="/{taxonomy_slug}/{keyword_slug}">Term</a>")

De code
Het eerste probleem dat ik wil tackelen is de juiste scripting om alle posts door te lezen en aan te passen. Ik dacht aan zoiets:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
foreach (preg_split("/\s/", $text) as $word)
 {
     $string[$word] = 1;
 }

 foreach ($keywords as $keyword)
 {
     if (isset($string[$keyword]))
     {
         [wp_update_post code]
     }
 }


Maar als ik het goed heb moet je via wp_update_post de hele content vervangen. Dat zou betekenen voor elke post de hele content (gemiddeld ~2500 karakters) steeds bijgeschreven zou moeten worden. Is het misschien beter te doen via SQL met een selectieve query - kan dat überhaupt binnen één entiteit?

Ondertussen ben ik al begonnen met de opzet en kom toevallig deze plugin tegen die vrijwel exact doet wat ik wil, maar de termen niet veranderd in de database, maar via een filter laat zien bij het aanroepen van de content. Ik denk dat deze code een flinke shortcut kan zijn voor mijn project - maar het leren ervan is ook een doel dus ik ga het wel zelf doen!

[ Voor 7% gewijzigd door Asitis op 28-06-2016 22:04 . Reden: aanvulling ]


Acties:
  • +1 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Basisvraag is voornamelijk : Heb je een redelijk vaste taxonomy of een wisselende?

Want in wezen is jouw aanpak wel goed, maar je werkwijze is denk ik verkeerd...
Asitis schreef op dinsdag 28 juni 2016 @ 21:31:
Het makkelijkst lijkt me om een plugin te maken met een script dat via een cronjob gedraaid wordt. Dat script gaat in basis alle content van de posts door;

- Haal gekoppelde taxonomies op van post-type
- Maak een array van alle keywords uit de taxonomy (ID, slug en titel)
- Loop met die array alle posts uit de taxonomy door
- Vervang alle resultaten ("Term") door links ("<a href="/{taxonomy_slug}/{keyword_slug}">Term</a>")
Denk eens groter dan 200 posts, hoe wil je dit ooit eens dagelijks gaan doen met 1 miljoen posts en 50.000 tags. Oftewel is dit schaalbaar om elke dag te doen, of je moet een heel ingewikkelde caching procedure gaan inbouwen in de vorm van post laatst gewijzigd, tag laatst gewijzigd etc.

Oftewel ik zou het niet via een cronjob doen (naast dat die je data beschadigd, wat wil je gaan doen met een term waarvan de link anders moet worden, dan moet je naast terms ook opeens gaan scannen op links etc.)
Ik zou het of in de view layer toepassen alhoewel ik niet weet of WP die formeel kent.

En anders zou ik het er via JS inzetten, op alleen de pagina van die gebruiker.
Niets retour naar de database, want het is namelijk een redelijke lichte bewerking per document dus je kan hem elke keer doen bij een view en je voorkomt dat je database vernageld raakt met oude tags / oude links etc etc.

Wil je het echt schaalbaar hebben (denk aan die 1 miljoen posts etc) dan zou ik eerder nog zeggen : Hang er een reverse proxy voor zodat je view laag niet elke keer benaderd wordt ipv het weg te schrijven in de database.

Alleen als je echt een in steen gehouwen taxonomy hebt zou ik je posts in de database veranderen (en dan alsnog in een extra veld, zodat je altijd de originele code nog hebt en je bij een taxonomy wijziging oid je dat extra veld kan leeggooien zodat je taxonomy opnieuw bekeken wordt per post).
Maar als ik het goed heb moet je via wp_update_post de hele content vervangen. Dat zou betekenen voor elke post de hele content (gemiddeld ~2500 karakters) steeds bijgeschreven zou moeten worden. Is het misschien beter te doen via SQL met een selectieve query - kan dat überhaupt binnen één entiteit?
Ik zou me totaal niet druk maken over het wegschrijven van 1 totale post tov enkel sql-mutaties, wat sql toch zeer waarschijnlijk achter de schermen doet is gewoon 1 totaal nieuwe post maken. En echt goede sql-mutaties zijn moeilijk om te maken.
Maarja, ik zou überhaupt geen mutaties op mijn database doen voor zoiets.

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 18:36

Ventieldopje

I'm not your pal, mate!

Waarom niet nu gewoon met een script schrijven dat de dingen vervangt (als ik het goed begrijp) en vervolgens een plugin schrijven welke met actions/filters de vervanging doet bij het opslaan/wijzigen van een post.

Dat lijkt me een betere aanpak dan met JS of zelfs een cronjob.

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • Asitis
  • Registratie: Augustus 2008
  • Laatst online: 28-08 13:11
Beide bedankt :D
@Gomez12 ik weet niet precies wat je bedoeld met een vaste of wisselende taxonomy; het is een groeiend aantal, maar wat in de content staat is vast. Vandaar dat ik de wijzigingen wel permanent wil doen - het is in weze iets dat ik in retrospect vanaf het begin consequent had moeten doen, dan was dit niet nodig.

@Ventieldopje; geweldig. Heb je volkomen gelijk in, da's echt veel makkelijker. Eenmalig alle bestaande content op de schop nemen en daarna via de plugin op elke save-actie de functie uitvoeren. Daar ga ik mee aan de slag! Ik focus me dan eerst op die plugin, als die goed werkt is het misschien nog wel te automatiseren dat ie de update_post actie op alle posts draait, heb ik daar ook geen ander script meer voor nodig :)

Acties:
  • 0 Henk 'm!

  • P_Tingen
  • Registratie: Maart 2005
  • Laatst online: 21:20

P_Tingen

omdat het KAN

Qua houdbaarheid is de oplossing van Gomez12 wel een stuk beter. In een database ben je vaak beter af wanneer je je basisdata niet wijzigt. En in zekere zin is je WP-content jouw database. En jij wilt wel je basisdata veranderen. Dat werkt ook wel, maar geeft je niet een stabiele basis voor de toekomst en introduceert een groter risico op fouten.

Stel nou eens dat je als tag hebt gebruikt 'Rock and Roll'. Je script gaat dat in de database omzetten naar:
code:
1
<a href="http://site/label/rock-and-roll">Rock and Roll</a>


Vervolgens bedenk je dat je óók een tag wil hebben voor "Rock" en dus gaat je script er nog een keer overheen en maakt er dit van:
code:
1
<a href="http://site/label/<a href="http://site/label/rock">Rock</a>-and-roll"><a href="http://site/label/rock">Rock</a> and Roll</a>

Dat rendert naar niks gok ik. Of hooguit onzin. En dan zit je met een probleem in je database, want als zoiets als dit gebeurt heb je het vaak niet direct door. Je komt er dan vaak later achter en dan moet je maar zien te achterhalen wát er precies fout is gegaan. En je moet je database posts weer herstellen en dat zal waarschijnlijk handmatig moeten. Veel succes.

Nou kun je stellen dat je niet van dit soort fouten maakt. Maar wees gerust: iedereen maakt fouten en als je niet deze fout maakt dan zul je vroeg of laat een keer een andere foute maken of iets verkeerd intikken. Bijvoorbeeld even snel nog 's avonds een nieuwe taxonomy toevoegen en je zet in de link "htp://" in plaats van "http://" of iets anders onnozels. Ook dan zul je handmatig (of met herstelscripts, nóg gevaarlijker) de boel moeten herstellen.

Daarom is de suggestie van Gomez12 beter: je raakt je brondata niet aan. Mocht je een keer wat vern**ken met je tags dan is er niets beschadigd.

En het hoeft niet alleen in fouten van jezelf te zitten, maar wat te denken van naamswijzigingen. Stel dat "Sony Records" zichzelf hernoemt naar "SonyMusic". Dan wil je je tags hernoemen. Ook dat is lastig als je je brondata hebt veranderd.

De oplossing van Ventieldopje werkt overigens alleen voor het opslaan van nieuwe posts. Als je een nieuwe taxonomy toevoegt zul je toch weer alle posts bij langs moeten gaan. Daar zit die nieuwe taxonomy nog niet in namelijk.

Al met al denk ik dat je beter af bent met een werkwijze á la https://wordpress.org/plugins/linkify-text/

... en gaat over tot de orde van de dag


Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 18:36

Ventieldopje

I'm not your pal, mate!

Daar heb je natuurlijk Regular Expressions voor dat dit soort dingen niet voor kunnen komen ;)

Maar dat terzijde kun je ook kiezen om dit soort tags in een shortcode om te toveren. Ik weet verder niet hoe je alles hebt ingedeeld maar ik kan me voorstellen dat je het kan vervangen door zoiets om het toch dynamisch te houden:

code:
1
[labeltag slug="sony-records" label="Sony Records"]


Met het ID of beter nog slug link je dan naar term en haal je in de shortcode functie de link op uit de meta. De shortcode poept dan de link uit met de juiste titel. Het label argument is optioneel maar zou ik er in laten voor het geval je een specifieke tekst er neer wil zetten of je kunt het als fallback gebruiken als de term niet meer bestaat.

Zo heeft de client ook niks te renderen en kan het op de server gecached worden. Scheelt ook een hele hoop requests met javascript om voor elke term de data op te halen. Alle data ophalen is ook overkill, zeker met veel terms.

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • P_Tingen
  • Registratie: Maart 2005
  • Laatst online: 21:20

P_Tingen

omdat het KAN

Maar ook dan pas je de data aan en dat moet je maar net willen. Voor onze zwemsite zijn we ooit overgestapt van een ander CMS naar WordPress. We hebben toen de oude posts geconverteerd, maar alle links in die oude posts verwijzen naar de oude structuur van de site.

Je weet nooit wat je gaat doen met je data. Misschien stap je over twee jaar wel over naar een compleet ander CMS en dan zit je met harde verwijzingen naar WordPress-gerelateerde plugins.

Nogmaals: het kan. Maar het schept mogelijk een probleem voor in de toekomst. Kiezen voor een werkwijze als in linkify-text (ik gebruik de plugin zelf niet overigens) betekent dat je data intact blijft. Bij een overstap naar een ander pakket geen centje pijn, al moet je dan natuurlijk een vergelijkbare functionaliteit zien te vinden.

En renderen op de client? Als je een snelle site wilt hebben, kun je het beste een caching-plugin gebruiken en dan hoeft elke pagina maar één keer opgebouwd te worden.

... en gaat over tot de orde van de dag


Acties:
  • 0 Henk 'm!

  • michel91
  • Registratie: Maart 2013
  • Laatst online: 29-06-2021
Toen ik las dat je het graag in de DB wilt aanpassen, dacht ik: waarom zou je dat willen en niet gewoon bij het ophalen van the_content een filter toepassen? Zal vast wel een plugin voor zijn, wat je zelf ook al zegt.

Dit voorkomt problemen. Wanneer je taxonomie wijzigt, hoef je niet alle records aan te passen. Wanneer je URL structuur wijzigt, heb je hetzelfde probleem.

Mocht je het toch graag in de DB willen, zou ik 1 keer een scriptje draaien die alle huidige posts aanpast en daarna scriptjes maken voor een wijziging van een post/taxonomie/url structuur

Acties:
  • +1 Henk 'm!

  • Asitis
  • Registratie: Augustus 2008
  • Laatst online: 28-08 13:11
Goede punten allemaal, zeker het verhaal van P_Tingen is treffend, heb in het verleden bij andere projecten wel eens van dit soort ongein meegemaakt ja. Wat Ventieldopje oppert heb ik in het verre verleden bij versie 0.2 van dit project ook eens geprobeerd; shortcodes gedefinieerd zoals [artiest]Bandnaam[/artiest]. Dat ging toen best aardig maar erg omslachtig (was geen efficiente code).

Idealiter heb ik geen markup nodig. In het voorbeeld haalde ik een label aan, maar het gaat vooral om artiesten-namen en het kan wel zijn dat ik nu iets schrijf waarin ik ArtiestB noem, die verder nog helemaal niet voorkomt en dus ook niet gelinkt is/hoef te worden, maar als ik dan twee weken later wél een post opver ArtiestB invoeg, zou die in retrospect alsnog een link moeten maken.

Dit betekend dus dat (inderdaad) opslaan bij bewerken/aanmaken van de post niet toereikend is. Telkens de hele content doorzoeken en herschrijven bij elke nieuwe post is ook niet ideaal, dus neig ik nu wel naar de client-side oplossing ja.

Edit: Dat Linkify Text eens geprobeerd, werkt gewoon out of the box zoals gewenst. Ik neig te denken dat mijn geknutsel daar toch niet tegenop kan bouwen. Het nadeel hiervan is alleen dat je handmatig alle termen > links in moet geven, dus misschien dat ik dat alsnog ga automatiseren.
En ik wil nog altijd wel het wiel opnieuw uitvinden voor de ervaring, maar ik kan hiermee wel alvast uit de voeten :)

[ Voor 16% gewijzigd door Asitis op 30-06-2016 11:00 ]

Pagina: 1