Bonjour à tous,
j'ai décidé de commencer à suivre la formation vidéo de Grafikart afin de voir comment réaliser un site digne d'un professionnel ;)
Pour le moment, afin de bien comprendre, je respecte à la lettre ce qu'il fait ... Sauf que chez lui ça fonctionne, mais pas chez moi :p

Si vous pouviez m'aider ce serait cool, je patauge depuis hier :/
Les erreurs sont les suivantes :
Warning: PDO::quote() expects parameter 1 to be string, array given in C:\wamp\www\CURRENT_PROJECT\Mon_Projet\core\Model.php on line 70
Warning: PDOStatement::execute(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 in C:\wamp\www\CURRENT_PROJECT\Mon_Projet\core\Model.php on line 80

J'ai beau cherché, rien trouvé.
Voici mes pages qui 'peuvent être en cause' :

Ma classe Model :

<?php
class Model
{
    static $connections = array();
    public $conf = 'default';
    public $table = false;
    public $db;
    public $primaryKey = 'id';
    public function __construct()
    {
        // Initialisation de quelques variables :
        if($this->table === false)
        {
            $this->table = strtolower(get_class($this)).'s';
        }
        // Connexion à la base
        $conf = Conf::$databases$this->conf];
        if(isset(Model::$connections$this->conf]))
        {
            $this->db = Model::$connections$this->conf];
            return true;
        }
        try
        {
            $pdo = new PDO('mysql:host='.$conf'host'].';dbname='.$conf'database'].';',$conf'login'],$conf'password'],
                array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
            Model::$connections$this->conf] = $pdo;
            $this->db = $pdo;

        }
        catch(PDOException $e)
        {
            if(Conf::$debug >= 1)
                die($e->getMessage());
            else
                die('Impossible de se connecter à la base de donnée');
        }
    }
    public function find($req)
    {
        $sql = 'SELECT';
        if(isset($req'fields']))
        {
            if(is_array($req'fields']))
                $sql .= implode(', ', $req'fields']);
            else
                $sql .= $req'fields'];
            $sql .= ' FROM '.$this->table.'';
        }
        else
            $sql .=' * FROM '.$this->table.'';
        if(isset($req'conditions']))
        {
            $sql .= ' WHERE ';
            if(!is_array($req'conditions']))
                $sql .= $req'conditions'];
            else
            {
                $cond = array();
                foreach($req'conditions'] as $k => $v)
                {
                    if(!is_numeric($v))
                        $v = $this->db->quote($v);
                    $cond] = "$k = $v";
                }
                $sql .= implode(' AND ',$cond);
            }
        }
        $pre = $this->db->prepare($sql);
        $pre->execute();
        return $pre->fetchAll(PDO::FETCH_OBJ);
    }
    public function findAll()
    {
        $sql = 'SELECT * FROM '.$this->table.'';
        $pre = $this->db->query($sql);
        $pre->execute();
        return $pre->fetchAll(PDO::FETCH_OBJ);
    }
    public function findFirst($req)
    {
        return current($this->find($req));
    }
    public function findCount($conditions)
    {
        $res = $this->findFirst(array(
            'fields' => ' COUNT('.$this->primaryKey.') as count',
            'conditions' => $conditions));
        return $res;
    }

}

Mon Controller :

<?php
class Controller
{
    public $request;
    private $vars = array();
    public $layout = 'default';
    private $rendered = false;
    function __construct($request = null)
    {
        if($request)
            $this->request = $request;
    }
    public function render($view)
    {   
        if($this->rendered) 
        {
            return false;
        }
        extract($this->vars);
        if(strpos($view, '/') === 0)
            $view = ROOT.DS.'view'.$view.'.php';
        else
            $view = ROOT.DS.'view'.DS.$this->request->controller.DS.$view.'.php';
        ob_start();
        require($view);
        $content_for_layout = ob_get_clean();
        require ROOT.DS.'view'.DS.'layout'.DS.$this->layout.'.php';
        $this->rendered = true;
    }
    public function set($key, $value = null)
    {
        if(is_array($key))
        {
            $this->vars += $key;
        }
        else
        {
        $this->vars$key] = $value;
        }
    }
    public function loadmodel($name)
    {
        $file = ROOT.DS.'model'.DS.$name.'.php';
        require_once($file);
        if(!isset($this->$name))
            $this->$name = new $name();
    }
    /**
     * Permet de gérer les erreurs 404
     */

    function e404($message)
    {
        $this->set('message_error', $message);
        $this->render('/errors/404');
    }
    function request($controller, $action)
    {
        $controller .='Controller';
        require_once ROOT.DS.'controller'.DS.$controller.'.php';
        $c = new $controller();
        return $c->$action();
    }
    static function cut_content($content, $nb)
    {
        return $content = substr($content, 0, $nb);
    }
}

Et mon layout :

<!doctype html>
<html class="no-js" lang="fr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><?= isset($title_for_layout)?$title_for_layout:'E-Time'; ?></title>
    <link rel="stylesheet" href="<?= BASE_URL;?>/webroot/stylesheets/app.css" />
    <link rel="stylesheet" href="<?= BASE_URL;?>/webroot/stylesheets/style.css" />
    <script src="<?= BASE_URL;?>/webroot/bower_components/modernizr/modernizr.js"></script>
  </head>
  <body>
    <nav class="top-bar" data-topbar>
        <ul class="title-area">
          <li class="name">
            <h1><a href="<?= BASE_URL.'/pages/'?>view/1">E-Time</a></h1>
          </li>
          <li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
        </ul>
        <section class="top-bar-section">
          <!-- Droite -->
          <ul class="right">
             <li class="divider"></li>
            <li><a href="#">S'inscrire</a></li>
            <li class="divider"></li>
            <li class="active"><a href="#">Se connecter</a></li>
          </ul>
            <!-- Gauche -->
          <ul class="left">
    <?php $pagesMenu = $this->request('Pages', 'getMenu');
    foreach($pagesMenu as $page)
    {
      ?>
             <li class="divider"></li>
            <li><a href="<?= BASE_URL.'/pages/view/'.$page->id; ?>"><?= $page->name; ?></a></li>
            <li class="divider"></li>
      <?php
    }
    ?>
      </ul>
      </section>
      </nav>

     <?php echo $content_for_layout; ?>
    <hr />
     <div class="header">
          <h4>Les dernières actualités :</h4>
      </div>
    </header>
    <div class="row" data-equalizer>
       <div class="column large-12">
        <ul class="pagination">
          <li class="arrow unavailable"><a href="">«</a></li>
          <li class="current"><a href="">1</a></li>
          <li><a href="">2</a></li>
          <li><a href="">3</a></li>
          <li><a href="">4</a></li>
          <li class="arrow"><a href="">»</a></li>
        </ul>
      </div>
       <?php $postsMenu = $this->request('Posts', 'postsMenu');
       foreach($postsMenu as $unpost)
      {
        ?>
       <div class="column large-4">
        <div class="panel" data-equalizer-watch>
          <div class="row">
            <div class="column large-12 small-6">
              <img src="<?= BASE_URL.'/webroot/img/posts/'.$unpost->picture; ?>" class="lorem" alt="Lorem Ipsum1"/>
            </div>
            <div class="column large-12 small-6">
              <h5></h5>
              <p class="post">
               <?= Controller::cut_content($unpost->content, 300); ?> ...<br /> 
              </p>
               <a class="tiny button" href="<?= BASE_URL.'/posts/view/'.$unpost->id; ?>"/>Lire la suite »</a>
               <div class="column large-12 medium-12">
                <p class="left">
                  14 Janvier 2014
                </p>
                <p class="right">
                  17 commentaires
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
      <?php } ?>
    </div>
    <div class="row">
        <div class="column large-12">
          <p>
            Les contenus présentés sont protégés par les lois de propriété intellectuelle. © E-time.fr - Tous droits réservés.
            <div class="column large-4 medium-4 small-4">
               <a href="#">Qui-sommes-nous ?</a>
            </div>
            <div class="column large-4 medium-4 small-4">
              <a href="#">Publicité</a>
            </div>
             <div class="column large-4 medium-4 small-4">
              <a href="#">Conditions générales</a>
            </div>
          </p>
        </div>
        <div class="column large-4 medium-4 small-4">
            <img src="<?= BASE_URL;?>/webroot/img/fb.png" alt="Facebook" class="logo">
            <img src="<?= BASE_URL;?>/webroot/img/twitter.png" alt="Twitter" class="logo">
          <img src="<?= BASE_URL;?>/webroot/img/google.png" alt="Google+" class="logo">
          </div>
    </div>
    <script src="<?= BASE_URL;?>/webroot/bower_components/jquery/dist/jquery.min.js"></script>
    <script src="<?= BASE_URL;?>/webroot/bower_components/foundation/js/foundation.min.js"></script>
    <script src="<?= BASE_URL;?>/webroot/js/app.js"></script>
    <script src="<?= BASE_URL;?>/webroot/js/main.js"></script>
    <script src="<?= BASE_URL;?>/webroot/js/jquery-syncheight.js"></script>
  </body>
</html>

Merci de votre aide !

10 réponses


Romano83
Réponse acceptée

J'ai eu le même problème il y a quelques temps quand j'ai suivi le tuto.
Pour le résoudre, j'ai remplacé

if(!is_numeric($v))
 $v = $this->db->quote($v);
$cond] = "$k = $v";

par

if(!is_numeric($v)){
    $v = '"'.addslashes($v).'"';
}                   
$cond] = "$k=$v";
Vallyan
Réponse acceptée

Tu serais surpris (ou pas, peut-etre) de voir le nombre de gens qui adoptent cette démarche de facilité, pourtant ... n'ayant pas l'honneur de te connaitre, je préfère directement préciser que la solution est sans doute facile a identifier par soi-meme.

Cela étant dit, je propose que tu nous fasses un copié / collé d'un var_dump($req) que tu aurais mis directement en première ligne de ta fonction find($req), qu'on voit ce qui pourrait poser problème ...

Vallyan
Réponse acceptée

Dans les deux arrays tu as une clé 'conditions', mais dans le premier cette clé renvoie a un array (de taille 2) qui correspond a tes conditions alors que dans le second elle renvoie a un array (taille 1, d'indice 0) qui contient lui-meme un array (taille 2) qui correspond a tes conditions. Tu as donc un niveau de profondeur en plus dans le second array, ce qui explique pourquoi tu te retrouves avec un arry plutot qu'un string pour $v.

Retrouve la ligne qui appelle la méthode Model::find($req) lorsque tu veux afficher les articles. Le paramètre que tu passes a ta méthode est mauvais. Identifie a quel moment tu ajoutes des condition dans ce paramètre, c'est la qu'est ton erreur.

Noudnou
Auteur

J'aurais jamais eu l'idée de faire ça ...
Merci beaucoup ! :)
Cependant une erreur est toujours présente :
Warning: addslashes() expects parameter 1 to be string, array given in C:\wamp\www\CURRENT_PROJECT\E-Time3\core\Model.php on line 70

Noudnou
Auteur

Je me permet de faire remonter ce sujet ;)
Si vous pouviez me mettre sur la voie ce serait top, merci ! :D

Comprends-tu ce que te dit PHP ? (la phrase a l'aire d'etre dite sur un ton condescendant/passif-aggressif mais pas du tout ^^ je demande vraiment si tu comprends la signification de cette erreur ...)

il te dit que $v est un array, et qu'il veut un string. Tu es probablement le mieux placé pour comprendre, a partir de ce que tu as fait, pourquoi tu te retrouve avec un array alors que Graf, apparement, avait un string.

Fait un var_dump($v) pour voir ce qu'il y a dedans, identifie la différence entre ce que tu attends et ce que tu as, et remonte dans ton code pour retrouver l'origine de cette différence. Tu peux voir par exemple que $v est une des entrées de $req, donc il est sans doute utile de faire un var_dump($req) ... $req est lui meme un parametre d'une fonction, donc il faudra remonter au moment ou tu appelles cette fonction, et identifier quelle variable tu lui passes en paramètre, sans doute faire un var_dump() de cette variable aussi ... etc ...

Faire du code a partir d'un tuto c'est génial pour débuter. Mais si vous rencontrez un bug, la démarche n'est pas de comparer, ligne par ligne, votre code avec celui du tuto, c'est plutot de décrypter le message d'erreur, et d'utiliser votre tete pour trouver le problème.

Bonne chance pour débugger !

Noudnou
Auteur

Tu crois que j'ai pas fait ça ? (la question a l'aire d'etre dite sur un ton condescendant/passif-aggressif mais pas du tout ^^). J'ai essayé des var_dump() dans tous les coins possibles et inimaginable, et même cela n'a pas permis de retrouver l'erreur, c'est pour ça que j'ai fais appel à vous si vous aviez vu une erreur grossière au niveau de mon code, mais apparemment ce n'est pas le cas.
Je sais bien ce que me dit l'erreur PHP, j'ai été voir la Doc, j'ai testé des fonctions tels que serialsize(), j'ai essayé de modifier le code à la source, de mettre des choses en commentaire, des die, des print_r, bref ...
Je sais bien que l'apprentissage ce fait par soi-même, en expérimentant, en cherchant et en ... expérimentant, je suis le premier à le dire quand quelqu'un demande une solution toute prête. Hors là, ce que je veux n'est pas le résultat, mais que l'on me mette sur la voie, que je comprenne si une erreur a été commise ;)
Merci pour la petite piqûre de rappel, on ne le dira jamais assez, c'est avec la tête que l'on code et pas avec les doigts ! :)

Noudnou
Auteur

le var_dump donne ça :
array (size=2)
'fields' => string ' COUNT(id) as count' (length=19)
'conditions' =>
array (size=2)
'online' => int 1
'type' => string 'post' (length=4)

array (size=1)
'conditions' =>
array (size=1)
0 =>
array (size=2)
'online' => int 1
'type' => string 'post' (length=4)

Je t'ai fais le résultat des deux requêtes (celle qui permet de récupérer de compter les articles et celle qui permet de les afficher) ;)
Le problème vient que de la deuxième j'ai l'impression. A quoi correspond ce 0 dans l'array ?

Noudnou
Auteur

J'ai cherché, j'ai cherché ... Quel blaireau je fais :o
Voici la fonction Avant :

return $this->Post->find(array(
            'conditions' => array($conditions)));

Après :

return $this->Post->find(array(
            'conditions' => $conditions));

Tout fonctionne, merci beaucoup.
En toute honnêteté, si tu te poses vraiment la question de si j'ai cherché, ou pas, j'ai vraiment cherché, je pense avoir passé plusieurs heures (au moins 2) à résoudre le problème.
Merci en tout cas :)

Je ne me pose pas la question, si tu me dis que tu as cherché j'ai pas de raison de ne pas te croire.
Debugger n'est pas inné, ca demande aussi de l'entrainement comme tout aspect du développement. Content de t'avoir aidé :)