Why is the instance still dealing cards? Even though clearly, the $isDealer tag is defaulted to false, except for the dealer?
$cards = array('Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King');
$suits = array('Hearts','Diamonds','Spades','Clubs');
class Person {
public $isDealer = false;
public $luck = 15;
public function dealCards() {
if ($isDealer) {
global $cards;
global $suits;
for ($i = 0; $i < 5; $i++) {
$pulledcard = rand(0,count($cards)-1);
$pulledsuit = rand(0,count($suits)-1);
echo $dealt = $cards[$pulledcard] .' of '. $suits[$pulledsuit] . '<br>';
}
}
else {
return 'You\'re not a dealer';
}
}
}
class Baller extends Person { public $luck = 50; }
class Dealer extends Person { public $isDealer = true; }
$dealer = new Dealer();
$theman = new Baller();
$random = new Person();
echo $theman->dealCards(); //this should return you're not a dealer but it deals cards instead
The last part should return a "You're not a dealer!" but instead, it deals cards. The same goes with the actual "Dealer".
You want
if ($this->isDealer) {
$isDealer does not mean $this->isDealer. It means a new, implicitly-created variable.
Plus, you can't override member variables like that.
When you write
if ($isDealer)
You are not checking the value for the variable that you expect. Your code is asking whether the variable $isDealer within the scope of the function dealCards() exists or is true/false. In order to check whether the member variable $isDealer for the class Person is true/false you must use $this->isDealer. This ensures that you are checking the member variable $isDealer within the cope of Person and not within the scope of the member function. So, you should get the behavior you expect if you use
if ($this->isDealer)
When you have this line:
class Dealer extends Person { public $isDealer = true; }
is it possible that public $isDealer = true; will overwrite the public $isDealer in class Person{}, having it that $isDealer will always be true? from another point of view, if this script is the only place where you use $isDealer, it might not be really necessary to define it as public?
Related
Sorry for the question but I don't understand how this works:
class Person {
public static $age = 1;
public function haveBirthday() {
static::$age +=1;
}
}
$joe = new Person;
$joe->haveBirthday();
echo Person::$age;
What I'm not understanding is this:
public function haveBirthday() {
static::$age +=1;
}
Isn't supposed to return $age otherwise the value is lost? Why is it still working?
Thanks!
You've defined it as static, which means those are class level variables instead of instance level.
So when you call $joe->haveBirthday(); it updates the class level variable of the Person class which can accessed using Person::$age;.
Static variables does not need to be returned, you can access it directly from Class.
public static $age = 1; suggests this is a static property, which means this as a class property, not an instance's.
The method haveBirthday() does not return anything, it simply increase the static variable $age.
A static variable is shared by all instances of this classes. So it is not a good idea in your case, as all persons will have the same age.
class Person {
public static $age = 1;
public function haveBirthday() {
static::$age +=1;
}
}
$joe = new Person;
$jane = new Person;
$joe->haveBirthday(); // +1 => 2
$jane->haveBirthday(); // +1 => 3
echo Person::$age; // Will return 3
Test it here.
I have been implementing a Wordpress plugin and I faced a problem with finding out if a variable has been declared or not.
Let's say I have a model named Hello; this model has 2 variables as hello_id and hello_name.
In the database we have table named hello with 3 columns as hello_id, hello_name , hello_status.
I would like to check if a variable has been declared and, if it has, set a value.
abstract class MasterModel {
protected function setModelData($data)
{
foreach($data as $key=>$value){
if(isset($this->{$key})){ // need to check if such class variable declared
$this->{$key} = $value;
}
}
}
}
class Hello extends MasterModel{
public $hello_id;
public $hello_name;
function __construct($hello_id = null)
{
if ($hello_id != null){
$this->hello_id = $hello_id;
$result = $wpdb->get_row(
"SELECT * FROM hello WHERE hello_id = $hello_id"
, ARRAY_A);
$this->setModelData($data);
}
}
}
The main reason why I am doing this is to make my code expandable in the future. For example I might not use some fields from the database but in future I might need them.
you can use several options
//this will return true if $someVarName exists and it's not null
if(isset($this->{$someVarName})){
//do your stuff
}
you can also check if property exists and if it doesn't add it to the class.
property_exists returns true even if value is null
if(!property_exists($this,"myVar")){
$this->{"myVar"} = " data.."
}
Use isset http://php.net/manual/en/function.isset.php
if(isset($var)){
//do stuff
}
Talking about a nullable class property, to check if it has been initialized:
class MyClass {
public ?MyType $my_property;
public \ReflectionProperty $rp;
public function __construct()
{
$this->rp = new \ReflectionProperty(self::class, 'my_property');
}
public function myMethod()
{
if (!$this->rp->isInitialized($this)) {
// Do stuff when my_property has never been initialized
}
}
}
This is useful when creating a caching system where the value can be null.
I'm currently trying to get back into object oriented programming How do i get my array inside my class? Global doesn't seam to cut it.
<?
$systems = file_get_contents('https://api.eveonline.com/map/Sovereignty.xml.aspx');
$systems = explode("<row ",$systems);
//print_r($systems);
for ($i = 1; $i <= count($systems); $i++) {
//system name
$systemnames=explode("solarSystemName=",$systems[$i]);
$systemnames=explode('"',$systemnames[1]);
$systemnames=$systemnames[1];
//system id
$systemid=explode("solarSystemID=",$systems[$i]);
$systemid=explode('"',$systemid[1]);
$systemid=$systemid[1];
$systembyid[$systemid]=$systemnames;
$systembyname[$systemnames]=$systemid;
}
class Systems{
public function __construct()
{
global $systembyid;
global $systembyname;
}
function getSystems($system)
{
if (is_numeric($system) && $systembyid[$system]) {
return $systembyid[$system];
}
elseif($systembyname[$system]){
return $systembyname[$system];
}
else{
return "Error: Invalid system id or name";
}
}
}
?>
Try passing the values into the constructor like this, also if you use the & you are just passing a reference and not making a copy of the whole array.
class Systems{
private $sysyembyid;
private $systembyname;
public function __construct(&$systembyid, &$systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
function getSystems($system){
if(is_numeric($system) && $this->systembyid[$system]){
return $this->systembyid[$system];
}
elseif($this->systembyname[$system]){
return $this->systembyname[$system];
}
else{
return "Error: Invalid system id or name";
}
}
}
I prefer to use Dependency Injection. Dependency Injection is when you inject your object's dependencies via the constructor. This ensures that the object will have its dependencies at creation.
class Systems {
protected $systembyid;
protected $systembyname;
public function __construct($systembyid, $systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
public function getSystems($system) {
//Access them with $this-> like below
$this->systembyid[$system];
$this->systembyname[$system];
}
}
Note If you want to be able to modify $systembyid and $systembyname outside of the class, and see the changes within the class, you can pass references to __construct() instead, by specifying the parameters as references:
public function __construct(&$systembyid, &$systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
Alternatively, you can pass them as parameters to your getSystems() method.
class Systems() {
public function getSystems($system, $systembyid, $systembyname) {
//Do stuff
}
}
The main drawbacks with this approach is that you always have to pass them as parameters to the method, and the method signature could get quite long.
You either need to use the global key word with var in the function where you use it, in this case getSystems() (bad) or pass them into the constructor or the function where you use them, or set them:
Probably the most common case:
public function __construct($s1, $s2)
{
$this->systembyid = $s1
$this->systembyname = $s2
}
//then use $this->systembyid etc in other functions
Or better yet, why not put all that processing code in a function off the class like processSystems() and set the vars there:
public function processSystems($file) {
$systems = file_get_contents($file);
$systems = explode("<row ",$systems);
//print_r($systems);
for ($i = 1; $i <= count($systems); $i++) {
//system name
$systemnames=explode("solarSystemName=",$systems[$i]);
$systemnames=explode('"',$systemnames[1]);
$systemnames=$systemnames[1];
//system id
$systemid=explode("solarSystemID=",$systems[$i]);
$systemid=explode('"',$systemid[1]);
$systemid=$systemid[1];
$systembyid[$systemid]=$systemnames;
$systembyname[$systemnames]=$systemid;
}
$this->systembyid = $systemnames;
$this->systembyname = $systemid;
}
Aside from that, I would say look into simple_xml or DOM for the XML parsing.
Also, you are storing the exact same data in each array. Just use one and either lookup the key or the value.
I have a $rawText class property that is supposed to be array. It's assigned a value during object construction, however the value may not be found so the variable remains without a value.
class TextProcessor {
public $rawText;
public function __construct($idText) {
if ($idText !== NULL) {
$this->$rawText = $this->getRawText();
}
}
}
Do I need to assign an empty array then?
public function __construct($idText) {
if ($idText !== NULL) {
$this->$rawText = $this->getRawText();
} else {
$this->$rawText = Array();
}
Or maybe it's even better to assign empty array when the property is defined?
class TextProcessor {
public $rawText = Array();
}
class TextProcessor {
public $rawText = array();
public function __construct($idText) {
if (! empty($idText)) {
$this->rawText = $this->getRawText();
}
}
}
I think that's what you trying to do.
I think the construct method is used to define some variables private usually. If you want to give $rawText a new value, after you instantiate this class, you can write a set property method to change its value.
I have set a property in a constructor like so
function __construct()
{
$this->count = count(#$_SESSION['filearray']); //count how many files in array
}
and using it in condition statements if($this->count > 10) //then do something
but it appears the count isn't being updated when I use another method of injecting values into this 'filearray' until I refresh the page.
am I doing something wrong? I thought that my constructor would detect a change had been made in the session and whenever I call $this->count I would get the current count value but it seems to be 1 step behind until I refresh the page.
If this is all vague I can include my form page that has all the method calls, but this is the jist of my question, why is my property not updating and how do I fix it :)
TIA
$this->count won't automatically be updated with the count every time you add or subtract from the filearray session. Constructors are only invoked upon instantiation of the class or when called directly.
You can achieve this sort of functionality using a getter.
class myClass {
public function getCount() {
return count(#$_SESSION['filearray']);
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->getCount(); // 1
Or by using the __get() magic-method:
class myClass {
public function __get($property_name) {
if ($property_name == 'count') {
return count(#$_SESSION['filearray']);
}
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->count; // 1
Or a combination of the two:
class myClass {
private $_count;
public function __get($property_name) {
if ($property_name == 'count') {
return $this->_getCount();
}
}
private function _getCount() {
return $this->_count = count(#$_SESSION['filearray']);
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->count; // 1