IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Accès concurrent à une page php


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut Accès concurrent à une page php
    Bonjour,

    Je suis en train réaliser une application web en php dans laquelle la saisie de texte (stocké en BDD) peut se faire de manière collaborative.

    Par contre il ne doit pas être possible de travailler sur le même texte (plus généralement la même ressource) en même temps. En clair lorsqu'un utilisateur veut accéder à une ressource en cours d'utilisation (et donc verrouillée) le système doit lui renvoyer un message d'erreur.

    Dans l'idéal le système doit être en mesure d'indiquer à l'utilisateur lorsque la ressource est libre.

    J'utilise le framework php Zend qui possède peut-être des classes en relation.

    Je n'ai rien trouvé de pertinent sur Internet.

  2. #2
    Membre expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Points : 3 972
    Points
    3 972
    Par défaut
    Bonsoir,

    Dans votre structure de base de données vous pouvez valoriser un champ "is_available" qui définit si le champ peut-être édité ou non.

    Par exemple avec la structure suivante cela donnerait :

    DocumentTypes(id,nom,date_ajout)
    Fields(id,nom,datatype,is_available,value,document_type_id)

    Ensuite pour savoir si un champ peut-être édité :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    class Field {
        private $_isAvailable, $_documenType, $_id, $_value;
     
        public function id(){
            return $this->_id;
        }
     
        public function value(){
            return $this->value;
        }
     
        public function documentType(){
            return $this->_document_type;
        }
     
        public function isAvailable(){
            return $_available;
        }
     
        static function loadFromDb($field_id){
            $field_row= mysql_fetch_array(mysql_query('SELECT * FROM Fields WHERE id='.$field_id));
            $field = new Field();
            $field->setDocumentType(DocumentType.loadFromDb($field_row['document_type_id']));
            $field->setAvailablity($field_row['is_available']);
            // etc..
            return $field;
        }
    }
    Ensuite lorsque vous listez les champs d'une table (un type de document) vous pouvez faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // $_GET['document_type_id'] = 20;
    $documentType = DocumentType.loadFromDb($_GET['document_type_id']);
    foreach($documentType->fields as $field){
        $is_available_attr = ($field->isAvailable()) ? '' : 'readonly="readonly"' ;
        echo '<input type="textbox" name="'.$field->id.'" value="'.$field->value.'" '.$is_available_attr.'/>';
    }
    Tu peux mettre à jour le champ is_available sur le onblur (perte de focus) d'un champ par exemple et mettre à jour la valeur du champ, afin de permettre à d'autres éditeurs de changer sa valeur. Pour l'effet inverse, c'est à dire reprendre la main sur un champ lorsque celui-ci se libère, tu peux faire une fonction de callBack avec AJAX qui aura pour but de vérifier le champ is_available du field en question et de rendre ce champ enabled si besoin.

  3. #3
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    Tu mets un marqueur dans ta base, pour indiquer sur la ressource est en modification. Par exemple tu as une table "BLABLA" avec une colonne "ISLOCKED" tu type entier ou booléen, lorsqu'un utilisateur ouvre en modification un des enregistrement tu modifie automatiquement ce même enregistrement en mettant la colonne à 1 ou true... Ainsi si une tierce personne venait à tenter de supprimer ou modifier la ressource, il n'en aurait pas le droit, sauf cas particulier.


    EDIT : grillé...

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut
    Merci pour vos réponses.

    J'ai pensé aussi utiliser un champ de la base de données pour indiquer si la ressource est disponible ou non. Je vais étudier vos solution.

    Le risque majeur est que l'utilisateur prenne une ressource et change son état à non disponible temporairement. Puis ne se déconnecte pas correctement (avec le bouton fermer du navigateur par exemple) et bloque la ressource à non disponible.

  5. #5
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    A partir du moment où il valide la ressource, le marqueur change.
    Cependant le risque de crash du navigateur est là, tu peux très bien faire une double vérification. Le première sur le marqueur et la seconde sur l'utilisateur en vérifiant s'il est toujours en ligne ou non...

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut
    Si mes souvenirs sont bons, il n'est pas possible de savoir exactement si l'utilisateur est toujours en ligne (problématique du compteur de visiteurs en ligne) mais il est possible de définir un timeout pour décrémenter le compteur (via son IP en BDD par exemple) au bout d'un certain laps de temps d'inactivité.

    J'ai bon ?

    Avec cette solution, une ressource pourrait quand même être bloqué alors qu'aucun utilisateur ne travaille dessus pendant une certaine période.

  7. #7
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    Tu peux très faire une requête asynchrone pendant que l'utilisateur visualise la page, qui toutes les 5 secondes valide sa présence.
    Si un nouvel utilisateur vient à vérifier la présence de la première, il regarde dans la base sa dernière validation, si elle date de plus de 5 secondes, dans ce cas il n'est plus considérer comme en ligne.
    Ou alors tu peux aussi le faire en fonction de son inactivité, c'est à dire que s'il ne fait rien pendant plus 5 minutes, il est "viré". Pour cela tu compte en javascript son temps d'inactivité, qui est mit à zéro dès qu'il bouge sa souris ou s'il appuie sur le clavier, au bout des 5 minutes, une requête est envoyé libérant la ressource, et par la même empêchant l'homme qui dort de continuer sa modification.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut
    Ok intéressant. Les 2 solutions que tu me proposent s'exécutent côté client, est-ce que ça ne risque pas de mettre le navigateur à genoux que de vérifier la présence de l'utilisateur toutes les 5 secondes ?

    Ceci étant dit, utiliser une requête javascript asynchrone me séduit bien dans ce cas là ^^ (ça rejoint l'idée de ThomasR avec AJAX).

  9. #9
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    Une requête toutes les 5 secondes ne créera qu'une montée de CPU toutes les 5sec entre 2 requêtes la charge disparait, mais comme il s'agit pas d'un traitement important de l'affichage est juste d'une requête, à moins d'utiliser une gameboy tout se passera bien.
    Mais si tu peux toujours augmenter l'intervalle.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut
    Ok, merci pour les réponses il me reste plus qu'à tester ça.

    J'ai encore des craintes au niveau fiabilité notamment en fonction du navigateur étant donnée que la solution est pour l'instant à base de javascript.

  11. #11
    Membre expert
    Avatar de ThomasR
    Homme Profil pro
    Directeur technique
    Inscrit en
    Décembre 2007
    Messages
    2 230
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2007
    Messages : 2 230
    Points : 3 972
    Points
    3 972
    Par défaut
    Citation Envoyé par Flynt Voir le message
    Ok, merci pour les réponses il me reste plus qu'à tester ça.

    J'ai encore des craintes au niveau fiabilité notamment en fonction du navigateur étant donnée que la solution est pour l'instant à base de javascript.
    Bonsoir,
    tu peux te servir de framework comme JQuery ou Prototype qui offre une grande compatibilité cross-browsers pour faire tes requêtes asynchrones.

    Le risque majeur est que l'utilisateur prenne une ressource et change son état à non disponible temporairement. Puis ne se déconnecte pas correctement (avec le bouton fermer du navigateur par exemple) et bloque la ressource à non disponible. [...] Ou alors tu peux aussi le faire en fonction de son inactivité
    Plus simple, tu peux executer une fonction en tache de fond côté serveur (cron) qui dévérouille les champs non modifiés depuis 1 minute par exemple.

  12. #12
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    J'aime bien Prototype, mais dans le cadre d'une utilisation assez rare d'action asynchrone, ce n'est pas très utile de l'utiliser, sauf si tu as besoin de toutes ses autres fonctionnalité, vraiment très pratique.
    Pour le cron c'est une bonne idée, mais 1 minutes c'est long (certes on peut diminuer, mais cela augmentera la charge serveur, surtout que le cron devra effectuer l'action pour un nombre inconnu d'enregistrement, certes c'est pas énorme, mais moi je préférais dans ce cas (chaque cas est différent) effectuer cette action que si nécessaire, en répartissant le travail coté client, c'est à dire uniquement si la modification est sollicitée, ou validée.

    Après chacun voit midi à sa porte, et l'idée du cron est tout aussi valable.

  13. #13
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Bonjour,

    Deux petites idées sur le sujet.

    1) Le is_available devrait à mon sens être une référence sur l'utilisateur
    qui s'approprie la ressource plutôt qu'un flag. ça évite le risque d'empêcher
    l'utilisateur qui a réservé la ressource de ne pas pouvoir la sélectionner si
    il revient sur la page donnant accès aux ressources libres. Celle-ci afficherait
    les ressources non bloquées ainsi que les ressources propres à l'utilisateur.

    2) Suivant la probabilité d'édition simultanée, il n'est pas forcement nécessaire
    de bloquer une ressource. On peut laisser les gens éditer et tester au moment
    de l'update. Si il y a eu deux éditions concurrentielles. Ceci peut se gérer avec un
    champ "lastmodified" qui contient la date de la dernière mise à jour.

    Ce champs est ajouté en tant que champ caché du formulaire et au moment
    de l'update on fait UPDATE ... WHERE id=$id AND lastmodified='$lastmodified'

    Si le nombre de mise à jours est de 0, c'est qu'il y a eu un update entre temps.
    Dans ce cas on affiche à l'utilisateur le champs modifié ainsi que sa saisie
    courante et on lui demande de gérer le conflit.

  14. #14
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    Je ne suis pas d'accord pour le second point, parce que le risque d'une erreur de vérification est trop grande, il vaut mieux stopper l'accès à la ressource en amont. De plus même dans le cas d'un nombre limité d'utilisateur la possibilité est toujours présente, surtout dans le cas de ressources récentes, et mobile, tel qu'une gestion de flux.
    Et comme il s'agit d'un outil dédié au travail collaboratif, le risque est d'autant plus grand.

    Le premier point est un plus non négligeable dans l'ergonomie.

  15. #15
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Citation Envoyé par deY! Voir le message
    Je ne suis pas d'accord pour le second point, parce que le risque d'une erreur de vérification est trop grande
    Peux-tu détailler ?

  16. #16
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Points : 2 284
    Points
    2 284
    Par défaut
    Citation Envoyé par marcha Voir le message

    2) ....
    Dans ce cas on affiche à l'utilisateur le champs modifié ainsi que sa saisie
    courante et on lui demande de gérer le conflit.
    Jolie solution, dans l'idéale.
    Concernant le point 1 je suis tout à fait d'accord, de plus cela permet derrière de faire du read only pour l'utilisateur qui n'a pas acquis le droit d'écriture.

    Dans la pratique des fois c'est assez compliqué de faire la différence si tu as des formulaires avec des champs générées à la volée..
    Du coup je suis plutôt, pour [strike]la fermeture[/strike] le contrôle en amont.

    Et j'en viens donc à mon idée de la chose sur ces questions d'ajax et autre requêtes asynchrones.
    Il y à qd même une solution technique multi navigateur, simple et efficace.. Une bête iframe avec meta refresh.
    Et c'est cette iframe qui va signifier que l'utilisateur Y est entrain de modifier la ressource Z.
    C'est aussi cette iframe qui va s'occuper de nettoyer les verrous morts car il ne faut surtout pas compter sur l'utilisateur pour cliquer sur le bouton fermer de l'application et pi un crash et si vite arrivé...

    a plus

  17. #17
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Une bête iframe avec meta refresh
    Cette solution a l'avantage d'être simple mais il y a un risque:

    Si pour une raison de surcharge du réseau ou du serveur, la requête n'aboutit
    pas, l'iframe se retrouve avec une page d'erreur et s'en est fini du refresh.

    Si on veut vraiment éviter d'utiliser XmlHTTPRequest on pourrait toujours
    utiliser la technique de l'iframe met en changeant sa source depuis la page
    principale à intervalles réguliers. ex: (page.php?user=...&stamp=...)

  18. #18
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Dans la pratique des fois c'est assez compliqué de faire la différence si tu as des formulaires avec des champs générées à la volée..
    Du coup je suis plutôt, pour [strike]la fermeture[/strike] le contrôle en amont.
    Oui, d'accord avec ça

  19. #19
    Membre averti Avatar de deY!
    Inscrit en
    Avril 2006
    Messages
    403
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2006
    Messages : 403
    Points : 414
    Points
    414
    Par défaut
    Citation Envoyé par marcha Voir le message
    Peux-tu détailler ?
    Le test au niveau de la mise à jour est trop risqué. Puisqu'il s'agit là de la dernière porte avant modification, une erreur de vérification est vite arrivée. Donc oui, on peut effectuer cette vérification, mais obligatoirement couplée avec un verrouillage de l'accès en édition avant.

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    96
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2007
    Messages : 96
    Points : 63
    Points
    63
    Par défaut
    Citation Envoyé par marcha Voir le message
    1) Le is_available devrait à mon sens être une référence sur l'utilisateur
    qui s'approprie la ressource plutôt qu'un flag. ça évite le risque d'empêcher
    l'utilisateur qui a réservé la ressource de ne pas pouvoir la sélectionner si
    il revient sur la page donnant accès aux ressources libres. Celle-ci afficherait
    les ressources non bloquées ainsi que les ressources propres à l'utilisateur.
    D'accord avec ça, merci pour l'idée.
    2) Suivant la probabilité d'édition simultanée, il n'est pas forcement nécessaire
    de bloquer une ressource. On peut laisser les gens éditer et tester au moment
    de l'update. Si il y a eu deux éditions concurrentielles. Ceci peut se gérer avec un
    champ "lastmodified" qui contient la date de la dernière mise à jour.
    Pas d'accord, comme le rappelle deY! l'outil est collaboratif, et il est vraiment nécessaire d'empêcher l'accès à une ressource en simultanée.

    Concernant les solutions techniques, je suis familier avec jquery et ses fonctions de requetes asynchrones.

    Une solution pourrait être de vérifier en javascript l'accès à la ressource par un utilisateur et de doubler cette vérification par un cron (aucune idée pour l'implémentation mais je devrais trouver) pour restreindre le risque en cas de problème côté client.

    Et j'en viens donc à mon idée de la chose sur ces questions d'ajax et autre requêtes asynchrones.
    Il y à qd même une solution technique multi navigateur, simple et efficace.. Une bête iframe avec meta refresh.
    Et c'est cette iframe qui va signifier que l'utilisateur Y est entrain de modifier la ressource Z.
    Je n'ai jamais expérimenté cette technique. J'ai cru lire que l'on obtenait pas le même résultat en fonction des navigateurs.
    De plus, est-ce que cette technique ne provoque pas un effet visuel désagréable ? Ce qui risque d'être un peu lourd si le refresh est effectué régulièrement.

Discussions similaires

  1. Accès d'une page php avec une iframe
    Par gianni7033 dans le forum Langage
    Réponses: 4
    Dernier message: 24/07/2009, 17h00
  2. [Sécurité] Protéger l'accès à une page php
    Par nitteN dans le forum Langage
    Réponses: 5
    Dernier message: 02/04/2008, 13h05
  3. [PHP-JS] interdire l'accès direct à une page php
    Par clem037 dans le forum Langage
    Réponses: 10
    Dernier message: 17/03/2008, 22h04
  4. Réponses: 1
    Dernier message: 20/09/2006, 00h29
  5. Réponses: 5
    Dernier message: 09/01/2006, 11h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo