Array Object In Php - php

i want to store Student Object to array. and i try to do with below code. but it always show array count as 0
class Student
{
$StudID = 0;
$Name = null;
}
class Students
{
static private $StudentData = array();
static public function AddNewStudent($id,$name)
{
echo("AuctionID :".$AuctionID."<br/>");
try{
$objstd = new Student();
$objstd->StuID = $id;
$objstd->Name = &name;
array_push($StudentData, $objstd);
}
catch (Exception $e)
{
echo("Error".$e->getMessage());
}
}
static public function TotalStudent()
{
return count($StudentData);
}
}
Students::AddNewStudent(1,"name");
Students::AddNewStudent(2,"name2");
Students::AddNewStudent(3,"name3");
echo('Total auction running : '.Students::TotalStudent().'<br/>');
when i try to show array count it shows 0. i want to store all student data in static list
or then after when ever i want to see the list i get the list from static class only...

Because you're creating a new array instead of referencing the one you declared. Use the self keyword to reference your static object property:
class Students
{
static private $StudentData = array();
static public function AddNewStudent($id,$name)
{
echo("AuctionID :".$AuctionID."<br/>");
try{
$objstd = new Student();
$objstd->StuID = $id;
$objstd->Name = &name;
array_push(self::$StudentData, $objstd);
}
catch (Exception $e)
{
echo("Error".$e->getMessage());
}
}
static public function TotalStudent()
{
return count(self::$StudentData);
}
}

In php you have to prefix static variables with self::, like this:
array_push(self::$StudentData, $objstd);
// and in count:
return count(self::$StudentData);

Why that complicated? Your Student class should take care of it's own, same for Students. Example:
$students = new Students();
$students[] = new Student(1, "name");
$students[] = new Student(2, "name2");
$students[] = new Student(3, "name3");
printf('Total auction running : %d.', count($students));
Example output:
Total auction running : 3.
The classes:
class Student
{
/**
* #var int
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #param int $id
* #param string $name
*/
public function __construct($id, $name) {
$this->id = $id;
$this->name = $name;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
}
class Students extends ArrayObject
{
public function __construct()
{
parent::__construct(array());
}
public function offsetSet($index, $newval) {
if (!($newval instanceof Student)) {
throw new InvalidArgumentException('You can only add values of type Student.');
}
parent::offsetSet($index, $newval);
}
}

Related

SQL request or php solution to manage employers

My entity :
class User{
id : int
name : string
boss : User()
}
I want to create a function that return an array() of users that work under a giving user.
example :
public function MyEmployers( User $user , array $usersList )
{
$myEmployers = array();
...
return $myEmployers;
}
$results = $this->myEmployers ( $employer1 , $allEmployers)
dump ( $results );
$results = [ 4 , 5 , 6 ];
I found a solution if someone can improve it feel free :
public $tree = array();
public function MyEmployers(User $user)
{
$superior_key_id = array();
$all_users = $this->getallusers();
$id = $user->getId();
foreach ($all_users as $user) {
if ($user->getSuperior())
$superior_key_id[$user->getSuperior()->getId()][] = $user;
}
$this->getSubEmployee($this->getUser(), $superior_key_id);
return ($this->tree);
}
public function getSubEmployee($user, $superior_key_id)
{
if (isset($superior_key_id[$user->getId()])) {
foreach ($superior_key_id[$user->getId()] as $user) {
$this->tree[] = $user;
$this->getSubEmployee($user, $superior_key_id);
}
}
return $user;
}
this one will get all bosses if you're interested :
public function MyBosses(User $user)
{
$bosses = array();
while ($user->getSuperior()) {
array_push($bosses, $user->getSuperior());
$user = $user->getSuperior();
}
return $bosses;
}
You could set up a one-to-many relationship between boss and employee
So you're user class could look like:
class User{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="employee")
*/
private $boss;
/**
* #ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="boss")
*/
private $employees;
public function __construct()
{
$this->employees = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* #return Collection|employees[]
*/
public function getEmployees(): Collection
{
return $this->employees;
}
public function addEmployee(employee $employee): self
{
if (!$this->employees->contains($employee)) {
$this->employees[] = $employee;
}
return $this;
}
public function removeEmployee(employee $employee): self
{
if ($this->employees->contains($employee)) {
$this->employees->removeElement($employee);
}
return $this;
}
public function getBoss(): ?Usesr
{
return $this->boss;
}
public function setBoss(?User $boss): self
{
$this->boss = $boss;
return $this;
}
}
You would need to set up the database relationship with the symfony make:entity command.
To get all employeers under a user, you could do something like:
function getAllEmployeesUnder(User $user)
{
$allEmployees = [];
foreach ($user->getEmployees as $employee) {
$allEmployees[] = $employee;
$allEmployees = array_merge($allEmployees, $this->getAllEmployeesUnder($employee));
}
return $allEmployees;
}

PhP foreach through class instances

I'm wondering about this weird thing:
public function getAllCustomers()
{
$customers = $this->redis->keys("customer:*");
foreach ($customers as $value) {
return new \Customer($this->redis->hget($value,"name"),$this->redis->hget($value,"id"),$this->redis->hget($value,"email"));
}
}
This method returns all customers from my database.
But if I try to loop through all of these customers:
foreach ($customerController->getAllCustomers() as $customer) {
var_dump($customer);
}
The getName() method is not found. var_dump returns:
NULL
NULL
NULL
Customer class:
class Customer {
var $name;
var $id;
var $email;
function __construct($name, $id,$email) {
$this->name = $name;
$this->id = $id;
$this->email = $email;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
public function __toString()
{
return "";
}
}
I'm pretty new to PHP and don't understand why I can't access the Customer object's field.
Your Problem: you do not return array of customer but only one. You getting null because your function return only 1 object -> and in PHP, when using foreach loop on object you get his fields -> and the fields do not have the getName function.
Solution: Init customer array, populate it and return from the function.
public function getAllCustomers()
{
$customers = $this->redis->keys("customer:*");
$customersObjs = array();
foreach ($customers as $value) {
$customersObjs[] = new Customer($this->redis->hget($value,"name"),$this->redis->hget($value,"id"),$this->redis->hget($value,"email")));
}
return $customersObjs;
}
Now you have array of the customersObjs you can loop on with:
foreach ($customerController->getAllCustomers() as $customer) {
echo $customer->getName();
}
Solution :
public function getAllCustomers()
{
$customers = $this->redis->keys("customer:*");
$custumersArray = array();
foreach ($customers as $value) {
$custumersArray[] = \Customer($this->redis->hget($value,"name"),$this->redis->hget($value,"email"),$this->redis->hget($value,"id"));
}
return $custumersArray;
}
the problem was that you are returning a single array but not a array list.

php class method within method

If I want to access the public method, I can do that easily. But if I want to access the property within method, what should I do, and is it recommended??
Can I do something like this in php?
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
}
}
and than in some other place
$auth = new Auth();
$auth->check('user1')->project;
Just so you people know its possible here is the Zend framework code from
Zend-Authentication
if ($result->isValid()) {
$this->getStorage()->write($result->getIdentity());
}
I believe your question is basically regarding Fluent Interfaces or Method Chaining in conjunction with the magic method __get
Attempting to run this:
<?php
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
}
}
$auth = new Auth();
$auth->check('user1')->project;
Results in:
Notice: Trying to get property of non-object in /in/Hi5Rc on line 13
because $auth->check('user1') returns NULL (or void) and NULL doesn't have a project property.
The first thing we require is for $auth->check('user1') to return something useful. Given that $project is a boolean and $this->project is an integer, it makes the most sense to just return $project and get the value.
<?php
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
return $project;
}
}
$auth = new Auth();
print_r($auth->check('user1'));
which results in :
bool(false)
But that doesn't address your question about how to fluently access a nonpublic field or parameter.
It appears that you are operating under the misconception that these projects are taking method scoped variables like $project in your check() class and making them accessible. They are not.
Not even in your example of the Zend-Authentication.
The field $storage itself is protected, but it has public (fluent) getters/setters.
So, $this->getStorage() returns an instance of new Storage\Session() which has a public write().
Thus $this->getStorage()->write() works.
So lets take your example class and modify it a bit to demonstrate.
<?php
class Project{
/**
* #var string
*/
private $name;
/**
* #var bool
*/
private $active;
/**
* #var string
*/
private $description;
public function __construct($name = 'Default', $active = false, $description = '')
{
$this->name = $name;
$this->active = $active;
$this->description = $description;
}
/**
* #param string $name
*
* #return Project
*/
public function setName(string $name): Project
{
$this->name = $name;
return $this;
}
/**
* #param bool $active
*
* #return Project
*/
public function setActive(bool $active): Project
{
$this->active = $active;
return $this;
}
/**
* #param string $description
*
* #return Project
*/
public function setDescription(string $description): Project
{
$this->description = $description;
return $this;
}
/**
* #return string
*/
public function getName(): string
{
return $this->name;
}
/**
* #return bool
*/
public function isActive(): bool
{
return $this->active;
}
/**
* #return string
*/
public function getDescription(): string
{
return $this->description;
}
public function toArray(){
return [
'name' => $this->name,
'active' => $this->active,
'description' => $this->description
];
}
public function toJson(){
return json_encode($this->toArray());
}
public function __toString()
{
return $this->toJson();
}
}
class Auth {
/**
* #var Project
*/
private $project;
public function __construct($project = Null)
{
$this->project = is_null($project)? new Project() : $project;
}
public function check($user = false){
if($user == 'user1'){
$this->project->setName("Project: $user")->setActive(true)->setDescription("This project belongs to $user");
}
return $this;
}
/**
* #param Project $project
*
* #return Auth
*/
public function setProject(Project $project): Auth
{
$this->project = $project;
return $this;
}
/**
* #return Project
*/
public function getProject(): Project
{
return $this->project;
}
}
$auth = new Auth();
echo $auth->check('user1')->getProject();
now results in:
{"name":"Project: user1","active":true,"description":"This project
belongs to user1"}
However, you wanted to access the private field as if it were a public field without using a defined getter/setter. So lets make some more changes to the Auth class.
class Auth {
/**
* #var Project[]
*/
private $private_project;
public function __construct($project = Null)
{
$this->private_project = is_null($project)? new Project() : $project;
}
public function check($user = false){
if($user == 'user1'){
$this->private_project->setName("Project: $user")->setActive(true)->setDescription("This project belongs to $user");
}
return $this;
}
public function __get($name)
{
if ($name === 'project'){
return $this->private_project;
}
}
}
Now you can fluently access the field as you requested:
$auth = new Auth();
echo $auth->check('baduser')->project;
echo "\n";
echo $auth->check('user1')->project;
results in:
{"name":"Default","active":false,"description":""}
{"name":"Project: user1","active":true,"description":"This project belongs to user1"}
Laravel's Eloquent models make great use of the __get()function for accessing model fields dynamically. Laravel also makes great use of the __call() magic method for fluency.
I hope that helps bring some clarity.
class Auth
{
protected $project;
public function __constructor($project = false)
{
$this->project = $project;
}
public function check($user = false)
{
if($user == 'user1')
{
$this->project = 1;
}
return $this;
}
public function project()
{
return $this->project;
}
}
then you can do the following:
$auth = new Auth();
$auth->check('user1')->project(); // returns 1
or if you want you can also set another default value for the $projectin the constructor
$auth = new Auth($other_default_value);
$auth->check('user2')->project(); // returns $other_default_value
If you don't want to create extra class properties and "preserve method chaining", what about yield?
class Auth
{
public function check($user = false)
{
$project = false; // make it somehow public
if($user === 'user1'){
(yield 'project' => $project); // making it public
}
return $this;
}
}
Later on you can discover it as follows:
$array = iterator_to_array($auth->check($user));
// array(1) { ["project"] => bool(false) }
But for this to use you won't be able to use method chaining, bec. you need to retrieve generator anyway, so better to revise approach for discovering the $project.
<?php
class Auth
{
public $project;
public function check($user = false)
{
$this->project = false;//make it somehow public
if ($user == 'user1') {
$this->project = 1;
}
return $this;
}
}
$auth = new Auth();
var_dump($auth->check('user1')->project);
This will return you 1. The local variables defined in function are only accessbile inside the function not outside hence you need to define them globally
$project is a local variable in your case, visible within the scope of the check method. You could define it as a member:
class Auth {
public $project = false;
public function check($user = false){
if($user == 'user1'){
$this-project = 1;
}
}
}
However, it is recommendable to make the member public and reach it via a getter, which will check whether it was initialized and if not, initialize it:
class Auth {
private $project = false;
public getProject($user = false) {
if ($this->project === false) {
check($user);
}
return $this->project;
}
public function check($user = false){
if($user == 'user1'){
$this-project = 1;
}
}
}
You will need to add it as a class variable:
class Auth {
public $project = false;
public function check($user = false) {
if($user == 'user1'){
$this->project = 1;
}
}
}
The property is then available as follows:
$auth = new Auth ();
$auth->check ('user1');
echo $auth->project; // 1

array of objects in an object in php

I am fairly new to php. I have classes called quiz and question. And the class quiz can have one or many questions. I have done a java representation
class Question () {
private int id;
private String question;
private String answer;
}
and the quiz class should be as follows,
class Quiz() {
private int id;
private List<Question> questionList;
}
my question is regarding how to represent the above java representation in php. please be kind enough to point me in the right direction.
getter and setter:
class Question {
private $id ;
private $question;
private $answer;
public function __construct(){
}
public function setId($value){
$this->id = $value;
}
public function setQuestion($value){
$this->question = $value;
}
public function setAnswer($value){
$this->answer = $value;
}
public function getId(){
return $this->id;
}
public function getQuestion(){
return $this->question;
}
public function getAnswer(){
return $this->answer;
}
}
class Quiz{
private $id;
private $questionList = array();
public function __construct(){
}
public function setQuestionList($value){
$this->questionList[] = $value;
}
public function getQuestionList(){
return $this->questionList;
}
}
//
$quiz = new Quiz();
//
$question = new Question();
$question->setId(1);
$question->setQuestion('question?');
$question->setAnswer('answer');
//
$quiz->setQuestionList($question);
//
$question = new Question();
$question->setId(2);
$question->setQuestion('question2?');
$question->setAnswer('answer2');
//
$quiz->setQuestionList($question);
//
//Getting questions
foreach($quiz->getQuestionList() as $object){
echo $object->getId().' - '.$object->getQuestion().' - '.$object->getAnswer().'<br />';
}
Generics type don't exist in standard PHP.
One way to represent such structure in PHP is :
class Question
{
private $id;
private $question;
private $answer;
}
class Quiz
{
private $id;
/**
* #var array<Question>
*/
private $questionList = array();
}
The docblock (#var ...) is just here to help others (and IDEs) to understand the structure of $questionList.
To add some check on $questionList content, you can use typed setter/adder :
public function addQuestion(Question $question)
{
$this->questionList[] = $question;
}

PHP RecursiveIterator traversing

I have a structure representing a form and I want to iterate it using RecursiveIterator.
The problem is this only returns the top-level questions. What am I doing wrong?
Whole form:
class Form implements RecursiveIterator{
private $id;
private $caption;
private $other_text;
private $questions = array();
private $current;
private function __construct(DibiRow $row){
$this->id = $row->id;
$this->caption = $row->caption;
$this->other_text = $row->other_text;
$this->loadQuestions();
}
private function loadQuestions(){
$questions = dibi::query('SELECT * FROM cyp_questions WHERE form_id = %i AND parent_id IS NULL', $this->id);
while($question = $questions->fetch()) $this->questions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1);
}
/**
* #throws InvalidArgumentException
* #param $id
* #return Form
*/
public static function loadById($id){
$form = dibi::query('SELECT * FROM cyp_forms WHERE id = %i', $id)->fetch();
if($form === false) throw new InvalidArgumentException('Form with id '.$id.' was not found.');
return new Form($form);
}
/**
* #throws FormFieldException
* #return bool
*/
public function validate($postfields){
}
public function getQuestions(){
return $this->questions;
}
public function getChildren(){
return $this->questions[$this->current];
}
public function hasChildren(){
return count($this->questions) > 0;
}
public function current(){
return $this->questions[$this->current];
}
public function key(){
return $this->current;
}
public function next(){
$this->current++;
}
public function rewind(){
$this->current = 0;
}
public function valid(){
return isset($this->questions[$this->current]);
}
}
Question:
class Question implements RecursiveIterator{
private $id;
private $type;
private $answers = array();
private $subquestions = array();
private $other_text;
private $triggers_unique;
private $caption;
private $current = 0;
public function __construct($id, $type, $caption, $other_text = null, $triggers_unique = false){
$this->id = $id;
$this->type = $type;
$this->caption = $caption;
$this->other_text = $other_text;
$this->triggers_unique = $triggers_unique;
$this->setSubQuestions();
}
private function setSubQuestions(){
$questions = dibi::query('SELECT * FROM cyp_questions WHERE parent_id = %i', $this->id);
while($question = $questions->fetch()) $this->subquestions[] = new Question($question->question_id, $question->type, $question->caption, $question->other_text, $question->triggers_unique == 1);
}
public function getOtherText(){
return $this->other_text;
}
public function getCaption(){
return $this->caption;
}
public function addAnswer($answer){
$this->answers[] = $answer;
}
public function getChildren(){
return $this->subquestions[$this->current];
}
public function hasChildren(){
return count($this->subquestions) > 0;
}
public function current(){
return $this->subquestions[$this->current];
}
public function key(){
return $this->id;
}
public function next(){
++$this->current;
}
public function rewind(){
$this->current = 0;
}
public function valid(){
return isset($this->subquestions[$this->current]);
}
public function getAnswers(){
return $this->answers;
}
}
Iteration:
$form = Form::loadById(1);
foreach($form as $question){
echo $question->getCaption().'<br />';
}
To iterate over a RecursiveIterator, you have to wrap it into a RecursiveIteratorIterator.
See some examples at
Introduction to Spl
SplWiki
The default iteration mode is only to list leaves. If you also want the containing nodes to appear in the iteration, pass RecursiveIteratorIterator::SELF_FIRST as the second argument to the constructor of the RecursiveIteratorIterator
Well, as you can see here
public RecursiveIterator RecursiveIterator::getChildren ( void )
Returns an iterator for the current iterator entry.
the method should return an object implementing the iterator. Your method return a simple array.
My guess would be to return something like:
public function getChildren(){
return new Question($this->subquestions);
}
This is because you're using a RECURSIVE iterator so it's expected to have each node of the tree of the same type (an iterator)

Categories