php5 - création de sous-objets

Petit nouveau ! | 7 Messages

08 févr. 2012, 17:52

Salut à tous,

je me prends un peu la tête sur une archi toute bête mais je vois pas la soluce. Disons que j'ai une classe principale "Webservice". L'une des méthodes permet d'authentifier un utilisateur: "Login()". J'aimerais en fait pouvoir agir sur l'objet "User" après le "Login". Par exemple:
$app = new Webservice;
$user = $app->Login('login', 'password');
$user->upload('/tmp/file/9dk3');
La classe Webservice gère toutes les méthodes publiques, y compris les appels Curl du Webservice.
J'aimerais activer/désactiver certaines méthodes en fonction de l'état de l'objet User.

Exemple:
$user = $app->Login(...) 
$user->upload(...)
// Une fois loggué, l'utilisateur peut uploader
// En revanche
$guest = $app->Guest(...)
$guest->download(...)
//Une fois loggué, le guest ne peut que downloader, pas uploader
Mais surtout l'idée est d'éviter d'instancier 15x Webservice, ou de devoir réécrire 15x les mêmes méthodes. J'ai pensé faire des classes "User" et "Guest", les instancier dans Login et dans Guest et les retourner pour avoir un object. Mais par facile d'interagir de nouveau à eux.

Si vous avez une idée, je suis preneur. Merci par avance :wink:

ViPHP
xTG
ViPHP | 7331 Messages

08 févr. 2012, 19:49

En un mot héritage : une class Guest et User qui hérite de la première en surchargeant les méthodes (car un User c'est un invité spécial en fait).
Ou bien le contrat : une interface qui répertorie toutes les fonctions et une class Guest et User qui les implémentent mais de façon différente.

Mammouth du PHP | 1511 Messages

09 févr. 2012, 04:47

Bonjour,
tu as une classe WebService que tu instancies une seule fois ? A t'elle un constructeur ?
Si ce n'est pas le cas, autant en faire une classe statique.
Chaque méthode retourne une instance de classe et c'est réglé.
Exemple:
<?php
class WebService {
	static public function login($user, $password) {
		$userInstance = new User((string)$user, (string) $password);
		//Quelques traitements en plus...
		return $userInstance;
	}
}

class User {
	public function __construct($user, $pass) {}
	public function upload($file) {[...]}
}

WebService::login('foo', 'bar')->upload('/tmp/qsd4646');

?>
Tu peux dans ta classe User ou dans ta méthode WebService::login stocker les données de l'utilisateur pour ne pas réinstancier un utilisateur à chaque fois.
Modifié en dernier par momox le 09 févr. 2012, 14:52, modifié 1 fois.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

09 févr. 2012, 14:48

@momox : ton exemple n'est en rien statique, il y a d'ailleurs des risque que php se fache vue que tu n'indique pas le mot clef statique.

Au final un mélange de tous cela serais une bonne solution :
- webservice devient un singleton
- utiliser l'héritage ou interface pour les classes user / guest (et oui il faudra deux classes :) ).

le singleton t'apportera le comportement que tu souhaite sr l'unicité de l'instance, par contre il faudra faire super gaffe au changement de valeur.

Par contre dans ton code exemple ne ne vois pas de multiple utilisation de webservice (peux être est ce dans le reste du code ?), si l'appel est unique autant ne pas trop t'emmerder.

Par contre si tu passe l'objet en session pourquoi pas.
(enfin perso je garderais ton webservice ainsi et i retourne soit "user" soit un "guest", et tu garde le retour en session, lors de la connexion tu remplace).

@+
Il en faut peu pour être heureux ......

Mammouth du PHP | 1511 Messages

09 févr. 2012, 14:51

Vi effectivement... Coder un snippet d'exemple a 3h du matin n'est pas une bonne idée...
J'ai corrigé mon code.

ViPHP
xTG
ViPHP | 7331 Messages

09 févr. 2012, 16:25

13h51 c'est l'heure de la sieste ! :D

public static function et non static public function en PHP ;)

Eléphant du PHP | 209 Messages

09 févr. 2012, 16:31

public static function et non static public function en PHP ;)
Tiens tu m'interpelles là. Je n'avais jamais fais la différence.. Quelle est-elle ?

Mammouth du PHP | 1511 Messages

09 févr. 2012, 16:43

Idem... Quelle est la différence ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

09 févr. 2012, 16:59

Il n'y en a pas, les 2 syntaxes sont équivalentes et acceptées.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Petit nouveau ! | 7 Messages

09 févr. 2012, 18:01

Hello, merci à tous pour vos réponses,
Par contre dans ton code exemple ne ne vois pas de multiple utilisation de webservice (peux être est ce dans le reste du code ?), si l'appel est unique autant ne pas trop t'emmerder.
en fait, si, car cela peut se passer en plusieurs temps. Un utilisateur doit se logguer pour accéder au Webservice
$user = $app->login('login', 'pass');
il peut ensuite effectuer différentes actions, par exemple créer un nouvel utilisateur sous lui:
$new_user = $user->addUser('email', 'password');
enfin, le nouveau utilisateur peut effectuer des actions dans son compte
$new_user->upload('my_file');

Voila ce que j'imaginais un peu. Du coup j'avais commencé à faire ça:
<?php

class Webservice {

	public function __construct() {
	
	}

	public function login($login, $pass) {
		return new User($login, $pass);
	}
	
	protected function createUser($email, $pass) {
	
	}
}


class User {
	
	public function __construct($login, $pass) {
		
	}
	
	public function createUser($email, $pass) {
		parent::createUser($email, $pass);
	}
}

$app = new Webservice;
$user = $app->login('login', 'pass');
$new_user = $user->createUser('email', 'pass');

?>
mais là, dans ce cas, la class Webservice n'est pas parente de la class User. Donc le parent::createUser foire lamentablement.
j'ai pensé à mettre la class User en extends Webservice mais du coup, Webservice est de nouveau instantiée.

L'idée est aussi de réussir à récupérer l'objet User qui a appelé Webservice::createUser afin de savoir que c'est l'User 1234 qui a créé l'user 4567.

EDIT: Je pourrais bien sûr le faire différemment, en me trimballant un array d'Users, ou en passant en paramètre de chaque méthode le User concerné par l'appel. J'aimerais autant éviter et faire un truc propre d'où cette idée de création d'objets dynamiques ayant leurs méthodes et leurs propriétés propres.

Merci
Modifié en dernier par Aquel le 09 févr. 2012, 18:10, modifié 1 fois.

ViPHP
xTG
ViPHP | 7331 Messages

09 févr. 2012, 18:05

Il n'y en a pas, les 2 syntaxes sont équivalentes et acceptées.
Au temps pour moi, en effet seul mon éditeur l'envoie balader mais l'exécution se passe correctement elle. :)

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

09 févr. 2012, 18:13

Il n'y en a pas, les 2 syntaxes sont équivalentes et acceptées.
Au temps pour moi, en effet seul mon éditeur l'envoie balader mais l'exécution se passe correctement elle. :)
Comme tu as écris correctement "au temps pour moi", je t'absous, mon fils
Image
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Petit nouveau ! | 7 Messages

09 févr. 2012, 18:14

Hmmm je crois que je me suis un peu pris la tête. Ca fonctionne tout simplement en fait:
<?php

class Webservice {

	public function __construct() {
	
	}

	public function login($login, $pass) {
		
	}
	
	protected function createUser($email, $pass) {
		echo 'ptotou';
	}
}


class User extends Webservice {
	
	public function __construct($login, $pass) {
		
	}
	
	public function createUser($email, $pass) {
		parent::createUser($email, $pass);
	}
}

$user = new User('login', 'pass');
$new_user = $user->createUser('email', 'pass');

?>

Tellement simplement que je dois oublier quelque chose. Il y a forcement un truc qui ne va pas fonctionner :D

Eléphant du PHP | 209 Messages

09 févr. 2012, 19:03

Tu m'as perdu dans ce que tu voulais faire là...
Déjà, il faut savoir si tu es consommateur ou émetteur. J'ai l'impression que tu es émetteur mais j'ai des doutes =/
Ton WebService de base n'est pas censé tout savoir faire. Il doit juste proposer des méthodes génériques pour les web services plus spécifiques. En gros connexion à une adresse, login, mot de passe d'accès, gestion des paramètres d'entrée, des paramètres de sortie, éventuellement parsing XML, couche sécurité etc.
Si je lis ton code, ton objet User est un WebService.. 0_ô

Petit nouveau ! | 7 Messages

09 févr. 2012, 19:16

Ton WebService de base n'est pas censé tout savoir faire. Il doit juste proposer des méthodes génériques pour les web services plus spécifiques.
Oui et non, je pourrais être d'accord avec toi. MAIS certaines méthodes comme l'upload peuvent être accessible au Guest et au User. Je fais pas faire un copier/coller de la méthode Upload dans la class User et dans la class Guest.

Ce que je voulais faire, c'était avoir une classe Webservice qui connaisse toutes les méthodes disponibles, y compris sécurité, distant calls, ... et plusieurs autres classes qui servent à activer l'accès aux méthodes de Webservice en fonction des droits. Par exemple, dans Webservice, il y a 2 méthodes: upload et download. Disons qu'un User authentifié a le droit d'utiliser les deux alors que le Guest n'a le droit que d'utiliser download. D'où mes classes Guest et User qui extend Webservice.
<?php 

// Authenticated User
class YSIUser extends Webservice {

	public $token;
	
	// Automatic login on instantiation
	public function __construct($api_key, $email, $password) {
		parent::__construct($api_key);
		if ($token = parent::userLogin($email, $password)) {
			// Saving token
			$this->token = $token;
		}
	}
	
	// User may upload
	public function upload() {
		parent::upload();
	}
	
	// User may download
	public function download() {
		parent::download();
	}	
}

// Guest User
class YSIGuest extends Webservice {

	private $token;
	
	// Automatic login
	public function __construct($api_key, $email) {
		parent::__construct($api_key);
		if ($token = parent::guestLogin($email)) {
			// Saving token
			$this->token = $token;
		}
		
		// User may download
		public function download() {
			parent::download();
		}		
	}
}

?>
Meilleure idée??