Créer un système « Crud » avec Php pour une application Angular.

IntroductionCRUD


 CRUD veut dire Créer-Lire-Mettre à Jour-Supprimer

Je vais écrire dans ce post tout ce que je peut trouver à propos d’un Crud Angular, et essayer de choisir le meilleur système.

Devant la jungle des solutions  trouvées sur le net pour élaborer un CRUD en Php, je crée donc un post. De plus, même les livres en Anglais que je possède n’ont pas décrit le fonctionnement d’un système concentré de CRUD en Bdd avec Angular.

Avec le puissance de nouvelles librairies MVC  Js comme Angular, on peut envisager de se servir des langages Php et Java uniquement pour gérer le Crud, qui par essence, devrait être réduit aux maximum, pour limiter les accès réseau.

Les questions sont:

  • Comment créer un CRUD Ajax qui serait le plus condensé et le plus simple possible ?
  • Comment, et quand utiliser le CRUD dans une application ANGULAR qui utilise le Binding de data à outrance… ( Le binding est la liaison bidirectionnelle automatisée des données du Modèle et de la Vue dans une application de type MVC(Modèle-Vue-Controlleur), qui simplifie énormément la manière de coder des applications en Javascript(Une révolution).
  • La concurrence est elle bien gérée et fiable par le système CRUD ?

Tour d’Horizon


Le CRUD (Create,Read,Update,Delete) ou autrement dit (Créer,Lire,Mettre à jour, Supprimer) peut en toute logique être mis en place avec :

Le Crud Angular affililé à Javascript :

  • Javascript ( On « Crud » directement dans le code de l’application, bien sur, les données ne sont pas sauvegardées lors d’une actualisation du navigateur) Exemple 
  • Web-Storage : Une nouvelle fonctionnalité HTML 5.0 qui permet de stocker des objets JSON dans la mémoire du  navigateur,selon la doc, c’est conservé jusqu’à une réinstall du navigateur, ou à un nettoyage(A vérifier) . De toute manière, c’est mieux que les « cookies » et super facile à utiliser.
  • MongoDb : On stocke directement des objets Json dans une base d’objets Json, du coup, ces objets sont sauvegardés, et on les retrouve. A voir si Node.js est nécessaire pour faire cela, mais je ne pense pas, d’après mes premiers tests.Le framework :http://mean.io/#!/ et une appli CRUD super bien ici :https://github.com/drumaddict/angular-music-db
  • Meteor : Au début j’étais emballé, puis quand j’ai vu que c’était un bloc compact, j’ai laissé tomber.

Le Crud Angular affilié aux BDD relationnelles :

  • On peut élaborer un CRUD avec PHP, PHP enregistre alors les objets Json dans une Bdd relationelle avec une requête SQL. C’est ce qui me parait le plus sympa et facile.
  • On peut élaborer un Crud avec Java , qui enregistre alors les objets Json dans une Bdd relationelle avec une Requête SQL. Les exemples que j’ai vu étaient effroyables de complexité… Faut pas exagérer, il ne s’agit là que d’enregistrer ou d’updater des données dans une BDD…

Les Cruds des autres langages :

  • Java possède JDBC pour la bdd relationnelle et Hibernate qui permet de stocker des objets Java en mode transparent( Du moins c’est ce qu’ils essayent de faire, si j’ai bien compris, et c’est génial, car le dév n’a en théorie plus besoin de se soucier des requêtes SQL ! Mais c’est hautement spécialisé…)
  • Des Frameworks Php  comme Symphony, Zend semblent avoir été créés pour faciliter l’accès aux BDD relationelles, mais dans le cadre d’une single page Application, aux premiers abords, cela ne peut pas servir..( Et puis, je n’aime pas trop, car Angular est déjà un framework, et je ne veux pas pour l’instant faire de ça, tant qu’à faire, je préfère JAVA, car c’est un langage qui peut être embarqué.)

Ce que je faisais jusqu’à présent, avec JQUERY :


Jusqu’à présent, pour faire du CRUD Ajax je faisais ceci avec Jquery:

J’avais une classe AJAX qui regroupe des méthodes Jquery Ajax destinées à transférer les objets JSon et/ou les variables Javascript à un fichier PHP. Ce fichier PHP contient une requête SQL CRUD qui écrit en base de donnée.

Le pb est que je n’avais pas minimisé ce système comme étant un réel système CRUD comme on peut le voir sur internet. Je créais les méthodes AJAX lors de chaque nouvel ajout de fonctionnalité dans l’application. De ce fait, il pouvait y avoir 2 méthodes jquery Ajax de lecture ou 4 méthodes jquery Ajax d’enregistrement… ça fonctionne, certes, mais c’est lourd de devoir ré-écrire à chaque fois tout le fichier PHP, toute la méthode AJAX…

Exemple d’une requête d’enregistrement (R comme record dans le CRUD): 

1. La méthode Jquery Ajax va enregistrer un formulaire avec la méthode serialize()(très pratique, lol!) et des variables … Elle transmet tout cela au fichier PHP enregistrementEtudiant.php… Une méthode de ce type est très facile à comprendre, générique, et reconnaissable par les autres devs… Sa fonction de rappel success() est trèès pratique, et s’exécute une fois que le fichier PHP a fini son exécution, c’est dans cette fonction qu’on récupère les variables provenant du fichier PHP, qui a encodé en JSON le résultat de la requête SQL(Dans le cas d’une requête lecture, mais pas dans ce cas-ci).

function enregistrementAjaxEtudiant(nomPhoto){
	document.getElementById("charge").style.visibility="visible";
	
           var totalFormulaire	= $("#retudiant").serialize()+'&'+$.param({'nomPhoto':nomPhoto}); // Récupère les données du formulaire de création Etudiant et le nom de la photo. 
	
	$.ajax({
		type: "GET",
		url: "enregistrementEtudiant.php", 
		data: totalFormulaire,
		success: function (data) {
			$("#infos").empty();
			$("#infos").append('Le nouvel Etudiant a ete enregistre');
			document.getElementById("charge").style.visibility="Hidden";
		}	
	})
;}

2. Le fichier PHP contient la requête SQL CRUD qui va donc écrire tout cela dans la base de données … ça marche très bien ! Le fichier PHP est extrêmement simple. (Il n’utilise pas PDO..)

<?php

include('connexionSql.php');
connexionSql();

// Transmission des var qui arrivent en mode get en variables classique PHP

$prenom			= $_GET['prenom'];
$nom			= $_GET['nom'];
$age			= $_GET['age'];
$adresse		= $_GET['adresse'];
$ville			= $_GET['ville'];
$cp				= $_GET['cp'];

$datenaissance	= $_GET['datenaissance'];
$paiement		= $_GET['paiement'];
$dateentree		=$_GET['dateentree'];
$datesortie		=$_GET['datesortie'];
$pays			=$_GET['pays']; 
$email			=$_GET['email'];
$phone			=$_GET['phone']; 

$nomPhoto		=$_GET['nomPhoto'];
 
$insertSitesql="INSERT INTO etudiant VALUES('','$nom','$prenom','$age','$datenaissance','$adresse','$dateentree','$datesortie','$paiement','$pays','$nomPhoto','$phone','','$email','','$ville','$cp');";
mysql_query($insertSitesql) or die(mysql_error());

Mes problèmes sont :

  • PEUT ON SIMPLIFIER CE SYSTEME CRUD ET LE COMPRESSER POUR CREER UNE FACTORY ANGULAR QUI S’OCCUPERA UNIQUEMENT DU CRUD ?
  • Ne serait-il pas plus judicieux de sauvegarder uniquement de très gros objets JSON de temps à autres, plutôt que de sans cesse faire des requêtes ajax uniques ? (!! Très IMPORTANT!!)

Les liens du WEB concernant un CRUD Angular avec PHP:


1. Un premier exemple d’enregistrement CRUD que j’ai trouvé, qui s’apparente à ma méthode avec Jquery, mais avec Http de Angular:

http://devzone.co.in/angularjs-simple-example-post-data-php-page/

On peut remarquer que l’objet Json est déconstruit avec json_decode() de Php dans son script PHP.

En voici un autre, simple : http://www.keyboardninja.eu/webdevelopment/a-simple-search-with-angularjs-and-php

Mais ce n’est pas vraiment ce que je recherche puisque ce n’est pas organisé comme un service autonome CRUD.

2. Il existe un framework Php nommé SLIM, mais qui n’a pas l’air très simple d’utilisation :

http://www.sitepoint.com/writing-a-restful-web-service-with-slim/

3. Voici un Crud que j’ai bien compris, qui est donc facile à comprendre : C’est un peu ce que je faisais avec Jquery, sauf que c’est avec Angular, et surtout, on décide quelle fonction Php (CRUD) lancer à l’aide D’angular comme ceci :db.php?action=add_product, ce qui permet de créer un seul fichier PHP avec tout notre système Crud à l’intérieur(Donc facile à débuguer et à comprendre).Je pense que je vais utiliser ça… Mais il n’utilise pas de framework… :

http://tech-blog.maddyzone.com/javascript/perform-addeditdeleteview-php-using-angular-js

Je vais publier dans ce post un exemple de Crud, voir le numéro 3 traduit.

Un autre Crud angular-Php du même style, ou toute les requêtes sont dans un seul fichier(En espagnol) :

http://www.desarrollohidrocalido.com/angular-js-crud-slim-php/

4. Juste pour info, un Rest Java avec Angular qui m’a l’air plutôt simple et qui serait Restfull :

http://draptik.github.io/blog/2013/07/28/restful-crud-with-angularjs/

Java est trop cool, car c’est très utilisé en ENTP, et c’est portable, c’est pourquoi j’en fait déjà .

Reflection Importante à propos d’une de mes applications existantes


Lorsque l’on regarde la fenêtre des paramêtres de mon application monPetit Stock :

http://nicolash.org/angular/app6.html

On constate qu’il faut 3 boutons Créer/modifier/Supprimer pour chaque élèments à paramétrer… on est donc dans le cadre d’un CRUD, et donc d’un système à rendre générique.

Il faut donc trouver le moyen de créer du code javascript autogénéré, et des requêtes sql auto-générées, pour automatiser le fonctionnement CRUD de tous ces boutons, et que tout soit facile à comprendre, et surtout pas obscur ou compliqué, dans la mesure du possible.

Publicités

Créer un Service Angular AJAX.

Introduction :


Pour clarifier le code et le rendre plus performant, on regroupe les fonctionnalités génériques d’une application WEB Angular dans des services.

Les services sont des « portions de codes » à visée générique.

Du coup, ses services sont ré-utilisables d’une application à un autre, et on peut même récupérer les services d’un autre développeur.

Par exemple, on peut créer un service qui gère tous les appels AJAX(Crud), du coup notre code Angular est plus facile à comprendre par les autres développeurs.Autrement dit, ce service s’occupera de toutes les actions de type « Lecture, Enregistrement,Mise à jour, suppression » des données dans une application WEB Angular. C’est un peu le concept d’une classe UML.

Comment faire?


Lire cet explication bien claire en Anglais:

  • http://www.benlesh.com/2013/02/angularjs-creating-service-with-http.html

Donc, on crée d’abord le service(Enfin là, c’est une factory, qui retourne un objet) comme ceci :

app.factory('monService', function($http) {
   return {
     getEtudiants: function(callback) {
       $http.get('Etudiants.json').success(callback);
     }
   }
});

Le code précédent contient une fonction qui lit un fichier JSON, et récupère les données du fichier JSON dans la variable data, dans le callback.

puis on y fait référence dans notre controlleur comme cela :


app.controller('MainCtrl', function($scope, monService) {
  monService.getEtudiants(function(data) {
     $scope.Etudiants = data;
  });
});

Le code précédent est un controleur, dans ce controleur, j’appelle le service de lecture du fichier au format json grâce à l’instruction monService.getEtudiants. Le service nous retourne le fichier json dans la variable « DATA », on peut donc exploiter les données de ce fichier directement dans notre controleur.

Pour un fonctionnement plus global de CRUD(Create, read, update, delete) ou ( Créer, Lire,Mettre à jour,supprimer), voir ce lien http://www.bennadel.com/blog/2612-using-the-http-service-in-angularjs-to-make-ajax-requests.htm ou il a créé un service qui fait tout cela à la fois, avec des appels AJAX.

Micro Application 7 : EvalEntretien avec Angular, Bootstrap, RestPhp

Introduction evalentretien2


Aujourd’hui, Je vais créer une application Web single page d’évaluation d’entretien avec Angular, Bootstrap pour  Angular, et avec un Rest en Php en partant de zéro. Peut être un peu de Jquery en plus …

Je suis sur cette appli en même temps que sur « Mon petit Stock ». A tester sur http://nicolash.org/angular/app7.html

Today, I’m going to create a pro evaluation meeting single page App, with Angular, Bootstrap, and a simple php Rest. I’ll work on this project at the same time than « Mon Petit Stock ».

Explication du principe fonctionnel du Programme :

Un DRH arrive le matin à son bureau, il ouvre le logiciel, clique sur la date du jour, puis découvre ses entretiens de la journée. Le candidat à l’emploi entre dans le bureau et l’évaluateur des ressources humaines clique sur « évaluer ». A la fin, l’entretien est enregistré, et on peut l’éditer à loisir. A la fin du processus de recrutement, les meilleurs candidats apparaissent dans l’ordre, en fonction des notes que l’évaluateur RH leur a attribué et de calculs mathématiques . Du coup, l’évaluateur peut envoyer automatiquement par EMAIL la décision de l’entreprise au candidat audité.

A terme, le DRH pourra paramétrer les emplois à pourvoir ainsi que leurs pré-requis.

Lire la suite

Truc 2 : Autocomplétion Google avec Angular et ngAutoComplete.

Introduction :


Petite librairie ngAutoComplete permettant l’autocomplétion Google dans des champs input: A tester ici 

Idéal à intégrer dans un projet.

Autres liens :

https://developers.google.com/maps/documentation/javascript/places-autocompletehttps://developers.google.com/maps/documentation/javascript/places-autocomplete

Le Code




<html ng-app="Test">
<head>

    <meta charset="utf8" >
	<script	type="text/javascript" 	src="angular-1.3.13/angular.min.js"></script>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css"href="style.css">
    
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
    <script src="script.js"></script>
    <script src="librairies/ngAutocomplete.js"></script>
  
  
</head>

<body>

<div ng-controller="TestCtrl">

<form id="form" role="form">

    <div class="form-group move-down">
        <label for="Autocomplete">Autocompletion Générique</label>
        <input type="text" id="Autocomplete" class="form-control" ng-autocomplete ng-model="result1" />
    </div>
    <div>resultat: {{result1}}</div>


    <div class="form-group move-down">
        <label for="Autocomplete">Autocompletion - Villes de France ou département</label>
        <input type="text" id="Autocomplete" class="form-control" ng-autocomplete ng-model="result2" details="details2" options="options2"/>
    </div>
    <div>resultat: {{result2}}</div>
    
    <div class="form-group move-down">
        <label for="Autocomplete">Autocompletion - Entreprises de France</label>
        <input type="text" id="Autocomplete" class="form-control" ng-autocomplete ng-model="result3" details="details3" options="options3"/>
    </div> 
     <div>resultat: {{result3}}</div>
</form>
</div>


</body>
</html>

<script>
angular.module( "Test", ['ngAutocomplete'])
  .controller("TestCtrl",function ($scope) {

    $scope.result1 = 'Entrez une recherche';
    $scope.options1 = null;
    $scope.details1 = '';

$scope.modd

    $scope.result2 = '';
    $scope.options2 = {
      country: 'fr',
      types: 'geocode'
      
    };    $scope.details2 = '';
    
    
    
    $scope.result3 = '';
    $scope.options3 = {
      country: 'fr',
	  
      types: 'establishment'
    };
    $scope.details3 = '';
  });
</script>

Truc 1 : Simple Facture Dynamique Angular

Introduction :


Une simple facture dynamique que l’on peut transformer en pleins de choses.

 

Le Code :



<html ng-app="magasin">
	<head>
		<meta charset="iso-8859-15" >
		<!-- -----------------------------------------------DEBUT DU CHARGEMENT DES LIBRAIRIES------------------------ -->
		<!--	APPEL LIB ANGULAR -->
		<script	type="text/javascript" 	src="angular-1.3.13/angular.min.js"></script>
		<script src="angular-filter.min.js"></script>

		<!--	APPEL LIB JQUERY -->
		<script	type="text/javascript" 	src="librairies/jquery.js"></script>
		<!--	APPEL LIB JQUERY UI ( look sympa du programme) -->
		<script type="text/javascript" 	src="librairies/jquery-ui.min.js"				></script>
			<link 	href="librairies/jquery-ui.css" rel="stylesheet" type="text/css" 	/>
		<script type="text/javascript" 	src="librairies/jquery.dialogextend.js"		></script>

		<!-- BOOTSTRAP -->
		<!-- CSS -->
			<link rel="stylesheet" href="bootstrap.min.css">
		<!-- Theme optionnel -->
			<link rel="stylesheet" href="bootstrap-theme.css">
		<!-- JavaScript -->
		<script src="bootstrap.min.js"></script>
		<!-- ----------------------------------------------FIN DU CHARGEMENT DES LIBRAIRIES------------------------ ----->
		<script>

			var monAppli = angular.module('magasin',['angular.filter']);

			monAppli.controller("Controleur", function ($scope) {

					$scope.facture = {
						Objets: [{
							qty: 10,
							description: 'Objet',
							cout: 9.95}]
					};

					$scope.addObjet = function() {
						$scope.facture.Objets.push({
							qty: 1,
							description: '',
							cout: 0
						});
					},

					$scope.removeObjet = function(index) {
						$scope.facture.Objets.splice(index, 1);
					},

					$scope.total = function() {
						var total = 0;
						angular.forEach($scope.facture.Objets, function(Objet) {
							total += Objet.qty * Objet.cout;
						})

						return total;
					}

				<!--  Fin du Controleur Angular -->
				});

		</script>
	</head>

<body ng-controller='Controleur' >
<h2>Facture</h2>
<div ng-controller="Controleur">
<table class="table">
<tr>
<th>Description</th>
<th>Qty</th>
<th>cout</th>
<th>Total</th>
<th></th>
</tr>
<tr ng-repeat="Objet in facture.Objets">
<td><input type="text" ng-model="Objet.description"class="input-small"></td>
<td><input type="number" ng-model="Objet.qty" ng-required class="input-mini"></td>
<td><input type="number" ng-model="Objet.cout" ng-required class="input-mini"></td>
<td>{{Objet.qty * Objet.cout | currency}}</td>
<td>
						[<a href ng-click="removeObjet($index)">X</a>]</td>
</tr>
<tr>
<td><a href ng-click="addObjet()" class="button btn-small">Ajouter Objet</a></td>
<td></td>
<td>Total:</td>
<td>{{total() | currency}}</td>
</tr>
</table>
</div>
</body>
</html>

<style>
.button {
   border-top: 1px solid #f797e9;
   background: #d66574;
   background: -webkit-gradient(linear, left top, left bottom, from(#e3aa39), to(#d66574));
   background: -webkit-linear-gradient(top, #e3aa39, #d66574);
   background: -moz-linear-gradient(top, #e3aa39, #d66574);
   background: -ms-linear-gradient(top, #e3aa39, #d66574);
   background: -o-linear-gradient(top, #e3aa39, #d66574);
   padding: 11px 30px;
   -webkit-border-radius: 16px;
   -moz-border-radius: 16px;
   border-radius: 16px;
   -webkit-box-shadow: rgba(0,0,0,1) 0 1px 0;
   -moz-box-shadow: rgba(0,0,0,1) 0 1px 0;
   box-shadow: rgba(0,0,0,1) 0 1px 0;
   text-shadow: rgba(0,0,0,.4) 0 1px 0;
   color: #ffffff;
   font-size: 20px;
   font-family: 'Lucida Grande', Helvetica, Arial, Sans-Serif;
   text-decoration: none;
   vertical-align: middle;
   }
.button:hover {
   border-top-color: #785128;
   background: #785128;
   color: #fff0ff;
   }
.button:active {
   border-top-color: #b52f6b;
   background: #b52f6b;
   }

</style>