Je ne suis pas un développeur PHP, donc je me demande si en PHP est plus populaire d'utiliser des getter / setters explicites, dans un pur style OOP, avec des champs privés (comme j'aime):
class MyClass {
private $firstField;
private $secondField;
public function getFirstField() {
return $this->firstField;
}
public function setFirstField($x) {
$this->firstField = $x;
}
public function getSecondField() {
return $this->secondField;
}
public function setSecondField($x) {
$this->secondField = $x;
}
}
ou simplement des domaines publics:
class MyClass {
public $firstField;
public $secondField;
}
Merci
php
oop
coding-style
marque
la source
la source
Réponses:
Vous pouvez utiliser les méthodes magiques php
__get
et__set
.la source
__get
et__set
. Il y a deux soulignements, pas un. Voici le lien direct vers la partie droite de la page: php.net/manual/en/… (+1 pour une réponse correcte)public
propriétés, s'il n'y a pas de validation / assainissement?Pourquoi utiliser des getters et setters?
la source
Google a déjà publié un guide sur l'optimisation de PHP et la conclusion était:
Aucun getter et setter Optimisation de PHP
Et non, vous ne devez pas utiliser de méthodes magiques . Pour PHP, la méthode magique est mauvaise. Pourquoi?
PHP n'est pas Java, C ++ ou C #. PHP est différent et joue avec des rôles différents.
la source
$dog->name = 'fido'
mieux que$dog->setName('fido')
. Lors de la mutation d'une propriété (ex:$dog->increaseAge(1)
je peux développer la méthode qui effectue la validation nécessaire et mute cette propriété. Mais toutes les actions ne nécessitent pas vraiment de mutation dans ce sens.L'encapsulation est importante dans n'importe quelle langue OO, la popularité n'a rien à voir avec cela. Dans les langages typés dynamiquement, comme PHP, il est particulièrement utile car il existe peu de moyens de garantir qu'une propriété est d'un type spécifique sans utiliser de setters.
En PHP, cela fonctionne:
En Java, cela ne fait pas:
L'utilisation de méthodes magiques (
__get
et__set
) fonctionne également, mais uniquement lorsque vous accédez à une propriété dont la visibilité est inférieure à celle à laquelle l'étendue actuelle peut accéder. Il peut facilement vous donner des maux de tête lorsque vous essayez de déboguer, s'il n'est pas utilisé correctement.la source
$bar
comme unint
dans le premier exemple: wiki.php.net/rfc/typed_properties_v2Si vous préférez utiliser la fonction __call, vous pouvez utiliser cette méthode. Cela fonctionne avec
$this->property()
$this->property($value)
$this->getProperty()
$this->setProperty($value)
kalsdas
la source
property_exists(get_class($this), $name)
et la récursivité est lente. Il existe un moyen d'y remédier avec le cache, mais cela sera toujours plus lent que de créer les getters et setters à la main. Je l'ai seulement écrit comme alternative. En fait, je ne recommande pas d'utiliser les "méthodes magiques". Le temps supplémentaire de création des getters et setters est généralement insignifiant.En plus des réponses déjà excellentes et respectées ici, je voudrais développer PHP n'ayant pas de setters / getters.
PHP n'a pas de syntaxe getter et setter . Il fournit des méthodessous-classées ou magiques pour permettre le "hooking" et le remplacement du processus de recherche de propriété, comme l'a souligné Dave .
Magic nous permet aux programmeurs paresseux de faire plus avec moins de code à un moment où nous sommes activement engagés dans un projet et le connaissons intimement, mais généralement au détriment de la lisibilité.
Performances Chaque fonction inutile, qui résulte du forçage d'une architecture de code de type getter / setter en PHP, implique son propre cadre de pile de mémoire lors de l'invocation et gaspille les cycles CPU.
Lisibilité: la base de code entraîne des lignes de code gonflées, ce qui a un impact sur la navigation dans le code, car plus de LOC signifie plus de défilement.
Préférence: Personnellement, comme règle de base, je prends l'échec de l'analyse de code statique comme un signe pour éviter de descendre sur la route magique tant que des avantages évidents à long terme m'échappent à ce moment-là.
Illusions:
Un argument commun est la lisibilité. Par exemple, c'est
$someobject->width
plus facile à lire que$someobject->width()
. Cependant, contrairement à une planètecircumference
ouwidth
, ce qui peut être supposé êtrestatic
, l'instance d'un objet telle que$someobject
, qui nécessite une fonction de largeur, prend probablement une mesure de la largeur d'instance de l'objet.Par conséquent, la lisibilité augmente principalement en raison de schémas de dénomination affirmés et non en masquant la fonction qui génère une valeur de propriété donnée.
__get / __set utilise:
pré-validation et pré-assainissement des valeurs immobilières
chaînes par exemple
Dans ce cas
generatelatex
, adhérerait à un schéma de dénomination actionname + methodnamecas spéciaux et évidents
Remarque: PHP a choisi de ne pas implémenter la syntaxe getter / setter. Je ne prétends pas que les getters / setter sont généralement mauvais.
la source
Prêt!
la source
Eh bien, PHP a des méthodes magiques
__get
,__set
,__isset
et__unset
, ce qui est toujours un début. Hélas, les propriétés OO sont bien plus que des méthodes magiques. Le principal problème avec l'implémentation de PHP est que les méthodes magiques sont appelées pour toutes les propriétés inaccessibles. Ce qui signifie que vous devez vous répéter (par exemple en appelant property_exists ()) dans les méthodes magiques pour déterminer si le nom est réellement une propriété de votre objet. Et vous ne pouvez pas vraiment résoudre ce problème général avec une classe de base à moins que toutes vos classes héritent de ie. ClassWithProperties, car PHP manque d'héritage multiple.En revanche, Python propose de nouvelles classes de style
property()
, ce qui vous permet de définir explicitement toutes vos propriétés. C # a une syntaxe spéciale.http://en.wikipedia.org/wiki/Property_(programming)
la source
J'ai fait une expérience en utilisant la méthode magique __call. Je ne sais pas si je devrais le poster (à cause de tous les avertissements "NE PAS UTILISER DE MÉTHODES MAGIQUES" dans les autres réponses et commentaires) mais je vais le laisser ici .. juste au cas où quelqu'un le trouverait utile.
Ajoutez simplement cette méthode ci-dessus dans votre classe, vous pouvez maintenant taper:
De cette façon, vous pouvez obtenir / définir tout dans votre classe s'il existe, donc si vous n'en avez besoin que pour quelques éléments spécifiques, vous pouvez utiliser une "liste blanche" comme filtre.
Exemple:
Maintenant, vous ne pouvez obtenir / définir que "foo" et "fee".
Vous pouvez également utiliser cette "liste blanche" pour attribuer des noms personnalisés pour accéder à vos vars.
Par exemple,
Avec cette liste, vous pouvez maintenant taper:
.
.
.
C'est tout.
Doc: __call () est déclenché lors de l'appel de méthodes inaccessibles dans un contexte d'objet.
la source
Après avoir lu les autres conseils, j'ai tendance à dire que:
En tant que GÉNÉRIQUE règle, vous définirez pas toujours setters pour TOUS les propriétés, spécialement les « internes » (sémaphores, drapeaux internes ...). Les propriétés en lecture seule n'auront évidemment pas de setters, donc certaines propriétés n'auront que des getters; c'est là que __get () vient réduire le code:
Oui! nous pourrions également écrire une méthode privée pour le faire, mais là encore, nous aurons de nombreuses méthodes déclarées (++ mémoire) qui finiront par appeler une autre méthode, toujours la même. Pourquoi tout simplement pas écrire un SEULE méthode pour les gouverner tous ...? [oui! jeu de mots absolument destiné! :)]
Les régleurs magiques peuvent également répondre UNIQUEMENT à des propriétés spécifiques, de sorte que toutes les propriétés de type date peuvent être filtrées contre les valeurs non valides dans une seule méthode. Si les propriétés de type date étaient répertoriées dans un tableau, leurs paramètres peuvent être définis facilement. Juste un exemple, bien sûr. il y a beaucoup trop de situations.
À propos de la lisibilité ... Eh bien ... C'est un autre débat: je n'aime pas être lié aux utilisations d'un IDE (en fait, je ne les utilise pas, ils ont tendance à me dire (et à me forcer ) comment écrire ... et j'ai mes goûts sur le codage "beauté"). J'ai tendance à être cohérent sur le nommage, donc l'utilisation de ctags et de quelques autres aides me suffit ... Quoi qu'il en soit: une fois que tous ces setters et getters magiques sont terminés, j'écris les autres setters qui sont trop spécifiques ou "spéciaux" pour être généralisé dans une méthode __set (). Et cela couvre tout ce dont j'ai besoin pour obtenir et définir des propriétés. Bien sûr: il n'y a pas toujours un terrain d'entente, ou il y a tellement de propriétés qui ne valent pas la peine de coder une méthode magique, et puis il y a toujours la bonne vieille paire setter / getter traditionnelle.
Les langages de programmation ne sont que cela: les langages artificiels humains. Donc, chacun d'eux a sa propre intonation ou accent, syntaxe et saveur, donc je ne prétendrai pas écrire un code Ruby ou Python en utilisant le même "accent" que Java ou C #, ni écrire JavaScript ou PHP pour ressembler Perl ou SQL ... Utilisez-les comme ils sont censés être utilisés.
la source
De manière générale, la première méthode est plus populaire dans l'ensemble, car ceux qui ont des connaissances en programmation peuvent facilement passer à PHP et effectuer le travail de manière orientée objet. La première voie est plus universelle. Mon conseil serait de rester fidèle à ce qui a fait ses preuves dans de nombreuses langues. Ensuite, quand et si vous utilisez une autre langue, vous serez prêt à accomplir quelque chose ( au lieu de passer du temps à réinventer la roue ).
la source
Il existe de nombreuses façons de créer un code source dans une convention netbeans. C'est sympa. Cela rend la pensée tellement plus facile === FAUX. Utilisez simplement la traditionel, surtout si vous n'êtes pas sûr de laquelle des propriétés doit être encapsulée et laquelle ne l'est pas. Je sais, c'est un code boi .... pla ..., mais pour les travaux de débogage et beaucoup d'autres pense que c'est le meilleur moyen clair. Ne passez pas trop de temps avec des milliers d'arts à faire de simples getters et setters. Vous ne pouvez pas implémenter trop de modèles de conception comme la règle déméter et ainsi de suite, si vous utilisez des magies. Dans une situation spécifique, vous pouvez utiliser magic_calls ou pour des solutions petites, rapides et claires. Bien sûr, vous pouvez également apporter des solutions aux concepteurs de design, mais pourquoi vous rendre la vie plus difficile.
la source
Validation + formatage / dérivation des valeurs
Les setters vous permettent de valider les données et les getters vous permettent de formater ou de dériver les données. Les objets vous permettent d'encapsuler les données et leur code de validation et de mise en forme dans un package soigné qui encourage DRY.
Par exemple, considérez la classe simple suivante qui contient une date de naissance.
Vous voudrez valider que la valeur définie est
Et vous ne voulez pas faire cette validation partout dans votre application (ou sur plusieurs applications d'ailleurs). Au lieu de cela, il est plus facile de rendre la variable membre protégée ou privée (afin de faire du setter le seul point d'accès) et de valider dans le setter car vous saurez alors que l'objet contient une date de naissance valide, quelle que soit la partie du l'application d'où provient l'objet et si vous souhaitez ajouter plus de validation, vous pouvez l'ajouter en un seul endroit.
Vous voudrez peut-être ajouter plusieurs formateurs qui fonctionnent sur la même variable membre, c.-à-d.
getAge()
EtgetDaysUntilBirthday()
et vous voudrez peut-être appliquer un format configurable engetBirthDate()
fonction des paramètres régionaux. Par conséquent, je préfère accéder systématiquement aux valeurs via des getters plutôt que de les mélanger$date->getAge()
avec$date->birth_date
.les getters et setters sont également utiles lorsque vous étendez des objets. Par exemple, supposons que votre application devait permettre des dates de naissance de plus de 150 ans dans certains endroits mais pas dans d'autres. Une façon de résoudre le problème sans répéter aucun code serait d'étendre l'
BirthDate
objet et de mettre la validation supplémentaire dans le setter.la source
setHired
etsetHireDate
. Il n'est pas valide de laisser quelqu'un fixer une date d'embauche sans définir également l'employé comme embauché. Mais il n'y a aucun moyen que vous appliquiez cela. Si vous l'imposez dans l'un de ces setters, alors vous forcez l'ordre de "setting", et cela nécessite plus de lecture de code d'un développeur pour le savoir. Ensuite, lorsque vous allez faire une méthode comme$employee->promote($newPosition);
vous devez vérifier un indicateur pour voir si la validation a été effectuée ou supposer que cela n'a pas été fait et recommencer (redondant).$employee->updateWorkStatus($hired, $hireDate);
- être ou si plus avancé$employee->adminUpdate(\Employee\AdminUpdateDTO $dto);
. Vous pouvez maintenant valider dans le contexte dont vous avez besoin et décider si une validation supplémentaire est nécessaire.Ce message n'est pas spécifiquement sur
__get
et__set
mais c'est plutôt__call
la même idée, sauf pour l'appel de méthode. En règle générale, je reste à l'écart de tout type de méthodes magiques qui permettent la surcharge pour les raisons décrites dans les commentaires et les messages CEPENDANT , j'ai récemment rencontré une API tierce que j'utilise qui utilise un SERVICE et un SOUS-SERVICE, par exemple :La partie importante de cela est que cette API a tout de même sauf la sous-action, dans ce cas
doActionOne
. L'idée est que le développeur (moi-même et les autres utilisateurs de cette classe) pourrait appeler le sous-service par son nom par opposition à quelque chose comme:Je pourrais faire à la place:
Pour coder en dur ce serait juste beaucoup de duplication (cet exemple ressemble très vaguement au code):
Mais avec la méthode magique de
__call()
je suis en mesure d'accéder à tous les services avec des méthodes dynamiques:L'avantage de cet appel dynamique pour le retour de données est que si le fournisseur ajoute un autre sous-service, je n'ai pas besoin d'ajouter une autre méthode dans la classe ou de créer une classe étendue, etc. Je ne sais pas si cela est utile pour tout le monde, mais je pensais que je montrerais un exemple où
__set
,__get
,__call
, etc. peut être une option pour une contrepartie puisque la fonction principale est le retour des données.ÉDITER:
Par coïncidence, j'ai vu cela quelques jours après la publication qui décrit exactement mon scénario. Ce n'est pas l'API à laquelle je faisais référence mais l'application des méthodes est identique:
Est-ce que j'utilise correctement l'api?
la source
Mise à jour: n'utilisez pas cette réponse car c'est un code très stupide que j'ai trouvé pendant que j'apprends. Utilisez simplement getter et setter, c'est beaucoup mieux.
J'utilise généralement ce nom de variable comme nom de fonction, et j'ajoute un paramètre facultatif à cette fonction, donc lorsque ce paramètre facultatif est rempli par l'appelant, je lui attribue la propriété et je renvoie $ cet objet (chaînage), puis lorsque ce paramètre facultatif n'est pas spécifié par appelant, je rends juste la propriété à l'appelant.
Mon exemple:
la source