IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques et frameworks PHP Discussion :

Paginer et trier un tableau [CakePHP]


Sujet :

Bibliothèques et frameworks PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut Paginer et trier un tableau
    Bien le bonjour,

    Après moultes jours de recherches et essais infructueux, je me permets de me tourner vers vous dans l'espoir qu'une âme charitable ai une réponse à apporter à mon problème. Car là j'ai essayé de retourner le truc dans tous les sens, mais je n'arrive à rien du tout...

    Je suis actuellement en train de réaliser une fonctionnalité de recherche avancée qui permet à un utilisateur de saisir un ensemble de paramètres puis de retourner tous les "AnalysisFile" correspondants à ces critères. Afin d'accélérer les requêtes sur la base de données et éviter un trop grand nombre de jointures, une vue à été réalisée dans la base de données. Celle ci comprend donc les ids de la majorité des tables de la base de données ainsi que des champs comme le nom de la feuille d'analyse, la date de réception de celle-ci, etc.

    En fonction des paramètres saisis par l'utilisateur je crée une requête SQL s'appuyant sur les fonctionnalités de CakePHP. Puis, je cherche à obtenir tous les "AnalysisFile" qui ont un id identique aux ids obtenus par la requête SQL effectuée sur la vue de ma base de données. Jusque là pas de soucis je récupère bien les bons "AnalysisFile". C'est là que ça se complique.

    Ce que j'essaye de faire désormais (sans succès), c'est de paginer tous les "AnalysisFile" correspondants aux critères définis par l'utilisateur et une fois dans ma vue CakePHP, de pouvoir trier ces résultats en cliquant sur les colonnes (via la méthode sort). Concretement, lorsque j'arrive sur ma vue j'obtiens bien une liste des fichiers correspondants à mes critères (donc ma requête est bonne), par ailleurs tout ce qui est lié à la pagination ne fonctionne pas. Au dessus de chacun de mes noms de colonnes (donc lors de l'appel de la méthode "sort") j'ai les trois warning suivants :

    Notice (8): Undefined index: AnalysisFile [APP/View/AnalysisFiles/analysis_file_advanced_results.ctp, line 5]

    Warning (2): array_filter() expects parameter 1 to be array, null given [CORE/Cake/View/Helper/PaginatorHelper.php, line 421]

    Warning (2): array_merge() [function.array-merge]: Argument #1 is not an array [CORE/Cake/View/Helper/PaginatorHelper.php, line 421]
    Et au pied de ma page (au niveau des $this->Paginator->prev et autres) :

    Notice (8): Undefined index: count [CORE/Cake/View/Helper/PaginatorHelper.php, line 638]

    Notice (8): Undefined index: limit [CORE/Cake/View/Helper/PaginatorHelper.php, line 641]

    Notice (8): Undefined index: count [CORE/Cake/View/Helper/PaginatorHelper.php, line 642]

    Notice (8): Undefined index: count [CORE/Cake/View/Helper/PaginatorHelper.php, line 643]

    Notice (8): Undefined index: page [CORE/Cake/View/Helper/PaginatorHelper.php, line 659]

    Notice (8): Undefined index: current [CORE/Cake/View/Helper/PaginatorHelper.php, line 661]

    Notice (8): Undefined index: count [CORE/Cake/View/Helper/PaginatorHelper.php, line 662]
    Alors soit ma syntaxe est mauvaise, soit CakePHP ne gère pas cela. Mais je n'ai rien trouvé sur le net m'indiquant que CakePHP était incapable de faire ce que je recherche (bon, je n'ai rien vu m'indiquant que c'était possible non plus ) .

    Si cela peut vous aider, voici une partie de mon code.

    Dans mon controller, la méthode qui récupère les critères de recherche et envoie tout vers la vue d'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public function analysisFileAdvancedResults()
    	{
    		$this->AnalysisFile->recursive = 0;
    		$paginate =
    			array(
    				'limit' => 20,
    					'order' => array(
    						'AnalysisFile.name' => 'asc'));
     
    		//On récupère le tableau sérialisé reçu via la méthode GET qui a été envoyé
    		//par la méthode filteringResultsAdvancedMode et on le déserialise
    		$receivedParameters = unserialize($this->request->params['named']['options']);
     
    		$conditionsArray = advancedSearchFormatConditions($receivedParameters);
     
    		//Les deux champs ci-dessous nécessitent un traitement particulier car ils ne sont pas
    		//compris dans la vue search_view. Il faut donc qu'on utilise la méthode query de cakePHP
    		//afin de récupérer les ids correspondant aux noms du requérant et de la ville (s'ils ont
    		//été spécifiés). C'est pourquoi on ne peut pas les traiter dans la méthode
    		//advancedSearchFormatConditions
    		if(empty($receivedParameters['advancedSearch']['applicantName']) == false)
    		{
    			$applicantIdResult = $this->AnalysisFile->Query("SELECT a.id FROM applicants a WHERE a.name = '".str_replace("'", "''", $receivedParameters['advancedSearch']['applicantName'])."';");
    			if(empty($applicantIdResult) == false)
    			{
    				//On remonte le résultat
    				$applicantId = $applicantIdResult[0][0]['id'];
    				$conditionsArray = array_merge($conditionsArray, array('applicant_id' => $applicantId));
    			}
    		}
     
    		if(empty($receivedParameters['cityName']) == false)
    		{
    			$cityIdResult = $this->AnalysisFile->Query("SELECT c.id FROM cities c WHERE c.name = '".str_replace("'", "''", $receivedParameters['cityName'])."';");
    			if(empty($cityIdResult) == false)
    			{
    				//On remonte le résultat
    				$cityId = $cityIdResult[0][0]['id'];
    				$conditionsArray = array_merge($conditionsArray, array('city_id' => $cityId));
    			}
    		}
     
    		$db = $this->AnalysisFile->getDataSource();
     
    		$subQuery = $db->buildStatement(
    							array(
    								'fields' => array('DISTINCT("search_view"."analysis_file_id")'),
    								'table' => '"mybase"."search_view"',
    								'alias' => 'search_view',
    								'limit' => null,
    								'offset' => null,
    								'joins' => array(),
    								'conditions' =>	$conditionsArray,
    								'order' => null,
    								'group' => null
    							),
    							$this->AnalysisFile
    						);
    		$subQuery = ' "AnalysisFile"."id" IN (' . $subQuery . ') ';
    		$subQueryExpression = $db->expression($subQuery);
     
    		$conditions[] = $subQueryExpression;
     
    		$this->set('analysisFiles', $this->AnalysisFile->find('all', compact('conditions')));
    	}
    A noter que j'ai bien essayé d'appeler $this->Paginate de plusieurs manières, comme par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    		$queryResult = $this->AnalysisFile->find('all', compact('conditions'));
    		$this->set('analysisFiles', $this->paginate($queryResult));
    Mais j'obtiens l'erreur suivante :

    Error: SQLSTATE[0A000]: Feature not supported: 7 ERREUR: l'ajout de colonnes ayant un type composé n'est pas implémenté LINE 1: ...file_id" = "AnalysisFile"."id") WHERE (("AnalysisFile" IN ('4136', 'D... ^
    (ce qui est d'ailleurs étrange, car au final je ne récupère pas un type composé mais des AnalysisFile, enfin c'est ce qu'il me semble)

    Et en ce qui concerne ma vue :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    <div class>
    	<table>
    		<tr>
    			<?php debug($analysisFiles); ?>
    			<th><?php echo $this->Paginator->sort($analysisFiles['AnalysisFile']['name'], 'Nom dossier'); ?></th>
    			<th><?php echo $this->Paginator->sort($analysisFiles['Service']['name'], 'Nom labo'); ?></th>
    			<th><?php echo $this->Paginator->sort($analysisFiles['AnalysisFile']['report_number'], 'Numéro PV'); ?></th>
    			<th><?php echo $this->Paginator->sort($analysisFiles['Applicant']['name'], 'Requérant'); ?></th>
    			<th><?php echo $this->Paginator->sort($analysisFiles['AnalysisFile']['receipt_date'], 'Date réception'); ?></th>
    			<th><?php echo $this->Paginator->sort($analysisFiles['AnalysisFile']['service_internal_number'], 'Numéro dossier labo'); ?></th>
    		</tr>
     
     
    		<?php foreach ($analysisFiles as $analysisFile): ?>
    		<tr>
    			<td><?php echo $analysisFile['AnalysisFile']['name'];?></td>
    			<td><?php echo $analysisFile['Service']['name'];?></td>
    			<td><?php echo $analysisFile['AnalysisFile']['report_number'];?></td>
    			<td><?php echo $analysisFile['Applicant']['name'];?></td>
    			<td><?php echo $analysisFile['AnalysisFile']['receipt_date'];?></td>
    			<td><?php echo $analysisFile['AnalysisFile']['service_internal_number'];?></td>
    		</tr>
    		<?php endforeach; ?>
    		<?php unset($analysisFile); ?>
    	</table>
    	<p>
    		<?php
    			echo $this->Paginator->counter(array(
    			'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
    			));
    		?>
    	</p>
    </div>
    <div class="paging">
    	<?php
    		echo $this->Paginator->prev('< ' . __('Précédent'), array(), null, array('class' => 'prev disabled'));
    		echo $this->Paginator->numbers(array('separator' => ''));
    		echo $this->Paginator->next(__('Suivant') . ' >', array(), null, array('class' => 'next disabled'));
    	?>
    </div>
    Et si ça peut vous aider, voici ce à quoi ressemble le résultat du debug fait dans la vue ci dessus :

    array(
    (int) 0 => array(
    'AnalysisFile' => array(
    'id' => '4136',
    'name' => 'Dossier 23_6_48',
    'service_id' => (int) 2,
    'report_number' => 'PV 7392',
    'applicant_id' => (int) 3,
    'receipt_date' => '2014-05-08',
    'closure_date' => '2014-05-21',
    'service_internal_number' => '2014-05-08_174',
    'validated' => true,
    'archived' => false,
    'comment' => null,
    'created' => '2014-04-24',
    'modified' => '2014-04-24'
    ),
    'Service' => array(
    'id' => '2',
    'name' => 'LPS Paris'
    ),
    'Applicant' => array(
    'id' => '3',
    'name' => 'TGI Lille',
    'city_id' => (int) 22746
    ),
    'RoadSafetyFile' => array(
    'id' => '4136',
    'analysis_file_id' => (int) 4136,
    'driver' => true,
    'gender_id' => (int) 2,
    'age' => (int) 67,
    'saliva_screening' => null,
    'fact_date' => '2014-05-07'
    )
    ),
    ...
    )
    Si quelqu'un a une solution à ce soucis, ou a une piste vers la quelle je pourrais me tourner, je suis grandement preneur !

    Merci par avance pour vos réponses !

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Bon, et bien après un court laps de temps, je me réponds à moi-même.

    Ce que je veux faire est en effet bien possible et j'y suis parvenu en paginant de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ...
    $conditions[] = $subQueryExpression;
     
    		$this->paginate =
    			array(
    				'limit' => 20,
    					'conditions' => $conditions,
    						'order' => array(
    							'AnalysisFile.name' => 'asc'));
     
    		$this->set('analysisFiles', $this->paginate('AnalysisFile'));
    Donc dans ce cas il semblerait qu'il ne soit pas nécessaire de faire appel à la méthode Find et qu'il suffise d'insérer les conditions dans la variable $this->Paginate !

    Merci tout de même et désolé du derangement

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Par défaut
    Tu n'utilises pas le composant Paginate de la bonne façon. Regarde la documentation, tout y est expliqué de manière très clair. Utiliser des query ne te permettra jamais de paginer correctement ce que tu souhaites, en tout cas pas en utilisant le composant intégré à Cake.

    Pourtant, celui-ci marche vraiment bien, jamais eu de soucis et qui plu est il est simple d'utilisation.

    Voici un squelette de code pour faire ta pagination :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        //Dans ton controller :
     
        public $components = array('Paginator');
     
        public function action() {
            $this->Paginator->settings = array(
                'limit' => 20,
                'order' => array(
                //'Table.colonne' => 'desc'
                ),
                'fields' => array(
                //liste de fields
                ),
                    //...
                    //Tous les paramètres de la fonction find('all') sont possibles (conditions, contain éventuellement, joins...)                   
            );
            $datas = $this->Paginator->paginate();
            $this->set('datas', $datas);
        }

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Salut et merci pour ta réponse !

    Je vais tâcher de rendre mon code un peu plus propre en m'appuyant sur ton explication.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Trier un tableau en 2 boucles
    Par SaladinDev dans le forum Assembleur
    Réponses: 9
    Dernier message: 07/05/2005, 22h38
  2. Trier un tableau par rapport à un autre tableau
    Par deaven dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 02/05/2005, 09h27
  3. [Débutant] Remplir et trier un tableau
    Par james-dean dans le forum Assembleur
    Réponses: 15
    Dernier message: 01/05/2005, 17h40
  4. Trier un tableau par ordre croissant
    Par Halleck dans le forum Algorithmes et structures de données
    Réponses: 15
    Dernier message: 01/11/2004, 00h04
  5. trier un tableau et compter des elements du tableau
    Par remi51 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 17/06/2002, 16h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo