Mot-clé - framework

Fil des billets

lundi, 6 juin 2016

Laravel : utilisation (cas d’une page dynamique)

Route

Créons une route qui mènera à la page power (c'est-à-dire http://localhost/monprojet/public/power), et dont les opérations seront gérées par la méthode activate() de mon contrôleur TestController :


Route::get('power','TestController@activate');

 

Vues

Afin d'aller un peu plus loin dans la découverte de Blade, nous allons garder les vues default.blade.php et informations.blade.php, comme nous les avons créées précédemment, mais en y ajoutant un peu de contenu.

vues.png

1. Le gabarit default (vue générique / parent)

J'ai étendu le gabarit pour permettre de constater que @yield peut agréger autre chose que des sections nommées content :


<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Page de test</title>
</head>
<body>
<h1>Mon site test</h1>

@yield('header')
@yield('nav')
@yield('content')

</body>
</html>

Nous allons voir que les @yield('header') et @yield('nav') permettent d'agréger les sections nommées 'header' et 'nav' de la vue enfant, comme cela était le cas pour la section content.

2. La vue informations (vue spécifique / enfant)

Dans la page informations.blade.php sous mon dossier test, j'ai adapté le code pour quelque chose de plus complet, qui permette de jauger plus significativement le potentiel de Blade :


@extends('default')


@section('header')
    <form method="get">
        <input type="submit" name="etat" value="{{ $value }}">
    </form>
@endsection


@section('nav')
    <ul>
        @foreach($nav as $item)
            <li><a href="#">{{ $item }}</a></li>
        @endforeach
    </ul>
@endsection


@section('content')
@if($value !== 'Activer')
    @include('test.bonjour')
@endif
@endsection

Section "header"

Dans la section header, je crée un simple formulaire en méthode GET. Aucun changement n'est observable dans cette partie du code, à l'exception de la value du formulaire qui accueille une variable entre double accolades. Les double accolades permettent d'afficher le contenu d'une variable en l'échappant. {{ $value }} revient à écrire : <?php echo htmlentities($value); ?> Le contenu de cette variable n'est pas renseigné dans la vue puisqu'il est envoyé depuis le contrôleur – que nous créerons dans le point suivant – vers la vue.

Section "nav"

Dans la section nav, j'appelle un tableau envoyé par le contrôleur – voir plus loin – sur lequel je réalise une boucle foreach et affiche chaque élément du tableau en l'échappant : {{ }}. Bien sûr, le code est adapté à la sauce Blade, tant pour l'affichage du contenu des variables que pour la boucle itérative. S'il était produit en PHP, le script serait écrit comme ceci :


<ul>
   <?php
   foreach($nav as $item) {
   ?>
     <li><a href="#"><?php echo htmlentities($item); ?></a></li>
   <?php
   }
   ?>
</ul>

Le code est donc largement simplifié puisqu'il permet notamment de se passer des (rébarbatives) balises PHP.

Section "content"

Afin d'avoir fait un tour satisfaisant des options de Blade, j'ai créé dans la section content une condition spécifiant que si la variable $value (du header) est différente d' "Activer", j'inclus une autre page nommée bonjour.blade.php, située au même niveau que la présente vue, sous le dossier test. Le @if et le @include sont également propres à la syntaxe de Blade.

3. La vue bonjour : inclusion

Voici la vue bonjour.blade.php, qui sera embarquée quand le site sera établi comme "Activé" :


<p>Le service est activé ! Les épices, c'est bon.</p>
<hr>
<p>{{ "<strong>hibou</strong>" }}</p>
<p>{!! "<strong>hibou</strong>" !!}</p>
{{-- Un commentaire --}}

On y trouve : du contenu échappé, entre {{ }}, du contenu non échappé – qui sera donc interprété – entre {!! !!}, ainsi qu'un commentaire, entre {{-- --}}. Nous verrons ce que donne le résultat de ces trois lignes de code un peu plus bas.

Contrôleur

Comme prévu, nous voilà dans la méthode du contrôleur à laquelle menait la route.


<?php
namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class TestController extends Controller {

	public function activate(Request $request) {
		$nav = ['aneth', 'bergamote', 'coriandre', 'estragon', 'fenouil']; ➊
		$etat = $request->etat;
		if($etat == 'Désactiver') {
			$value = 'Activer';
		} else {
			$value = 'Désactiver';
		} ➋
		return view('test.informations', compact('nav', 'value')); ➌
	}
}

➊ Nous pouvons trouver dans ce contrôleur le tableau $nav à 5 valeurs que nous avons déjà traité avec la boucle foreach (cf. point section nav de la vue 'informations').

➋ Ici, nous abordons les requêtes. Dans la ligne 11 du code ci-dessus, on affecte à la variable $etat la valeur du GET obtenue en cliquant sur le bouton (submit) du formulaire (cf. section header de la vue 'informations'). On demande en effet à Laravel d'établir une requête et d'aller chercher la valeur du GET auquel on a attribué l'attribut name, c'est-à-dire le submit lui-même.

⚠ Pour que $request->[name_du_get] fonctionne, il est nécessaire d'appeler le fichier Request au sommet du contrôleur (use Illuminate\Http\Request;) ainsi qu'en paramètre de la méthode (Request $request, Request servant à instancier l'existant). Ensuite j'établis une condition : si la variable $etat vaut "Désactiver", j'affecte à une variable nommée $value la valeur "Activer" ; mais pour toute autre valeur, la chaîne de caractères "Désactiver" sera affectée à ma variable $value.

➌ Enfin, on retourne la vue informations qui se trouve dans le dossier test, tout en passant à cette vue les variables $nav (➊) et $value (➋), de sorte qu'elles puissent y être exploitées, ce qui a été fait !

Résultat

Les vues ci-dessous varient en fonction qu'on clique sur le bouton en dessous du titre. Si l'on clique sur "Activer" (parce que le site est désactivé), on l'active, et le bouton prend alors dynamiquement la valeur "Désactiver" pour opérer dans le sens inverse (cf. Contrôleur). Par ailleurs, la vue bonjour n'est visible qu'à condition que le site soit établi comme actif (cf. Vue informations, section content).

active.png desactive.png

Conclusion

Désormais, nous avons fait un tour presque complet de Blade. @if @elseif @else, @for, @forelse, @isset – pour ne citer que celles-là – sont d'autres fonctions exploitables que vous pourrez découvrir sur la documentation officielle de Laravel. Le présent article nous a permis de voir comment communiquer des variables du contrôleur à la vue, ce qui est un premier pas vers l'élaboration d'un site ou d'une application plus dynamique. Dans le prochain article, nous verrons la gestion des formulaires en POST, Artisan (l'interface en ligne de commande) et les interactions avec une base de données. See you soon :) !

dimanche, 5 juin 2016

Laravel : utilisation (cas d'une page statique)

Vues

1. Le gabarit (vue générique / parent)

Avec Blade – le moteur de templates de Laravel –, il convient de créer un gabarit sous resources > views. Nommons le default.blade.php, et déposons-y ce contenu :


<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Page de test</title>
</head>
<body>

<h1>Mon site test</h1>

@yield('content')

</body>
</html>

Comme nous pouvons le voir, ce fichier HTML n'est pas complètement normé/standard. L'élément @yield('content') est en effet une des premières caractéristiques de Blade. L'élément yield permet d'agréger le contenu 'content' d'une page tierce, qui héritera du gabarit default.blade.php. Créons donc cette page tierce pour y voir plus clair.  

2. La vue (vue spécifique / enfant)

Dans le dossier views, créons un dossier test et créons-y un fichier informations.blade.php comprenant ce contenu :


@extends('default')

@section('content')
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>
@endsection

Dans ce fichier, nous pouvons comprendre le code comme suit : hérite du fichier default (sous-entendu default.blade.php), gabarit qui agrègera (@yield) le contenu de la section 'content'.  

Route

Comme vu dans l'article précédent, le fichier routes.php – présent dans le dossier app > Http – indique l'action à accomplir en fonction de l'URL saisie dans le navigateur. Nous allons donc établir la route comme suit :


Route::get('informations', function() {
	return view('test.informations');
});

Dans le présent exemple, Laravel récupère la vue située dans mon dossier resources > views > test > informations pour l'afficher à l'adresse http://localhost/monprojet/public/informations.   ... Mais cette formulation est un raccourci barbare. Préférons-lui :


Route::get('informations', 'TestController@index');

Cette instruction peut être traduite comme suit : pour la route menant à http://localhost/monprojet/public/informations, exécute la méthode index() du contrôleur TestController. Reste donc à créer ledit contrôleur pour que la route génère un résultat...  

Contrôleur

Dans le dossier App > Http > Controllers, créez un contrôleur TestController avec ce contenu :


<?php
namespace App\Http\Controllers;

class TestController extends Controller {

	public function index() {
		return view('test.informations');
	}

}

La méthode index() du contrôleur ici présent – à laquelle il a été fait appel dans la route ci-dessus – retourne la vue informations.blade.php issue du dossier test sous resources > views (on aurait tout aussi bien pu écrire test/informations, Laravel accepte les deux nomenclatures)  

Résultat

En se rendant sur la page : http://localhost/monprojet/public/informations, nous obtenons ce résultat :  

Conclusion

Rien ne justifie le choix d'un framework pour la réalisation d'un site statique, puisqu'il complexifie énormément les choses, comme vous pouvez le voir. Toutefois, dès lors que nous exploiterons des données dynamiquement et communiquerons avec la base de données, les procédures s'en trouveront allégées : moins de code, plus de sécurité ;) . Le prochain article s'attardera sur la création d'une page plus dynamique pour permettre d'exploiter les vues Blade, les routes et les contrôleurs un peu plus loin. Et ce sera toujours sans modèle ni base de données, pour y aller pas à pas. Enregistrer

samedi, 4 juin 2016

Laravel : introduction

laravel.pngNé en 2011, Laravel est le framework PHP à architecture MVCR dont on parle probablement le plus après Symfony depuis quelques années. Je suis partie à la rencontre de cet outil, et pour ne rien perdre des connaissances que j'en ai engrangées, je délivre dans le même temps ce mémo.


Installer Laravel

  • Installer Composer.composer.png
  • Installer Laravel : depuis l’invite de commandes, accéder au dossier www/htdocs de votre wamp/xampp et exécuter la commande suivante :
    composer create-project laravel/laravel {directory} "~5.0.0" --prefer-dist
  • Établir la connexion à la base de données : adapter les paramètres sous le fichier .env à la racine du dossier.

Préambule

Arborescence du framework

  • app (cœur de votre application)
    • Commands
    • Console
    • Events
    • Handlers
    • Commands
    • Events
    • Http
      • Controllers
      • Middleware
      • Requests
    • Providers
    • Services
  • bootstrap (fichiers d’initialisation de Laravel)
  • config (fichiers de configuration)
  • database (fichiers liés à la base de données)
    • migrations
    • seeds
  • public (assets : fichiers images, js, css)
    • package
  • resources (vues et fichiers de langue)
    • lang
    • views
  • storage (données temporaires de l’application : clés de session, caches…)
    • cache
    • logs
    • meta
    • sessions
    • views
    • work
  • tests (fichiers de tests unitaires)
  • vendor (composants de Laravel & dépendances)

Routes

Laravel impose l'utilisation de routes pour faire le pont entre ses vues et ses contrôleurs. S'il s'agit d'une caractéristique plutôt rébarbative au premier abord ((Face à des frameworks comme CodeIgniter, CakePHP ou Nette qui gèrent les routes automatiquement, Laravel force à se concentrer sur une composante de plus.)), on lui reconnaît les qualités de renforcer la sécurité et surtout d'améliorer la vitesse d'affichage, et donc l'expérience utilisateur. Présent dans le dossier app > Http, le fichier routes.php indique l'action à accomplir en fonction de l'URL saisie dans le navigateur. En fonction de l'URL explorée, les routes transmettent des données à la méthode d'un contrôleur, qui se charge d'exécuter une série d'instructions – en passant si nécessaire par le modèle, destiné à l'élaboration de requêtes dans la base de données – pour renvoyer enfin le résultat à la vue.

mcvr-1.png

Artisan

Laravel propose une interface en ligne de commande nommée Artisan. Artisan permet d'automatiser toute une série d'opérations de gestion au sein du framework, telles que la création de contrôleurs, de modèles, de migrations, ou l'affichage des routes existantes établies au sein de l'application créée.

Blade

Blade est le moteur de templates dépendant de Laravel. Il fonctionne sur un système d'héritage qui lui permet d'agréger des vues, et de faciliter par ailleurs l'affichage de variables (code PHP) en échappant la plupart des données qui sont embarquées dans les vues.

Eloquent

Eloquent est un ORM (Object-relational Mapping) implémentant ActiveRecord qui permet de faciliter les requêtes dans la base de données par une syntaxe voulue plus éloquente que du simple SQL. Il supporte nativement plusieurs SGBD : MySQL, PostgreSQL, Sqlite3 et SQLServer. Eloquent est typiquement utilisé dans les modèles, situés dans le dossier app > Http. Depuis Laravel 4, il n'est toutefois plus obligatoire pour gérer les requêtes au sein du framework. Il peut être par ailleurs remplacé par d'autres ORM qui correspondraient mieux aux attentes du développeur.

Conventions de nommage

  • Les tables des bases de données doivent figurer au pluriel.
  • Les colonnes de la base de données doivent normalement figurer en snake_case.
  • Les noms de classes doivent être déclarées UpperCamelCase.
  • Le nom des méthodes et des fonctions est prévu en lowerCamelCase.
  • Les constantes sont toutes déclarées en UPPERCASE_AVEC_UNDERSCORES.
  • Le nom des modèles, rappelant celui des tables doit figurer au singulier.
  • Les contrôleurs n'imposent rien quant au genre (singulier ou pluriel).

Précautions

Contrairement à d'autres frameworks, Laravel propose une upgrade (et non une update !) à chaque sous version, et ce, de manière extrêmement rapide ((Laravel a proposé sa version 5.0 en février 2015, sa version 5.1 en juin 2015 et sa version 5.2 en décembre 2015 !)). En procédant à l'upgrade d'un projet sur lequel vous avez déjà bien avancé, vous risqueriez de ne plus pouvoir exécuter celui-ci comme avant en raison des changements opérés au sein du noyau même de l'outil en passant, par exemple, de la version 5.1 à la version 5.2 du framework. Je vous recommande donc de conserver la version avec laquelle vous avez entamé votre site/application. Toutefois, pas de panique : les différentes versions du framework sont supposées être maintenues assez durablement, et leurs documentations rester disponibles tant que les versions précédentes "vivront".

laravel-releases.png

Dans l'article suivant, nous nous pencherons sur une utilisation basique du framework – sans base de données – pour appréhender les interactions entre les routes, les contrôleurs et les vues Blade. Enregistrer

mardi, 24 novembre 2015

Nette framework : utilisation

Ici, nous voyons les interactions entre une présentation et ses vues, comment fonctionnent les formulaires, ainsi que l'ajout et l'édition de données dans la base de données.

Avant de commencer, admettons que vous ayez connecté votre base de données (cf. article précédent) en prenant soin de privilégier InnoDB comme moteur de stockage, et que vous ayez créé deux tables : posts et comments.

Presenter / Présentation

app/presenters/PostPresenter.php


namespace App\Presenters;

use Nette,
    Nette\Application\UI\Form;

class PostPresenter extends BasePresenter
{
/** @var Nette\Database\Context */
private $database;

public function __construct(Nette\Database\Context $database)
{
    // connexion à la base de données
    $this->database = $database;
}

public function renderDefault() ➊
// génère une vue default.latte
{
   // récupère les données et
   // les envoie dans la vue sous la variable $posts
   $this->template->posts = $this->database->table('posts')
      ->order('created_at DESC')
      ->limit(5);
}

public function renderShow($postId) ➋
// génère une vue show.latte
{
   // récupération du $postId,
   // s'il n'existe pas, afficher une erreur,
   // sinon envoyer le résultat dans la vue
   $post = $this->database->table('posts')->get($postId);
   if (!$post) {
       $this->error('Post not found');
   }

   $this->template->post = $post;
   $this->template->comments = $post->related('comments')
       ->order('created_at');
}

protected function createComponentCommentForm() ➌
// sera récupéré dans la vue sous "CommentForm"
{
    // création d'un formulaire
    $form = new Form;

    $form->addText('name', 'Your name:') // ('name', 'label')
        ->setRequired() // required
        ->setAttribute('class', 'toto')
        ->setAttribute('placeholder', 'Please type your name')
        ->setAttribute('onchange', 'mafonction()');

    $form->addText('email', 'Email:')
        ->setType('email');

    $sex = array(
        'm' => 'male',
        'f' => 'female',
    );
    $form->addRadioList('gender', 'Gender:', $sex);

    $form->addCheckbox('Human', 'Are you a human ?');

    $countries = array(
        'Europe' => array(
            'CZ' => 'Czech republic',
            'SK' => 'Slovakia',
            'GB' => 'United Kingdom',
        ),
        'CA' => 'Canada',
        'US' => 'USA',
        '?'  => 'other',
    );
    $form->addSelect('country', 'Country:', $countries)
        ->setPrompt('Pick a country');

    $form->addTextArea('content', 'Comment:')
       ->setDisabled(); // disabled

    $form->addUpload('thumbnail', 'Thumbnail:')
        ->addRule(Form::IMAGE, 'Thumbnail must be JPEG, PNG or GIF');

    $form->addSubmit('send', 'Publish comment');

    $form->onSuccess[] = array($this, 'commentFormSucceeded'); ➍

    return $form;
}

➍ public function commentFormSucceeded($form, $values) {
$postId = $this->getParameter('postId');

$this->database->table('comments')->insert(array(
     'post_id' => $postId,
     'name' => $values->name,
     'email' => $values->email,
     'content' => $values->content,
));

$this->flashMessage('Thank you for your comment', 'success'); ➎
$this->redirect('this');
// alternative :
// $this->redirect('show', $post->id);
}

public function actionEdit($postId) ➒
// actionEdit et non renderEdit :
// il ne s'agit pas que d'un travail de rendu dans ce cas-ci.
{
    $post = $this->database->table('posts')->get($postId);
    if (!$post) {
        $this->error('Post not found');
    }
    $this['postForm']->setDefaults($post->toArray()); ➏
}

protected function createComponentPostForm() ➏
{
$form = new Form;
$form->addText('title', 'Title:')
     ->setRequired();
$form->addTextArea('content', 'Content:')
     ->setRequired();

$form->addSubmit('send', 'Save and publish');

$form->onSuccess[] = array($this, 'postFormSucceeded'); ➐

return $form;
}

➐ public function postFormSucceeded($form, $values) {
$postId = $this->getParameter('postId');

if ($postId) {
   $post = $this->database->table('posts')->get($postId);
   $post->update($values);
} else {
   $post = $this->database->table('posts')->insert($values);
}

$this->flashMessage('Post was published', 'success'); ➎
$this->redirect('show', $post->id);
}

}

View / Vue

app/templates/Post/default.latte


{block content} ➑
    <h1 n:block="title">Blog</h1>

    {foreach $posts as $post}
    <div class="post">
        <div class="date">{$post->created_at|date:'F j, Y'}</div>

        <h2>{$post->title}</h2>

        <div>{$post->content}</div>
    </div>
    {/foreach}

    <a n:href="Post:create">Write new post</a>

{/block}

➋ app/templates/Post/show.latte


{block content} ➑
<p><a n:href="Homepage:default">← back to posts list</a></p>
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h1 n:block="title">{$post->title}</h1>
<div class="post">{$post->content}</div>
➒ <a n:href="edit $post->id">Edit this post</a>

<h2>Post new comment</h2>
➌ {control commentForm}

<h2>Comments</h2>
<div class="comments">
    {foreach $comments as $comment}
        <p><b><a href="mailto:{$comment->email}"
         n:tag-if="$comment->email">
         {$comment->name}</a></b> said:</p>
        <div>{$comment->content}</div>
    {/foreach}
</div>

app/templates/Post/edit.latte


{block content} ➑
<h1>Edit post</h1>

➏ {control postForm}

app/templates/@layout.latte (gabarit inclusif)


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>{ifset title}{include title|striptags} | {/ifset}Nette Web</title>
    <!-- embarque/agrège le title spécifié dans la vue -->

    <link rel="shortcut icon" href="{$basePath}/favicon.ico">
</head>

<body>
     ➎ <div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
            {$flash->message}
        </div>
    <!-- affiche les messages d erreur liés
    à la complétion du formulaire (champs requis et autres règles)-->

     ➑ {include content}
        <!-- embarque/agrège le contenu des vues : {block content} -->

    {block scripts}
    <script src="//nette.github.io/resources/js/netteForms.min.js"></script>
    {/block}
</body>
</html>

Formulaires : validation et récupération des données


$form->addPassword('password', 'Password:')
    // if password is not longer than 5 characters ...
    ->addCondition(Form::MAX_LENGTH, 5)
        // ... then it must contain a number
        ->addRule(Form::PATTERN, 'Must contain number', '.*[0-9].*')
        ->addRule(Form::RANGE, 'You must be older 18 years and be under 120.', array(18, 120));

// récupération des valeurs après soumission :
$values = $form->getHttpData($form::DATA_TEXT, 'sel[]');
$values = $form->getHttpData($form::DATA_TEXT | $form::DATA_KEYS, 'sel[]');

Parmi les règles et conditions, voici la liste des fonctions possibles ((Liste non exhaustive.)) :

  • Form::MIN_LENGTH : minimum de caractères ou de fichiers accepté
  • Form::MAX_LENGTH : maximum de caractères ou de fichiers accepté
  • Form::LENGTH : nombre strict de caractères ou de fichiers accepté
  • Form::EMAIL : impose un format email
  • Form::URL : impose un format url
  • Form::INTEGER : impose un nombre entier
  • Form::FLOAT : impose un nombre décimal
  • Form::RANGE : impose une fourchette entre X et Y
  • Form::PATTERN : expression régulière
  • Form::BLANK : le champ doit rester vide
  • Form::MAX_FILE_SIZE : impose le poids d'un fichier
  • Form::MIME_TYPE : vérifie si le type MIME est valide
  • Form::IMAGE : impose un fichier au format .gif, .png ou .jpg
  • Form::FILLED : vérifie si le champ est rempli
  • Form::EQUAL : vérifie que la valeur est égale à celle prescrite
  • Form::NOT_EQUAL : vérifie que la valeur est différente de celle prescrite
  • Form::IS_IN : vérifie si la valeur fait partie d'un tableau
  • Form::VALID : vérifie si le champ est acceptable pour la validation

Sources

lundi, 23 novembre 2015

Nette framework : présentation et installation

nette.pngNette est un framework MVP* qui a le vent en poupe en République tchèque (d’où il vient) et en Slovaquie. Il existe depuis 2009 et Sitepoint le place dans le trio de tête des frameworks PHP en 2015, malgré quelques carences au niveau des performances, comme pour Zend et Laravel :

 

sp-compare.gif

Bien que la Belgique et la France ignorent pour le moment ce framework, je l’ai testé pour comparer son fonctionnement à ceux de Laravel, CodeIgniter et CakePHP.

Nette comporte pléthore de qualités : parmi elles, sa prise en main d’une simplicité déconcertante, sa sécurité manifeste, ses outils de débogage (Tracy), sa documentation complète et accessible (qui commence au b.a.-ba, contrairement à certaines…) et sa communauté anglophone plutôt dynamique.

A l’inverse de certains frameworks, il fonctionne selon une architecture Modèle-Vue-Présentation, version évoluée de l’architecture Modèle-Vue-Contrôleur.

mvp.png

Le MVP garde le même principe que le MVC mais élimine l’interaction entre la vue et le modèle. Le relais est assuré par la présentation qui organise les données à afficher dans la vue. Plus d’informations.

Dans cet article et ceux qui suivront, vous trouverez des mémos d’utilisation du framework, comme je l’ai fait en son temps pour CakePHP.


Installer Nette Framework

  • Installer Composercomposer.png
  • Installer Nette : depuis l’invite de commandes, accéder au dossier www/htdocs de votre wamp/xampp et exécuter la commande suivante :
    composer create-project nette/sandbox [app_name]
  • Mettre à jour Nette : la dernière version stable du framework sera installée en exécutant à partir du dossier générique de l’appli la commande suivante :
    composer update
  • Installer les composants nécessaires au bon fonctionnement du framework :
    composer require latte/latte
  • Établir la connexion à la base de données en INNODB : adapter les paramètres sous app > config > config(.local)*.neon (* Si vous testez l'appli en local ou en production). Attention à l'indentation au sein du fichier .neon !

Prérequis

⚠ Mémo :

nette-structure.png

  • Il y a autant de vues qu’il y a d’actions/méthodes dans le presenter.
  • Il y a autant de dossiers de vue (sous Templates) qu’il y a de presenters.

Standards de programmation

  • L'indentation est importante : elle se fait par tabulations et non par espaces.
  • Les lignes de codes sont limitées à 120 caractères (idéalement, 80 ou moins).
  • Les constantes TRUE, FALSE, NULL sont toujours en capitales.
  • Nette recommande l'utilisation de l'UTF-8 et de l'ASCII en guise d'encodage de caractères.
  • L'utilisation de <?php est la seule manière valable d'amorcer du code en php (oubliez les '<?= ?>').
  • La fermeture ?> doit être omise dans les fichiers qui contiennent du PHP exclusivement.
  • Limitez-vous à une déclaration par ligne.
  • Aucune espace ne doit traîner à la fin des lignes de code.
  • Les noms de fichiers et noms de classes doivent être identiques.
  • La déclaration de variables, fonctions ou constantes globales est fortement déconseillée.
  • @, l'opérateur de contrôle d'erreur (ou de mise en veilleuse) doit être commenté comme suit :
@mkdir($dir); // @ - directory may exist

Conventions de nommage

  • Les classes doivent être déclarées en UpperCamelCase.
  • Les propriétés et méthodes doivent être déclarées en lowerCamelCase.
  • Les opérateurs de comparaison forts (===/!==) sont préférés aux autres (==/!=).
  • Les structures conditionnelles utilisent elseif et non else if.
  • Se limiter à des caractères alphanumériques dans le choix des noms.
  • Les variables doivent être explicites : $i, $n ne sont admises que pour faire office de compteur dans les boucles.
  • La concaténation demande un espace avant et après le "."
  • Les tableaux doivent être déclarés avec la déclaration entre [], avec des espaces après chaque virgule pour augmenter la lisibilité du code : [$un, $deux, $trois]
  • Le nom des interfaces commence toujours par un "I". Exemple : IPresenter.
  • Les mots-clés "extends" et "implements" doivent être déclarés sur la même ligne que le nom de la classe.

Sources

vendredi, 17 juillet 2015

CakePHP 3 : manipuler les vues et helpers

Les vues portent l'extension .ctp.

Agréger des contenus


$this->start('sidebar');
echo $this->fetch('sidebar'); // affiche le bloc
echo $this->element('sidebar/popular_topics');
$this->end();

Échapper du texte


echo h($user->bio);

Helpers

Form

Créer des formulaires


// si () ∅, controller route courante / envoi en POST
echo $this->Form->create();

// sinon :
echo $this->Form->create(null, ['url' => [
    'controller' => 'Articles',
	'action' => 'publish'],
	'type' => 'GET'...);

echo $this->Form->input('nom_champ_db', array(
'label'=>'...',
'type'=>'...',
'placeholder'=>'...',
'required'=>TRUE
));
// le format du champ s'adapte en fonction du type défini
// dans la DB (ex : id=hidden, longtext=textarea).
// Pour modifier, changer le type (SAUF inputs radio)

// ou (nomenclature spécifique selon le type)
echo $this->Form->text('nom_champ_db', ['options'=>'...']);
echo $this->Form->password('password');
echo $this->Form->hidden('id');
echo $this->Form->textarea('blabla', 'escape'=>FALSE);
echo $this->Form->checkbox('Oui', ['value'=> 555]);
echo $this->Form->radio(
    'favorite_color',
    [
        ['value'=>'r','text'=>'Red','style'=>'color:red;'],
        ['value'=>'u','text'=>'Blue','class'=>'blue'],
        ['value'=> 'g','text'=>'Green','id'=>'green'],
    ]
);
echo $this->Form->select('nom_champ_db',$array_options,['multiple'=>'checkbox']); // multiple facultatif
echo $this->Form->dateTime/time/year/month/day/hour/minute('nom_champ_db'); // * selon les besoins
echo $this->Form->label('nom_champ_db','Label souhaité');

// les fichiers nécessitent l'ajout d'option dans le create
echo->this->Form->create($document, ['enctype'=>'multipart/form-data']);
echo $this->Form->file('file');

echo $this->Form->submit();
echo $this->Form->end('Valeur du submit');

HTML

Créer des liens


$this->Html->charset('format');
$this->Html->css('style'); // recherche dans webroot/css
$this->Html->css(['forms', 'tables', 'menu']); // styles multiples
$this->Html->script('scripts'); // recherche dans webroot/js
$this->Html->image('cake_logo.png', ['alt' => 'CakePHP']); // recherche dans webroot/img
$this->Html->link('Valeur', '/pages/home', ['class' => 'button', 'target' => '_blank']);
$this->Html->link('Effacer', [
'controller' => 'Articles',
'action' => 'delete', 6],
['confirm' => 'Êtes-vous sûr d\'effacer ?']
);
$this->Html->media('audio.mp3');

Sources

jeudi, 16 juillet 2015

CakePHP 3 : manipuler les modèles

Initialize

Elle permet de déclarer l'ensemble de la configuration du modèle et des associations avec les autres modèles.

public function initialize(array $config) {
 $this->belongsTo('Articles');
 $this->belongsToMany('Tags');
}

TableRegistry

Cette fonction permet de récupérer la configuration des connexions et métadonnées liées aux tables. Elle rend les données accessibles en objets.

// controller
use Cake\ORM\TableRegistry;

$articles = TableRegistry::get('Articles');

$query = $articles->find();

foreach ($query as $row) {
    echo $row->title;
}

Requête avec fonction


// model / table
public function findDuree(Query $query) {
 $query->select(['avg_duree_appel'=>$query->func()->avg('duree_appel')]);
 return $query;
}

// controller
$avg = $appel->find('Duree')->toArray();

Jointure

// model / table
use Cake\ORM\Query;

public function findGetUser(Query $query) {
 $query->select(['Utilisateurs.nom'])->contain('Utilisateurs');
 return $query;
}

// controller
$users = $appel->find('GetUser');
// isoler le find de la méthode provenant du modèle

Sources

mercredi, 15 juillet 2015

CakePHP 3 : manipuler les contrôleurs

Appeler une vue depuis le contrôleur


class PostsController extends AppController {
    public function my_action() {
        $this->render('custom_file'); }
		// Affiche src/Template/Posts/custom_file.ctp
		// au lieu de src/Template/Posts/my_action.ctp
}

Transmettre des données du contrôleur à la vue


$this->set('framework', 'cakephp'); // controller
echo "Vous utilisez $framework;" // view

// controller
$data = array(
'livre' => 'Léviathan',
'auteur' => 'Paul Auster',
'type' => 'roman');
$this->set($data);

// view
echo $livre.' / '.$auteur.' - '.$type;

Redirections


return $this->redirect('http://www.unsite.eu'); // absolute
return $this->redirect('/controller/function'); // relative
$this->setAction('index'); // same controller, other action

Requêtes


$articles = $this->Articles->find('all');
$artcond = $this->Articles
->find()
->where(array('Articles.validated' => 1))
->order(array('Articles.created' => 'DESC'));
$artcondlimit = $artcond->limit(10);

Requêtes - Réponses

La requête permet d'accéder aux différentes informations liées à la requête.


$this->request

La réponse permet à l'application de construire la réponse qui doit être retournée au client (header, download, etc.)


$this->response

Afficher un menu déroulant avec les entrées d'une DB


// model > créer AgesTable.php avec le contenu suivant :
namespace App\Model\Table;
use Cake\ORM\Table;
class AgesTable extends Table {
    // code...
}

// CONTROLLER
$this->loadModel('Ages');
$ages = $this->Ages->find('list',[
	'keyField' => 'age_id',
    'valueField' => 'age_title']);
$data = $ages->toArray();
$this->set(compact('ages',$data));
// devient $ages dans la vue

// VIEW
echo $this->Form->input('age_id',['options'=>$ages]);

Sources

- page 1 de 2