PHP|Débutant :: Forums

Advertisement

Besoin d'aide ? N'hésitez pas, mais respectez les règles

Vous n'êtes pas identifié(e).

#1 14-12-2013 10:42:28

caema
Membre
Inscription : 26-11-2013
Messages : 5

[MVC] inclure une vue dans une autre?

Bonjour à tous,

J'ai conçu un MVC en suivant le tuto du site MVC Grafikart.
Tout fonctionne bien, j'ai réalisé le tuto jusqu'au bout.

La question que je me pose concerne la page d'accueil de mon site.
Actuellement elle est gérée comme toutes les autres pages, pourtant c'est une page un peu "spéciale": je souhaite en effet qu'elle contienne un div reprenant les dernières news.
Ces news, je les gère déjà via un controller PostsController, et une vue index.php.
En gros, j'ai donc cette arborescence:

/controller
    * PagesController.php
    * PostsController.php

/view
    /pages
        * view.php
    /posts
        * index.php

Mon idée de départ, c'était de mettre ceci dans view.php:


<?php
  if ($page->id == 1){
    include_once('posts/index.php');
  }
?>
 

et donc d'inclure une vue, dans une autre vue.
Mais ce semble pas fonctionner puisque j'ai 2 erreurs:

Warning: include_once(posts/index.php): failed to open stream: No such file or directory in ....
Warning: include_once(): Failed opening 'posts/index.php' for inclusion (include_path='.;C:\wamp\bin\php\php5.4.16\pear;') in ...

Ma question est donc, en MVC, est-il possible d'inclure une vue dans une autre vue?
Et si non, comment raisonner pour résoudre mon problème?


D'avance merci!

Hors ligne

#2 14-12-2013 12:14:45

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : [MVC] inclure une vue dans une autre?

Bonjour,

La réponse à votre question est oui.
Par contre l'erreur que vous avez viens du fait que vous n'avez aucune gestion du chemin d'accès à vos fichiers. Je vous laisse regarder sur le forum, on a déjà pris le temps très récemment d'expliquer comment fonctionnent les chemins d'accès aux fichier dans une application dans les grandes lignes.

Bon week-end à vous


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#3 14-12-2013 13:42:50

caema
Membre
Inscription : 26-11-2013
Messages : 5

Re : [MVC] inclure une vue dans une autre?

OK, merci à vous d'avoir pris la peine de me répondre, c'est très aimable. smile
Je vais visiter le forum à la recherche des chemins d'accès, et je reviendrai ici si j'ai une question/interrogation à ce sujet.

En attendant, bon à vous week-end également

Cordialement

Hors ligne

#4 14-12-2013 17:29:28

caema
Membre
Inscription : 26-11-2013
Messages : 5

Re : [MVC] inclure une vue dans une autre?

Bon, alors je ne sais pas si je suis dans le bon, j'ai cherché dans les messages récents du forum sans succès, mais j'ai trouvé ceci: developpez.com
J'ai donc modifier mon includes, et j'ai fait ceci:


<?php
  if ($page->id == 1){
    include_once(dirname(__DIR__) .'/posts/index.php');
  }
?>
 

Pour information, voici ce que contient le fichier /view/posts/index.php que je tente d'inclure:

<div>
  <div class="row">
    <div class="span13">
      <div class="page-header">
        <h1><?php echo isset($title)?$title:'Le blog'; ?></h1>
      </div>
      <?php foreach ($posts as $k => $v): ?>
        <div class="clearfix">
          <h3><?php echo $v->name; ?></h3>
          <?php echo substr(strip_tags($v->content),0,300); ?>...
        </div>
        <p style="text-align:right"><a href="<?php echo Router::url("posts/view/id:{$v->id}/slug:$v->slug"); ?>">Lire la suite &rarr;</a></p>
        <p>&nbsp;</p>
      <?php endforeach ?>

      <div class="pagination">
        <ul>
          <?php for($i=1; $i <= $page; $i++): ?>
            <li <?php if($i==$this->request->page) echo 'class="active"'; ?>><a href="?page=<?php echo $i; ?>"><?php echo $i; ?></a></li>
          <?php endfor; ?>
        </ul>
      </div>
    </div>
    <!-- INCLUSION SIDEBAR
      <?php require('sidebar.php'); ?>
    -->
  </div>
</div>

Mon inclusion "fonctionne" puisqu'elle affiche ce qui est en statique, mais pour le reste j'ai quelques erreurs:

Undefined variable: posts et Invalid argument supplied for foreach() in... pour la ligne

<?php foreach ($posts as $k => $v): ?>

et 2 erreurs Object of class stdClass could not be converted to int in... pour cette ligne:

<?php for($i=1; $i <= $page; $i++): ?>

Je précise que ce fichier à inclure, il fonctionne sans erreur si j'y accède via sur url propre.
Je sais pas, je suis un peu paumée je crois, l'erreur peu venir de pas mal de trucs: mes redirections, mes htaccess peut être?

Pas le choix je dois trouver une solution, mon projet est lancé lol

Dernière modification par caema (14-12-2013 17:32:17)

Hors ligne

#5 16-12-2013 04:20:00

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : [MVC] inclure une vue dans une autre?

Bonjour,

En effet si tout le contenu de votre fichier index.php est là, vous avez un problème, bien qu'il faudrait vérifier l'ensemble des includes en amont pour vérifier et en être certain.

Sinon pour la deuxième erreur, essayez avec


<?php
   $page=intval($this->request->page);
   for($i=1; $i <= $page; $i++): ?>
  <li <?php if($i===$page) echo 'class="active"'; ?>><a href="?page=<?php echo $i; ?>"><?php echo $i; ?></a></li>
<?php endfor; ?>
 

++

Dernière modification par Jc (16-12-2013 04:20:57)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

#6 16-12-2013 10:33:48

caema
Membre
Inscription : 26-11-2013
Messages : 5

Re : [MVC] inclure une vue dans une autre?

Le soucis, c'est que la variable $posts(de /posts/index.php) est construite depuis le contrôleur PostsController, et qu'elle est transmise à la vue index.php, d'où l’impossibilité de récupérer la variable $posts dans une vue autre que celle de son contrôleur/action.

Il faudrait que je puisse créer une méthode qui gère la construction de la variable $posts dans une "super class" dont héritera les controlleurs PostsController et PagesController, mais je ne sais pas comment faire...

Que ce soit pour PostsController ou PagesController, les 2 extends de d'un fichier Controller
Je peux donc envisager de déclarer $posts dans ce fichier Controller.php ?
Je ne sais pas, je suis complètement paumée dans ce soucis, au plus je fais des tests, au plus je me paume...

Pour info, voici le contenu de PostsController: (je n'ai copié que les fonctions pertinentes)


<?php
class PostsController extends Controller{
 
  /**
  * Blog, liste les articles
  **/
  function index(){
    $perPage = 10;
    $this->loadModel('Post');
    $condition = array('online' => 1,'type'=>'post');
    $d['posts'] = $this->Post->find(array(
      'conditions' => $condition,
      'fields'     => 'Post.id,Post.name,Post.slug,Post.created,Category.name as catname,Post.content,Category.slug as catslug',
      'order'      => 'created DESC',
      'limit'      => ($perPage*($this->request->page-1)).','.$perPage,
      'join'       => array('categories as Category'=>'Category.id=Post.category_id')
    ));
    $d['total'] = $this->Post->findCount($condition);
    $d['page'] = ceil($d['total'] / $perPage);
    $this->set($d);
  }

  /**
  * Permet d'afficher les posts d'une catégorie
  **/
  function category($slug){
    $this->loadModel('Category');
    $category = $this->Category->findFirst(array(
      'conditions' => array('slug' => $slug),
      'fields'     => 'id,name'
    ));
    if(empty($category)){
      $this->e404();
    }
    $perPage = 10;
    $this->loadModel('Post');
    $condition = array('online' => 1,'type'=>'post','category_id' => $category->id);
    $d['posts'] = $this->Post->find(array(
      'conditions' => $condition,
      'fields'     => 'Post.id,Post.name,Post.slug,Post.created,Category.name as catname,Post.content,Category.slug as catslug',
      'order'      => 'created DESC',
      'limit'      => ($perPage*($this->request->page-1)).','.$perPage,
      'join'       => array('categories as Category'=>'Category.id=Post.category_id')
    ));
    $d['total'] = $this->Post->findCount($condition);
    $d['page'] = ceil($d['total'] / $perPage);
    $d['title'] = 'Tous les articles "'.$category->name.'"';
    $this->set($d);
    // Le système est le même que la page index alors on rend la vue Index
    $this->render('index');
  }

  /**
  * Affiche un article en particulier
  **/
  function view($id,$slug){
    $this->loadModel('Post');
    $d['post']  = $this->Post->findFirst(array(
      'fields'   => 'Post.id,Post.content,Post.name,Post.slug,Category.name as catname,Category.slug as catslug',
      'conditions' => array('Post.online' => 1,'Post.id'=>$id,'Post.type'=>'post'),
      'join'     => array('categories as Category'=>'Category.id=Post.category_id')
    ));
    if(empty($d['post'])){
      $this->e404('Page introuvable');
    }
    if($slug != $d['post']->slug){
      $this->redirect("posts/view/id:$id/slug:".$d['post']->slug,301);
    }
    $this->set($d);
  }
}
 

Et voici mon fichier Controller.php:


<?php
class Controller{
 
  public $request;    
  private $vars     = array();  
  public $layout    = 'default';    
  private $rendered = false;  

  function __construct($request = null){
    $this->Session = new Session();
    $this->Form = new Form($this);

    if($request){
      $this->request = $request;  // On stock la request dans l'instance 
      require ROOT.DS.'config'.DS.'hook.php';    
    }
   
  }

  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;
    }
  }

  function loadModel($name){
    if(!isset($this->$name)){
      $file = ROOT.DS.'model'.DS.$name.'.php';
      require_once($file);
      $this->$name = new $name();
      if(isset($this->Form)){
        $this->$name->Form = $this->Form;  
      }
    }

  }

  function e404($message){ 
    header("HTTP/1.0 404 Not Found");
    $this->set('message',$message);
    $this->render('/errors/404');
    die();
  }

  function request($controller,$action, $params = null){
    $controller .= 'Controller';
    require_once ROOT.DS.'controller'.DS.$controller.'.php';
    $c = new $controller();
    return $c->$action();
  }

  function redirect($url,$code = null ){
    if($code == 301){
      header("HTTP/1.1 301 Moved Permanently");
    }
    header("Location: ".Router::url($url));
  }


}
?>
 

Merci de votre aide, je suis perdue lol

Hors ligne

#7 17-12-2013 00:05:24

Jc
Membre
Lieu : Zillisheim - Alsace
Inscription : 15-04-2010
Messages : 1 629
Site Web

Re : [MVC] inclure une vue dans une autre?

Bonjour,

o_O d'où provient ce code? l'architecture y est très sommaire et discutable... bref très léger pour un contrôleur...
Au delà de ça, dans le code que vous nous avez fourni, votre variable $posts qui est censée, si j'ai bien compris, représenter une instance de PostsController, contient plusieurs anomalies :
- On ne voit nulle part le code qui instancie la classe dans $posts (d'où l'erreur rencontrée)
- Vu que la requête URL est stockée dans $vars (variable privée) de la classe Controller, rien n'est mis en place pour permettre d'accéder à son contenu d'une manière publique et l'appel de $v->name ne peut fonctionner en l'état du code fourni car le seul name présent dans vos classes controller est le nom d'une catégorie, mais là encore innaccessible au niveau public de la classe.

++

EDIT du 18/12

o_O d'où provient ce code? l'architecture y est très sommaire et discutable... bref très léger pour un contrôleur...

Quand je dis ça, c'est pour que vous preniez conscience qu'il y a une différence entre un tuto qui est là pour vous aider à comprendre l'architecture d'un contrôleur dans ses rôles et ses fonctions, et à l'implémenter en PHP orienté objet, et un tuto de mise en place d'un controller de production. Une fois que vous avez compris comment cela fonctionne, si vous voulez accéder à des modèles viables de production, téléchargez zend ou drupal et épluchez le code. A moins de mettre en place votre propre architecture applicative, inspirez-vous des design pattern au niveau controller, choisissez celui qui corresponds le plus à votre besoin, et partez là-dessus, c'est un bon conseil je pense.

++

Dernière modification par Jc (18-12-2013 02:26:17)


POO PHP+Ajax en MVC avec PDO et Bases de données épaisses  : What else?

Hors ligne

Pied de page des forums