Réaliser une application web avec Firebase, Firestore

Firebase d’avoir une base de données NoSQL principalement dans le cloud. Mais ça ne se limite pas à ça, il y a aussi du stockage d fichier, de code, de l’analytics, mais le principal usage à ma connaissance est la base temps réel NoSQL, son avantage est de permettre de mettre sur pied rapidement une application, pour peu qu’on soit familier avec lui.

Création d’un compte Firebase

Pour créer un compte Firebase, vous devez disposer d’un compte Google, et ensuite activer votre compte Firebase.

Contexte du tutoriel

Le contexte de l’application est une application dans une page html, donc pas besoin d’avoir NodeJs, nous verrons qu’il est possible de créer un projet de cette façon et de faire appel aux librairies, mais pour des raisons de simplicité, nous allons au plus simple.

Ensuite vous devez créer un projet et remplir des informations sur votre projet. Vous disposez d’niformation de configuration pour votre application.

Inclusion des scripts

Il y a plusieurs scripts à inclure en fonction de ce que vous voulez faire (analytics ou non) mais le principal fichier à inclure est le firebase-app.js

    <!-- The core Firebase JS SDK is always required and must be listed first -->
    <script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-auth.js"></script>

    <script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-firestore.js"></script>
    <!-- TODO: Add SDKs for Firebase products that you want to use
     https://firebase.google.com/docs/web/setup#available-libraries -->
    <script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-analytics.js"></script>
#exemple de configuration Firebase
        // Your web app's Firebase configuration
        var firebaseConfig = {
            apiKey: "DCZ28p7gilP15WoymVHn-A",
            authDomain: "myapp-bull3503.firebaseapp.com",
            databaseURL: "https://myapp-bull3503.firebaseio.com",
            projectId: "myapp-bull3503",
            storageBucket: "myapp-bull3503.appspot.com",
            messagingSenderId: "2017024",
            appId: "1:2017024:web:e282485405d09",
            measurementId: "G-J4XXXQPHT9"
        };

// initialisation de l'app
firebase.initializeApp(firebaseConfig);

Créer une base de données orientée documents Cloud Firestore

Cette base est en accès public pour une durée de 30 jours, vous pourrez vous y connecter sans mot de passe, passé ce délai, vous recevrez une alerte comme quoi la base ne sera plus accessible en public. Dans la cnsole, vous verrez Realtime Database et Cloud Firestore, quelle est la différence? C’est expliqué sur cet article.

#paramétrage de la base de données
à l'origine le paramétrage est permissif pour vous permettre de tester la base

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.time  < timestampe.date(2020,7,6);
    }
  }
}

Mais au bout de 30 jours vous recevez un mail pour modifier l'accès à la base avec des règles plus strictes.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Mais au bout de 30 jours vous recevez un mail pour modifier l'accès à la base avec des règles plus strictes.

Créer un utilisateur

Pour créer un utilisateur, chargez d’abord la librairie auth, qui vous permet de créer un utilisateur et de gérer les connexion.

#création d'un utilisateur via un formulaire
        firebase.auth().createUserWithEmailAndPassword(email, password).catch(function (error) {
            // Handle Errors here.
            var errorCode = error.code;
            var errorMessage = error.message;
            console.log(errorCode, ':', errorMessage)
        });

Si la création d’un utilisateur s’est faite avec succès, vous êtes automatiquement loggé. Si vous n’arrivez pas à créer un utilisateur de cette façon (probablement parce que vous avez oublié d charger la librairie auth) et que vous désirez rapidement en créer un, vous pouvez aller directement sur la console, dans la sidebar de gauche Authentification puis Ajouterun utilisateur

Connexion d’un utilisateur

        firebase.auth().signInWithEmailAndPassword(email, password).catch(function (error) {
            // Handle Errors here.
            var errorCode = error.code;
            var errorMessage = error.message;
            console.log(errorCode, ':', errorMessage)
        });

Pour maintenir la connexion de l’utilisateur entre différentes pages, il vous faudra utiliser le localStorage.

Lire une table

Je suppose que vous incluiez à chaque page les librairie correspondantes.

        var firebaseConfig = {
            ...
        };
        // Initialize Firebase
        firebase.initializeApp(firebaseConfig);
        firebase.auth().signInWithEmailAndPassword(email, password).catch(function (error) {
          ...
        });
#instanciation de la connexion à Firestore
var db = firebase.firestore();

Découvrez comment administrer la base de données depuis le site de Firebase.

Doctrine Query Builder

Il existe dans Symfony plusieurs façons de faire des requêtes SQL, dont l’une spécifique à Doctrine, l’utilisation de Query Builder est sans doute la plus utilisée. Notez qu’il y a aussi Native Query qui se veut ‘proche’ de SQL de base.

Requête simple avec Query Builder

Requête avec WHERE

$this->createQueryBuilder('u')
            ->andWhere('u.id_utilisateur_groupe = :id')
            ->andWhere('u.is_active = :is_active')
            ->setParameter('id', $idEquipe)
            ->setParameter('is_active', 1)
            ->getQuery()
            ->getResult()

Requête avec ORDER BY

$this->createQueryBuilder('u')
            ->andWhere('u.id_utilisateur_groupe = :id')
            ->andWhere('u.is_active = :is_active')
            ->orderBy('u.lastname','ASC')
            ->setParameter('id', $idEquipe)
            ->setParameter('is_active', 1)
            ->getQuery()
            ->getResult()
        ;

Reference : https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/query-builder.html

Défaire une action dans Git

Parfois on peut se tromper dans Git ! Il est donc utile de savoir comment annuler une action (en ligne de commande c’est mieux)

Défaire une modification de fichier non ajouté dans le staging area

git checkout -- nomfichier

Défaire un add

git reset fichier

Défaire un commit

# défaire le dernier commit
git reset --soft HEAD~1
# on revient à l'état où les fichiers sont ajoutés au staging area

$git reser --hard HEAD~1
#on revient à l'état où les fichiers sont non ajoutés au staging area

Défaire un commit qui été poussé

Ne plus trackere un fichier et l’ignorer du versioning

git rm --cached fichier

Vous aimeriez aussi savoir comment pusher sans mot de passe

Git cherry-pick sélectionner un commit d’une autre branche

Je vous présente une commande assez peu utilisée, considérée par certain comme une pas bonne pratique. J’ai u l’utiliser dans une situation bien particulière, en effet j’étais sur develop et j’ai fait une modif dans une autre branche on va dire une feature, que j’aurais dû faire sur develop. Ok on n’est pas sensé bosser sur develop en direct !

Mais c’est un projet où j’étais tout seul, donc je me permettais quelques arrangements.

Branch bleu (develop), branche rouge (feature), je prend le commit ‘taux valeur admin OK’

Je me place dans la branche de destination, develop donc en faisant un git checkout develop

Ensuite je repère le hash du commit de la branche feature, et je fait :

$ git cherry-pick hashDuCommit

Le résultat est le suivant :

On voit que develop a maintenant le commit avec le message ‘taux valeur admin ok’

N’utilisez le cherry-pick qu’avec parcimonie, je pense que si c’est mal fait, vous risquer de mettre votre git dans un sale état.

Vous aimeriez aussi savori comment mettre des commentaires multilignes dans vos commit

mysql

SQL Faire un division dans sa requête

Plutôt que de lire des données et effectuer la division en code PHP par exemple, si vous avez la possibilité, faites directement la division dans la requêtes SQL

Il y a plusieurs façons de le faire, soit avec un sous requêtes (mais il semble qu’il y ait des problèmes de performance), mais c’est le plus simple à mon avis, ou alors il faut utiliser des variables SQL locales.

Méthode avec une sous requête

Le principe est de calculer le dénominateur (par exemple) dans une sous requête, et de le mettre au dénominateur de la requête principale

# la sous requête
SELECT count(*) FROM table1 WHERE type='toto'

# la requête principale 
SELECT count(*) FROM table1 WHERE type='tata'

#le tout
SELECT count(*)/
(SELECT count(*) FROM table1 WHERE type='toto')

 FROM table1 WHERE type='tata'

Attention à la division par zéro (la question à se poser systématiquement quand on a une division, ce doit être un réflexe), on utilise NULLIF

SELECT count(*)/
NULLIF((SELECT count(*) FROM table1 WHERE type='toto'),0)

 FROM table1 WHERE type='tata'

source du NULLIF

Méthode avec des variables

Mysql logo

SQL : avoir un décompte égal à zéro si pas de correspondance avec LEFT JOIN

Récemment pour un projet, j’ai eu à faire une série de diagramme voir image ci-dessous :

Deux périodes avec des données pas toujours consistentes, des barres de taille hétérogène, pas top pour l’affichage. On veut la taille des barres constantes, donc forcer l’affichage des données même si le décompte est zéro.

Le soucis c’est que chaque mois, on n’a pas forcément chaque libellé, donc les données qui sont fournit avec une requête inner join, ne retourne rien, et j’ai des fois deux barre au lieu de 5 voir plus.

Il fallait trouver un moyen de retourner tous les libellé, même si le décompte retournait 0.

Ainsi on aura des graphiques plus harmonieux, et pas des barres de différentes tailles suivant les périodes.

Le technique : elle consiste à retourner dans un premier temps dans une sous requêtes des données faites avec un INNER JOIN, donc dans ce cas, on aura seulement deux barres, mais dans un second temps on va prendre le résultat de cette sous-requête et faire une jointure à nouveau avec la table de tous les libellés existants, mais cette fois ci avec un LEFT JOIN, ainsi on aura tous les libellés. Il faut voir le résultat de la sous requête comme une nouvelle table, c’est la clé de cette technique.

Requête d’origine menant au graphique présenté

SELECT count(*) as count, MD.ID_ETAT_MATRICE_DETAILS, MD.LIBELLE_ETAT_MATRICE_DETAILS as libelle 
FROM MATRICE M
LEFT JOIN ETAT_MATRICE_DETAILS MD on MD.ID_ETAT_MATRICE_DETAILS = M.ID_ETAT_MATRICE_DETAILS
 where M.ID_ETAT_MATRICE = 3 and M.DATE_SIGNATURE BETWEEN '2020-07-01' AND '2020-07-30' 
 AND USR_ID = '9999'
 GROUP BY MD.ID_ETAT_MATRICE_DETAILS;

Nouvelle requête en transformant en sous requête la requête actuelle, et en faisant une jointure avec la table des libellés

SELECT IFNULL(count,0), C.ID_ETAT_MATRICE_DETAILS , EMD.LIBELLE_ETAT_MATRICE_DETAILS 
	FROM ETAT_MATRICE_DETAILS EMD
	LEFT JOIN 
(SELECT count(*) as count, MD.ID_ETAT_MATRICE_DETAILS , MD.LIBELLE_ETAT_MATRICE_DETAILS as libelle 
FROM MATRICE M
INNER JOIN ETAT_MATRICE_DETAILS MD on MD.ID_ETAT_MATRICE_DETAILS = M.ID_ETAT_MATRICE_DETAILS
 where M.ID_ETAT_MATRICE = 3 and M.DATE_SIGNATURE BETWEEN '2020-07-01' AND '2020-07-30' 
 AND USR_ID = '9999'
 GROUP BY MD.ID_ETAT_MATRICE_DETAILS)  
 C on C.ID_ETAT_MATRICE_DETAILS = EMD.ID_ETAT_MATRICE_DETAILS
 WHERE EMD.ID_ETAT_MATRICE = 3;

Notez que j’ai forcé à zéro le décompte si il vaut null (en effet LEFT JOIN retourne une donnée même s’il n’y a pas de correspondance, donc ça devient NULL.)

Passage de paramètre à une fonction callback

vous connaissez tous la requête Ajax avec JQuery

$.ajax({
url:url,
method:'GET',
success:function(data){
  console.log(data)
}
})

En passant en callback une fonction anonyme, on définit la fonction à la volée, donc pas de problème pour passer des paramètres.

Mais qu’en est-il si on utilise une fonction nommée à la place?

function callback(data) {
console.log(data)
}

On serait tenté d’écrire :

$.ajax({
url:url,
method:'GET',
success:callback(data)
})

ça ne marche pas en effet, vous devez passer la fonction par référence, autrement dit vous devez passer le handler, en ajoutant des parenthèses vous exécutez la fonction. Donc on doit avoir la syntaxe suivante, mais qui amène à poser la question : mais comment on passe le paramètre data?

$.ajax({
url:url,
method:'GET',
success:callback
})

Il existe en Javascript la variable argument, qui fait référence aux paramètres qui sont passés, c’est un tableau commençant à l’index 0 pour le premier paramètre (donc data dans notre cas)

function callback() {
console.log(argument[0])
}

#marche quelquesoit le nombre de paramètres
symfony

Memento Twig

Petit article pour consigner les techniques de Twig qu’on a trop tendance à oublier car peu utilisée, il est ici utilisé dans un contexte Symfony

Chercher l’url d’une route

{{ url('home') }} << ou un autre nom de route, ici on a le nom de domaine

Boucle for dans twig

    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}

Comment dumper une variable

Vraiment très fondamental, le dump permet de voir ce que contient une variable, et c’est un raccourci très efficace dans la connaissance d’une librairie

{{ dump(app.request) }}

Ainsi l’exemple ci-dessus peut nous donner plein d’informations sur l’objet request et ainsi nous permettre dde récuérer des informations comme path_info ou des variable de paramétrage dans les fichier de configuration de Symfony.

#exemple de dump
public 'server' => 
    object(Symfony\Component\HttpFoundation\ServerBag)[16]
      protected 'parameters' => 
        array (size=41)
          'REDIRECT_STATUS' => string '200' (length=3)
          'HTTP_HOST' => string 'terrav2' (length=11)
          'HTTP_CONNECTION' => string 'keep-alive' (length=10)
          'HTTP_CACHE_CONTROL' => string 'max-age=0' (length=9)
          'HTTP_UPGRADE_INSECURE_REQUESTS' => string '1' (length=1)
          'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' (length=121)
          'HTTP_ACCEPT' => string 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' (length=124)
          'HTTP_REFERER' => string 'http://terrav2/matrice/export' (length=33)
          'HTTP_ACCEPT_ENCODING' => string 'gzip, deflate' (length=13)
          'HTTP_ACCEPT_LANGUAGE' => string 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' (length=35)
          'HTTP_COOKIE' => string 'PH..

# pour getter le hTTP_HOST par exemple :
{{ dump(app.request.server.get('HTTP_HOST')) }}

Comment accéder à un rôle d’un user

{{ app.user.roles[0] }}

Créer un lien hypertexte

{{ url('nomDeLaRoute',{ 'param':'value'}) }}

Accès aux variables de configuration de Symfony depuis Twig : Substitution de variable

Dans le fichier services.yaml :

parameters:
    pdf_folder: '%kernel.root_dir%/../public/medias/pdf'

Dans le fichier twig.yaml

twig:
    globals:
        pdf_path: '%pdf_folder%'

Dans le fichier template twig :

{{pdf_path}}

Accéder à une propriété d’une table liée

Il hy a la table Users qui contient le champ IdGroupe ,puis la table UtilisateurGroupe qui contient l’IdGroupe (jointure donc) et le libellé du groupe auquel on veut accéder

Le chainage est possible avec la notation pointée

A la fin on aura

{{user.idUtilisateurGroupe.getIdUtilisateurGroupe }}
Mysql logo

Trucs et astuces sur PHPMyadmin

Comment montrer la totalité d’une cellule

Phpmyadmin lorsque vous faites une requêtes peut ne mpas montrer toutes les données d’une celluele, ce qui est OK lrsque que vous faites une requêtes classqieu (SELECT), mais il y a des cas où vous avez besoin de connaitre une donnée en particuliers (par exemple lister la requête de création d’une table) et il vous faut toute la donnée. Voici la marche à suivre pour avoir la totalité des données

Après avoir fait votre requête,  cliquez sur +Options et il y a un bouton radio FUL TEXT et voilà
exemple : 
SHOW CREATE TABLE CHALLENGE

CREATE TABLE `CHALLENGE` (
 `ID_CHALLENGE` int(50) NOT NULL AUTO_INCREMENT,
 `ID_CHALLENGE_TYPE` int(50) NOT NULL,
 `ACTIF_CHALLENGE` int(1) NOT NULL DEFAULT '1',
 `LIBELLE_CHALLENGE` varchar(250) NOT NULL,
 PRIMARY KEY (`ID_CHALLENGE`),
 KEY `ID_CHALLENGE_TYPE_idx` (`ID_CHALLENGE_TYPE`),
 CONSTRAINT `CHALLENGE_TYPE` FOREIGN KEY (`ID_CHALLENGE_TYPE`) REFERENCES `CHALLENGE_TYPE` (`ID_CHALLENGE_TYPE`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1

Le Layouting dans WPF

Dans un précédent article je parlais de la création d’un application WPF en général, dans cet article on va se concentrer sur le XAML, el langage xml qui permet de disposer les élément WPF dans la fenêtre.

Concevoir son interface en XAML

Au démarrage d’une application XAML, il y a une fenêtre vide, mais le code XAML n’est pas vide pour autant. Il y a un code minimal :

<Window x:Class="PriceGrabber.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PriceGrabber"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        
    </Grid>
</Window>
Fenêtre minimale xaml

Vous voyez une fenêtre blanche. Mais en fait i y a bien des choses en dessous.

Ajouter un StackPanel comme enveloppe de vos éléments plus petits

Sur la gauche de VisualtStudio se trouve la Toolbox, dont vous pouvez glisser-déplacer les élément vers la fenêtre au centre.

WPF Stackpanel

La fenêtre XAML se met à jour automatiquement, avec des valeurs par défaut que vous pouvez changer.

Le stackpanel héberge les éléments dans toute sa largeur.

stack panel exemple

WPF comment ajouter des élément dans une combobox?

Tout simplement en y ajoutant des comboBoxItem.

<ComboBox x:Name="comboBox">
    <ComboBoxItem Content="X"/>
    <ComboBoxItem Content="Y"/>
    <ComboBoxItem Content="Z"/>
</ComboBox>

Ajouter via le code des éléments dans une comboBox

Si vous ne connaissez pas à l’avance les éléments de la comboBox, vous pouvez le faire dynamiquement via code c#, mais c’est très fastidieux.

php

Accélérez votre site web avec un cache Opcode

Toujours sur un serveur dédié, et sous Debian voici la procédure à faire pour accélérer votre site web:

  1. Installez APC : aptitude install php-apc
  2. Configurer le fichier  php.ini en éditant le ichier  « /etc/php5/conf.d/apc.ini » et en ajoutant: apc.enabled=1
    apc.shm_segments=1
    apc.shm_size=128
  3. Redémarrez Apache
  4. Créez une page web pour pourvoir monitorer les performance de ce cache (remplacez mysite par le bon répertoire de votre serveur) :gzip -dc /usr/share/doc/php-apc/apc.php.gz > /home/mysite/public_html/apc.php

Voilà c’est tout !

Comment trouver le fichier info.plist dans Xcode

Le fichier info.plist contient les informations diverses et variées mais importantes sur votre application que vous allez déployer sur l’Appstore

Récemment pour résoudre le problème d’une application rejetée car ne fonctionnant pas sur Ipad, j’ai dû trouver un moyen pour forcer le déploiement sur iphone. Même sur Stackoverflow c’était pas clair pour beaucoup de gens qui pensaient que ce n’était pas possible.

Après un build Ionic, le fichier info.plist se trouve sur dans /platform/ios/nom-appli/nom-appli-Info.plist.

L’éditer avec un éditeur de texte, et ajouter une clé UIRequiredDeviceCapabilities

Pourquoi vous devez éditer le fichier directement, parce que il me semble que dans Xcode lui même je ne pouvais pas ajouter la clé manuellement (bug?)

	<key>UIRequiredDeviceCapabilities</key>
	<dict>
		<key>telephony</key>
		<true/>
	</dict>

Ensuite sur Xcode dans l’onglet Info, forcer à rafraîchir l’onglet qui reflétera le fichier.

Voici la documentation officielle d’Apple sur les différente clé qu’on peut mettre.

Lien pour savoir comment archiver une app et la déployer sur l’Appstore.

ERROR ITMS-9000: “Redundant Binary Upload

Note 1 : Si vous avez ce message parce que vous avez essuyé un refus, puis refait un upload, il vous faut aller dans « General » et « Build » et incrémenter le numéro de build. Un numéro de build correct doit être un entier, il est différent de la version de l’application. En incrémentant le numéro de build vous n’avez pas besoin de changer le numéro de version de l’application pour resoumettre.

Note 2 : si vous avez une application ciblant Iphone et Ipad, vous ne pouvez plus dans une version ultérieure restreindre aux Iphone seulement.

Développer une application web en ReactJS

ReactJS à la différence de Angular et de VueJS, est une librairie qui s’occupe uniquement de la vue, très véloce, grâce à l’utilisation d’un virtual DOM. Le principe es de ne mettre à jours que ce qui est nécessaire.

Mise en place du projet

$ npx create-react-app myApp
# npx fourni depuis la version npm@5.2.0 est sensé vous faciliter la vie, si npx <command>, et que la <command> n'est pas dans le PATH, iil est capable d'installer la commande depuis NPM et l'invoquer.
# sortie de la commande npx create-react-app
Initialized a git repository.

Success! Created jeu at /Users/poste5hookipa/sites/reactapplication/jeu
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd jeu
  yarn start

Installer votre environnement de développement web sous Mac

Votre MacBookPro livré, il faut maintenant installer un environnement d’exécution pour vos sites web, et aussi un environnement de développement.

Pour ce qui est de l’environnement d’exécution, reportez vous à ces liens:

Pour ce qui est de l’environnement de développement, nous allons voir dans les lignes qui suivent les opérations à faire

Installation de Xcode ou Xcode Command Line Tool (CLT)

Pourquoi installer Xcode CLT? il est nécessaire pour exécuter certaines commandes en Shell, notamment pour installer Homebrew le gestionnaire de package de MacOS.

Pour vérifier si vous avez déjà mis en place(on en sait jamais) Xcode CLT, vous pouvez tapez les commandes:

$ gcc
# ou
$ xcode-select -p
Si Xcode CLT n'est pas installé, vous aurez une popup vous invitant à l'installer.

Téléchargez Xcode CLT sur le site https://developer.apple.com/download/more/

Choisissez bien le package, il y a beaucoup de fichiers listés, et vous risquez de ne pas télécharger la bonne version, classez dans un premier temps par date et regardez le nom commençant par « Command line tools for Xcode xx », et regardez bien la version de Xcode la plus récente.

cf lien :

# testons voir si c'est bien installé
$ xcode-select -p
/Library/Developer/CommandLineTools
# c'est bon c'est installé

Installation de Homebrew

Maintenant que Xcode est installé, nous pouvons faire la ligne de commande suivante pour installer Homebrew, qui va nous permettre d’installer MySQL et autres applicatifs.

#il est conseillé d'installer Homebrew sous /usr/local/homebrew
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Installation des logiciels

MySQL

#la version par défaut de MySQL est la 8 pour Homebrew
#si on veut la 5.7 voici les étapes
# montrer les infos de la version 5.7
$ brew info mysql@5.7
mysql@5.7: stable 5.7.29 (bottled) [keg-only]

#installation
$ brew install mysql@5.7

We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

mysql@5.7 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have mysql@5.7 first in your PATH run:
  echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.bash_profile

For compilers to find mysql@5.7 you may need to set:
  export LDFLAGS="-L/usr/local/opt/mysql@5.7/lib"
  export CPPFLAGS="-I/usr/local/opt/mysql@5.7/include"


To have launchd start mysql@5.7 now and restart at login:
  brew services start mysql@5.7
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/mysql@5.7/bin/mysql.server start
==> Summary
🍺  /usr/local/Cellar/mysql@5.7/5.7.29: 319 files, 232MB
==> Caveats
==> openssl@1.1
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because openssl/libressl is provided by macOS so don't link an incompatible version.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.bash_profile

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

==> mysql@5.7
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

mysql@5.7 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have mysql@5.7 first in your PATH run:
  echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.bash_profile

For compilers to find mysql@5.7 you may need to set:
  export LDFLAGS="-L/usr/local/opt/mysql@5.7/lib"
  export CPPFLAGS="-I/usr/local/opt/mysql@5.7/include"


To have launchd start mysql@5.7 now and restart at login:
  brew services start mysql@5.7
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/mysql@5.7/bin/mysql.server start

Lisez bien les information ci-dessus pour savoir comment démarrer, arrêter, et faire quelques opérations en ligne de commande.

react native

Les Hooks en React

Les hook sont apparus avec la version de React 16.8.

Le Hook UseState en ReactJS

Le hook UseState se charge du state dans les composants fonctionnels. Dans le composant de classe on avait :

this.setState(nouveauState)
#avec useState
const [state,setState] = useState(initialState)

Le hook useEffect

Il est l’équivalent de plusieurs fonction de cycle dans les composant de classe. Il remplace ComponentDidMount, ComponentDidUpdate.

#invocation au premier rendu
useEffect( () => {

},[])

#invocation au premier rendu et à chaque update du state
useEffect( () => {

},[variable])


#invocation uniquement à chaque update (et pas au premier chargement)

const isInitialMount = useRef(true);

useEffect(() => {
  if (isInitialMount.current) {
     isInitialMount.current = false; //grâce à cette astuce on bypasse l'exécution du code d'update au premier rendu
  } else {
      // le code pour chaque update
  }
});
javascript

Installer NPM sans avoir les problèmes de droit d’accès à des répertoire

Une des choses qui m’énervent le plus (et les développeur) est que dans certains processus de build avec NodeJs, on est confronté à des erreurs qui résultent de droits d’accès à des répertoires parce qu’on n’est pas utilisateur root. Ce problème se produit surtout en environnement MacOS et Linux. sous Windows vous travaillez en Administrateur en général.

Sur le site de NPM, il vous est expliquée ue procédure d’installation de NodeJS qui vous évite cet écueil. Le principe consiste à changer le répertoire par défaut de NPM.

https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally

tuto ionic 4

Builder un projet avec Ionic sous Windows

D’abord il faut installer l’environnement de développement. Pou rle JDK, Gradle,NodeJS, n’oubliez pas de configurer la variable Path!

Installation de JDK

Pour ce faire il vous faut aller sur le site d’Oracle et créer un compte 🙁

Installation de NodeJS (donc de NPM)

Installation de Ionic et cordova

Installation de Android Studio

Lors du build vous allez avoir des erreurs, mais ce doit être minime si vous avez effectué les étapes de ci-dessus.

Gradle qui est le builder doit être installé indépendamment même s’il vient avec Android Studio (ne me demandez pas pourquoi) Télécharger Gradle depuis ce site.

Premier build et possibles problèmes

Pour le premier build ou run, mettez vous en mode verbose pour voir les détail sdes potentiels problèmes :

ionic cordova run android --verbose

Problèmes possibles avec Gradle : à un moment vous pouvez avoir le message comme quoi vous n’avez pas validé la license du SDK

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Failed to install the following Android SDK packages as some licences have not been accepted.
     platforms;android-28 Android SDK Platform 28
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.

Il faut vous rendre à ce répertoire sous Windows

C:\Users\admin\AppData\Local\Android\Sdk\tools\bin

Exécutez cette commande dans ce répertoire et validez par ‘y’ toutes les questions.

tuto ionic 4

Tuto application Ionic 3 IBeacon et déploiement vers le device sous IOS

J’ai du faire récemment une application démonstrateur (POC : proof of concept) avec Ionic et des iBeacon, devant le peu d’information je pose un petit tuto par ici en espérant que ça peut servir, n’hésitez pas à poser des questions j’aurais peut être réponse.

Ibeacon qu’est ce que c’est?

Un iBeacon est un objet électronique qui émet des signaux bluetooth à intervalles réguliers. Il émet un seul message, qui contient des données. Et si un smartphone est équipé du Bluetooth et un programme pour capter ces messages, il peut les interpréter et par exemple faire une action. Un iBeacon est un device qui doit être positionné de façon fixe. Il sert de repère géolocalisé. Une application exemple est celle d’un musée, si vous êtes équipé de l’application du musée, et que vous vous présentez devant un tableau, l’application peut vous fournir des informations sur ce tableau.

En commerce, le filon est exploité de façon un peu différente : quand vous disposez de l’application de la chaine de magasins, si vous passez à proximité, vous recevez une notification push sur une promotion.

Le iBeacon est capable d’émettre sur 70m ! en Bluetooth low energy (BLE), de fait un distingue 3 zones, proximité immédiate, proximité, et éloigné.

Source https://gorillalogic.com/

Ibeacon est une émanation de Apple, Google a répliqué avec les eddystones. Il y a une différence entre les eddystones et les ibeacons, les devices sont identifiés par leur uuid, un identifiant qui est sensé les rendre unique. Une des différences à ma connaissance est que sur IOS, il faut connaitre à l’avance les uuid de vos iBeacons, sinon votre application IOS ne verra rien. Par contre une application Android avec des eddystones pourra scanner tous les eddystones se trouvant à proximité, même si ces derniers n’ont pas le même uuid que celui mis dans l’application.

Ionic qu’est-ce que c’est?

Ionic est un framework de développement d’application mobile, vous développez des applications sans avoir à connaitre Java, ni Swift. Donc c’est destiné aux développeurs d’application web, qui n’auront pas besoin d’avoir la douleur d’apprendre un nouveau langage. Ceci dit, le plus difficile au début c’est de comprendre comment fonctionne Ionic.

Ionic est basé sur Cordova, une solution open source d’application mobile en y ajoutant une couche plus « native ». Depuis la version 3 il fonctionne avec le framework Javascript Angular 2+ et le langage est TypseScript, une surcouche de Javascript en plus typé. En mode développement, l’application peut être vue sur un navigateur web. Vous pouvez ensuite déployer sur une des plateforme prise en charge (Android ou IOS), et il vous faudra disposer de Android Studio pour faire marcher dans un émulateur virtuel Android, et de Xcode pour émuler sur un device IOS.

Vous pouvez aussi déployer sur un smartphone en phase de développement, ceci est nécessaire car nous utilisons des fonctionnalités disponibles seulement sur un device physique.

Il faut savoir que si vous êtes sur Windows, vous ne pourrez pas déployer sur IOS. Par contre sur Mac, vous pourrez déployer sur IOS et Android.

Bootstrapper une application ionic

ionic start MyApp --type=ionic-angular

Importer les librairies pour iBeacon

#installation des librairies

Paramétrer vos iBeacons : importante distinction entre les iBeacons et les EddyStones (rappel)

Pour configurer les iBeacons, téléchargez l’application iBKS config. Reportez vous à la documentation pour paramétrer chaque iBeacon, un peu laborieux au début.

Note : uuid doit être en minuscule ! pas de trait d’union pour paramétrer l’uuid dans le iBeacon.

Déployer l’application Ionic sous IOS

Note : Pour builder pour Android, voir cet article pour builder une application Ionic sous Windows, c’est à peu près la même chose, mais sachez que vous avez besoin d’un Mac pour builder pour IOS, impossible de faire autrement que d’investir dans un macbook PRO par exemple (16 Go de RAM conseillé)

Déployer pour le device

ionic cordova build ios --device

Ensuite allez dans le répertoire projet et les sous répertoire /platforms/ios et cliquez sur le fichier .xcodeproj pour ouvrir Xcode. Configurez Xcode pour le lier à votre compte développeur Apple sans quoi vous ne pouvez rien faire. En effet vous devez créer un provisioning profile.

Ensuite cliquez sur la liste des devices en haut à gauche, puis sur le triangle noir pour déployer sur votre device.

Déployer pour la production IOS

ionic cordova build ios --prod

Répétez les mêmes process que précédemment, mais en buildant vous aurez une erreur de type code signing ou pas suivant si vous avez sélectionné le certificat que vous aurez créé pour votre application. Pour paramétrer le certificat, il faut aller dans votre projet dans Xcode (icône bleue dans la sidebar), puis General puis la section Signing et cochez la case « Automatically manage signing »

Cliquez sur à côté du triangle noir en sélectionnant dans la liste le device Generic ou si vous avez un device branché, le device correspondant. En fait il faut sélectionner Generic Device lorsque vous n’avez pas de device branché.

1 – Création de l’archive

Ensuite allez dans Produit > Archive dans le menu en haut de l’écran de votre Mac, l’archivage se lance et une nouvelle fenêtre se lance.

2 – Choix du type de distribution

3 – Optionnel : App thinning

Important : over the air installation, vous permet de télécharger l’IPA depuis un lien web, pratique pour des application d’entreprise, si vous voulez éviter le processus de validation de l’Appstore

4 – Le chemin de votre archive sur le site web

5 – Export de l’IPA

Export de l’IPA sous forme d’un dossier, récupérez le dossier généré et uploadez le le en ligne.

6 – Installation over the air

Une fois que vous avez mis votre archive en ligne, vous pouvez le télécharger depuis le l’adresse paramétré à l’étape 4.

Une fois téléchargé, l’application ne se lancera pas, vous avez un avertissement de droit. Pour autoriser l’application, allez dans Paramètres, Général > Gestion de l'appareil > App d'Entreprise (Nom entreprise) puis cliquer sur Faire confiance à « Nom Entreprise ».

Le fichier contenant le lien pour télécharger l’archive :

<html>
<head>
	<title>Mon application</title>
	<meta name="viewport" content="width=device-width" />
	<meta charset="utf-8">
</head>
<body>
	<ul>
		<li><a href="itms-services://?action=download-manifest&url=https://www.monsite.fr/app10/manifest.plist">Installer/MAJ New App IBeacon V 1.0.12 Build 1</a></li>
	</ul>
	<p>Instruction : Après installation allez dans Paramètres, Général > Gestion de l'appareil > App d'Entreprise (Mon entreprise)  puis cliquer sur Faire confiance à "Mon entreprise"</p>
</body>
</html>

Débugger votre application sur un device

Il est possible de débugger votre application même s’il tourne sur un smartphone, pour ce faire, si c’est pour Android, il faut ller à l’url :

chrome://inspect/#devices
Si votre smartphone est connecté par USB et que vous avez autorisé le debug par USB dans les paramètres de votre smartphone,dès que l'application tourne (après avoir fait la commande : ionic cordova run android --device )
vous aurez l'option pour ouvrir une nouvelle fenêtre :

Lien : https://ionicframework.com/docs/v3/developer-resources/developer-tips/

Cliquez sur Inspect pour débugger dans votre navigateur.

Déployer l’application Ionic pour Google Play (Instruction sous MacOS)

Mais il y a peu de différence sous Windows. Lien vers la documentation officielle

Créer la release

On est en release donc l’apk sera dans le répertire de release et non debug.

ionic cordova build --release android
/Users/monposte/sites/myApp/platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk

Signer l’APK

Le bundle généré par la précédente commande n’est pas signée, il faut le faire manuellement. Pour ce faire il faut générer une clé, si vous avez déjà la clé, passer cette étape

Générer le certificat pour signer l’application

 keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

Il vous sera demandé un mot de passe pour le keystore, un fichier nommé my-release-key.keystore sera créé. CE FICHIER EST ULTRA IMPORTANT NE LE PERDEZ PAS ! il n’est pas versionné de base.

Signature de l’application

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore /Users/monposte/sites/myApp/platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk alias_name

Si vous avez tout bon jusque là félicitation ! Maintenant une opération d’optimisation pour réduire la taille. Avec l’utilitaire zipalign,

~/Library/Android/sdk/build-tools/28.0.3/zipalign -v 4  /Users/monposte/sites/myApp/platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk myApp.apk

Maintenant on est prêt à déployer sur Google Play !!

Note sur Android App Bundle (.aab)

C’est un nouveau format qui permet une taille d’application plus réduite. C’est le format du futur qui remplacera le format apk. L’idée est de laisser la plateforme Google Play optimiser le code pour vous, et l’on obtient une taille d’application diminuée de moitié par rapport à un apk (sur un apk de 50 Mo)

Lien sur générer aab avec Ionic

Note si pas de réseau sur la version déployée sur Android

A partir du SDK28 (ou 27) vous ne pouvez plus faire de requêtes vers les url non sécurisées, sauf si vous ajoutez une directive dans AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...
        android:usesCleartextTraffic="true"
        ...>
        ...
    </application>
</manifest>

Source :

https://stackoverflow.com/questions/30326148/cordova-ionic-http-request-not-processing-while-emulating-or-running-on-dev

symfony

Test unitaire et fonctionnel avec Symfony

Pour lancer un test unitaire (cela suppose que vous avez installé ce qu’il faut pour lancer les tests):

./bin/phpunit
#pour lancer un test en particulier
./bin/phpunit tests/Utils/HelperTest.php   //indiquer le chemin complet

Pour les tests fonctionnels, on va faire comme si on avait un navigateur (mais ce n’est pas un vrai navigateur au sens où l’on démarre vraiment Google Chrome ou Firefox, pour ça il faut voir le plugin Panther)

Le cod eminimal pour ce genre de test est :

<?php
namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use App\Controller\SecurityController;

class RouteTest extends WebTestCase
{
    public function testLoginRoute()
    {

        $client = static::createClient();
        $client->request('GET', '/login');
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
    }
}

En fait on se sert du code PHP directement pour faire le rendu logique de la page. Pour se logger on fera de la manière suivante :

    public function testAdminLoginToApp()
    {
       $client = static::createClient([], [
            'PHP_AUTH_USER' => 'moi@mail.com',
            'PHP_AUTH_PW' => 'monpass',
        ]);

        // go to dashboard
        $crawler = $client->request('GET', '/dashboard');
        $elem = $crawler->filter('html > body > div > h1');

        // Verify the text in h1 as a proof i'm in
        $this->assertEquals('Dashboard', $elem->text());

    }

A la création du client, on injecte les identifiant et mot de passe, et on est loggé. Ensuite on émule le crawler en lui passant une requête de type GET. Puis on va explorer le DOM en utilisant la fonction filter pour extraire un élément du DOM

Suivre une redirection

Il est possible de suivre une redirection :

        $crawler = $client->request('GET', '/dashboard');
        $crawler = $client->followRedirect();
        $elem = $crawler->filter('html > body > div > h1');

Les tests fonctionnels peuvent prendre du temps, à la différence des test unitaires, vous pouvez vous rendre compte du temps avec la commande shell suivante :

time ./bin/phpunit

Restreindre le coverage des tests

Dans le fichier phpunit.xml.dist, vous pouvez indiquer les répertoires dont les tests seront exécutés.

symfony

Symfony custom form validation

Cette méthode est intéressante pour affiner votre contrôle d’un champ de formulaire. Par exemple nous allons ajouter un contrôle d’unicité de numéro de téléphone. Nous allons créer depuis le terminal un validateur

Création du validateur

php bin/console make:validator

Un prompt vous demande le nom de la classe validateur

 The name of the validator class (e.g. EnabledValidator):
 > UniquePhoneValidator                                 

 created: src/Validator/UniquePhoneValidator.php
 created: src/Validator/UniquePhone.php

On doit avoir deux classes, UniquePhone qui va servir pour créer l’annotation et UniquePhoneValidator qui contient le code qui va faire le contrôle d’unicité proprement dit.

Ensuite l’entité sur laquelle cette vérification va se faire, imaginons qu’on ait une entité Contrat, importons la classe créée qui se trouve dans la répertoire validator

Préparation de la classe UniquePhone

Pour pouvoir utiliser les annotation plus tard, nous devons importer une classe

<?php

namespace App\Validator;

use Doctrine\Common\Annotations\Annotation\Target;//ajouté
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD","ANNOTATION"}) // ajouté
 */
class UniquePhone extends Constraint
{
    /*
     * Any public properties become valid options for the annotation.
     * Then, use these in your validator class.
     */
    public $message = 'Le numéro de téléphone {{ value }} existe déjà.'; // modifié
}

Préparation de la classe UniquePhoneValidator

<?php

namespace App\Validator;

use App\Repository\MatriceRepository;//ajouté
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UniquePhoneValidator extends ConstraintValidator
{
    private $matriceRepository;v // on a besoin du repository pour faire le check
    public function __construct(MatriceRepository $matriceRepository)
    {
        $this->matriceRepository = $matriceRepository;
    }
    public function validate($value, Constraint $constraint)
    {
        /* @var $constraint \App\Validator\UniquePhone */

        $existingPhone = $this->matriceRepository->findOneBy(['clientTelFixe' => $value]); // ajouté

        if(!$existingPhone){ // ajouté
            return;
        }
        // TODO: implement the validation here
        $this->context->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $value)
            ->addViolation();
    }
}
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use App\Validator\UniquePhone;

Ensuite plus loin nous avons la propriété ( le champ) qui sera concernée par cette vérification.

    /**
     * @var string
     * @UniquePhone()
     * @ORM\Column(name="CLIENT_TEL_FIXE", type="string", length=50, nullable=false)
     */
    private $clientTelFixe;

    /**
     * @var string|null
     * @UniquePhone()
     * @ORM\Column(name="CLIENT_TEL_MOBILE", type="string", length=50, nullable=true)
     */
    private $clientTelMobile;

Remarquez que tout se fait par annotation, c’est Doctrine qui se charge de faire marcher ces annotations. Donc il suffit d’ajouter l’annotation@uniquePhone() aux deux propriétés de l’entité pour activer la vérification.

Contrainte sur une classe entière

Pour placer l’annotation sur une classe et non sur une méthode, vous devez modifier la classe de contraint UniquePhone

<?php

namespace App\Validator;

use Doctrine\Common\Annotations\Annotation\Target;//ajouté
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD","ANNOTATION","CLASS"}) // modifié
 */
class UniquePhone extends Constraint
{
    /*
     * Any public properties become valid options for the annotation.
     * Then, use these in your validator class.
     */
    public $message = 'Le numéro de téléphone {{ value }} existe déjà.'; // modifié

    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;  // ajouté
    }

}

On a modifié l’annotation Target pour ajouter CLASS, et on a ajouté la méhode getTargets() pour que le validator puisse retourner la classe. Et au dessus de l’entité, enlever les annotations au dessus des propriétés de l’entité pour mettre au dessus de la class.

* MyEntity 
* @UniquePhone()
....
class MyEntity
{
...

Modifier la classe UniquePhoneValidator, cette étape est très importante sinon le messagene s’affichera pas. $value représente désormais la classe, et plus le numéro de téléphone (évidemment),

class UniquePhoneValidator extends ConstraintValidator
{
    private $matriceRepository;

    public function __construct(MatriceRepository $matriceRepository)
    {
        $this->matriceRepository = $matriceRepository;
    }

    public function validate($value, Constraint $constraint)
    {
        /* @var $constraint \App\Validator\UniquePhone */

        // at matrice creation we do the check,
        if (is_null($value->getIdMatrice())) {
            $existingPhone = $this->matriceRepository->findOneBy(['clientTelFixe' => $value->getClientTelFixe()]);
        } else {
            // at edition we do not do the check
            return ;
        }

        if (!$existingPhone) {
            return;
        }


        // TODO: implement the validation here
        $this->context->buildViolation($constraint->message)
            ->atPath('clientTelFixe') // la propriété concernée par la contrainte, avec cette ligne le message d'erreur s'affichera
            ->setParameter('{{ value }}', $value->getClientTelFixe())
            ->addViolation();
    }
}

Note sur la vérification d’unicité

Cela fait beaucoup de travail pour une simple vérification d’unicité, je vous suggère de garder à l’idée qu’une vérification clientside peut être utile et plus simple, couplé à une requête Ajax.

Audit rapide d’un serveur Linux

Espace disque restant

$ du -sh /*

Type de distribution Linux

$ cat /etc/*release*

configuration matérielle (disques)

$ lsblk
#mémoire
cat /proc/meminfo

Mémoire RAM libre

$ free

Adresse IP

react native

React Native les permissions sur Android et IOS

https://github.com/react-native-community/react-native-permissions#ios

Il faut installer si ce n’est déjà fait le package react-native-permission

Exemple : Autoriser la camera

Pour Android

Aller dans le fichier AndroidManifest.xml et ajouter les entrées en xml, par exemple pour la caméra :

    <uses-permission android:name="android.permission.CAMERA" />

Pour IOS

Il faut éditer le fichier plist.info

#dans le fichier info.plist
	<key>NSCameraUsageDescription</key>
	<string>Usage de camera</string>

#dans le fichier Podfile
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec"

#après faites un 
cd ios && pod install

https://medium.com/@rossbulat/react-native-managing-app-permissions-for-ios-4204e2286598

https://github.com/moaazsidat/react-native-qrcode-scanner/issues/213

Il existe d’autres types d’autorisation (SMS, vibrations etc)

xcode

Xcode, IOS comment créer un provisioning profile

Update : MacOS Catalina, connaitre son UDID

Le provisioning profile vous permet de développer et déployer des application mobile sur IOS.

Pour qui n’a jamais fait, c’est un véritable challenge, tant sur la complexité et le sens obscure des mots techniques.

C’est quoi un provisioning profile? Avant tout dites vous que Apple a envie de tout controler, et veut s’assurer qu’on montre patte blanche avant de pouvoir utiliser sa plateforme. Ainsi pour installer une application, à la différence d’Android, il faut que votre application soit signée électroniquement. Et c’est là qu’intervient le provisioning profile.

Résumons : pour pouvoir installer votre application sur un device IOS, il vous faut un compte développeur sur developer.apple.com, il vous en coûtera 99 euros au minimum par an.

En phase de développement, vous choisissez quelle application doit tourner sur quel device (c’est très limitatif, mais c’est Apple !)

Le provisioning profile se construit à partir de l’id du device physique (UDID), du certificat (qui lui même est fait à partir du CSR qui est généré plus tôt)

Le provisioning profile est à télécharger depuis votre compte développeur sur votre ordinateur pour pouvoir dans XCode builder votre application. Ce provisioning profile sera ensuite mis sur votre device, sans quoi votre application ne pourra démarrer. Ceci peut arriver quand vous avez un provisioning profile effacé du compte développeur, vous pouvez installer l’application, mais elle ne démarrera pas (voire ne s’installera pas)

De quoi est composé un provisioning profile
  • Le development certificate : nécessaire pour tester une application sur une device physique (pour un émulateur pas besoin)
  • Unique Device Identifier, le UDID de votre device (grâce à Itunes vous pouvez le voir en connectant votre device à votre Mac, oui si vous n’avez pas de Mac, vous pouvez oublier les app IOS, il est possbile de contourner, mais est ce que le temps perdu à bidouiller en vaut-il la peine?
  • App ID, c’est l’Id de votre application (à créer sur le compte développeur)

Les étapes de création du provisioning profile:

  • créer un CSR (Certificate Signing Request)
  • sur votre compte développeur créez une application (il aura un AppId)
  • composer votre provisioning profile ensuite

Créer un CSR

Ouvrir l’application Trousseau D’accès (Keychain en anglais) et aller dans Certificate Assistant > demander un certificat. Enregistrez le

Sauvez votre certificat, allez dans votre compte développeur Apple, allez à la section « Certificates, Identifier & Profile », cliquez sur le + pour créer un certificat, uploader votre CSR, et un certificat (fichier avec extension .cer)sera généré que vous allez télécharger. Sur votre Mac, double cliquez sur ce certification pour le mettre dans le trousseau (keychain). Votre certificat a une durée de validité.

Si vous avez pris le soin de nommer votre clé, vous verrez dans votre trousseau la clé publique et privée. On peut passer à la suite

Sur le compte Apple, créez l’app Id (ou BundleId)

Il s’agit , allez dans la rubrique « Identifier », cliquez sur le +, vous allez créer une application avec un nom et un reverse domain (nom de domaine inversé en guise d’identifiant technique)

Ajoutez un device physique (entrez le UDID de votre appareil)

Pour une application React Native, allez dans le Finder, le répertoire IOS, et cliquez sur le fichier avec extension xcworkspace et non celui avec l’extension xcodeproj .

Créez votre provisioning profile

Enfin nous y sommes pour cette partie importante ! Allez dans la rubrique « Profile », créez un profile.

En phase de développement, choisissez « Development », pour déployer sur le store, ce sera un « Distribution » provisioning profile. Sur l’écran suivant vous allez choisir sur quelle application vous allez créer ce provisioning profile.

Enfin sur l’écran suivant, sélectionnez le certificat (le fichier avec extension .cer que vous avez téléchargé plus tôt)

Après avoir choisi le certificat (qui représente votre ordinateur Mac en fait) vous allez affecter au device (que vous avez entré plus tôt)

Ensuite vous pouvez télécharger votre provisioning profile, mais ce n’est pas nécessaire si vous laisser XCode gérer le signin automatiquement (recommandé)

Liens pour plus de lecture:

react native

Ajouter un splash screen sur React Native la méthode facile

Vous avez fini votre application et vous êtes sur la dernière ligne droite?

Pour avoir une application mobile professionnelle, il vous faut les icônes qui vont bien et le splash screen.

Image du splash screen, il est conseillé d’avoir une image de 3000 x 3000 pixels, et pour les icônes, il faut aussi une grande image, la méthode présentée va générer les différentes résolutions. icon.png sert de base à la génération d’icône, et monSplash.png à la génération du splash screen

Télécharger les packages npm nécessaires :

npm i @bam.tech/react-native-make
npm i react-native-splash-screen
# pour IOS il faut faire un pod install
cd ios && pod install
# génération du splash
# If you are using our cover splash
react-native set-splash --path "monSplash.png" --resize cover

#génération des icônes (pour Android et IOS)
react-native set-icon --path "icon.png"

https://blog.bam.tech/developer-news/set-up-your-react-native-splash-screen-in-15-minutes

Une méthode plus proche du natif pour mettre un splash screen:

https://medium.com/handlebar-labs/how-to-add-a-splash-screen-to-a-react-native-app-ios-and-android-30a3cec835ae

php

Manipulez les dates en PHP

La façon la plus commune que j’ai vu jusqu’à ce jour de créer une date en PHP est:

$today = date('Y-m-d')

la fonction date() et la classe DateTime

Traditionnellement on utilise date(), mais il existe aussi une classe DateTime, d’une utilisation plus complexe (car orienté objet et possédant plus de méthode et attributs). Voyons comment créer une date avec cette classe :

Ajouter des jours

$date = new DateTime(); // date d'aujourd'hui
#ajouter une durée à un objet DateTime


# on ajoute  un DateInterval
$date = new DateTime('2020-06-01');
$date->add(new DateInterval('P10D'));// ajoute 10 jours
echo $date->format('Y-m-d') . "\n";//on formate pour pouvoir afficher

on le voit sur l’exemple de l’ajout de durée, l’écriture est un peu plus lourde?La documentation officielle de PHP vous donnera plus d’informations. Le framework Symfony utilise l’objet DateTime.

Enlever des jours

# soustraire une durée DateInterval à un objet DateTime
$date = new DateTime('2020-06-01');
$date->sub(new DateInterval('P10D'));// enlève 10 jours
echo $date->format('Y-m-d') . "\n";

Ajouter un mois

$today = date('Y-m-d');
$time = strtotime($today);
$expire_date = date('Y-m-d',strtotime('+ 1 month');

calculer les jours ouvrés

formater une date

formater selon la locale

strtotime() est votre ami

strtotime() est une fonction qui convertit une date en un temps UNIX, en seconde compté depuis le 1 Janvier 1970, ce jour est appelé EPOCH. Donc elle vous donne le nombre de secondes écoulées depuis EPOCH. Documentation officielle de strtotime()

strtotime est une fonction puissante, qui permet de convertir en temps UNIX une date même si elle exprimée dans différents formats.

Là où strtotime est très utile, c’est justement sa capacité à convertir en UNIX timestamp (ou temps UNIX) différents format de date, permettant ainsi de faire des manipulation de date.

Ajouter une journée à une date

Nous allons voir comment ajouter simplement une journée à une date

$today = date('Y-m-d');
$unjour = 3600 * 24;//24 heures en secondes
$tomorrow = date('Y-m-d',strtotime($today) + $unjour)

Conversion de format de date

$format_us = '2020/06/16';
$timestamp = strtotime($format_us );
$format_fr = date('d/m/Y',$timestamp);
echo $format_fr; // 16/06/2020
#à noter que strtotime() selon la documentation "essait" de lire une date, il peut arriver qu'il ne parvienne pas à le faire.
#il n'y a pas vraiment de conversion automatique, on se sert de strtotime pour normaliser une date, en le convertissant en secondes.

Ajouter un fuseau horaire à une date

Parfois Javascript n’arrive pas à instancier une date si le string de la date n’est pas bien formé. Par exemple :

#format date envoyé par php :
date = '2020-06-12 12:21:22'
var d = new Date(date) // null
#il faut formater la date
date = '2020-06-12T12:21:22'

# pour ce faire lorsque que vous avez une date en PHP du type :
'2020-06-12 12:21:22'd, il faut utiliser strtotime :
$date = date('Y-m-d\TH:i:s',strtotime($abo['2020-06-12 12:21:22']) )
echo $date; //2020-06-12T12:21:22

TODO:

étant donné un mois, trouver le premier jour du mois précédent

le dernier jour du mois précédent

à partir d’une date get le mois seulement

Retour en haut