Merci pour ce cours qui est très clair et didactique.
Par contre concernant la dernière activité sur les liens les mots de passe ne marchent plus, impossible de se connecter.
Serait il possible de modifier le fichier content.sql sur le dépôt github qui sert de référence (et que l'on ne doit pas modifier en théorie) avec des mots de passe dont le hachage est valide par défaut (ils utilisent l'ancien algo actuellement).
Ou alors, ça fait partie de l'activité de prendre en compte le changement d'algo de hachage ?
Merci d'avance
NB: pendant que j'y suis, je bloque sur un pb d'affichage sur la dernière activité ( il ne me reste plus que ça et ça me rend dingue ! ): Comment restreindre la largeur de la cellule title dans l'onglet link situé sur la page admin ?
J'ai le même code html et le même css , et pourtant ...
EDIT : Pour la connexion, la solution est de changer l'encodage par défaut.
Je me suis attaqué à l'activité 1 du cours "Architecture PHP professionnelle" et j'ai une petite question toute bête.
je bug sur ce point là :
Documentation de toutes les méthodes sous forme de commentaires au format phpDoc, comme dans le cours.
"La doc comme dans le cours" c'est à dire ? Les commentaires qui sont présent dans les classes ? Bref en gros si vous pouvez m'éclairer sur le meilleur moyen pour mettre en place ma doc je vous en serai infiniment reconnaissant.
Merci beaucoup !!
Les hommes construisent trop de murs et pas assez de ponts - Isaac Newton -
C'est comme si twig n'était pas enregistré comme service ... Hors il est enregistré dans app.php qui lui même est inclus dans ... Zut, t'aurais pas oublié d'inclure app.php dans index.php ??
Merci pour ce cours qui est très clair et didactique.
Par contre concernant la dernière activité sur les liens les mots de passe ne marchent plus, impossible de se connecter.
Serait il possible de modifier le fichier content.sql sur le dépôt github qui sert de référence (et que l'on ne doit pas modifier en théorie) avec des mots de passe dont le hachage est valide par défaut (ils utilisent l'ancien algo actuellement).
Ou alors, ça fait partie de l'activité de prendre en compte le changement d'algo de hachage ?
Merci d'avance
NB: pendant que j'y suis, je bloque sur un pb d'affichage sur la dernière activité ( il ne me reste plus que ça et ça me rend dingue ! ): Comment restreindre la largeur de la cellule title dans l'onglet link situé sur la page admin ?
J'ai le même code html et le même css , et pourtant ...
- Edité par πro 31 mai 2017 à 11:05:09
Bonjour,
J'ai exactement le même problème, j'ai modifié l'encodage car celui par défaut ne convient pas.
Ajouter au fichier app.php le code suivant :
$app['security.default_encoder'] = function ($app) {
return $app['security.encoder.digest'];
};
Là je retrouve un mot de passe identique à celui dans la BDD et j'arrive à m'authentifier.
Par contre je ne sais pas pourquoi j'ai toujours un message d'erreur, la variable "app.user.username" dans le fichier layout.html.twig est nulle.
Du coup j'ai fait un test avec un utilisateur directement enregistré dans le fichier app.php en laissant l'encodeur par défaut (user = admin, pass = foo) :
Je ne vois pas où est le souci dans mon code, quand je passe par un utilisateur de la base de données il est bien authentifié mais la variable app.user.username est nulle et me renvoie une erreur, alors qu'en passant par un utilisateur enregistré directement dans le fichier ça marche !
Merci Baptiste pour ce cours/tutoriel très bien ficelé sur silex/php/bootstrap !!
Je développe actuellement un site associatif de type catalogue (et j'étais initialement parti sur du XML/XSLT et je voulais faire du REST pour alimenter ma base... bref). Je pense tout faire dans cette architecture MVC avec Silex désormais.
Cependant, j'ai besoin d'avoir la fonctionnalité de traduction activée selon la locale de l'utilisateur.
J'utilise donc le projet du cours pour m'entrainer et faire mes tests, mais j'achoppe toujours sur une problématique...
Admettons que je veuille les routes suivantes :
/ => redirection sur la locale de l'usr /{_locale}/
/{_locale}/ (qui fait le binding avec 'Home')
/{_locale}/articles
/{_locale}/login
...
J'ai donc préfixé mes routes par "/{_locale}" puis j'ai rajouté les paramètres 'locale' et 'locale_fallbacks' au service de traduction ainsi qu'un loader de XLIFF et les chemins des fichiers de traduction.
Jusque-là j'ai bien le comportement attendu, tant en redirection qu'en traduction...
Maintenant, cela se complique avec le SecurityServiceProvider : les tests d'authentification non passants sont KO car je n'obtiens pas le message d'erreur et mon url devient de la forme suivante "www.site.com/login/login"
J'ai cependant rajouté à la configuration du service les paramètres suivants :
(Je prendrai la locale de la session dans une itération future pour que l'utilisateur puisse choisir sa lange de préférence :
$app['session']->get('locale')
)
Du coup, selon vous qu'est-ce que je devrais encore modifier pour que cela fonctionne, car là je sèche sur la doc.
Pour info, je me pose toujours les questions suivantes que je n'ai pas encore pu tester faute de temps :
-modifier la variable 'pattern' de security.firewall pour rajouter la locale. -charger l'ordre de chargement des fournisseurs de service LocaleServiceProvider et TranslationServiceProvider pour les mettre avant SecurityServiceProvider (après celui de la session)
Et par hasard, quelqu'un a-t'il donc déjà fait fonctionner la localization (i18n) sur le projet du cours ???...
Je travaille sur une appli avec Silex, Twig et Bootstrap, mais je peine un peu avec Twig. Voici mon problème: Je souhaite afficher les catégories ainsi que éditeurs (voir code) dans la partie gauche et des ouvrage dans la partie droite. Seul problème pour l'instant, le catégories et éditeurs s'affichent en boucle, je veux qu'ils s'affichent une fois uniquement. Le grand problème que j'ai, j'imagine c'est au niveau de variable. Voici le code:
<section class="row col-md-12">
<h2>Page title here</h2>
<aside class="col-md-3">
<div id="category_title">Catégorie</div>
{% for book in books %}
<ul id="category_item">
<li>{{ book.category }}</li>
</ul>
{% endfor %}
<div id="book_editor">Editeur</div>
{% for book in books %}
<ul id="editor_item">
<li>{{ book.editor }}</li>
</ul>
{% endfor %}
</aside>
<div id="list_books" class="col-md-9">
{% for book in books %}
<div class="col-md-3" id="book_item">
<h3>{{ book.title }}</h3>
<small>{{ book.author }}, {{ book.editor }}</small>
<article>{{ book.description }}</article>
</div>
{% endfor %}
</div>
</section>
[2017-06-11 11:15:47] WebLinks.CRITICAL: Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException: Neither the property "website" nor one of the methods "getWebsite()", "website()", "isWebsite()", "hasWebsite()", "__get()" exist and have public access in class "WebLinks\Domain\Link". (uncaught exception) at C:\wamp64\www\WebLinks\vendor\symfony\property-access\PropertyAccessor.php line 505 {"exception":"[object] (Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException(code: 0): Neither the property \"website\" nor one of the methods \"getWebsite()\", \"website()\", \"isWebsite()\", \"hasWebsite()\", \"__get()\" exist and have public access in class \"WebLinks\\Domain\\Link\". at C:\\wamp64\\www\\WebLinks\\vendor\\symfony\\property-access\\PropertyAccessor.php:505)"} []
@Walid El harrouchi : Tu es bien sûr que tu ajoutes bien ta route? Sans avoir beaucoup plus d'infos sur ton contexte, c'est bien difficile d'aider. Prnt Scr nous aiderait.
Bam92 c'est plus un petit problème commun d’algorithmique qu'un problème spécifique à twig.
En premier jet, je ferais un truc du genre :
{% set categoryArray = [] %}
{% for book in books %}
{% if book not in categoryArray %}
<ul id="category_item">
<li>{{ book.category }}</li>
</ul>
{% set categoryArray[] = book.category %}
{% endif %}
{% endfor %}
Je n'ai pas vérifié si ça marche, mais adapte au cas où ... l'idée est là !
NB : Oups j'ai corrigé une grosse typo sur le nom de la variable qui remplit le tableau.
suis null en francais pardon mais essayer de me comprendre aujourd'hui j'ai vu une poste dans ce site que demande l'aide pour cree un calculatrice donc il m'a donner un idee alors j'essayer de construire un sans regarder le script que l"a demande l'aide our le fixé mon calculatrice fonction tous bien mais comme vous etes des pros and je suis null ouvey vous e donner quelque conseille a mon script je debut de lire PHP 2 semains and now im so happy to do what i did
here its the script please if there is any faults or any advice contact so that i can fix it and learn from it and ty in advance
Essaye d'utiliser la boucle switch c'est facile à utiliser et c'est très pratique dans ce genre de situation. Je te laisse un exemple très simple juste pour te faire une idée de son utilisation.
@πro: J'ai essayé ce que vous m'avez suggéré et j'ai ce message d'erreur:
(1/1) Twig_Error_Syntax
Unexpected token "punctuation" of value "[" ("end of statement block" expected).
in books.html.twig (line 109)
Voici ce que j'ai fais plutôt:
{% set bookCat = null %}
{% for book in books %}
{% set bookCat = book.category %}
<p>{{ bookCat }}</p>
{% endfor %}
<p>{{ bookCat }}</p>
Ca donne le résultat mais pas comme je veux. Il y a toujours des répetitions. Je veux plutot que je puisse récuper une et une seule fois une catégorie donnée (bien qu'il peut y en voir plusieurs).
pouvez-vous m'aider a mon page je fais une site web formulaire mais je reconnectre un probleme c'est quand quand je veux afficher l'annee de naissance le programme n'affiche rien(le date de naissance i mean) que je click on (submit) mais le nom et prenom s'affiche voici le code ;;;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bonjour</title>
</head>
<body>
Bonjour votre nom est: <?php
echo $_POST['nom'];
?> et votre prenom est
<?php echo $_POST['prénom'];
?>
tu es né le <?php
if(isset($_POST['$year']))
{
echo $_POST['$year'];
}
?>
</body>
</html>
@bam92 après renseignement on ne peut pas utiliser les tableaux comme ça ... fait plutôt :
{% set categoryArray = [] %}
{% for book in books %}
{% if book.category not in categoryArray %}
<ul id="category_item">
<li>{{ book.category }}</li>
</ul>
{% set categoryArray = categoryArray|merge([book.category]) %}
{% endif %}
{% endfor %}
Mais je pense plutôt que ce genre de choses n'a strictement rien à faire dans une vue et que tu devrais lui passer un tableau déjà épuré, ça serait plus propre.
Je crois c'est un bon conseil. Un tableau depuis le controleur j'imagine. Bien évidemment le tableau books vient du controlleur.
Dans le soucis d'aller plus loin je souhaite afficher () le nbre de livre par catégorie. P.ex Droit (8). Tout ce que j'ai tenté me donne plutôt le nombre de caractère (avec le filtre lenht) comme ceci: Droit (5) parce qu'il y a 5 lettres.
Ce que je crains ce faire trop de requête en bdd (performance).
Je te donne un peu le contexte de ce que je fais:
Le controleur front ne pose pas de problème. Idem pour la route.
Voici le modèle
Mon POPO (book.php)
<?php
namespace Yekola\Domaine;
class Book
{
/**
* Book id.
*
* @var integer
*/
private $id;
/**
* Book title.
*
* @var string
*/
private $title;
/**
* Book author.
*
* @var string
*/
private $author;
/**
* Book category.
*
* @var string
*/
private $category;
/**
* Book editor.
*
* @var string
*/
private $editor;
/**
* Book description.
*
* @var string
*/
private $description;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
return $this;
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function getAuthor() {
return $this->author;
}
public function setAuthor($author) {
$this->author = $author;
return $this;
}
public function getCategory() {
return $this->category;
}
public function setCategory($category) {
$this->category = $category;
return $this;
}
public function getEditor() {
return $this->editor;
}
public function setEditor($editor) {
$this->editor = $editor;
return $this;
}
public function getDescription() {
return $this->description;
}
public function setDescription($description) {
$this->description = $description;
return $this;
}
}
DAO
<?php
namespace Yekola\DAO;
use Doctrine\DBAL\Connection;
use Yekola\Domaine\Book;
class BookDAO extends DAO
{
/**
* Return a list of all books, sorted by book_title asc.
*
* @return array A list of all articles.
*/
public function findAll() {
$sql = "select * from book order by book_title asc";
$result = $this->getDb()->fetchAll($sql);
// Convert query result to an array of domain objects
$books = array();
foreach ($result as $row) {
$bookId = $row['book_id'];
$books[$bookId] = $this->buildDomainObject($row);
}
return $books;
}
public function findCategories() {
$sql = "select book_id, book_category from book order by book_category asc";
$result = $this->getDb()->fetchAll($sql);
// Convert query result to an array of domain objects
$categories = array();
foreach ($result as $row) {
$bookId = $row['book_id'];
$categories[$bookId] = $this->buildDomainObject($row);
}
return $categories;
}
/**
* Creates Book object based on a DB row.
*
* @param array $row The DB row containing Article data.
* @return \Yekola\Domaine\Book
*/
protected function buildDomainObject(array $row) {
$book = new Book();
$book->setId($row['book_id']);
$book->setTitle($row['book_title']);
$book->setAuthor($row['book_author']);
$book->setCategory($row['book_category']);
$book->setEditor($row['book_editor']);
$book->setDescription($row['book_description']);
return $book;
}
}
Controleur
<?php
namespace Yekola\Controller;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Yekola\Domaine\Book;
class BookController {
public function bookAction (Application $app) {
$books = $app['dao.book']->findAll();
return $app['twig']->render('books.html.twig', array('books' => $books));
}
}
Enfin la vue
{% extends "layout.html.twig" %}
{% block content %}
<div class="jumbotron">
<div class="container">
<h1>Page title here</h1>
<p>Sub title here</p>
<div class="pull-right"><button class="btn-primary">Ajouter un livre</button></div>
<div class="form-group">
<input type="search" class="input-sm form-control" placeholder="Que voulez-vous lire aujourd'hui?">
<button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-eye-open"></span>Chercher</button>
</div>
</div>
</div>
<nav class="row col-md-12 region region-navigation">
<ul>
<li class="region-books col-md-6">Bibliothèque</li>
<li class="region-quiz col-md-6">Quiz & exercices</li>
</ul>
</nav>
<section class="col-md-12 recent" id="recent-books">
<h1>Ouvrages récement ajoutés</h1>
<p>Recently added books will be here, limit 4</p>
<p class="">
<img src="{{ asset('/images/ebook.jpg') }}" alt="test" class="book-item-img"/>
{#<div class="book-info row">
<h3>Title</h3>
<p>Editor</p>
<p>Author</p>
</div>#}
</p>
<p class="book-item-box"><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
<p class=""><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
<p class=""><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
</section>
<section class="col-md-12 popular" id="last-books-read">
<h1>Ouvrages les plus populaires</h1>
<p>Most read books here, limit 4</p>
<p class="col-md-3">
<img src="{{ asset('/images/ebook.jpg') }}" alt="test" />
{#<div class="book-info row">
<h3>Title</h3>
<p>Editor</p>
<p>Author</p>
</div>#}
</p>
<p class="col-md-3"><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
<p class="col-md-3"><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
<p class="col-md-3"><img src="{{ asset('/images/ebook.jpg') }}" alt="test" /></p>
</section>
<section class="col-md-12 recent" id="recent-quiz">
<h1>Meilleurs scores de quiz</h1>
<p>Last quizes scores, limit 4</p>
</section>
<section class="row col-md-12">
<aside class="col-md-3">
<div id="category_title">Catégorie:</div>
{% set categoryArray = [] %}
{% for book in books %}
{% if book.category not in categoryArray %}
<ul id="category_item">
<li>{{ book.category }} ({{ loop.index0 }})</li>
</ul>
{% set categoryArray = categoryArray|merge([book.category]) %}
{% endif %}
{% endfor %}
<div id="book_editor">Editeur</div>
{% set editorArray = [] %}
{% for book in books %}
{% if book.editor not in editorArray %}
<ul id="category_item">
<li>{{ book.editor }}</li>
</ul>
{% set editorArray = editorArray|merge([book.editor]) %}
{% endif %}
{% endfor %}
</aside>
<div id="list_books" class="col-md-9">
{% for book in books %}
<div class="col-md-3" id="book_item">
<h3>{{ book.title }}</h3>
<small>{{ book.author }}, {{ book.editor }}</small>
<article>{{ book.description }}</article>
</div>
{% endfor %}
</div>
</section>
<section class="row">
<h1>This a test and will be deleted after success</h1>
{% set categoryArray = [] %}
{% for book in books %}
{% if book.category not in categoryArray %}
<ul id="category_item">
<li>{{ book.category }}</li>
</ul>
{% set categoryArray = categoryArray|merge([book.category]) %}
{% endif %}
{% endfor %}
<h2>Test again</h2>
{% for book in books %}
<ul id="category_item">
<li>{{ book.category }}</li>
</ul>
{% endfor %}
</section>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('/css/book.css') }}" rel="stylesheet">
{% endblock %}
Je suis un peu dépassé, après avoir fini ce cours, je souhaite créer un petit site exactement sur le même principe : silex, Bootstrap, twig, etc. le problème est que lorsque je crée mon formulaire qui invite le visiteur à s'exprimer , je ne comprend pas comment insérer des smiley... Ainsi que la possibilité de mettre en gras, en italique... Mais comment insérer cela dans un formulaire tel que celui-ci :
petite question j’obtiens cette erreur lorsque je veux rajouter un link. Je ne comprend pas l'erreur car j'ai bien ajouter le user_id avez vous une idée :
C:\wamp64\www\WebLinks\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\AbstractMySQLDriver.php line 112 {"exception":"[object] (Doctrine\\DBAL\\Exception\\NotNullConstraintViolationException(code: 0): An exception occurred while executing 'INSERT INTO t_link (link_title, link_url, user_id) VALUES (?, ?, ?)' with params [\"Grantham\", \"https:\\/\\/fr.wikipedia.org\\/wiki\\/Grantham\", null]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'user_id' ne peut être vide (null) at C:\\wamp64\\www\\WebLinks\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\AbstractMySQLDriver.php:112, Doctrine\\DBAL\\Driver\\PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'user_id' ne peut être vide (null) at C:\\wamp64\\www\\WebLinks\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\PDOStatement.php:93, PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'user_id' ne peut être vide (null) at C:\\wamp64\\www\\WebLinks\\vendor\\doctrine\\dbal\\lib\\Doctrine\\DBAL\\Driver\\PDOStatement.php:91)"} []
et voici mon code :
<?php
namespace WebLinks\DAO;
use WebLinks\Domain\Link;
class LinkDAO extends DAO
{
/**
* Returns a list of all links, sorted by id.
*
* @return array A list of all links.
*/
public function findAll() {
$sql = "select * from t_link order by link_id desc";
$result = $this->getDb()->fetchAll($sql);
// Convert query result to an array of domain objects
$entities = array();
foreach ($result as $row) {
$entitieId = $row['link_id'];
$entities[$entitieId] = $this->buildDomainObject($row);
}
return $entities;
}
/**
* Creates an Link object based on a DB row.
*
* @param array $row The DB row containing Link data.
* @return \WebLinks\Domain\Link
*/
protected function buildDomainObject(array $row) {
$link = new Link();
$link->setId($row['link_id']);
$link->setUrl($row['link_title']);
$link->setTitle($row['link_url']);
$link->setUserId($row['user_id']);
return $link;
}
/**
* Returns an link matching the supplied id.
*
* @param integer $id
*
* @return \WebLinks\Domain\link|throws an exception if no matching link is found
*/
public function find($id) {
$sql = "select * from t_link where link_id=?";
$row = $this->getDb()->fetchAssoc($sql, array($id));
if ($row)
return $this->buildDomainObject($row);
else
throw new \Exception("No link matching id " . $id);
}
/**
* Saves an link into the database.
*
* @param \WebLinks\Domain\link $link The link to save
*/
public function save(Link $link) {
$linkData = array(
'link_title' => $link->getTitle(),
'link_url' => $link->getUrl(),
'user_id' => $link->getUserId(),
);
if ($link->getId()) {
// The link has already been saved : update it
$this->getDb()->update('t_link', $linkData, array('link_id' => $link->getId()));
} else {
// The link has never been saved : insert it
$this->getDb()->insert('t_link', $linkData);
// Get the id of the newly created link and set it on the entity.
$id = $this->getDb()->lastInsertId();
$link->setId($id);
}
}
/**
* Removes an link from the database.
*
* @param integer $id The link id.
*/
public function delete($id) {
// Delete the link
$this->getDb()->delete('t_link', array('link_id' => $id));
}
}
et le domain :
<?php
namespace WebLinks\Domain;
class Link
{
/**
* Link content.
*
* @var integer
*/
private $userId;
/**
* Link content.
*
* @var integer
*/
private $content;
/**
* Link id.
*
* @var integer
*/
private $id;
/**
* Link title.
*
* @var string
*/
private $title;
/**
* Link url.
*
* @var string
*/
private $url;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
return $this;
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function getUrl() {
return $this->url;
}
public function setUrl($url) {
$this->url = $url;
return $this;
}
public function getContent() {
return $this->content;
}
public function setContent($content) {
$this->content = $content;
return $this;
}
public function getUserId() {
return $this->userId;
}
public function setUserId($userId) {
$this->userId = $userId;
return $this;
}
}
@Walid El harrouchi le message d'erreur est pourtant clair :
an exception occurred while executing 'INSERT INTO t_link (link_title, link_url, user_id) VALUES (?, ?, ?)' ..... Le champ 'user_id' ne peut être vide (null)
Donc dans la partie de ton code qui enregistre un nouveau lien dans la BDD le champs user_id est vide.
A première vue tu n'as pas l'air de créer un nouvel utilisateur et donc l'id qui s'y réfère ...
D'ailleurs stocker juste le user_id dans ta classe Link n'est pas très pertinent ,regarde bien le cours !
Cours Architecture PHP professionnelle / Questions
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Déployez simplement votre site internet avec Dploy, Évoluez vers une architecture PHP professionnelle
Déployez simplement votre site internet avec Dploy, Évoluez vers une architecture PHP professionnelle