I am trying to build some classes for a project and I was wondering how to achieve the following. I am not really sure how to ask this with words but I will provide an example:
class Table{
private $name;
private $fields = [];
public function addField(Field $field){
$this->fields[$field->getName()] = $field;
}
public function getName(){
return $this->name;
}
}
class Field{
private $name;
public function getName(){
return $this->name;
}
public function getTableName(){
//return Table::getName
}
public function getTable(){
//return a ref to the Table object
}
}
$table = new Table();
$field = new Field();
$table->addField($field);
What I am trying to achieve here, once the $field is added to the $table, is there some sort of way to get the reference of the $table from any of the methods in the $field object
I would greatly appreciate any help or ideas how to restructure it so I can achieve my goal
Thank you in advance
class Table{
private $name;
private $fields = [];
public function addField(Field $field){
$this->field->setTable($this);
$this->fields[$field->getName()] = $field;
}
public function getName(){
return $this->name;
}
}
class Field{
private $name;
private $relatedTable;
public function getName(){
return $this->name;
}
public function setName($name){
$this->name = $name;
}
public function getTableName(){
return $this->relatedTable->getName();
}
public function getTable(){
return $this->relatedTable;
}
public function setTable(Table $table){
$this->relatedTable = $table;
}
}
$field = new Field;
$field->setName('Field1');
$table = new Table;
$table->addField($field);
echo $field->getTable()->getName();
Although you have to be aware that when you pass an object to a function, it will be passed by "reference" (I know there's another term for this.)
// in case you're running it in a for loop
$field = new Field;
$table = new Table;
for($i = 0; $i < 3; $i++)
{
$field->setName("Field{$i}");
$table->addField(clone $field); // notice the clone there.
}
I think this approach is kind of similar with Observer Pattern
Related
I'm trying to figure out the best way to iterate over an object's properties so I can build a sql query for an insert or update. I also am looking to be able to omit certain fields in the iteration.
Below is an example object where I would like to grab name and age but omit employer because that is a join from another table.
class person
{
private $_name, $_age, $_employer;
public function get_name()
{
return $this->_name;
}
public function get_age()
{
return $this->_age;
}
public function get_employer()
{
return $this->_employer;
}
}
I could cast an object as an array to get the properties but I still don't have a good way to omit certain properties.
$personObj = new person();
foreach((array)$personObj as $k => $v)
{
$sql .= "...";
}
Hope this gives you a hint
class person
{
private $_name = 'dude';
private $_age = '27';
private $_employer = 'yes';
public function get_name()
{
return $this->_name;
}
public function get_age()
{
return $this->_age;
}
public function get_employer()
{
return $this->_employer;
}
}
$person = new person();
$required = array('name','age');
foreach($required as $req)
{
$func = "get_{$req}";
echo $person->$func();
}
https://3v4l.org/vLdAN
I want have an in-memory data structure to be able to add or remove an item (in this instance a student) into some sort of table (just like a shopping cart) from the collection class I have created. At the moment, it just displays students. For instance, if I click add student, it will pop up below, and I can delete this student from below also.
How I could implement this?
Here is my Member.php class
<?php
class Member {
private $name;
private $age;
private $gender;
private $course;
public function __construct($name,$age, $gender, $course){
$this->name = $name;
$this->age = $age;
$this->gender = $gender;
$this->course = $course;
}
public function setName($name) { //Sets the age value
$this->name = $name;
}
public function setAge($age) { //Sets the age value
$this->age = $age;
}
public function setGender($gender) { //Sets the gender value
$this->gender = $gender;
}
public function setCourse ($course) {
$this->course = $course;
}
public function getName() { //Gets the name value
return $this->name;
}
public function getAge() { //Gets the age value
return $this->age;
}
public function getGender() { //Gets the gender value
return $this->gender;
}
public function getCourse() {
return $this->course;
}
}
?>
Here is my ObjectCollection.php
<?php
class ObjectCollection
{
//This is an array to hold line items
private $items_array ;
private $itemCounter; //Count the number of items
public function __construct() {
//Create an array object to hold line items
$this->items_array = array();
$this->itemCounter=0;
}
public function getItemCount(){
return $this->itemCounter;
}
public function addItem($item) {
$this->itemCounter++;
$this->items_array[] = $item;
}
public function getItem($index) {
return $this->items_array[$index];
}
}
?>
And finally displaying this through testcollection.php
<?php
$ObjColl = new ObjectCollection();
$member1 = new Member("Jessica Davidson", 21, "Female", "Computing");
$ObjColl->addItem($member1);
$member2 = new Member("Lucy Barnes", 22, "Female", "History");
$ObjColl->addItem($member2);
$member3 = new Member("Mark Smith", 24, "Male", "Social Science");
$ObjColl->addItem($member3);
for($i = 0;$i < $ObjColl->getItemCount();$i++){
$item = $ObjColl->getItem($i);
if ($item instanceof Member) {
print "<br> University Member: ";
}
print "Name: " . $item->getName();
print ". Age: " . $item->getAge();
print ". Gender: " . $item->getGender();
print ". Enrolled on: " .$item->getCourse() . " course<br>";
}
?>
At first if your ObjectCollection must collect only objects of Member class, use parameter type declaration. It’s good practice in OOP.
public function addItem(Member $item)
At second if you want work with ObjectCollection like with array, implement ArrayAccess and Iterator interfaces.
Example
<?php
class Member{
private $__name;
public function __construct($name){
$this->__name = $name;
}
public function getName(){
return $this->__name;
}
}
class MemberCollection implements ArrayAccess, Iterator{
private $__Collection = [];
private $__position = 0;
public function __construct(){
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->__Collection[] = $value;
} else {
$this->__Collection[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->__Collection[$offset]);
}
public function offsetUnset($offset) {
unset($this->__Collection[$offset]);
}
public function offsetGet($offset) {
return isset($this->__Collection[$offset]) ? $this->__Collection[$offset] : null;
}
function rewind() {
$this->__position = 0;
}
function current() {
return $this->__Collection[$this->__position];
}
function key() {
return $this->__position;
}
function next() {
++$this->__position;
}
function valid() {
return isset($this->__Collection[$this->__position]);
}
public function addItem(Member $Member){
$this->offsetSet(null, $Member);
}
}
$MC = new MemberCollection();
$Member1 = new Member('Name 1');
$Member2 = new Member('Name 2');
$MC->addItem($Member1);
$MC->addItem($Member2);
foreach ($MC as $Member){
echo '<br>' . $MC->key() . ':<br>';
var_dump($Member->getName());
}
unset($MC[0]); //Delete member from collection
?>
I've been doing a project in PHP for the last few hours and I have encountered into a problem.
The problem is I don't know how to access private variables in a class and I can't find it online.
Example:
<?php
class Example{
private $age;
public function __construct() {
$age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->$age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
As far as I know, I should be able to access the variable with $this->$age but it isn't working.
Thank you.
EDIT: Got it working with help of the awesome stackoverflooooooooow community, this is how a working one looks.
<?php
class Example{
private $age;
public function __construct() {
$this->age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
Look at this approach.
first: create Entity that stores and retrieves data inside of private $attributes array, and with magic __set(), __get() You can also do like: $object->variable = 123
second: extend Entity with Human class and add some function specific to child class (for example hasValidAge()):
<?php
class Entity {
private $attributes;
public function __construct($attributes = []) {
$this->setAttributes($attributes);
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
return $this;
}
public function setAttributes($attributes = []) {
foreach($attributes AS $key => $value) {
$this->setAttribute($key, $value);
}
}
public function getAttribute($key, $fallback = null) {
return (isset($this->attributes[$key]))?
$this->attributes[$key] : $fallback;
}
public function __get($key) {
return $this->getAttribute($key);
}
public function __set($key, $value) {
$this->setAttribute($key, $value);
}
}
class Human extends Entity {
public function __construct($attributes = []) {
$this->setAttributes($attributes);
$this->checkAge();
}
public function hasValidAge() {
return ($this->getAttribute('age') > 12)? true : false;
}
}
$boy = new Human(['name' => 'Mark', 'age' => 14]);
if($boy->hasValidAge()) {
echo "Welcome ".$boy->name."!";
}
?>
p.s. I've removed echo "Welcome!" part from constructor because it's not cool to do echo from model object, in our example Human is model of Entity.
I have two classes
class Table {
public $rows = array();
public $name;
public function __construct($name, $rows) {
$this->name = $name;
$this->rows = $rows;
}
}
class Row {
public $name;
public function __construct($name) {
$this->name = $name;
}
}
Now I want to create an object table and add 2 rows to it.
$rows = array(
new Row("Row 1"),
new Row("Row 2")
);
$table = new Table("Table 1", $rows);
So far so good..
But is there a possibility to get the containing table of a row?
For example:
foreach($table->rows AS $row) {
echo $row->name . ' is member of table ' . $row->getContainingTable()->name;
}
This is only an example...
You would have to change your Row class (pass the Table object to it):
class Row {
public $name;
protected $table;
public function __construct($name, Table $table) {
$this->name = $name;
$this->table = $table;
}
public function getContainingTable(){
return $this->table;
}
}
If you cannot do that on instantiation, create a setter method and use it after you pass the rows to the table :)
Actually, here's a better idea:
class Table {
public $rows = array();
public $name;
public function __construct($name, array $rows) {
$this->name = $name;
$this->rows = $rows;
foreach($rows as $row)
$row->setContainingTable($this);
}
}
class Row {
public $name;
protected $table;
public function __construct($name) {
$this->name = $name;
}
public function setContainingTable(Table $table){
$this->table = $table;
}
public function getContainingTable(){
return $this->table;
}
}
I think you should change your class structure to something like this
<?php
class MyCollection implements IteratorAggregate
{
private $items = array();
private $count = 0;
// Required definition of interface IteratorAggregate
public function getIterator() {
return new MyIterator($this->items);
}
public function add($value) {
$this->items[$this->count++] = $value;
}
}
$coll = new MyCollection();
$coll->add('value 1');
$coll->add('value 2');
$coll->add('value 3');
foreach ($coll as $key => $val) {
echo "key/value: [$key -> $val]\n\n";
}
?>
have a look at iterators in php 5 and see the examples this example is from there to
apologies in advance for being a OO noob...
I am trying to write a method to aggregate a property of all objects that exist for a given class. The code below describes what I want to do.
Class TeamMember(){
function SetScore($value) {
$this->score = $value;
}
function GetTotalScoreForTeam() {
//best way to iterate over all the objects to get a sum??????
return totalScore;
}
}
$john = new TeamMember();
$john->SetScore('182');
$paul = new TeamMember();
$paul->SetScore('212');
$totalScore = TeamMember->GetTotalScoreForTeam;
Thanks!
Even if this is not the best way to approach this problem, I think it is the most explaining your problem with your pre-written code:
class TeamMember { // a class is not a function/method; removed the ()
public static $members = array(); // holds the instances
public $score; // It is simply good practice to declare your fields (it is not necessary)
function __construct () {
self::$members[] = $this; // save the instances accessible for your score-calcuating method
}
function setScore ($value) {
$this->score = $value;
}
static function getTotalScoreForTeam () { // a static method is best here
$totalScore = 0;
foreach (self::$members as $member) // foreach over the instances holding list
$totalScore += $member->score;
return $totalScore;
}
}
$john = new TeamMember();
$john->setScore('182');
$paul = new TeamMember();
$paul->setScore('212');
$totalScore = TeamMember::getTotalScoreForTeam(); // for static access, use a :: instead of ->
As Mike B said in the comment you should first group your TeamMember instances in an instance of a Team class and then run some aggregate function to calculate the total score of that particular team, e.g.
<?php
$team1 = Team::create('Team 1')
->add( TeamMember::create('john')->SetScore(182) )
->add( TeamMember::create('paul')->SetScore(212) );
$team2 = Team::create('Team 2')
->add( TeamMember::create('peter')->SetScore(200) )
->add( TeamMember::create('marry')->SetScore(300) );
foo($team1);
foo($team2);
function foo(Team $team) {
$score = $team->membersReduce(
function($v, $e) {
return $v+$e->getScore();
}
);
$members = $team->membersMap(
function($e) {
return $e->getName();
}
);
echo 'team : ', $team->getName(), "\r\n";
echo 'score: ', $score, "\r\n";
echo 'members: ', join(' | ', $members), "\r\n";
}
class TeamMember {
protected $score = 0;
protected $name;
public static function create($name) {
return new TeamMember($name);
}
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function SetScore($value) {
$this->score = $value;
return $this;
}
public function GetScore() {
return $this->score;
}
}
class Team {
protected $members = array();
protected $name;
public static function create($name) {
return new Team($name);
}
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function add(TeamMember $t) {
// <-- check if $t already member of team -->
$this->members[] = $t;
return $this;
}
public function membersReduce($fn) {
return array_reduce($this->members, $fn);
}
public function membersMap($fn) {
return array_map($fn, $this->members);
}
}
prints
team : Team 1
score: 394
members: john | paul
team : Team 2
score: 500
members: peter | marry