Je kunt een LEFT JOIN gebruiken.quote:Op dinsdag 27 oktober 2015 13:51 schreef wobbel het volgende:
Ik heb weer 'n kut vraag...hoe doe ik een join maar dan omgekeerd
Tabel 1: Klanten met een klant ID
Tabel 2: Bestellingen gekoppeld aan klant ID
Ik wil nu alle klanten krijgen die géén bestelling hebben. Doe ik dit ook gewoon met een JOIN ofzo? Want die moet ik altijd koppelen op de ID's en dat wil ik nu juist niet
Jawel, je wilt wel joinen op id's, maar daarna wil je alle regels waar die join resultaten oplevert er weer uit filteren.quote:Op dinsdag 27 oktober 2015 13:51 schreef wobbel het volgende:
Ik heb weer 'n kut vraag...hoe doe ik een join maar dan omgekeerd
Tabel 1: Klanten met een klant ID
Tabel 2: Bestellingen gekoppeld aan klant ID
Ik wil nu alle klanten krijgen die géén bestelling hebben. Doe ik dit ook gewoon met een JOIN ofzo? Want die moet ik altijd koppelen op de ID's en dat wil ik nu juist niet
1 2 3 4 | SELECT klant.* FROM klant LEFT JOIN bestelling ON klant.id = bestelling.klant_id WHERE bestelling.id IS NULL; |
Je kan dan beter WHERE NOT EXISTS() gebruiken.quote:Op dinsdag 27 oktober 2015 14:12 schreef Aether het volgende:
[..]
Je kunt een LEFT JOIN gebruiken.
Voor rijen die niet gekoppeld konden worden krijg je NULL terug waarop je kunt filteren.
Dan heb je een dependant subquery en waarschijnlijk minder optimalisatiemogelijkheden. Bij kleine aantallen (tientallen) maakt dat niet uit, bij grotere aantallen klanten en/of bestellingen zou ik het eerst vergelijken om te zien welke oplossing beter presteert.quote:Op dinsdag 27 oktober 2015 14:37 schreef TwenteFC het volgende:
[..]
Je kan dan beter WHERE NOT EXISTS() gebruiken.
SELECT K.ID
FROM Klanten AS K
WHERE NOT EXISTS ( SELECT 1 FROM Bestellingen AS B WHERE B.KlantID=K.ID )
Waarom? Als je een rare oplossing moet zoeken, dan betekend het meestal dat je iets fout doet.quote:Op woensdag 28 oktober 2015 16:50 schreef Ser_Ciappelletto het volgende:
Pagina.php zet ik liever niet in de webroot. Kan ik een verwijzing maken vanuit die andere map?
Het gaat om een paar duizend records, dus op zich valt het mee. Maar bedankt voor het meedenken, zoeken met NULL functioneert inderdaad Weer wat geleerd vandaag.quote:Op woensdag 28 oktober 2015 19:17 schreef Light het volgende:
[..]
Dan heb je een dependant subquery en waarschijnlijk minder optimalisatiemogelijkheden. Bij kleine aantallen (tientallen) maakt dat niet uit, bij grotere aantallen klanten en/of bestellingen zou ik het eerst vergelijken om te zien welke oplossing beter presteert.
Kun je die span niet op iets anders pakken dan dat het het 12e item is? Iets met een id, class of ander attribuut zou het leven veel makkelijker maken, dan ben je niet meer volledig afhankelijk van de volgorde waarin de items staan.quote:Op donderdag 29 oktober 2015 08:06 schreef wobbel het volgende:
[..]
Het gaat om een paar duizend records, dus op zich valt het mee. Maar bedankt voor het meedenken, zoeken met NULL functioneert inderdaad Weer wat geleerd vandaag.
Gaan we ons vandaag eens inlezen in DOMDocument...moet een 12e span uitlezen uit een HTML document
Geen idee of het een rare oplossing is en of ik iets fout doe.quote:Op woensdag 28 oktober 2015 20:25 schreef Darkomen het volgende:
[..]
Waarom? Als je een rare oplossing moet zoeken, dan betekend het meestal dat je iets fout doet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | SELECT ... CASE WHEN LOCATE( '<blockquote>', `contents` ) != 0 THEN MID( `contents`, LOCATE( '<blockquote>', `contents` ) + 12, (LOCATE( '</blockquote>', `contents` ) - LOCATE( '<blockquote>', `contents` )) - 12 ) ELSE '' END AS post_quote, CASE WHEN LOCATE( '<blockquote>', `contents` ) != 0 THEN CONCAT_WS( LEFT( `contents` , LOCATE( '<blockquote>', `contents`) - 1), ' ', RIGHT( `contents` , LENGTH(`contents`) - (LOCATE( '</blockquote>', `contents` ) + 12)) ) ELSE `contents` END AS post_contents, ... FROM fok_topic, fok_post WHERE ... |
1 2 3 4 5 6 | <blockquote><font size="1" face="verdana, aial, helvetica">quote:</font> <hr>Feedback is geen vrijblijvend "post hier wat je wilt"-forum. Als je denkt grappig te moeten zijn, je postaantal te moeten opkrikken of om een andere reden een post plaatst die in de FB-context totaal geen nut heeft, loop je de kans dat je post verwijderd wordt.<hr> </blockquote>Nog steeds geldt in Feedback het "post dan niks"-principe: als je niks te melden hebt, ga dan wat anders doen. Er moeten nog te veel compleet nutteloze posts verwijderd worden... |
Jup, klopt Ik was vergeten te vermelden dat het niet naar een PHP script gaat. Deze data wordt aan een Sphinx zoekserver index gevoed en ik kan helaas niets manipuleren. Dit moet dus in de query worden gedaan.quote:Op zaterdag 31 oktober 2015 20:03 schreef Monolith het volgende:
Volgens mij heeft MySQL nog steeds niet echt lekkere support voor regular expressions, maar dit is een schoolvoorbeeld van een situatie waarbij je die wilt gebruiken.
Is het geen optie om gewoon het geheel te selecteren en de regex replace in PHP te doen?
Sphinx ken ik niet echt als search engine, maar heeft die niet net als bijvoorbeeld ElastisSearch en SOLR gewoon filtermogelijkheden op de gevoede data?quote:Op zaterdag 31 oktober 2015 20:06 schreef bondage het volgende:
[..]
Jup, klopt Ik was vergeten te vermelden dat het niet naar een PHP script gaat. Deze data wordt aan een Sphinx zoekserver index gevoed en ik kan helaas niets manipuleren. Dit moet dus in de query worden gedaan.
Het is bij Sphinx mogelijk om gebruik te maken van een xml pipe. Dan kan ik de data zelf aan de indexer voeden vanuit een php script. Dit is echter zeer traag en daarom geen optie. Helaas is het maar een simpele server en als er heel veel tegelijk uitgevoerd moet worden vertraagt de boel.quote:Op zaterdag 31 oktober 2015 20:11 schreef Monolith het volgende:
[..]
Sphinx ken ik niet echt als search engine, maar heeft die niet net als bijvoorbeeld ElastisSearch en SOLR gewoon filtermogelijkheden op de gevoede data?
Is zoiets geen optie?quote:Op zaterdag 31 oktober 2015 20:17 schreef bondage het volgende:
[..]
Het is bij Sphinx mogelijk om gebruik te maken van een xml pipe. Dan kan ik de data zelf aan de indexer voeden vanuit een php script. Dit is echter zeer traag en daarom geen optie. Helaas is het maar een simpele server en als er heel veel tegelijk uitgevoerd moet worden vertraagt de boel.
Dank, ga ik even checken. Het is mijn eigen server, denk dat ik die mogelijkheid wel heb. En anders creëer ik dezequote:Op zaterdag 31 oktober 2015 20:27 schreef Monolith het volgende:
[..]
Is zoiets geen optie?
https://github.com/hholzgra/mysql-udf-regexp
Als je tenminste UDFs kunt gebruiken op je server.
Zoiets?quote:Op maandag 2 november 2015 20:36 schreef Keiichi het volgende:
Ik heb een bestan met op elke lijn 2 of meerdere bestandsnamen. Deze zijn gescheiden door een spatie en spaties in bestandsnamens geescaped. (Voor de nieuwsgierigen, output van fdupes -1 -r -S ./)
Ik wil deze lijnen met preg_split splitten, maar ik breek m'n hersens over hoe ik met die escaped spatie om moet gaan. Hoe krijg ik dit voor elkaar?
Zelfs $files = str_getcsv($line," ","","\\"); biedt geen uitkomst.. (Waarom herkent ie de backslashes niet?)
1 2 3 4 5 | <?php $s = '123.php 456\ 789.php ab\ c\ def.php'; $a = preg_split( '~(?<!\\\)\\s~', $s ); print_r($a); ?> |
1 2 3 4 5 6 | Array ( [0] => 123.php [1] => 456\ 789.php [2] => ab\ c\ def.php ) |
1 | <img class="rde_img_smiley" src="http://i.fok.nl/s/clown.gif" width="15" height="15" alt=":+" /> |
1 | <img data-src="http://www.voorbeeld.com/bla.jpg" style="visibility:hidden;" /> |
1 2 3 | <?php $result = preg_replace('/<img(?<!class="rde_img_smiley")[^>]+\>/i', "[afbeelding verwijderd]", $post_contents); ?> |
Some people, when confronted with a problem, thinkquote:Op zaterdag 7 november 2015 14:14 schreef bondage het volgende:
Ik zit met een regex probleempje en aangezien ik nogal faal als het aankomt op reguliere expressies kom er niet uit
Wat ik wil is plaatjes uit posts filteren, echter moeten plaatjes met een bepaalde class wel blijven staan.
Dit moet blijven:
[ code verwijderd ]
Dit moet weg:
[ code verwijderd ]
Ik gebruik deze regex maar die haalt alle afbeeldingen weg:
[ code verwijderd ]
Iemand idee hoe dit op te lossen?
En dan moet je er nog rekening mee houden dat die class kan worden voorafgegaan en/of gevolgd door een andere class. En dat een afbeelding zonder die class gevolgd kan worden door een met die class, dan moet je wel de goede afbeelding verwijderen. En over een half jaar moet je ook nog snappen wat de regex doet (ook als het er niet in commentaar bij staat).quote:Op zaterdag 7 november 2015 18:22 schreef Nattekat het volgende:
Als je al RE's wilt gebruiken, dan hoef je enkel te kijken of de string 'class=*"rde_smiley"' (niet) bevat.
Dus .*(class\=).*(\"rde_smiley\").*
Dit is dan per DOM-element (wat sowieso al een aanrader is om te doen), even niet helemaal goed naar de vraag gekeken. In zo'n hele post is het bijna geen doen meer om nog een RE te gebruiken idd.quote:Op zaterdag 7 november 2015 18:32 schreef Light het volgende:
[..]
En dan moet je er nog rekening mee houden dat die class kan worden voorafgegaan en/of gevolgd door een andere class. En dat een afbeelding zonder die class gevolgd kan worden door een met die class, dan moet je wel de goede afbeelding verwijderen. En over een half jaar moet je ook nog snappen wat de regex doet (ook als het er niet in commentaar bij staat).
Dank, dat had ik zelf ook wel kunnen bedenken natuurlijkquote:Op zaterdag 7 november 2015 18:03 schreef Light het volgende:
[..]
Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems. (bron / meer info)
Ik zou DOMDocument gebruiken, in combinatie met DOMNode::removeChild() (die je gewoon hebt, want DOMDocument extends DOMNode).
Met zoveel eisen zou ik aan de voorkant met javascript sowieso realtime een "checklist" afvinken terwijl de gebruiker typt.quote:Op zaterdag 7 november 2015 19:08 schreef Chandler het volgende:
Vraagje, stel je hebt een formulier met gebruikersnaam en wachtwoord.
Beide elementen moeten voldoen aan veel eisen.
Naam ; minimaal 6, maximaal 30 tekens. Geen spaties en bepaalde karakters, Geen herhalingen van letters (3x een e achter elkaar bv). En minimaal 1 hoofdletter.
Wachtwoord: minimaal 6, maximaal 30 tekens. Geen spaties. Minimaal 1 teken, 1 cijfer en 1 hoofdletter.
Hoe ga je om met gevonden fouten als je het formulier controleert??
Waarom maximaal 30 tekens en geen spaties voor een wachtwoord? Als het goed is, sla je ze toch goed gehashed op en dan maken spaties en het aantal tekens niet zo heel veel uit.quote:Op zaterdag 7 november 2015 19:08 schreef Chandler het volgende:
Vraagje, stel je hebt een formulier met gebruikersnaam en wachtwoord.
Beide elementen moeten voldoen aan veel eisen.
Naam ; minimaal 6, maximaal 30 tekens. Geen spaties en bepaalde karakters, Geen herhalingen van letters (3x een e achter elkaar bv). En minimaal 1 hoofdletter.
Wachtwoord: minimaal 6, maximaal 30 tekens. Geen spaties. Minimaal 1 teken, 1 cijfer en 1 hoofdletter.
Ik heb ondertussen ook even geprobeerd dit op te lossen en er zijn een paar punten waar je rekening mee moet houden. Dit is mijn oplossing:quote:Op zaterdag 7 november 2015 18:46 schreef bondage het volgende:
[..]
Dank, dat had ik zelf ook wel kunnen bedenken natuurlijk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | <?php class FokDemo { /** @var DOMDocument */ private $document; /** * FokDemo constructor. */ public function __construct() { $this->document = new DOMDocument(); $this->document->preserveWhiteSpace = true; } /** * @param string $content */ public function setContent($content) { @$this->document->loadHTML($content); } /** * @return string */ public function getContent() { return $this->document->saveHTML(); } /** * @param string $tagName * @param array $exceptWithClass * * @return int The number of removed items */ public function removeElements($tagName, array $exceptWithClass = array()) { $removed = 0; $doc = $this->document; // This list is dynamic. Any change in the document will immediately be reflected here $nodes = $doc->getElementsByTagName($tagName); for ($nodeIndex = $nodes->length - 1; $nodeIndex >= 0; $nodeIndex--) { $node = $nodes->item($nodeIndex); if ($this->shouldNodeBeRemoved($node, $exceptWithClass)) { $parent = $node->parentNode; $parent->removeChild($node); $removed++; } } return $removed; } /** * @param DOMNode $node * @param array $exceptWithClass * * @return bool */ private function shouldNodeBeRemoved($node, array $exceptWithClass) { if ($exceptWithClass === array()) { $result = true; } else { $classAttribute = $node->attributes->getNamedItem('class'); if ($classAttribute instanceof DOMAttr) { $classNames = explode(' ', $classAttribute->value); $result = array_intersect($exceptWithClass, $classNames) === array(); } else { $result = true; } } return $result; } } ?> |
Dankje Ik wou er vandaag even mee aan de slag en dit komt goed van pas, hoef ik het zelf niet uit te zoeken.quote:Op zaterdag 7 november 2015 22:58 schreef Light het volgende:
[..]
Ik heb ondertussen ook even geprobeerd dit op te lossen en er zijn een paar punten waar je rekening mee moet houden. Dit is mijn oplossing:
[ code verwijderd ]
Was even een voorbeeld.quote:Op zaterdag 7 november 2015 20:46 schreef Light het volgende:
Waarom maximaal 30 tekens en geen spaties voor een wachtwoord? Als het goed is, sla je ze toch goed gehashed op en dan maken spaties en het aantal tekens niet zo heel veel uit.
Inmiddels geïmplementeerd en werkt, mijn dank is groot. Heb wel een kleine wijziging aangebracht omdat ik (indien gewenst) het element graag wil vervangen.quote:Op zaterdag 7 november 2015 22:58 schreef Light het volgende:
[..]
Ik heb ondertussen ook even geprobeerd dit op te lossen en er zijn een paar punten waar je rekening mee moet houden. Dit is mijn oplossing:
[ code verwijderd ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php public function removeElements($tagName, array $exceptWithClass = array(), $replaceWith = array()) { $removed = 0; $doc = $this->document; // This list is dynamic. Any change in the document will immediately be reflected here $nodes = $doc->getElementsByTagName($tagName); for($nodeIndex = $nodes->length - 1; $nodeIndex >= 0; $nodeIndex--) { $node = $nodes->item($nodeIndex); if($this->shouldNodeBeRemoved($node, $exceptWithClass)) { $parent = $node->parentNode; if(isset($replaceWith['element']) && isset($replaceWith['contents'])) { $replace_node = $doc->createElement($replaceWith['element'], $replaceWith['contents']); $parent->replaceChild($replace_node, $node); }else{ $parent->removeChild($node); } $removed++; } } return $removed; } ?> |
Iets specifiekerquote:Op maandag 16 november 2015 15:54 schreef Ser_Ciappelletto het volgende:
Heeft iemand hier ervaring met utf-8 troubleshooting?
Ik heb een html-pagina die met require_once een php-scriptje aanroept, dat Griekse letters uit een MySQL-database queriet en in een tabel echoot.quote:
Lastig om zo te zeggen waar het probleem zit.quote:Op maandag 16 november 2015 16:10 schreef Ser_Ciappelletto het volgende:
[..]
Ik heb een html-pagina die met require_once een php-scriptje aanroept, dat Griekse letters uit een MySQL-database queriet en in een tabel echoot.
De database is gecreëerd met DEFAULT CHARACTER SET "utf-8" en DEFAULT COLLATE utf8_general_ci. De default charset is in php.ini ingestelt op "utf-8". De HTML-pagina heeft in de header <meta charset="utf8"> staan. En nog krijg ik allemaal ????'jes in plaats Griekse letters...
1 | header('Content-Type: text/html; charset=utf-8'); |
Die had ik al gevonden, maar dat helpt helaas niet.quote:Op maandag 16 november 2015 16:13 schreef Aether het volgende:
[..]
Lastig om zo te zeggen waar het probleem zit.
Probeer eens bovenin je script:
[ code verwijderd ]
Websites die zulke eisen stellen aan wachtwoorden moeten door de internetshredder. Wat een ellende.quote:Op zaterdag 7 november 2015 19:08 schreef Chandler het volgende:
Vraagje, stel je hebt een formulier met gebruikersnaam en wachtwoord.
Beide elementen moeten voldoen aan veel eisen.
Naam ; minimaal 6, maximaal 30 tekens. Geen spaties en bepaalde karakters, Geen herhalingen van letters (3x een e achter elkaar bv). En minimaal 1 hoofdletter.
Wachtwoord: minimaal 6, maximaal 30 tekens. Geen spaties. Minimaal 1 teken, 1 cijfer en 1 hoofdletter.
Hoe ga je om met gevonden fouten als je het formulier controleert??
Dit toevoegen werkt om de een of andere reden wel...quote:Op maandag 16 november 2015 16:16 schreef Ser_Ciappelletto het volgende:
[..]
Die had ik al gevonden, maar dat helpt helaas niet.
1 | mysqli_set_charset($conn, "utf8"); |
Aan te raden is om PDO te gebruiken i.p.v. mysqli.quote:Op maandag 16 november 2015 17:33 schreef Ser_Ciappelletto het volgende:
[..]
Dit toevoegen werkt om de een of andere reden wel...
[ code verwijderd ]
Wat is het verschil? Zijn die commando's verder hetzelfde?quote:Op dinsdag 17 november 2015 20:50 schreef robin007bond het volgende:
[..]
Aan te raden is om PDO te gebruiken i.p.v. mysqli.
PDO heeft ondersteuning voor meerdere databases en is objectgeoriënteerd. Eigenlijk is PDO een abstractielaag.quote:Op dinsdag 17 november 2015 20:53 schreef Ser_Ciappelletto het volgende:
[..]
Wat is het verschil? Zijn die commando's verder hetzelfde?
Hmm, die syntax ziet er in ieder geval al een stuk logischer uit dan die van mysqli.quote:Op dinsdag 17 november 2015 21:03 schreef robin007bond het volgende:
[..]
PDO heeft ondersteuning voor meerdere databases en is objectgeoriënteerd. Eigenlijk is PDO een abstractielaag.
En als je migreert naar een andere database hoef je maar één tekstregeltje veranderen. Dat is een groot voordeel.quote:Op dinsdag 17 november 2015 21:09 schreef Ser_Ciappelletto het volgende:
[..]
Hmm, die syntax ziet er in ieder geval al een stuk logischer uit dan die van mysqli.
Met zulke wachtwoordeisen hoef je je sowieso geen zorgen te maken om de functies om een nieuwe gebruiker aan te maken. Die worden dan toch nooit aangeroepenquote:Op maandag 16 november 2015 16:23 schreef Boze_Appel het volgende:
[..]
Websites die zulke eisen stellen aan wachtwoorden moeten door de internetshredder. Wat een ellende.
En dan hopen dat je andere database hetzelfde SQL-dialect spreekt. Dat is, ook bij relationele databases, niet gegarandeerd.quote:Op dinsdag 17 november 2015 21:19 schreef robin007bond het volgende:
[..]
En als je migreert naar een andere database hoef je maar één tekstregeltje veranderen. Dat is een groot voordeel.
Ik weet niet wat de Django ORM gebruikt, maar bij Doctrine kun je ook gebruik maken van yaml of xml of gewoon php voor je mapping. Niet dat het daar overzichtelijker van wordt, maar 't kan welquote:Op dinsdag 17 november 2015 22:15 schreef robin007bond het volgende:
Alleen wordt het soms wel een clusterfuck met al die annotations. Django's ORM vind ik een stuk mooier.
Voor dergelijke connections gebruik je in PHP vaak een Singleton, zie dit voorbeeldje.quote:Op woensdag 18 november 2015 11:07 schreef Ser_Ciappelletto het volgende:
Is het zo dat je in PHP vanuit een function geen beroep kan doen op een eerder geopende connectie? Hoe is dat het makkelijkste op te lossen zonder in iedere function terug die connectie te moeten openen?
Oh, en ik kan niet dezelfde functie tweemaal achtereen aanroepen met verschillende argumenten? Als ik ze allebei heb staan, werkt alleen de eerste. Als ik de eerste wegcomment, werkt de tweede perfect. --> oplossing was om de connectie correct te sluiten.
Zo te zien heb ik daar niets aan, want het zijn verbindingen met twee verschillende databases. Als !$dbConn == false, kan er nog een nieuwe verbinding aangemaakt moeten worden voor de andere database.quote:Op woensdag 18 november 2015 13:59 schreef Monolith het volgende:
[..]
Voor dergelijke connections gebruik je in PHP vaak een Singleton, zie dit voorbeeldje.
Nee, met een singleton kun je maar 1 instance hebben dus dan ga je nooit connecties naar 2 databases kunnen hebben. Die beperking is niet handig.quote:Op woensdag 18 november 2015 13:59 schreef Monolith het volgende:
[..]
Voor dergelijke connections gebruik je in PHP vaak een Singleton, zie dit voorbeeldje.
1 2 3 4 | <?php $db1 = new PDO('mysql://dbname=db1;host=localhost', 'user1', 'pass1'); $db2 = new PDO('mysql://dbname=db2;host=my.external.db.server', 'user2', 'pass2'); ?> |
Dat hoeft niet hoor. Met een singleton kun je best meerdere connection objecten beheren als je dat zou willen. Die eis had ik overigens gemist in het oorspronkelijke verhaal.quote:Op woensdag 18 november 2015 20:10 schreef Light het volgende:
[..]
Nee, met een singleton kun je maar 1 instance hebben dus dan ga je nooit connecties naar 2 databases kunnen hebben. Die beperking is niet handig.
Je kunt gewoon meer dan 1 PDO connectie openen:
[ code verwijderd ]
Iedere class die db-toegang nodig heeft, moet als constructor-parameter hebben voor een database-verbinding (of een setter om dat in te stellen, maar dan heb je meer kans dat het vergeten wordt). Dat wordt een class property en daar kun je vanuit iedere method in die class bij. En in plaats van een PDO-object kun je ook een wrapper maken om PDO of op een andere manier een abstractielaag gebruiken. PDO extenden is een slecht idee.quote:Op woensdag 18 november 2015 11:07 schreef Ser_Ciappelletto het volgende:
Is het zo dat je in PHP vanuit een function geen beroep kan doen op een eerder geopende connectie? Hoe is dat het makkelijkste op te lossen zonder in iedere function terug die connectie te moeten openen?
Een functie twee maal aanroepen met verschillende argumenten, hoort gewoon te werken, maar als het mis gaat door database-connecties kan het wel zijn dat het aantal openstaande connecties tegen het maximum van de database-server zit...quote:Oh, en ik kan niet dezelfde functie tweemaal achtereen aanroepen met verschillende argumenten? Als ik ze allebei heb staan, werkt alleen de eerste. Als ik de eerste wegcomment, werkt de tweede perfect. --> oplossing was om de connectie correct te sluiten.
Misschien had ik het oorspronkelijke verhaal in eerste instantie ook niet goed gelezen.quote:Op woensdag 18 november 2015 20:15 schreef Monolith het volgende:
[..]
Dat hoeft niet hoor. Met een singleton kun je best meerdere connection objecten beheren als je dat zou willen. Die eis had ik overigens gemist in het oorspronkelijke verhaal.
Als ik een fatsoenlijke applicatie wil maken, dan gebruik ik geen PHP. Maar dat terzijde.quote:Op woensdag 18 november 2015 20:55 schreef Light het volgende:
[..]
Misschien had ik het oorspronkelijke verhaal in eerste instantie ook niet goed gelezen.
Maar ik ben sowieso geen fan van singletons. Het voorbeeld in het artikel is geschikt voor 1 database-verbinding. Als je met 2 databases wilt kunnen verbinden, zul je waarschijnlijk veel code moeten copy-pasten (duplicate code, antipattern). (En wat nou als ik morgen een use-case heb met 10 databases? Alles maar 10x copy-pasten?)
Verder zijn de gegevens voor het maken van de verbinding hardcoded, da's ook niet handig (misschien alleen gedaan met het oog op het voorbeeld, maar toch). Die credentials moeten ergens vandaan komen, en je kunt ze slecht aanleveren. Maar als die DbConn zelf op zoek moet naar de credentials die ergens in een config file staan, gaat dat ten koste van herbruikbaarheid.
Verder wordt er bij de singleton gebruik gemaakt van static method calls en die zijn notoir slecht te mocken voor gebruik in tests. Als je een object van class Foo verwacht, kan ik je ook een object van Bar geven als Bar extends Foo. Dan moet ik alleen zorgen dat de methods die je aanroept wel iets teruggeven waar je mee verder kunt. Bij static method calls lukt dat niet, omdat overal in de code wordt verwezen naar de class Foo en mijn mock methods in Bar dus niet worden aangeroepen.
En ja, bij testen wil ik mocks kunnen gebruiken. Helemaal van iets als een database-connection. Als ik iets doe met het resultaat van een functie van een andere class, wil ik in mijn test niet weten hoe die andere class dat resultaat heeft bedacht maar alleen of mijn method goed kan omgaan met het gegeven resultaat.
1 2 3 4 5 6 7 8 | +-----+ ----------+----------+--------------+ | ID | Titel | Tabel | Bijschrift | +-----+-----------+----------+--------------+ | 1 | Eerste | Tabel1 | Bladiebla | | 2 | Tweede | Tabel2 | Lalalala | | 3 | Derde | Tabel3 | Nogmeer | | 4 | Vierde | Tabel4 | Yapyapyp | +-----+-----------+----------+--------------+ |
Nope.quote:
Je vraagt je af of mensen zich überhaupt wel eens de vraag hebben gesteld waarom die dingen RELATIONELE databases heten.quote:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | +----+------------+-------+------------------------+ | id | titel | tabel | bijschrift | +----+------------+-------+------------------------+ | 1 | Lidwoorden | | Dit zijn de lidwoorden | +----+------------+-------+------------------------+ +-------------+-----------+------------+-----------+ | Naamval | Mannelijk | Vrouwelijk | Onzijdig | +-------------+-----------+------------+-----------+ | Nominativus | ὁ | ἡ | τό | | Genitivus | τοῦ | τῆς | τοῦ | | Dativus | τῷ | τῇ | τῷ | | Accusativus | τόν | τήν | τό | | Nominativus | οἱ | αἱ | τά | | Genitivus | τῶν | τῶν | τῶν | | Dativus | τοῖς | ταῖς | τοῖς | | Accusativus | τούς | τάς | τά | +-------------+-----------+------------+-----------+ |
PHP heeft voor- en nadelen. Maar laten we hier geen discussietopic over maken over of je wel of niet php moet gebruiken.quote:Op woensdag 18 november 2015 23:16 schreef Monolith het volgende:
[..]
Als ik een fatsoenlijke applicatie wil maken, dan gebruik ik geen PHP. Maar dat terzijde.
Vaak, dus niet altijd. Een goede ORM staat je toe om meer dan 1 db-connectie te maken. Daarnaast gaat credential injection niet handig werken als je een private constructor hebt (om een singleton te bouwen). Je weet immers niet wanneer de singleton wordt aangemaakt.quote:Een singleton is een pattern met als doel iets te maken waar je er slechts één van kunt hebben. In het geval van PHP is dat vaak een DB connectie.
Dat zegt natuurlijk verder niets over hoe je credentials injecteert. Doorgaans gebruik je daar gewoon vormen van property of dependency injection voor.
In php kun je classes niet final maken. Dat kan wel met methods. De de facto standaard voor Unit Tests in PHP is PhpUnit, uit de xUnit familie. En het mocken van static methods is niet het grootste probleem, het zorgen dat die methods worden aangeroepen wel.quote:Ik heb al te lang niet veel met PHP gedaan om nog echt te weten welke mocking frameworks PHP heeft, maar doorgaans niet het mocken van static functies niet zo'n punt zijn. Bovendien, Singletons subsclasses is doorgaans niet de bedoeling. Ik zou ze ook gewoon final maken.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php class DbSingleton { private $connection; private static $instance; private __construct() { $this->connection = new PDO(...) } public static function getConnection() { if (self::$instance === null) { self::$instance = new self(); } } } class Foo { public function bar() { $result = DbSingleton::getConnection()->query(...)->fetchAll() return $result; } } ?> |
Yep. Doctrine comes to mind. Geen singletons, wel veel gebruikt, goed getest en actief in ontwikkeling.quote:Ik kan overigens zo legio manieren bedenken om zonder duplicate code een wat uitgebreidere singleton instantie te maken die een verzameling aan connecties bijhoudt.
Bij voorkeur gebruik je gewoon een framework met een beetje fatsoenlijke ORM of OGM support natuurlijk.
Wat je moet doen is het id van de ene tabel opnemen als extern veld in de andere tabel. Dat ziet er dan zo uit:quote:Op vrijdag 20 november 2015 19:50 schreef Ser_Ciappelletto het volgende:
Heel leuk die joins, maar hoe zet ik nou de ene tabel in de andere? Beter gezegd: wat moet ik in mijn tabel 'compleet' onder 'tabel' zetten om de tabel 'lidwoorden' op te roepen?
[ code verwijderd ]
Ik kan trouwens 'lidwoorden' neerzetten en dat terug invoeren in een query om die tabel op te vragen, maar is daar geen makkelijkere oplossing voor?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | +----+------------+------------------------+ | id | titel | bijschrift | +----+------------+------------------------+ | 1 | Lidwoorden | Dit zijn de lidwoorden | +----+------------+------------------------+ +----------+-------------+-----------+------------+-----------+ | tabel_id | Naamval | Mannelijk | Vrouwelijk | Onzijdig | +----------+-------------+-----------+------------+-----------+ | 1 | Nominativus | ὁ | ἡ | τό | | 1 | Genitivus | τοῦ | τῆς | τοῦ | | 1 | Dativus | τῷ | τῇ | τῷ | | 1 | Accusativus | τόν | τήν | τό | | 1 | Nominativus | οἱ | αἱ | τά | | 1 | Genitivus | τῶν | τῶν | τῶν | | 1 | Dativus | τοῖς | ταῖς | τοῖς | | 1 | Accusativus | τούς | τάς | τά | +----------+-------------+-----------+------------+-----------+ |
1 2 | select * from lidwoorden join compleet on compleet.id=lidwoorden.tabel_id |
1 2 | select * from lidwoorden l join compleet c on c.id=l.tabel_id |
1 2 | select l.Naamval, l.Mannelijk, c.titel, c.bijschrift from lidwoorden l join compleet c on c.id=l.tabel_id |
Juist, dat ga ik eens proberen. Bedankt voor de hulp!quote:Op zaterdag 21 november 2015 08:02 schreef Arcee het volgende:
[..]
Wat je moet doen is het id van de ene tabel opnemen als extern veld in de andere tabel. Dat ziet er dan zo uit:
[ code verwijderd ]
Het veld 'tabel' kan dus weg uit de eerste tabel en het veld 'tabel_id' is toegevoegd aan de tweede. In dat laatste veld komen dus de id's uit de eerste tabel (de records in 'lidwoorden' zouden eventueel ook een eigen id kunnen krijgen, trouwens)
Je linkt ze dan als volgt aan elkaar:
[ code verwijderd ]
Ik heb voor de duidelijkheid de tabellen geen alias gegeven, maar vaak doe je zo:
[ code verwijderd ]
Je 'zet' dus niet de ene tabel in de andere, maar relateert ze aan elkaar met een join (en met 'select * from' haal je er gegevens uit).
Zo haal je alle velden van beide tabellen op, maar je kunt ook uit beide tabellen alleen bepaalde velden selecteren, bijvoorbeeld zo:
[ code verwijderd ]
Hulde voor de tijd nemen om het helder en compleet uit te leggen.quote:Op zaterdag 21 november 2015 08:02 schreef Arcee het volgende:
[..]
Wat je moet doen is het id van de ene tabel opnemen als extern veld in de andere tabel. Dat ziet er dan zo uit:
[ code verwijderd ]
Het veld 'tabel' kan dus weg uit de eerste tabel en het veld 'tabel_id' is toegevoegd aan de tweede. In dat laatste veld komen dus de id's uit de eerste tabel (de records in 'lidwoorden' zouden eventueel ook een eigen id kunnen krijgen, trouwens)
Je linkt ze dan als volgt aan elkaar:
[ code verwijderd ]
Ik heb voor de duidelijkheid de tabellen geen alias gegeven, maar vaak doe je zo:
[ code verwijderd ]
Je 'zet' dus niet de ene tabel in de andere, maar relateert ze aan elkaar met een join (en met 'select * from' haal je er gegevens uit).
Zo haal je alle velden van beide tabellen op, maar je kunt ook uit beide tabellen alleen bepaalde velden selecteren, bijvoorbeeld zo:
[ code verwijderd ]
1 2 3 4 5 6 7 8 | $array = ["One","Two","Three"]; echo serialize($array); unset($array[1]); array_values($array); echo serialize($array); |
1 | a:3:{i:0;s:3:"One";i:1;s:3:"Two";i:2;s:5:"Three";} |
1 | a:2:{i:0;s:3:"One";i:2;s:5:"Three";} |
array_values geeft een array terug. Als je het resultaat gebruikt zou je een element 0 en 1 moeten hebben.quote:Op dinsdag 1 december 2015 21:58 schreef BrainOverfloW het volgende:
Even een kort vraagje. Ik heb de volgende code:
[ code verwijderd ]
De eerste echo geeft me:
[ code verwijderd ]
De tweede echo geeft me:
[ code verwijderd ]
Het verwijderen van het element uit de array gaat op zich dus goed. Maar hoe krijg ik het voor elkaar dat die index (ik neem aan dat die "i" daar voor staat) weer netjes doornummert van 0 naar 1 ipv naar de originele 2.
Alvast bedankt
Forum Opties | |
---|---|
Forumhop: | |
Hop naar: |