Posts by FangorN

    Gebruik overal UTC / GMT. En reken overal met UTC / GMT. De datums en -tijden die je overal toont kun je in lokale datum/tijd weergeven want functies als date() enzo nemen UTC al als uitgangspunt. Zorg ook dat je één bron hebt voor de tijd: ofwel in PHP, ofwel in MySQL, maar niet beide, want dan ben je mogelijk met twee maten aan het meten.


    Voorbeeld:


    Levert:


    Amsterdam: 2017-10-30 17:17:09


    Los Angeles: 2017-10-30 09:17:09




    Dus ook al verander je de tijdszone, je gebruikt in beide gevallen dezelfde timestamp als basis ($now). Je rekent op die manier dus altijd met één universele klok. Welke tijd je vervolgens toont hangt bijvoorbeeld af van een gebruikersinstelling (de tijdszone waarin deze persoon zit).

    Dat is het "nadeel" van het groeperen: je groepeert meerdere account-records op basis van IP. Het is dan redelijk willekeurig welke (enkele) naam wordt getoond in een resultaatrij. Daarom gebruik je GROUP_CONCAT(). Deze trekt de namen van meerdere kolommen samen in één rij.


    Zoals ik al aangaf, een alternatief is dat je, uitgaande van die IP's een nieuwe query (of subquery) bakt waarin je die records dus wel apart (in meerdere rijen) opvraagt.


    Maar dan nog, als je deze informatie vervolgens toont op een scherm dan zul je deze IP's toch op een of andere manier "grafisch" moeten groeperen, door tijdens het uitlezen bij te houden welke accounts -op basis van IP- bij elkaar horen.


    Misschien heb je iets aan het volgende, voortbordurend op het vorige voorbeeld:


    En als dit allemaal abracadabra is, dan loont het misschien de moeite om je ofwel wat meer te verdiepen in de materie, of een programmeur in te huren/aan te nemen.

    Realiseer je je dat elk IP-adres maar één keer voorkomt in de resultaatset omdat je groepeert op IP?


    Weet niet precies wat er misgaat maar als ik dit test werkt dit prima.

    De volgende query:

    SQL
    SELECT ip, GROUP_CONCAT(username), COUNT(ip) AS aantal
    FROM leden
    GROUP BY ip
    HAVING aantal > 1


    Levert precies wat ik verwacht:

    Bash
    ip		GROUP_CONCAT(username)		aantal
    127.0.0.1	Henk,Piet,Klaas			3
    127.0.0.2	Harry,Hennie			2

    Bekijk mijn query nogmaals. Als je het principe begrijpt kun je dit omschrijven naar wat jij wilt hebben.


    SQL
    SELECT ip, COUNT(ip) AS aantal
    FROM leden

    De eerste regel bevat de kolomnamen waarin je geinteresseerd bent en een COUNT() op de IP-kolom, dit is het argument waar je op gaat groeperen. Deze sla je op als de (alias)kolom "aantal" om hier later makkelijker aan te refereren.


    De tweede regel bevat de betrokken tabel(len).


    SQL
    GROUP BY ip

    Het argument waarop je de resultaatrijen samenvoegt. Dit doe je op IP-adres.


    Code
    HAVING aantal > 1

    Hiermee geef je aan dat je alleen in de IP-adressen geinteresseerd bent die meer dan één keer voorkomen in je leden-tabel. Dit is dus een soort van filter op je resultaatset. Alle accounts met een uniek IP vallen hierdoor af uit de resultaten. Wat je overhoudt is een lijst van IP-adressen waaronder meerdere accounts (ten minste twee) geregistreerd staan.


    Omdat je groepeert op IP wordt het lastig om meer informatie in een enkele resultaatkolom te proppen omdat de resultaten al worden samengevoegd maar je zou hier bijvoorbeeld de waarden van de gebruikersnamen in op kunnen nemen door middel van GROUP_CONCAT().


    Toegepast op de informatie hierboven wordt dit dus zoiets als:

    SQL
    SELECT ip, GROUP_CONCAT(username), COUNT(ip) AS aantal
    FROM leden
    GROUP BY ip
    HAVING aantal > 1

    Wil je vervolgens meer account informatie ophoesten kun je dit het beste met een aparte query doen. Ik ging er in eerste instantie vanuit dat je vlug een overzicht wilde van mensen die zich mogelijk meerdere keren hadden geregistreerd.

    Met mijn query vraag je de IP's op via welke meerdere accounts (meer dan één) geregistreerd staan. Vervolgens kun je daarbij de concrete accounts zoeken, of, zoals aangegeven, iets met GROUP_CONCAT() doen.


    Deze doet het niet, hij geeft nu 2 verschillende ip adressen aan, in plaats van dezelfde.

    Dit houdt in dat beide IP's meerdere accounts herbergen. De "aantal" kolom geeft aan hoeveel accounts onder elk IP-adres geregistreerd staan.


    Als dit aantal laag is wil dat in principe niet veel zeggen. Denk aan een huishouden of een studentenhuis, naar buiten toe hebben vaak alle, of in ieder geval meerdere, computers eenzelfde IP-adres omdat ze via hetzelfde netwerk aan het internet hangen.

    Simpele SQL-query? Moet je wel de IP-informatie hebben uiteraard:


    SQL
    SELECT ip, COUNT(ip) AS aantal
    FROM leden
    GROUP BY ip
    HAVING aantal > 1

    Ik ken de exacte tabel- en kolomnamen uiteraard niet, maar bovenstaande query dekt de lading wel lijkt mij.


    Ook zou je iets als GROUP_CONCAT(gebruikersnaam) kunnen doen, om gelijk de bijbehorende account- of gebruikersnamen weer te geven. En als je hostingprovider een soort controlepaneel heeft zit daar vaak ook iets bij als phpMyAdmin. En als je shell access hebt doe je het direct via de prompt :p.

    Welke telefoon?
    Welk OS (versie)?
    Welke browser (versie)?


    Blijkbaar is het probleem nogal specifiek. En als het niet aan een van de bovenstaande zaken ligt, kan het ook nog de video zelf zijn, dat het formaat (codec, audio, video) om een of andere reden niet afgespeeld kan worden.


    Heb je al op (sommige van of al) deze kenmerken specifiek gezocht?

    Nog een toevoeging, kon deze niet in vorige bericht kwijt (10.000 karakters was te krap :p):
    PS het feit dat in het artikel compleet voorbij wordt gegaan gaat aan het expliciet instellen van een character encoding geeft voor mij al aan dat het allemaal nogal oppervlakkig is. Dat is namelijk een bron van zeer veel ellende die nog altijd zwaar onderschat wordt. Vaak omdat mensen (of nog erger, programmeurs) niet van het bestaan weten.


    Dit artikel lijkt mij in zekere zin nog steeds een beter artikel dat zich bezighoudt met fundamenten, en niet zozeer met specifieke oplossingen. Dit artikel is vandaag de dag nog zeer relevant, en wordt eigenlijk steeds relevanter. Voordat dit als een soort van gospel ingeprent is bij alle programmeurs zouden ze eigenlijk in het geheel niet met databases mogen werken.

    Okay, hier gaan we weer :D. (hiermee bedoel ik de eeuwige PDO versus MySQLi discussie)

    Ik vroeg mij dus af, of ik dan het beste in PDO of MySQLi werk voor performantie en beveiliging

    Bij een juist gebruik zijn beide even (on)veilig. Performance is vrijwel hetzelfde voor alle MySQL drivers / API's (zie het onderdeel Recommended API).


    of is dit gewoon persoonlijke voorkeur?

    Ja, tenzij je moet voldoen aan zekere standaarden? Gaat dit ergens in geintegreerd worden, of is dit een standalone ding of maken jullie er een API van? In het laatste geval houd je zelf de controle en zou je het als dienst kunnen aanbieden zonder een letter code uit handen te geven?


    Indien ik de data die binnenkomt controleer en escape, is dit dan genoeg?

    Het adagium is nog steeds filter input, escape output. Ik hoop dan ook van harte dat je geen input escaped. Dit is slechts in uitzonderlijke, en gedocumenteerde, gevallen wenselijk. Misschien is er verwarring over wat input en wat output is. Als je USER DATA ontvangt via een formulier, querystring of zelfs uit de database (dit is nog steeds USER DATA en dus nog steeds onbetrouwbaar) kun je deze onderwerpen aan allerlei tests om te zien of deze voldoet aan een zeker formaat of bepaalde regels. Dit is het filteren van input: je controleert of deze op grond van eigen spelregels correct is voor verder gebruik. Vervolgens ga je deze USER DATA in een bepaalde context gebruiken: als output op een HTML-pagina of als DATA in een SQL string. Afhankelijk van deze context en wanneer je deze data niet kunt vertrouwen is het zaak dat je deze binnen de context onschadelijk maakt. Denk in HTML aan functies als htmlspecialchars(). Dat is het escapen van output: het onschadelijk maken van data binnen een bepaalde context. Nog eentje voor aan de muur: Never Trust User Data.


    Of zijn prepared statements echt een must?

    Prepared statements zijn slechts een middel, geen doel. Een verkeerd gebruik hiervan (eentje waarbij SQL statements worden opgebouwd door onder andere externe DATA te concateneren in de SQL-string en dan wat gegoochel met prepared statements) is nog steeds funest.


    Het grootste verschil zit hem waarschijnlijk in dat MySQLi op een gegeven moment eruit gaat, en PDO het stokje volledig overneemt.

    Dat is interessant, heb je hier ook een bron van die dit onderbouwt? Of een officiele aankondiging van de geplande end-of-life van de MySQLi driver / API? Ik denk dat de te schrijven programmacode die hier gebruik van maakt eerder zal worden vervangen / opgeschoond eerlijk gezegd. Daarnaast kun je je queries zo in je code compartimenteren dat je slechts de queries hoeft te vervangen of dat je -in het gunstigste geval- enkel de schil waarmee je met de database communiceert hoeft aan te passen en niet al je code. Hoe je dit kunt ondervangen staat verderop in dit verhaal.


    Zie code.tutsplus.com/tutorials/pd…should-you-use--net-24059 voor als je nog twijfels hebt

    Oh. Dat artikel. Uit 2012. Let ook vooral op de datum van dit soort technische artikelen, deze kunnen vrij snel hun houdbaarheid verliezen.


    Ik ga wat proberen uit te leggen over PDO die je mogelijk kan helpen bij het maken van een keuze.


    In het verleden heb ik mij verdiept in MySQLi en PDO. Ik ben ook op zoek geweest naar beweegredenen om voor PDO te kiezen (boven MySQLi als je een MySQL db gebruikt). De enige zinnige reden die uiteindelijk overeind bleef was het argument waarbij het bij de ontwikkeling van de applicatie nog niet vaststaat welk db-type je uiteindelijk gaat gebruiken. Dit is het enige echte zinnige argument wat ik kon vinden in alle discussie. De rest was meer persoonlijke voorkeur, waar het in het eerder gelinkte artikel ook sterk naar neigt. Maar goed, omgekeerd, als je wéét dat je enkel een MySQL-database gaat gebruiken, dan is het naar mijn mening gewoon veel zinniger om een driver/API te kiezen die hiervoor gemaakt is.


    De argumenten in het artikel gaan slechts gedeeltelijk, niet echt, of echt niet op (waarom PDO "beter" zou zijn) en daarvoor moet je wat dieper graven in PDO om te snappen hoe dit precies in zijn werk gaat. Allereerst, PDO zelf is slechts een handjevol klasses die het praten met databases standaardiseert. Maar hier kun je meteen al de boot ingaan qua interpretatie: het praten met de database is dan wel gestandaardiseerd, maar de SQL-taal die gesproken wordt is nog steeds DATABASE SPECIFIEK. Wat je moet begrijpen is dat PDO géén database-abstractie regelt, maar enkel fungeert als een data-access abstractie laag. Dus eigenlijk regelt PDO zelf in het geheel geen database-specifieke zaken. Dit doen de PDO drivers.


    En dat is meteen een vette adder onder het gras. Immers, omdat PDO geen database-specifieke dingen regelt is deze op voorhand dus ook niet afgestemd/geoptimaliseerd voor gebruik van een specifieke database. Zo'n standaard manier van communiceren met een database is misschien handig, maar daar zit de leercurve ook helemaal niet! Deze zit in de drivers! Tegenwoordig zullen alle standaard instellingen wel redelijk zinnig zijn, maar als je je bijvoorbeeld niet wilt verdiepen in alle PDO attributen die gemoeid zijn met een specifieke database, wat deze inhouden, en wat voor specifieke implicaties deze hebben op de werking en het gebruik (leercurve) dan is MySQLi wellicht toch wat simpeler :p. MySQLi is gebruiksklaar: deze is specifiek geschreven en geoptimaliseerd voor gebruik van MySQL-databases.


    Het artikel adverteert met "PDO ondersteunt veel meer databases (dan MySQLi)". Maar dit is vaak een non-argument in die zin dat je in de levensloop van een applicatie niet continu schakelt van database-type. Althans niet zonder te testen. Tenzij het product uit allerlei verschillende bronnen / database-typen informatie haalt, maar dan moet je des te beter nadenken over de architectuur hiervan en dan kan PDO mogelijk uitkomst bieden. Dit neemt echter niet weg dat je je zult moeten verdiepen in de werking van ALLE gebruikte PDO-drivers.


    En als je toch enkel van MySQL gebruik maakt, dan is dit "PDO ondersteunt veel meer databases" nogal nutteloos. Maar simpelweg zeggen, of hiermee een soort van onderbuikgevoel kweken, dat PDO daarom beter zou zijn is natuurlijk je reinste kwats. Natuurlijk, het is een industriestandaard (? of liever gezegd "iedereen" gebruikt het?), maakt het nog niet de beste keuze voor jouw specifieke probleem. Daarnaast, als niet is vastgelegd wat je zou moeten gebruiken heb je nog altijd zelf de keuze.


    Het artikel vind ik dus persoonlijk een soort van reclamefolder van een enthousiaste PDO-gebruiker die anderen met oneigenlijke argumenten probeert te overtuigen.


    On a side note: de "prepared statements" die PDO gebruikt is een soort van clientside prepared statements, deze maakt (tenzij je het PDO-attribuut PDO::ATTR_EMULATE_PREPARES juist instelt) geen gebruik van de native support die MySQL (op database-niveau) heeft voor prepared statements. Dit zijn twee compleet verschillende dingen! Voor de goede orde zou je de waarden van alle relevante attributen af moeten lopen en/of expliciet in moeten stellen om je ervan te vergewissen dat alles naar behoren werkt. En natuurlijk moeten weten wat deze alle betekenen en wat voor implicaties dat heeft (leercurve).


    On another side note: de laatste keer dat ik in PDO prepared statements gebruikte negeerde deze mijn typehints compleet. Als ik de MySQL log mocht geloven behandelde 'ie alles als string, ook al gaf ik aan dat dit getallen / reals / floats / whatever betrof.


    Okay, nog wat korte notities over MySQLi. Prepared statement zoals MySQLi deze aanbiedt: niet gebruiken, is compleet ruk. Het opbouwen, aanroepen en uitlezen van queries en -resultaten wordt ontzettend wollig en bovendien compleet onleesbaar. Wat ik persoonlijk zou doen is voor MySQLi zelf een data-access abstractie laag (DAAL) te schrijven of ergens vandaan te plukken. Dit om je database-oplossing niet compleet te hardcoden en hiermee ondervang je ook het probleem dat als er iets in MySQL-land verandert dat je, met enig geluk, deze wijzigingen kunt ondervangen door je DAAL aan te passen en geen dingen in je code hoeft te searchen en te replacen. Het op deze manier rechtstreeks hardcoden van je MySQLi-functies of -methoden in je code, dat zou echt een heel erg slecht idee zijn.


    Dus, ff wat leidraden:
    - ligt het vast wat je moet gebruiken, ben je klaar (en dan hoop ik dat de personen die dit besluit namen niet het genoemde artikel als leidraad gebruiken, maar toch wat beter geinformeerd zijn)
    - gebruik je enkel MySQL, gebruik MySQLi, maak / download een DAAL, houd database-aanroep-specifieke code buiten code en in je DAAL; ik zou dan gaan voor de OOP aanpak met het handmatig escapen van alle DATA binnen de SQL; dit legt wat verantwoordelijkheid bij je programmeurs, maar als je hier geen afspraken over kunt maken, zou ik de integriteit van de rest van je code ook niet vertrouwen
    - gebruik je iets anders of verschillende dingen: denk eerst nog eens goed na over hoe je dit aan gaat pakken


    Meer vragen / opmerkingen: ben benieuwd.


    /rant

    @M.Beers maar dat gaat over een straal (radius, afstand tot een middelpunt). Dat is een nogal zware berekening. Zoals @A.Bijlsma aangeeft heb je gewoon een rechthoek.


    De coordinaten hiervan worden bepaald door het middelpunt van de map, het zoomniveau en de afmeting van de Google map.


    Hoogstwaarschijnlijk heeft de Google Maps API wel een functie waarmee je deze coordinaten op kunt halen. Vervolgens zou je de markers in kunnen laden met AJAX zodat deze in deze rechthoek vallen.


    En zelfs als je werkt met een hele moeilijke functie waarmee je hemelsbrede afstanden kunt berekenen die binnen een bepaalde straal vallen loont het de moeite om deze te combineren met een vierkant die precies om deze cirkel past. Zo selecteer je eerst alle markers die binnen dit vierkant vallen en vervolgens gooi je alleen deze moeilijke / dure berekening over deze subset van markers, en niet over alle markers in je database want dan wordt je query takketraag :p.


    En inderdaad, als het middelpunt, de afmetingen of het zoomniveau van de Google Map veranderen verandert deze "bounding box" ook uiteraard.

    Beide snippets doen ook verschillende dingen.


    De eerste snippet stuurt alle URL's waarbij het domeinnaam ongelijk is aan domeinnaam.nl door naar domeinnaam.nl.
    De tweede snippet stuurt alle URL's die specifiek beginnen met de domeinnaam stoffenvoordeel.nl door naar stoffensite.nl.


    Tevens is het tweede snippet waarschijnlijk incorrect. Elke regel die begint met een # (hashtag, pound) wordt gezien als een commentaarregel die effectief niets doet.


    Ook inspecteer je in het tweede snippet, als je het commenten van laatste regel even buiten beschouwing laat, de specifieke pagina waar je vandaan komt, en word je naar deze specifieke pagina ($1) doorgestuurd in het nieuwe domein, mits deze relatieve verwijzing verschilt van "site-stoffenpermeter" (let op het uitroepteken voor deze paginanaam).


    Het is inderdaad, zoals @Ferhat.Remory aanhaalt, handiger om aan te geven wat precies je doel is. Er bestaan waarschijnlijk meerdere oplossingsvormen om dat doel te bereiken.

    Wat is de foutmelding? $query is in het tweede fragment al een object van de klasse mysqli_result (of false als de query fouten bevatte). Waarschijnlijk werd als tweede parameter van de tweede mysqli_query() aanroep een string verwacht. $query zou gewoon onveranderd moeten blijven, je voert 1x te vaak mysqli_query() uit.

    Pro tip: escape output. Data kan speciale karakters bevatten binnen de HTML-context.


    Dus in plaats van:

    PHP
    <?php
    echo '<pre>'.print_r($data, true).'</pre>';
    ?>

    Gebruik:

    PHP
    <?php
    echo '<pre>'.htmlspecialchars(print_r($data, true), ENT_QUOTES, 'UTF-8').'</pre>';
    ?>

    NB: met de tweede parameter van print_r() kun je aangeven dat de data geretourneerd moet worden als string. Op die manier hoef je je pre's niet apart te echo'en en kun je je code verder inkorten.


    In het algemeen is het handig om een functie te hebben die output "HTML safe" maakt:

    PHP
    <?php
    function escape($in) {
        return htmlspecialchars($in, ENT_QUOTES, 'UTF-8');
    }
    ?>

    En je kunt (dan) natuurlijk ook functies stapelen:


    PHP
    <?php
    function dump($a) {
        echo '<pre>'.escape(print_r($a, true)).'</pre>';
    }
    ?>

    Zodat je zaken als gebruikte character encoding maar op één plaats vastlegt (die je bijvoorbeeld uit config / een constante kunt trekken) zodat je deze vervolgens ook maar op één plaats hoeft te wijzigen (en al helemaal ideaal als dat dan de config / een constante is, je hoeft dan verder geen letter code te veranderen).

    Misschien is het een idee om operaties te bundelen zodat de API bepaalde standaard taken kan uitvoeren? Hoe dit dan onder de motorkap is geregeld is de verantwoordelijkheid van de API. Daarom is het m.i. niet nodig om username/password op te slaan, het volstaat prima om deze als parameters mee te geven in een login() routine.


    Vervolgens zou je standaard operaties kunnen maken (afhankelijk van privileges?), dus in plaats van meteen weer terug te vallen op (rauwe) requests (heeft niet zoveel toegevoegde waarde) schrijf je routines die wat meer werk verzetten. Ik zou in een API dus eerder een methode getAvailabilty(<params>) verwachten in plaats van een semi-rauwe cURL-call via request(<params>) naar /domains/<domain>/availability, dit zou abstractie moeten zijn die de API (+initiële configuratie) verder voor je regelt.


    Verder: definieer je klasse-variabelen: debug/testMode. Vervolgens zou je iets kunnen doen met magische getters en setters, het is niet nodig om voor elk van deze variabelen een aparte methode te schrijven. Desnoods maak je een protected klasse-variabele (een array) voor configuratie. Kun je in de setter afdwingen dat het een bestaande config-key betreft.


    En laat je booleans ook echt booleans zijn, en geen strings :).


    Denk bij het ontwerp aan een meer "functioneel gedreven design", oftewel, vraag je af wat voor standaard taken iemand zou willen uitvoeren via zo'n API om werk uit handen te nemen. Daar lijken mij API's bij uitstek geschikt voor.

    Wat is het verschil tussen pimage_id en p_id in de productimages tabel en weet je zeker dat je inderdaad wilt joinen op pimage_id (en niet iets anders, bijvoorbeeld p_id)?


    En als pimage_id inderdaad de foreign key is naar products is dat nou niet bepaald een fantastisch gekozen naam :/.


    Verder is het denk ik in het algemeen handiger om te refereren aan primary keys in je WHERE-conditie, in plaats van foreign keys, dat schept meestal wat sneller duidelijkheid over wat de query zou moeten doen.


    Dat gezegd hebbende, hoe ziet je dataset er uit, welke resultaten verwacht je die je niet krijgt?


    En van wat voor engine maken de tabellen gebruik? MyISAM? InnoDB? Als je een SHOW CREATE TABLE doet op zowel products alsook productimages, wat voor resultaten krijg je dan terug?


    En als je LEFT JOIN gebruikt dan kunnen resultaten NULL-waarden bevatten, controleer je hier ook op? Dump voor de gein (je) $row(s) eens.

    Zucht, ik bedoel. Als de klant zover is dat zijn zut PHP 7 ready is dat je dan dingen overzet van 5.6 server naar 7 server. En je zou dan ook tegelijkertijd zowel 5.6 live kunnen hebben staan en alvast op 7 test draaien. Daar valt best iets voor te zeggen.

    Maar als je op de pagina van een specifieke blog post zit dan zal er dus op een of andere manier een blog id bekend moeten zijn.


    Als het geen probleem is om voor het ophalen van de tags een aparte query uit te voeren dan kan dit met een eenvoudige query waarbij je enkel de tags- en taxonomy-tabel gebruikt, de blogs-tabel hoef je in dat geval niet te betrekken in je query.


    Het zal dan zoiets worden als:


    SELECT tg.id, tg.tag_name
    FROM tags tg
    INNER JOIN taxonomy tx ON tx.tag_id = tg.id
    WHERE tx.blog_post = <id van huidige blog-post>

    In de startpost is al duidelijk gemaakt waarom de topicstarter twee versies wilt draaien. That's it.

    Zoveel is duidelijk, maar jullie lijken er al van overtuigd hoe dat zou moeten gebeuren. Ik stel een alternatief voor wat hetzelfde doel bereikt, ik suggereer nergens dat je deze oplossing zou MOETEN gebruiken (net zoals jullie nergens suggeren dat jullie oplossing de enige oplossing is, right?).

    Neem een kop thee, en lees de draad nog eens rustig door!

    Het op deze manier ridiculiseren van iemand met een andere mening is uitermate kinderachtig. Probeer je hier de schijn te wekken dat iedereen weet waar het over gaat, maar ik het punt mis? Wauw, wat infantiel.

    Ik zie zelf niet in waarom er verantwoording moet worden gegeven?

    Dat kan ik mij goed voorstellen want jij reageert meestal direct op een vraag met een antwoord dat iemand (meestal) in de goede richting stuurt of direct 1 op 1 kan gebruiken. En daarmee is het brandje geblust. En staat iemand morgen weer klaar met een nieuwe vraag die voortborduurt op een mogelijk slechte ontwerpbeslissing.


    Ikzelf ben wat kritischer en probeer eerst een beeld te krijgen of de topicstarter ergens over heeft nagedacht en geen andere oplossingen (die potentieel beter zijn) op voorhand heeft uitgesloten.


    Iets met vissen en hengels?


    Daarnaast neigt dit een beetje naar paniekvoetbal. Reden te meer voor een bezinningsmoment.

    Maar de pagina waar je deze informatie ophoest, wat zou deze weer moeten geven? Wat voor doel dient deze?


    Is dit een pagina met een overzicht van blogs met bijbehorende tags?
    Is dit een pagina met een specifieke blog (in welk geval er een WHERE-conditie mist)?
    Is dit een pagina met een overzicht van tags met bijbehorende blogs?


    Je zou ook eerst een query kunnen maken waarin je de tags opslaat in een array tag-id => tag-naam.
    En vervolgens voer je een query op blogs uit waarin je de tags GROUP_CONCAT zodat je niet tig rijen per blog terugkrijgt.


    Maar hoe je dit (in code en op je scherm) vormgeeft wordt in eerste instantie bepaald door wat voor doel de pagina heeft.


    Los hiervan zul je in je JOINs aan moeten geven hoe je tabellen aan elkaar fietst. Na LEFT JOIN tags wordt waarschijnlijk een JOIN-conditie (ON a.id = b.id) verwacht want deze lijkt verplicht.