simple class method not working - php

this is a super basic question but my classes are not working the way I expect them to. I am a CS student in my second year so go easy on me! The only other language I know is Java. Here is my class, called class.Team.php (represents a team).
<?php
class Team
{
private $teamId='';
private $teamName='Tyler';
private $teamCity='';
private $homeField='';
private $headCoach='';
private $mascot='';
private $wins=0;
private $losses=0;
private $roster;
function display(){
return $teamName;
}
}
?>
So when I call the display() method it should return a string (hardcoded as "tyler). Here is my test script. It is simply displaying nothing. A blank white page. Am I missing something??
<?php
include ('class.Team.php');
$um = new Team;
$string = $um->display();
print ($string);
?>
THANKS!

You need to use the $this keyword.
function display(){
return $this->teamName;
}

It's not Java. You have to use $this to reference own instance.
return $this->teamName;

Related

How to create sub-variables in PHP class

I started using OOP in PHP for first time, and I dont know how to achieve the following structure for my variables:
$this->myData->generalData->title;
$this->myData->generalData->description;
$this->myData->amount;
$this->myData->addNewData();
Up till now, what I am achieving is a normal variable inside a class:
$this->variablename
I tried doing this code, but it's not working at all:
$this->CDNE = "CDNE";
$this->CDNE->FOLDER = "hello man";
Can you explain me, how all this works?
Just to ilustrate my comment. Doing it with sub-objects could be something like this (a very basic example without attributes initialization):
class GeneralData{
public $title;
public $description;
}
class MyData{
public $generalData;
public $amount;
function __construct(){
$this->generalData = new GeneralData();
}
function addNewData(){
}
}
class MainClass{
public $myData;
function __construct(){
$this->myData = new MyData();
}
}

Passing an instance of a Class with methods to a function PHP

I am struggling with some PHP code here. Like the title says, I am trying to pass an instance of a Class as a parameter to a function (Note, this file is in another file and has a different scope, and thus I need to pass it as a parameter).
This is the code I have currently set up:
// requires built this page, the classes and the functions are in seperate files.
// That's why I need to pass it in as a parameter.
class ClassName {
private $name;
private $age;
public function getAge(){
return $this->age;
}
} $className = new ClassName();
// seperate file
var_dump($className); // works, but has no methods.
function randomFunc($className){
echo $className->getAge(); // call to undefined method className::getAge()
} randomFunc($className);
EDIT 2:
I have uploaded my code here:
http://sandbox.onlinephpfunctions.com/code/99954d61ca4d3f53ce549dab9f8333630633d89c
I hope you people can help me, any help would be much appreciated.
This works fine:
<?php
class ClassName {
private $name;
private $age = 19;
public function getAge(){
return $this->age;
}
}
function randomFunc($className){
echo $className->getAge(); // call to undefined method className::getAge()
}
$className = new ClassName();
randomFunc($className);
Outputs: 19
Your code also runs fine for me, it just outputs nothing since $age is empty.
What version of PHP are you running?

PHP OOP Construct explination unclear

This is not a question about a particular problem, but rather a question asking for advice and / or assistance.
Im a 2nd year student, Im really struggling to get the hang of OOP programming, the fact that my textbook is not very clear, in its explanation is not helping either. I know there are 100's of examples on the web of this probably but I would like to focus specifically on the example used in my textbook.
The introduction to OOP in php starts with this:
EXAMPLE 1
class Person{
var $name;
function set_name($data){
$this->name=$data;
}
function get_name(){
return $this->name;
}
}
$ralph = new Person;
$ralph->set_name('Ralph');
echo 'friend name is '.$ralph->get_name();
Fine I get that no problem However it then goes on giving, what is in my view a very brief explanation on constructors, saying:
Wouldn't it be nice if you could both create and initialize an object at the same time, PHP allows you to do that with constructors.
And then proceeds to give the following example
EXAMPLE 2(UNCLEAR...?)
class Person{
var $name;
function __construct($data)
{
$this->name=$data
}
function set_name($data){
$this->name=$data;
}
function get_name(){
return $this->name;
}
}
$dan = new Person;
echo"Friend name is ", $dan->get_name(), ".";
My Question
I would really like to know what is the difference between the two examples above? Also if a beginner practical example could be included it will be enormously appreciated!
It's no wonder you are confused, that is a very bad example (looks like they forgot to include passing the name to the constructor)! There are also some outdated styles here as well, typically people do not use var anymore for property declarations but declare their scope (public, private, protected, etc.), also some syntax errors (missing semicolon), but that is for another day.
What would have made this a lot more clear is if they actually used the new power of the constructor, which for some reason, they did not. Here is an updated example where the constructor is actually being used:
class Person{
private $name;
function __construct($data)
{
$this->name=$data;
}
function set_name($data){
$this->name=$data;
}
function get_name(){
return $this->name;
}
}
// pass the name to the constructor and you can bypass the set_name call
$dan = new Person("Timothy");
echo "Friend name is ", $dan->get_name(), ".";
This definitely gets much more useful than passing scalars, but hopefully it illustrates what constructors can do a little bit better. Constructors are called automatically whenever you instantiate a new object from a class. Let me know if you have any questions.
The difference between two class is first one you can not initialize data at a time but in second class you can initialize data at a time.
In First Class
class Person{
private $name;
function set_name($data){
$this->name=$data;
}
function get_name(){
return $this->name;
}
}
$ralph = new Person; // you can not initialize value here
$ralph->set_name('Ralph');
echo 'friend name is '.$ralph->get_name(); //friend name is Ralph
In second Class
class Person{
private $name;
function __construct($data)
{
$this->name=$data
}
function set_name($data){
$this->name=$data;
}
function get_name(){
return $this->name;
}
}
$dan = new Person('Sahadat'); //you can initialize value here
echo"Friend name is ", $dan->get_name(), "."; //Friend name is Sahadat
$dan->set_name('John');
echo"Friend name is ", $dan->get_name(), "."; //Friend name is John
The second way is the best way.
Here is a simple answer. First you seem to use javascript var in the above code, so I omit this below. As you can see, the Person is the Object of concern. In the above example, the author is adding only a name to a Person object - but a person could have many other characteristics such as age, date of birth etc... So when a person object is initialized, the Person object will have a place to store its $name in memory. Since the the $name property is private, the above code uses setters and getters to set and get the $name property.
class Person{
private $name;
function setName($name){
$this->name = $name;
}
function getName(){
return $this->name;
}
function setName($name){
$this->name = $name;
}
}
$ralph = new Person;
$ralph->set_name('Ralph');
echo 'friend name is '.$ralph->get_name();
// Friend name is Ralph
The second example combines two steps ( btw you seem to have copied the wrong snippet ) the object will accept one parameter $data .
class Person{
private $name;
function __construct($data)
{
$this->name=$data
}
function setName($name){
$this->name=$name;
}
function getName(){
return $this->name;
}
}
$dan = new Person('Dan');
echo"Friend name is ", $dan->get_name(), ".";
//Friend name is Dan
A true object Oriented example should look like this:
class Person{
private $name;
function __construct($data)
{
$this->name=$data
}
function setName($name){
$this->name=$name;
return $this; // return $this to allow chaining of method calls
}
function getName(){
return $this->name;
}
}
Here is the extra, In real world applications, you find stuff like in this example
public function billTo(array $user){
// Create the Bill To info
$billto = new AnetAPI\CustomerAddressType();
$billto->setFirstName($user['firstname']);
$billto->setLastName($user['lastname']);
$billto->setCompany($user['company_name']);
$billto->setAddress($user['address']);
$billto->setCity($user['city']);
$billto->setState($user['state']);
$billto->setZip($user['zipcode']);
$billto->setCountry($user['country']);
$billto->setEmail($user['email']);
$billto->setPhoneNumber($user['phone']);
return $billto;
}
The above functions creates an instance of the class CustomerAddressType() and stores data from the User array ( passed as a parameter ) in that CustomerAddressType instance. Same as the first example given by the author.

Dependency Injection in PHP using pimple

I'm new to DI ,using Pimple. Using: php 5.3.5 (wamp), namespaces as well.
I'm refactoring code, using it, but came to a problem (s):
I have my Container that extends from Pimple, lets call it PContainer.php:
class ReuseableContainer extends Pimple{
private function initOutterClass(){
$this['special_location_class'] = '\SpecialLocation';
$this['special_location'] = function($c){return new $c['special_location_class']($c['location_details'],$c['location']);};
}
private function initGlobalFunctions(){
$this['getGeneralDataFromArray'] = function($c){
// returning a function
return function($arr){
foreach ($arr as $key => $value){
// do something
$new_data = $c['general_data_type'];
$new_data->id = $value['id'];
$new_data->name = $value['name'];
}
}
}
public function __construct(){
$this['location_class'] = '\Location';
$this['location_details_class'] = '\LocationDetails';
$this['general_data_type_class'] = '\GeneralDataType';
// define some objects
$this['location'] = function ($c) {
return new $c['location_class']();
};
$this['location_details'] = function ($c) {
return new $c['location_details_class']();
};
$this['general_data_type'] = function ($c) {
return new $c['general_data_type_class']();
};
$this->initOutterClass();
$this->initGlobalFunctions();
}
}
global $container ;
$container = new Pimple();
// embed the SomeContainer container
$container['embed'] = $container->share(function () { return new ReuseableContainer(); });
Ok. So i got a SpecialHelper.php which holds:
final class SpecialLocation{
public $name;
public $location;
public $picture;
public function __construct($location){
$this->location; // dependent on class: Location
}
}
final class SpecialUser{
private $id;
private $location;
public function __construct(\Location $location,$id=''){
$this->id = $id;
$this->location = $location; // $container['embed']['location'];
}
and we got our GeneralHelper.php which holds:
final class Location{
public $lat;
public $lng;
public function __construct($lat='',$lng=''){ $this->lat = $lat; $this->lng = $lng;}
}
final class LocationDetails{
public $id;
public $addresss;
public function __construct($id='',$address=''){$this->id = $id; $this->address = $address;}
}
class GeneralDataType{
public $id;
public $name;
public function getName(){ return $this->name;}
public function getId(){ return $this->id;}
}
and we have our "Special Class" controller, which looks something like this:
final class SpecialController{
public function foor($some_array){
$this->doSomething($some_array);
}
private function doSomething($ret_value){
// do something
$arr = array();
foreach($ret_value as $key => $value){
$something = $container['embed']['getGeneralDataFromArray']($value);
$special_location = $container['embed']['special_location'];
$arr[] = special_location;
}
return $arr;
}
}
Finally we have our main "driver", main.php
require('PContainer.php');
....
...
$some_array = array(....);
$special_controller = new SpecialController();
$special_controller->foor($some_array);
Problems:
1) I had to add initOutterClass function inside ReuseableContainer to decouple the "Special" classes, how could have i decoupled them in a better way? creating a new "special" 9container or something? as EVERYTHING now sitts inside the container.. same goes to the initGlobalFunctions()
2) regarding SpecialHelper.php: i have there SpecialLocation, which one of its properties is a \Location class, i've put it in the constructor , but if i have 20 object properties that are dependent, i must put them all as INPUT params for the constructor?? same goes to the SpecialUser class, it has a $location which if i could i would have made $this->location = $container['embed']['location']; instead of $this->location = $location; resulting in a dependent on the DI! :/
3) I've had to create SpecialHelper.php in a different file, despite wanting to put it in the "special class controller", just so there won't be any unknowns (due to require statement order)
4) MOST importantly: about the "Special class" controller, how do i solve the doSomething method? i must create "Special Location" object inside the loop but i get that $container is unrecognized (despite being global, as of scope probably) but more over it's really dependent! and it's a private function, i don't wish to pass the container to EVERY class i'll use from now on, it isn't IoC right?
Any help is appriciated... i'm trying to understand the best practices..
Thank you
4)Most important: IoC is correct. That an implementation is not correctly working does not reflect the principle of IoC itself.
If you want to use the global $container within a function, then should you use the global keyword within that function. That is how PHP works. Making it static is solving the problem of reference, but does not make a real difference.
An IoC container resolves the dependencies for the caller. The caller does not have to know anything about the internals of the callee - and he doesn't care either. So, there should be some kind of contract by which the exchange of data is regulated. If you have that situation, then you have IoC.
3)That problem is too vague to answer, but imo also not relevant from a practical perspective. Does it work? Ok, good to know. :-)
2)The clue of IoC is the use of contracts. The IoC container is there to connect the caller to the proper contract. The contract resolves to a concrete callee. The callee will return information inline with the contract. The caller understands the answer. Therefor will you need that the input and output in this process is independent of a certain implementation at a certain time. So don't use 20 object properties as input, but use an array or general object instead.
1) I get the idea that you are mixing functional flow (data flow) with technical flow (relationships between classes). An IoC container serves the purpose of the technical flow, it optimizes the dependency in the relationships between classes. For instance, if you want to connect to a database, then might you reuse an existing connection instead of creating new connections all the time. Or if you want to use a special functionality on several moments in your flow, then might you use IoC for that.

Mock private method in a test function by PHPUnit

Writing unit tests for code which is already written is fun sometimes.
I am writing a test case for the following code (an example):
<?php
class mockPrivate {
public static function one($a){
$var = static::_two($a);
return $var;
}
private static function _two($a){
return $a+1;
}
}
?>
The test class is like this:
<?php
require_once 'mockPvt.php';
class mockPrivate_test extends PHPUnit_Framework_TestCase {
public $classMock;
protected function setUp(){
$this->classMock = $this->getMock('mockPrivate', array('_two'));
}
public function test_one(){
$a = 1;
$retVal = 2;
$classmock = $this->classMock;
$classmock::staticExpects($this->once())
->method('_two')
->with($a)
->will($this->returnValue($retVal));
$value = $classmock::one($a);
$this->assertEquals($value, $retVal);
}
}
?>
After running by $ phpunit mockPrivate_test.php I got this error:
PHP Fatal error: Call to private method Mock_mockPrivate_531a1619::_two() from context 'mockPrivate' in /data/www/dev-sumit/tests/example
s/mockPvt.php on line 6
But if I change the
private static function _two()
to
public static function _two() or
protected static function _two()
it works totally fine. Since this is a legacy code I can't change the private to public/protected. So is there any way I can test the function one or Is this a limitation of phpunit?
Another option is to create a class that extends mockPrivate, allowing accessibility to the object you wish to test. Your engineers should be thinking long and hard about why something is private (because that means the class is not easily extensible). Also remember that you can mock the test class if you need to override what it returns.
class Test_MockPrivate extends MockPrivate
{
/**
* Allow public access to normally protected function
*/
public static function _two($a){
return parent::_two($a);
}
}
// Code to force the return value of a now public function
$mock = $this->getMock('Test_MockPrivate', array('_two'));
$mock->expects($this->any())
->method('_two')
->will($this->returnValue('Some Overridden Value');
You can use reflection for changing visibility of methods. You can find more info in
PHP object, how to reference?
Use mock and reflection... (posted this solution, since this is the top google result)
$oMock = $this->getMock("Your_class", array('methodToOverride'));
$oMock->expects( $this->any() )
->method('methodToOverride')
->will( $this->returnValue( true ) );
$oReflection = new ReflectionClass("Your_Class");
$oMethod = $oReflection->getMethod('privateMethodToInvoke');
$oMethod->setAccessible( true );
$oMethod->invoke( $oMock );

Categories