[Firebase] Requêtes SQL converties en Firebase noSql.

Firebase

Introduction


Firebase est une base de données géniale de Google en ligne comparable à MongoDb mais avec pleins de fonctionnalités  supers du style Auth, sécurité etc …

Firebase est pas mal pour créer des maquettes d’applications rapidement par exemple ou pour développer dans l’urgence une petite application temporaire (6 mois d’utilisation.).

Par contre c’est du stock d’objets JSON, du coup on peut pas requêter en SQL dessus.

Comment requêter sur Firebase  ?


Regarder le blog de ces personne qui ont converti des rqts SQL communes en rqts Firebase:

https://firebase.googleblog.com/2013/10/queries-part-1-common-sql-queries.html
https://firebase.googleblog.com/2014/11/firebase-now-with-more-querying.html

Publicités

Application de base avec identification Firebase et filtrage par utilisateur.

Introduction :


App traduite en Français, basée sur le vieux angularFire 0.0.9, fonctionnelle.

Bonne base pour créer des apps sécurisées  sur la base de données en ligne Firebase avec Angular.Js 1.x

Les utilisateurs ne peuvent pas modifier les articles des autres utilisateurs. Un utilisateur non identifié ne peut pas accéder aux données ni à l’application, en l’apparence, mais la sécurité firebase n’est pas traitée.

Pour tester, cliquer ici. (log-in:a@a.fr pass:aaaaaaaa)

Basée sur ce tuto :

Le Code :


nicolash.org/truc43.zip

 

Charger une partie d’une BDD noSql Firebase, sous contrainte de filtre.

Introduction


Suite à l’exercice 13 que j’ai fait, on peut constater que charger une BDD Firebase de plus de 500 objets JSON d’un seul coup commence à être un peu long pour l’utilisateur, même si cela fonctionne encore.

Du coup, une piste est

  • Soit d’utiliser la pagination.
  • Soit de charger une partie de la BDD, en spécifiant un critère de filtrage, ceci en permanence.

Comment faire ?


Une première piste ici :

http://stackoverflow.com/questions/17179532/using-limits-with-angularfire

et là :

https://www.firebase.com/blog/2013-10-01-queries-part-one.html

 

Solution 1 : BASIQUE


 

Lors de le connexion à notre BDD, spécifier un limit(x), cela limite le nombre d’objets json chargés . Si l’on ajoute startAt(), cela charge uniquement les premiers objets créés dans notre modèle de données .

Exemple :

var ref = new Firebase(« https://blinding-heat-8502.firebaseio.com/villes »).limit(50).startAt();

Paginer une Base de Données noSql Firebase

INTRODUCTION


Une lib existe pour paginer une base de données noSql Firebase :

http://firebase.github.io/firebase-util/#/toolbox/Paginate/example/page

Leur exemple comporte une erreur à la ligne :

<li ng-repeat="item in scrollItems">{{item.$id}}: {{item.string}}</li>

Pour le voir marcher, il faut écrire :

<li ng-repeat="item in pageItems">{{item.$id}}: {{item.string}}</li>

 


EXEMPLE FONCTIONNEL(Cliquer ici pour tester) :


 

index.html

<!DOCTYPE html>
<html  class="" lang="en">
	<head>

		<!-- CHARGEMENT DES LIBRAIRIES -->

				<!-- CHARGEMENT LIB ANGULAR -->
				<script type="text/javascript" src="librairies/angular-1.3.13/angular.min.js"></script>

				<!-- AngularFire pour firebase-->
				<script src="https://cdn.firebase.com/libs/angularfire/1.1.3/angularfire.min.js"></script>

				<!-- Firebase Utils -->
				<script src="https://cdn.firebase.com/js/client/2.2.9/firebase.js"></script>
				<script src="https://cdn.firebase.com/libs/firebase-util/0.2.5/firebase-util.min.js"></script>
				<script>
					Firebase.util.logLevel('log');
					Firebase.util.log('hello world');
				</script>

					<!--	APPEL LIB BOOTSTRAP -->
				<script src="librairies/bootstrap/js/ui-bootstrap-tpls-0.14.3.min.js"></script>
				 	<link rel='stylesheet prefetch' href='librairies/bootstrap/css/bootstrap.css'>
				 	<link rel='stylesheet prefetch' href='http://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.min.css'>
				
				
				
				<!-- Le CONTROLEUR -->
				<script src="controleurs/app.js"></script>
	</head>

<body ng-app="app" ng-controller="ctrl">
<h4>Showing: Page {{ pageItems.currentPageNumber }} of {{ pageItems.pageCount }}<span ng-show="pageItems.couldHaveMore"> or more</span></h4>
<ul>
	<li ng-repeat="item in pageItems">{{item.$id}}: {{item.string}}</li>
</ul>
<button class="btn btn-primary"
            ng-click="pageItems.page.setPage(1)"
            ng-disabled="pageItems.currentPageNumber < 2">
        <i class="glyphicon glyphicon-fast-backward"></i>
    </button>

    <button class="btn btn-primary"             ng-click="pageItems.page.prev()"             ng-disabled="!pageItems.page.hasPrev()">
        <i class="glyphicon glyphicon-backward"></i>
    </button>

    <button class="btn btn-primary"             ng-click="pageItems.page.next()"             ng-disabled="!pageItems.page.hasNext()">
        <i class="glyphicon glyphicon-forward"></i>
    </button>

    <button class="btn btn-primary"             ng-click="pageItems.page.setPage(pageItems.pageCount)"             ng-disabled="!pageItems.page.hasNext() || pageItems.currentPageNumber >= pageItems.pageCount">
        <i class="glyphicon glyphicon-fast-forward"></i>
    </button>

</body>
</html>

app.js :

var app = angular.module('app', ['firebase']);

app.controller('ctrl', function($scope, $pageArray) {
   var ref = new Firebase('https://fbutil.firebaseio.com/paginate');
  $scope.pageItems = $pageArray(ref, 'number');
});

app.factory('$pageArray', function($firebaseArray) {
  return function(ref, field) {
    // Créer une référence de pagination
    var pageRef = new Firebase.util.Paginate(ref, field, {maxCacheSize: 250});
    // génére un tableau synchronisé utilisant  the special page ref
    var list = $firebaseArray(pageRef);
    // store the "page" scope on the synchronized array for easy access
// stocke le scope de la page sur le tableau synchronisé pour faciliter l'acces
    list.page = pageRef.page;

    // when the page count loads, update local scope vars
// Quand la page compte les enregitrement, mettre à jour le scope local de variables
    pageRef.page.onPageCount(function(currentPageCount, couldHaveMore) {
      list.pageCount = currentPageCount;
      list.couldHaveMore = couldHaveMore;
    });

    // when the current page is changed, update local scope vars
    pageRef.page.onPageChange(function(currentPageNumber) {
      list.currentPageNumber = currentPageNumber;
    });

    // load the first page
    pageRef.page.next();

    return list;
  }
});

Ajouter un bouton « Montrer les 25 prochains objets » avec Firebase.

Introduction


Il existe une lib pour gérer la pagination avec Firebase sous Angular 1.0:

http://firebase.github.io/firebase-util/#/

 

Exemple fonctionnel (Cliquer ici pour tester):


Index.html :


<!DOCTYPE html>
<html  class="" lang="en">
	<head>

		<!-- CHARGEMENT DES LIBRAIRIES -->

				<!-- CHARGEMENT LIB ANGULAR -->
				<script type="text/javascript" src="librairies/angular-1.3.13/angular.min.js"></script>

				<!-- AngularFire pour firebase-->
				<script src="https://cdn.firebase.com/libs/angularfire/1.1.3/angularfire.min.js"></script>

				<!-- Firebase Utils -->
				<script src="https://cdn.firebase.com/js/client/2.2.9/firebase.js"></script>
				<script src="https://cdn.firebase.com/libs/firebase-util/0.2.5/firebase-util.min.js"></script>
				<script>
					Firebase.util.logLevel('log');
					Firebase.util.log('hello world');
				</script>

				<!-- Le CONTROLEUR -->
				<script src="controleurs/app.js"></script>
	</head>

	<body ng-app="app" ng-controller="ctrl">
<h4>Items loaded: {{scrollItems.length}}</h4>
<button class="btn btn-primary" 			  ng-click="scrollItems.scroll.next(25)" 			  ng-disabled="!scrollItems.scroll.hasNext()">
			  Load Next 25
		  </button>
<ul class="scrollbox" scroll-to-bottom="scrollItems">
	<li ng-repeat="item in scrollItems">{{item.$id}}: {{item.nom}}</li>
</ul>
</body>
</html>

app.js

var app = angular.module('app', ['firebase']);

app.controller('ctrl', ['$scope', '$firebaseArray', '$scrollArray',
  function($scope, $firebaseArray, $scrollArray) {
    var servicesRef = new Firebase('https://fbutil.firebaseio.com/paginate');
    $scope.scrollItems = $scrollArray(servicesRef, 'number');
}])

app.factory('$scrollArray', ['$firebaseArray', function($firebaseArray) {
  return function(ref, field) {
    var scrollRef = new Firebase.util.Scroll(ref, field);
    var list = $firebaseArray(scrollRef);
    list.scroll = scrollRef.scroll;

    return list;
  }
}])

// just some scroll magic to show the bottom of the list as new records are loaded
app.directive('scrollToBottom', function () {
  var unbind;
  return {
    restrict: 'A',
    scope: { scrollToBottom: "=" },
    link: function (scope, element) {
      if( unbind ) { unbind(); }
      unbind = scope.$watchCollection('scrollToBottom', function () {
        // assumes we have jQuery, which handles the pretty animation
        // otherwise, just use this code instead:
        element[0].scrollTop = element[0].scrollHeight;
        $(element).animate({scrollTop: element[0].scrollHeight});
      });
    }
  }
});

 

 

 

Truc 35 : Une factory ANGULARJS dédiée à la gestion de FIREBASE

FirebaseIntroduction


Un code ANGULARJS très bien organisé, avec une factory CRUD pour FIREBASE.

La factory utilise les instructions $add, $save et $remove de Firebase.

Tout est mis à jour en temps réel. On rappelle qu’avec ce système moderne, il n’y a plus de Back-end. (Et que ça, c’est sympa, sauf quand on aime SQL).

Note : je vais tenter de dériver ce code afin de gérer des sous élèments de modèles de données JSON, ensuite, ce sera une super base pour créer des apps, et j’ai déjà commencé à créer une app avec Authentification.

Une application partagée  en ligne à tester ici .

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

Pour vérifier que c’est partagé, ouvrir 2 onglets de l’application, on voit alors les modifications s’appliquer en temps réel dans les 2 onglets…

Lire la suite

Truc 33 : Gérer l’authentification avec Firebase et AngularJs

FirebaseIntroduction


La base de données Firebase dispose d’un système automatisé de gestion des utilisateurs.

Le service $firebaseAuth s’inclue à un controleur AngularJs, et permet la création, la suppression d’utilisateurs.

Chaque nouvel utilisateur dispose d’un UID créé automatiquement, qui permet à la suite, toujours dans Firebase d’attribuer des droits en lecture ou en écriture.

Ce système est une sur un serveur spécifique de Firebase, ce n’est pas inclu à notre modèle de données géré sur Firebase.

Pour tester sur mon serveur, c’est ici.

Le code.


<html ng-app="sampleApp">
    <head>
        <meta charset="utf8" >
        <title>Une Application partagée de gestion de contacts AngularJs-Firebase </title>
         
        <!-- CHARGEMENT DES LIBRAIRIES -->
         
        <!-- CHARGEMENT LIB ANGULAR -->
        <script type="text/javascript" src="angular-1.3.13/angular.min.js"></script>
        <script src="angular-route.min.js"></script>
        <script src="librairies/angular-locale_fr-fr.js"></script>
        <!-- CHARGEMENT LIB FIREBASE -->
        <script src='https://cdn.firebase.com/js/client/2.2.1/firebase.js'></script>
        <!-- AngularFire -->
        <script src="https://cdn.firebase.com/libs/angularfire/1.1.3/angularfire.min.js"></script>
        <!-- CSS DE L'APPLICATION -->  
        <link href="truc28.css" media="screen" rel="stylesheet" type="text/css" /> 
         
        <!-- FIN DE CHARGEMENT DES LIBRAIRIES -->
         
        <script>
				 var app = angular.module("sampleApp", ["firebase"]);

			// Factory ré-utilisable qui générer l'instance firebaseAuth
			app.factory("Auth", ["$firebaseAuth",
			  function($firebaseAuth) {
				var ref = new Firebase("https://blinding-heat-8502.firebaseio.com/");
				return $firebaseAuth(ref);
			  }
			]);

			// ON peut ensuite l'utiliser la factory dans le controlleur
			app.controller("SampleCtrl", ["$scope", "Auth",
			  function($scope, Auth) {
				$scope.createUser = function() {
				  $scope.message = null;
				  $scope.error = null;

				  Auth.$createUser({
					email: $scope.email,
					password: $scope.password
				  }).then(function(userData) {
					$scope.message = "User créé avec uid: " + userData.uid;
				  }).catch(function(error) {
					$scope.error = error;
				  });
				};

				$scope.removeUser = function() {
				  $scope.message = null;
				  $scope.error = null;

				  Auth.$removeUser({
					email: $scope.email,
					password: $scope.password
				  }).then(function() {
					$scope.message = "Utilisateur supprimé";
				  }).catch(function(error) {
					$scope.error = error;
				  });
				};
			  }
			]);
			
			
			<!-- AUTHENTIFICATION ANONYME -->
			app.controller("AuthController", ["$scope", "$firebaseAuth",
				function($scope, $firebaseAuth) {
					$scope.login = function() {
						$scope.authData = null;
						$scope.error = null;

						auth.$authAnonymously().then(function(authData) {
							$scope.authData = authData;
						}).catch(function(error) {
							$scope.error = error;
						});
					};
				}
			]);
			
			<!-- AUTHENTIFICATION PAR MOT DE PASSE -->
			app.controller("AuthControllerPwd", ["$scope", "$firebaseAuth",
				function($scope, $firebaseAuth) {


					$scope.login = function() {
					  $scope.authData = null;
					  $scope.error = null;

					  $scope.authObj.$authWithPassword({
						  	email: $scope.email,
							password: $scope.password
						}).then(function(authData) {
						  console.log("Logged in as:", authData.uid);
						  $scope.message2 = "Logged in as:", authData.uid;
						  $scope.log = authData.uid;
						  
						}).catch(function(error) {
						  console.error("Authentication failed:", error);
						  $scope.error = error;
						});
					};
				  }
			]);
		</script>
    </head>
  
<!-- La page HTML générale -->
<body ng-controller="SampleCtrl">
 
 <h2>Créer un Utilisateur authentifié :</h2><br>
 <div ng-app="sampleApp" ng-controller="SampleCtrl">
	Email: 		<input ng-model="email" type="text">
	Password: 	<input ng-model="password" type="text"><br><br>
	<button ng-click="createUser()">Créer un Utilisateur	</button>
	<button ng-click="removeUser()">Supprimer un Utilisateur</button>
	<p ng-if="message">Message: <strong>{{ message }}</strong></p>
	<p ng-if="error">Erreur: <strong>{{ error }}</strong></p>
</div>


<h2>S'identifier anonymement</h2><br>
<div  ng-app="sampleApp" ng-controller="AuthController">
  <button ng-click="login()">S'identifier anonymement</button>
	<p ng-if="authData">	Utilisateur Loggé: <strong>{{ authData.uid }}</strong></p>
  <p ng-if="error">Erreur: <strong>{{ error }}</strong></p>
</div>

<h2>S'identifier Avec un Email-Password</h2><br>
<div  ng-app="sampleApp" ng-controller="AuthControllerPwd">
	Email: <input ng-model="email" type="text">
	Password: <input ng-model="password" type="text">
	<button ng-click="login()">Login </button>
	<p ng-if="log">Logged in user: <strong>{{ log }}</strong></p>
	<p ng-if="error">Error: <strong>{{ error }}</strong></p>
</div>


</body>
</html>

<style>
	div{
		-moz-box-shadow:inset 0px 1px 0px 0px #cf866c;
		-webkit-box-shadow:inset 0px 1px 0px 0px #cf866c;
		box-shadow:inset 0px 1px 0px 0px #cf866c;
		background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #d0451b), color-stop(1, #bc3315));
		background:-moz-linear-gradient(top, #d0451b 5%, #bc3315 100%);
		background:-webkit-linear-gradient(top, #d0451b 5%, #bc3315 100%);
		background:-o-linear-gradient(top, #d0451b 5%, #bc3315 100%);
		background:-ms-linear-gradient(top, #d0451b 5%, #bc3315 100%);
		background:linear-gradient(to bottom, #d0451b 5%, #bc3315 100%);
		filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0451b', endColorstr='#bc3315',GradientType=0);
		background-color:#d0451b;
		-moz-border-radius:3px;
		-webkit-border-radius:3px;
		border-radius:3px;
		border:1px solid #942911;
		display:inline-block;
		cursor:pointer;
		color:#ffffff;
		font-family:Arial;
		font-size:13px;
		padding:6px 24px;
		text-decoration:none;
		text-shadow:0px 1px 0px #854629;

	}
</style>