PHP OOP: Iterate over all objects created from a class - php

I want to create a <select> field from all Gender objects. Is there a way to iterate over all the objects created from the class of Gender?
class Gender {
public static $counter = 0;
public $id;
public $gender;
public function __construct($gender){
Gender::$counter++;
$this->id = Gender::$counter;
$this->gender = $gender;
}
}
// Objects
$gender_male = new Gender('Male');
$gender_female = new Gender('Female');

Is there a way to iterate over all the objects created from the class of Gender?
To a degree, yes, but it's a very bad idea design-wise.
Why not put all the relevant objects you want to query into an array?
$genders = array();
$genders["male"] = new Gender('Male');
$genders["female"] = new Gender('Female');
you can then walk through each element using
foreach ($genders as $gender)
echo $gender->id;

Something like this you could do.
class Gender {
public static $genders = array();
public $gender;
public function __construct($gender){
$this->gender = $gender;
self::genders[] = $this;
}
}
// Objects
$gender_male = new Gender('Male');
$gender_female = new Gender('Female');
foreach(Gender::genders as $gender) {
...
}

This is my solution:
$_genders = array('Male','Female','Alien');
$gender = array();
foreach($_genders as $g)
{
$gender[$g] = new Gender($g);
}

Maybe a Container-Class would fit perfect for this task.
Take a look to: SplObjectStorage

class Gender {
public static $counter = 0;
public $id;
public $gender;
private static $instances = array();
public function __construct($gender){
Gender::$counter++;
$this->id = Gender::$counter;
$this->gender = $gender;
self::$instances[] = $this;
}
public static function getInstances(){
return self::$instances;
}
}
new Gender( "male" );
new Gender( "male" );
foreach( Gender::getInstances() as $genderInstance ) {
echo $genderInstance->gender;
}

I understand now that it's an extreme overkill to use a class but for the sake of knowing how it's done, here's the new code (based on all your comments):
class Gender {
public static $counter = 0;
public static $genders = array();
public function __construct($gender){
// Here it is
Gender::$genders[++Gender::$counter] = $gender;
}
}
// Objects
$gender_male = new Gender('Male');
$gender_female = new Gender('Female');
It's a group achievement in its own way but I think I'll switch to arrays instead. :-)

Related

Can't add data from php array to json database

I have got problem with array. When i add string to json_encode it save in db but $object give me [{},{},{}]Can you tell me guys what i am doing wrong?
$objects = array();
$objects[] = new Person(1, 'John', 'Smith','java');
$objects[] = new Person(2, 'Stacy', 'Smith','php');
$Db ='./DB.json';
$saveInBase = json_encode($objects);
file_put_contents($Db, $saveInBase);
$loadFromBase = file_get_contents($Db);
$loadFromBase = json_decode($loadFromBase, true);
Please implement JsonSerializable on Person class, you only will have to implement jsonSerialize method, here you have an example:
<?php
class Person implements JsonSerializable
{
private $id;
private $name;
private $last_name;
private $lang;
public function __construct($id, $name, $last_name, $lang)
{
$this->id = $id;
$this->name = $name;
$this->last_name = $last_name;
$this->lang = $lang;
}
public function jsonSerialize()
{
return get_object_vars($this);
}
}
$objects = array();
$objects[] = new Person(1, 'John', 'Smith','java');
$objects[] = new Person(2, 'Stacy', 'Smith','php');
$Db ='./DB.json';
$saveInBase = json_encode($objects);
file_put_contents($Db, $saveInBase);
$loadFromBase = file_get_contents($Db);
$loadFromBase = json_decode($loadFromBase, true);

Can be create constructor doble in a php class?

im work with php and mysql, sometimes i need instantiate my php class in data access layer for return objects, load list etc... but sometimes I use the class constructor and others do not.
Can i create doble constructor in a class?
example:
class Student {
private $id;
private $name;
private $course;
function __construct() {
}
//get set id and name
function setCourse($course) {
$this->course = $course;
}
function getCourse() {
$this->course = $course;
}
}
class Course {
private $id;
private $description;
function __construct($id) {
this->id = $id;
}
//get set, id, description
}
In my access layer sometime I use the constructor in different ways
for example:
$result = $stmt->fetchAll();
$listStudent = new ArrayObject();
if($result != null) {
foreach($result as $row) {
$student = new Student();
$student->setId($row['id']);
$student->setName($row['name']);
$student->setCourse(new Course($row['idcourse'])); //this works
$listStudent ->append($sol);
}
}
But sometimes I need to use the constructor in another way, for example
$result = $stmt->fetchAll();
$listCourses = new ArrayObject();
if($result != null) {
foreach($result as $row) {
$course = new Course(); //but here not work, becouse Class course receives a id
$course->setId($row['idcourse']);
$course->setDescription($row['description']);
$listCourses->append($sol);
}
}
My english is very bad,
i hope you understand me
Use default arguments:
class Course {
private $id;
private $description;
function __construct($id = 0) {
this->id = $id;
}
// getters and setters for id and description
}
Now, you can use it like that:
$course = new Course(12); // works with argument
or:
$course = new Course(); // works without argument
$course->setId(12);
class Course {
private $id;
private $description;
public function __construct() {
// allocate your stuff
}
public static function constructWithID( $id ) {
$instance = new self();
//do your stuffs here
return $instance;
}
call like Course:: constructWithID(..id) when you have to pass id otherwise make object (new Course()).

How to achieve this: object->object->property

I see a lot of code where the calls are like this.
An example:
$person->head->eyes->color = "brown";
$person->head->size = 10;
$person->name = "Daniel";
How do I achieve what I wrote above?
That just means that $person, $person->head, and $person->eyes each have properties that are other objects. head is a property of $person, eyes is a property of $person->head, and so on.
So, when you set $person->head->size, for example, you are setting the size property of $person->head, meaning $person->head must be an object. Put differently, the statement $person->head->size = 10; means set the size property of the head property of $person to 10.
Example Code:
<?php
class Eyes
{
var $color = null;
}
class Head
{
var $eyes = null;
var $size = null;
function __construct()
{
$this->eyes = new Eyes();
}
}
class Person
{
var $head = null;
var $name = null;
function __construct()
{
$this->head = new Head();
}
}
$person = new Person();
$person->head->eyes->color = "brown";
$person->head->size = 10;
$person->name = "Daniel";
var_dump($person);
This outputs:
class Person#1 (2) {
public $head =>
class Head#2 (2) {
public $eyes =>
class Eyes#3 (1) {
public $color =>
string(5) "brown"
}
public $size =>
int(10)
}
public $name =>
string(6) "Daniel"
}
First thing: there are no method being called in your example.
To the answer:
This can be achieved by using another objects instances as attributes. Eg:
class Head{
public $size, $eyes, $etc;
}
class Person{
public $name, $age, $head;
public function __construct(){
$this->head = new Head();
}
}
$person = new Person();
$person->head->size = 'XL';
This is one way of doing it
You can also cast arrays as objects. This will generate stdClass instances with array indexes as attributes:
$person = array(
'name' => 'Foo',
'age' => 20
);
$personObject = (object) $person;
var_dump($personObject);
PHP method chaning is the secret, return on each getter method $this
class Person
{
public function head()
{
...
return $this;
}
public function eyes()
{
...
return $this;
}
}
$person->head->eyes->color = "brown";
https://en.wikipedia.org/wiki/Method_chaining#PHP

How to get all public properties of a class as json?

Consider following example:
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
// how can i get json of this class which contains only public properties ?
// {"name":"jimmy","sex":"male"}
}
}
$p = new p();
$json = $p->get_p_as_json();
echo $json;
Question: How to get all public properties of a class as JSON?
You just create another class q extends from p. And then the code looks like following:
class p {
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknown properties here ..
function test(){
echo $this->name;
}
}
class q extends p {
function get_p_as_json($p) {
return json_encode(get_object_vars($p));
}
}
$q = new q();
$p = new p();
$json = $q->get_p_as_json($p);
echo $json;
$a = array();
$reflect = new ReflectionClass($this /* $foo */);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
/* here you can filter for spec properties or you can do some recursion */
$a[ $prop->getName() ] = $a[ $prop->getValue()];
}
return json_encode($a);
Since the public members can also be accessed outside of the class..
Accessing members outside of the class
$p = new p();
foreach($p as $key => $value) {
$arr[$key]=$value;
}
Demo
Accessing the public members within the class by making use of ReflectionClass
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
static $arr;
$reflect = new ReflectionClass(p);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
$arr[$prop->getName()]=$prop->getValue($this); //<--- Pass $this here
}
return json_encode($arr);
}
}
$p = new p();
echo $json=$p->get_p_as_json();
Demo
The best way to do this would not be to call a method of the class, per se.
However, you could initiate the following:
$myPublicMethodsInJson = json_encode(get_class_methods($p));
However, you would not be able to call get_class_methods from within the class because it will return ALL of your methods, private and public. When you call it from outside of the class it will only return the public methods.

PHP Classes: Define default return object

I have a PHP Class with a Constructor and some Methods. Every Method need to have the same return stdClass Object. Only a few properties in each functoin of the stdClass Object should be diffrent from the default one(like the property value or status). How would you do that? I mean, i can define in every function an stdClass Object with all properties, but as I said, I only need to change a few properties in each function for the return.
Examplecode which doesn't work:
<?
class Person{
public $sName;
public $oReturn = new stdClass();
$oReturn->status = 200;
$oReturn->value = "Personname";
function __construct($sName) {
$this->sName = $sName;
}
public function something($oData){
//Declaration
$this->oReturn->value = $oData->newName;
//Main
//Return
return $this->oReturn;
}
}
?>
You can't declare properties like this:-
public $oReturn = new stdClass();
That is illegal in PHP. Do it like this:-
class Person{
public $sName;
public $oReturn;
function __construct($sName) {
$this->sName = $sName;
$this->oReturn = new stdClass;
$this->oReturn->status = 200;
$this->oReturn->value = "Personname";
}
public function something($oData){
//Declaration
$this->oReturn->value = $oData->newName;
//Main
//Return
return $this->oReturn;
}
}
Now you can set whatever properties you want in $this->oReturn which, I think, is what you want to achieve.
See it working
You could just return a shared method that formats the data for you.
<?php
class Foo
{
protected
$defaults = array(
'a' => 1,
'b' => 2,
);
protected function reply(array $params = null) {
$properties = $this->defaults;
if ($params) {
$properties = array_merge($properties, $params);
}
return (object) $properties;
}
public function a($a) {
return $this->reply(array('a' => $a));
}
public function b($b) {
return $this->reply(array('b' => $b));
}
}
$foo = new Foo;
var_dump($foo->a('a'));
var_dump($foo->b('b'));
/*
object(stdClass)#2 (2) {
["a"]=>
string(1) "a"
["b"]=>
int(2)
}
object(stdClass)#2 (2) {
["a"]=>
int(1)
["b"]=>
string(1) "b"
}
*/
I think you might be after method chaining. You can create a class whose methods return $this, and then you can change your method calls.
Consider a class like the following:
<?php
class User
{
protected $id;
protected $name;
protected $email;
public function setName($name)
{
$this->name = $name;
return $this;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
}
You can then use it as follows:
<?php
$user = new User();
$user->setName('Martin')->setEmail('martin#example.com');
After this, your User class’s properties will reflect what values you’ve assigned to them in your chained method calls.
You can assign non-scalar values to class properties after class instantiation(AKA after new). See that the $oReturn value assignment is moved into the constructor.
class Person{
public $sName;
public $oReturn;
protected $default_status = 200;
protected $default_value = "Personname";
function __construct($sName) {
$this->sName = $sName;
$this->oReturn = new stdClass();
$this->oReturn->status = $this->default_status;
$this->oReturn->value = $this->default_value;
}
public function something($oData){
//Declaration
$this->oReturn->value = $oData->newName;
//Main
//Return
return $this->oReturn;
}
}
Now, you can extend this class, to make small variations.
class PersonNotFound extends Person {
protected $default_status = 404;
protected $default_value = 'NotFound';
}
Let's see their results:
$oData = new stdClass();
$oData->newName = 'Neo';
$person_a = new Person("Triniti");
var_dump( $person_a->something($oData) );
// status = 200
$person_b => new PersonNotFound("Cyon");
var_dump( $person_b->something($oData) );
// status = 404
EDIT:
Constructor injection version:
class Person{
public $sName;
public $oReturn;
function __construct($sName, $status = 200, $value = "Personname") {
$this->sName = $sName;
$this->oReturn = new stdClass();
$this->oReturn->status = $status;
$this->oReturn->value = $value;
}
public function something($oData){
$this->oReturn->value = $oData->newName;
return $this->oReturn;
}
}
$person_a = new Person("Neo"); // 200, Personname as default
$person_b = new Person("Triniti", 404, "NotFound");

Categories