Hi all,

Met dank aan een tutorial waar Arien me opgewezen heeft, (tijdje geleden al, maar kwam er nu pas echt aan toe)

Heb ik dus de tabeltype van producten tabel aangepast naar myisam en een fulltext index gemaakt op
prod_title en op prod_description

In phpmyadmin werkt het geweldig. Maar in php krijg ik helemaal niks terug.

Ik debug de query in php, en print deze op het scherm, en ziet er goed uit.
Kopieren->plakken naar SQL in phpmyadmin geeft gewoon resultaten terug.

De query is ongeveer als volgt:

SELECT p.*,COUNT(r.rev_id) as revAmount, SUM(r.rev_score) as revTotal,h.*,m.* 
FROM dnshop_products p
      LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
      LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
      LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id

WHERE p.prod_visible = 1 
AND m.media_weight = 1 
AND p.prod_price < 900 

GROUP BY p.prod_id 

ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20


Zien jullie iets verkeerds?

Mijn select functie is als volgt:

function __construct($DB_TYPE, $DB_NAME, $DB_HOST, $DB_USER, $DB_PASS) {
        parent::__construct($DB_TYPE . ':host=' . $DB_HOST . ';dbname=' . $DB_NAME, $DB_USER, $DB_PASS);
    }

    public function select($query, $array = array(), $fetchMode = PDO::FETCH_ASSOC) {
        $sth = $this->prepare($query);
        foreach($array as $key => $value) {
            $sth->bindValue(':' . $key, $value);
        }
        
        if($this->debug)
            print_r($sth->queryString);
        
        $sth->execute();

        if($sth->rowCount() == 0) {
            return false;
        } else {
            return $sth->fetchAll($fetchMode);
        }
    }

Ik gebruik gewoon PDO type:mysql
- hoe roep je deze select() methode precies aan? hoe luiden de parameterwaarden?
- wat geeft deze methode weer als $this->debug true is?
- als je de query logt: hoe luidt de query die daadwerkelijk is uitgevoerd? dit is overigens de énige manier om duidelijkheid te krijgen wat er aan de hand is
- staat dit alles (aanroep van select()) in een try-catch blok?
- worden fouten gemeld (in het algemeen en voor PDO specifiek)? wat is de waarde van PDO::ATTR_ERRMODE? dit is standaard PDO::ERRMODE_SILENT, oftewel, er kraait dan geen haan naar opgetreden fouten
- hoe luidt de waarde van PDO::ATTR_EMULATE_PREPARES? dit is standaard true, oftewel, als er fouten optreden (die mogelijk niet gemeld worden) dan komt dit pas tot uiting bij de execute() en niet al bij prepare(), omdat ingeval je prepared statements emuleert er geen SQL-sjabloon naar de database wordt verstuurd

Ik debug de query in php, en print deze op het scherm, en ziet er goed uit.
Kopieren->plakken naar SQL in phpmyadmin geeft gewoon resultaten terug.

Maar dat is niet de exacte query die wordt uitgevoerd? Log dat ding, en kijk welke query er daadwerkelijk wordt uitgevoerd. Werk van daaruit terug naar je code.
Hey Thomas,

de query die ik bovenaan noemde, is toch wel hetgene wat ik krijg als debug true is ;-)
Behalve dat het naast elkaar staat dan, en de price:


AND p.prod_price < 900 

==

AND p.prod_price < :tPrice 


Dus wordt dan:


$getResults = $this->model->getSearchResult('SELECT p.*,COUNT(r.rev_id) as revAmount, SUM(r.rev_score) as revTotal,h.*,m.*
FROM dnshop_products p
      LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
      LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
      LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id

WHERE p.prod_visible = 1
AND m.media_weight = 1
AND p.prod_price < :tPrice

GROUP BY p.prod_id

ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20',array('tPrice' => 900))

Hoewel ik de bindValue al weg gehaald had en alles static in de query gezet heb.

Ik zal vanavond de ERRMODE_EXCEPTION eens instellen en eventueel de try blok proberen, misschien dat ik dan foutmeldingen krijg? En waarschijnlijk zelf wel uitkom, anders kan ik hier duidelijkere informatie geven.

Momenteel zijn geen fouten, maar gewoon lege result.
Hoewel dat waarschijnlijk komt door:

if($sth->rowCount() == 0) {
            return false;
        } else {
            return $sth->fetchAll($fetchMode);
        }


[size=xsmall]Toevoeging op 17/08/2016 20:34:40:[/size]

kom er nou achter, dat blijkbaar de vps er zin in had om een backup terug te zetten..
of moet ik de FULLTEXT INDEX () elke keer weer toevoegen als ik ga zoeken?

[size=xsmall]Toevoeging op 17/08/2016 21:06:06:[/size]

Ik wil ook graag op partials zoeken.
Bijv. 5 punt
Moet ik resultaten krijgen zoals 5 puntsgordel

Nou zag ik dat dit ALLEEN kan met, MATCH (field) AGAINST ('*5*punt*' AS BOOLEAN)
(als voorbeeld), maar dan is de MATCH natuurlijk 0 of 1. Dus is er weinig te sorteren op daadwerkelijke 'match score'

Is hier een oplossing voor ?
Een query met SELECT * en ook COUNT(*) oid erin gaat doorgaans mis:

Als je een aggregatie functie (zoals count, sum, avg etc) gebruikt, moeten ALLE andere kolommen in GROUP BY staan.

Ik zie in jouw query p.*, h.* en m.* staan, maar je groupt alleen op p.prod_id....

http://wiki.pfz.nl/group-by

In principe hoor je daar een foutmelding op te krijgen.
Hi Ivo,

deze opmerking heb ik al eens eerder gehad geloof ik.
Suggereer je dat ik

GROUP BY p.prod_id, m.media_prod_id, h.hlight_prod_id

moet doen ? Momenteel met vele producten, meerdere media en de hlight is maar een enkele record p product (als die er uberhaubt is(de hlight))

Dan nog zit ik met partial match, waar ik problemen mee heb.
Is daar een oplossing voor?
je moet strikt genomen ALLE kolommen noemen.

als je SELECT * FROM adres
doet
en adres bevat adres_id, naam, straat, postcode

dan hoort er bij
SELECT count(1), adres.* FROM adres
dus GROUP BY adres_id, naam, straat, postcode

Daarom is het gebruik van * in combinatie met een aggregatie functie niet zo'n goed idee.

Ook al omdat een tabel best kan worden aangepast. Stel iemand bedenkt dat de kolom Land ook wel handig is in je adres. Dan zou je die moeten toevoegen, terwijl je dat land mogelijk helemaal niet nodig hebt bij die query.
Ivo P op 18/08/2016 11:38:20

je moet strikt genomen ALLE kolommen noemen.

als je SELECT * FROM adres
doet
en adres bevat adres_id, naam, straat, postcode

dan hoort er bij
SELECT count(1), adres.* FROM adres
dus GROUP BY adres_id, naam, straat, postcode

Daarom is het gebruik van * in combinatie met een aggregatie functie niet zo'n goed idee.

Ook al omdat een tabel best kan worden aangepast. Stel iemand bedenkt dat de kolom Land ook wel handig is in je adres. Dan zou je die moeten toevoegen, terwijl je dat land mogelijk helemaal niet nodig hebt bij die query.


Jeetje, wordt dan wel een gigantische query -.- als ik ALLE 'SELECT' velden moet opgeven.
Zijn er bekende problemen, als je dit niet doet ?

Momenteel werkt alles nog altijd naar behoren in de huidige situatie.
Ik heb inderdaad alle gegevens van product, de 1e media, en highlight tabel nodig, ok media_prodprod_id, media_weight en hlight_prod_id zijn niet perse nodig nee.

De tabel media, kan meerdere records hebben op 1 prod_id, maar highlight max. 1
De media heb ik al gevangen door media_weight = 1 te geven.
Dus ik ben niet bang dat ik ooit meerdere records krijg.

Reageren