views:

36

answers:

3

I am not even sure how to ask. I do this all the time in C# but for the life of me I cannot find any decent examples in PHP. Can you help?

What I am trying to do is for example. Say I have a class called Company who has many Employees.

I want to be able to store all the employees in the company class then later when I iterate through the Company object I need to be able to iterate through all the employees that are assigned to that company and I am having a heck of a time trying to find a straight forward example.

I can populate it, but fro the life of me I cant loop through the Employees. I know I am doing something wrong but cannot figure it out. Here is what I have for example.

Employee

This could be completely wrong for all I know as getting the data back out.

    class Employee
    {
        private $first;
        private $last;

        public function __construct($first = null, $last = null)
        {
            if(isset ($first))
                $this->first = $first;

            if(isset ($last))
                $this->last = $last;
        }

        public function getEmployee()
        {
            return Employee($this->first, $this->last);
        }

        public function getFirst()
        {
            return $this->first;
        }

        public function getLast()
        {
            return $this->first;
        }
    }

Company has an array of employees.

In c# I would use something like a generic

    public List<Employee> Employees {get;set;}

Then in the constructor I would do something like

    Employees = new List<Employee>();

Then I could do something like

    foreach(var x in Customer.Employees)
            x.first;

That is what I am kind of trying to do.

    class Company
    {
        private $companyName;

        private $employees;


        public function __construct($nameOfCompany)
        {
            $this->companyName = $nameOfCompany;               
        }

        public function setEmployee(Employee $employee)
        {
            $this->employees[] = $employee;
        }

        public function getCompanyName()
        {
            return $this->companyName;
        }

        public function setCompanyName($nameOfCompany)
        {
            $this->companyName = $nameOfCompany;
        }

        public function getEmployees()
        {
            return $this->employees;
        }
    }

Create and populate

    $c = new Company("Test");
    $c->setEmployee(new Employee('A','B'));
    $c->setEmployee(new Employee('C','D'));
    $c->setEmployee(new Employee('E','F'));

Up until this point all is well.

To get the name of the company no problem.

    echo $c->getCompanyName();

    echo "<PRE>";
    print_r($c);
    echo "</PRE>";

But how do I loop through the employees?

I want to be able to do something like cast Companies employees in a loop to a single Employee then do something like

    foreach(customers employees)
           echo Employee->getFirst, etc...

Can someone please provide some guidance?

Thanks

+2  A: 
foreach ($company->getEmployees() as $emp) {
    //do something with $emp
}

See foreach.

One note:

    public function __construct($first = null, $last = null)
    {
        if(isset ($first))
            $this->first = $first;

        if(isset ($last))
            $this->last = $last;
    }

is exactly the same as

    public function __construct($first = null, $last = null)
    {
        $this->first = $first;
        $this->last = $last;
    }

because the fields first and last, having no initializer, are initialized to null. isset, in your case, only checks if the argument's null, since it's guaranteed to be set (it's an argument).

Artefacto
Thank you the answer. I guess I was trying to do a strong type of $emp.For example like (Employee)$emp, or is that not really possible in PHP?Again thank you so much for the quick response.
nitefrog
@nite Those casts are not possible in PHP if that's what you're asking.
Artefacto
@Artefacto ok, now it makes sense...
nitefrog
+2  A: 

version 1: explicit getter method

<?php
class Employee
{
  private $first;
  private $last;

  public function __construct($first = null, $last = null)
  {
    if(isset ($first))
    $this->first = $first;

    if(isset ($last))
    $this->last = $last;
  }

  public function getFirst()
  {
    return $this->first;
  }

  public function getLast()
  {
    return $this->first;
  }
}

class Company
{
  private $companyName;
  private $employees;

  public function __construct($nameOfCompany)
  {
    $this->companyName = $nameOfCompany;
  }

  public function addEmployee(Employee $employee)
  {
    $this->employees[] = $employee;
  }

  public function getCompanyName()
  {
    return $this->companyName;
  }

  public function getEmployees()
  {
    return $this->employees;
  }
}

$company = new Company('ACME');
$company->addEmployee(new Employee('A', 'A'));
$company->addEmployee(new Employee('B', 'B'));
$company->addEmployee(new Employee('C', 'C'));

foreach( $company->getEmployees() as $e ) {
  echo $e->getFirst(), "\n";
}

version 2: using __get

class Company
{
  private $companyName;
  private $employees;

  public function __construct($nameOfCompany)
  {
    $this->companyName = $nameOfCompany;
  }

  public function addEmployee(Employee $employee)
  {
    $this->employees[] = $employee;
  }

  public function __get($name) {
     // this will allow access to any member of the class
     // so you might want to test access first
     if ( isset($this->$name) ) {
       return $this->$name;
     }
   }

}

$company = new Company('ACME');
$company->addEmployee(new Employee('A', 'A'));
$company->addEmployee(new Employee('B', 'B'));
$company->addEmployee(new Employee('C', 'C'));

foreach( $company->employees as $e ) {
  echo $e->getFirst(), "\n";
}

$company = new Company('ACME');
$company->addEmployee(new Employee('A', 'A'));
$company->addEmployee(new Employee('B', 'B'));
$company->addEmployee(new Employee('C', 'C'));

foreach( $company->employees as $e ) {
  echo $e->getFirst(), "\n";
}
VolkerK
Don't give him ideas with `__get` -- at least not without telling him about the inherent problems.
Artefacto
Thank you very much for this response. It gets me in the right direction. Question, is it because of the __get that allows you to do this, foreach( $company->employees as $e )? I want to say yes, but I just want to make sure I understand it. Also what are the gotchas? Artefacto mentioned inherent problems?Thank you again
nitefrog
@nite __get is much slower than direct access to an object property (and will be even more so in the next version of PHP). In a heavy object-oriented application, it will probably make a difference.
Artefacto
@nitefrog: Yes, it's because of the __get($name) method. This method is called when something tries to access an inaccessible property of the object. So, keep at least in mind that the method will not be called if you have something like `class Foo { public $bar; } .... echo $foo->bar;`
VolkerK
+2  A: 

PHP has something called the PHP Standard Library built into the language. The PHP Standard Library comes with a number of interfaces that allow you to implement certain core language functionality into your own defined objects. Once of these is the iterator interface. Define a class that implements this interface, and then write an implementation that will allow your object to do what you want when it's placed in a foreach loop.

Also, depending on the semantic you're after, you could just as easily do a

foreach($company->getEmployees() as $employee)
{
    var_dump($employee);
}

The getEmployees method will only be called once.

Alan Storm
Hello Alan, thank you for the repose. I was not aware of the iterator. It has been a long time since I have done any PHP and man coming from other languages to this is a little confusing.Thank you again...
nitefrog