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.
Related
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.
How do I see variables from another function in the same class?
Here is the problem i have:
class slike {
public function __construct($dire) {
$this->dire=$dire;
}
function skupljanjeslika() {
$slike = array();
$handler = opendir($this->dire);
while ($file = readdir($handler)) {
if ($file != "." && $file != "..") {
$slike[] = $file;
}
}
closedir($handler);
return $slike; // **Array i want to use!**
}
function prikazradnomslike() {
$slike; // Here is the array from first function, but I can't see it here
$rezultat = count($slike)-1;
$koliko=rand(0, $rezultat);
$slika=$slike[$koliko];
return $slika;
}
}
did you try to do this :
$slike = $this->skupljanjeslika();
Or if you method skupljanjeslika is used before, try this :
In your class, add a var :
protected $slike;
In skupljanjeslika replace the return by this :
$this->slike = $slike;
And in prikazradnomslike, do this :
$slike = $this->slike;
To be more efficient, you can definitly do this :
class slike {
protected $slike;
public function __construct($dire) {
$this->dire=$dire;
}
function skupljanjeslika() {
$slike = array();
$handler = opendir($this->dire);
while ($file = readdir($handler)) {
if ($file != "." && $file != "..") {
$slike[] = $file;
}
}
closedir($handler);
$this->slike = $slike;
}
function prikazradnomslike() {
$rezultat = count($this->slike)-1;
$koliko=rand(0, $rezultat);
$slika=$this->slike[$koliko];
return $slika;
}
}
Add a variable to the class:
class slike
{
$protected $slike;
public function __construct($dire) {
...
Access it like this:
$this->slike;
You need to define your variable as a class variable, i suggest to read this to see how to declare class variables.
class slike {
...
function prikazradnomslike()
{
$slike = $this->skupljanjeslika();
return $slike[ array_rand($slike, 1) ];
}
}
see http://docs.php.net/return and http://docs.php.net/array_rand
You can either call skupljanjeslika() from where you want your return value like this: $slike = $this->skupljanjeslika(); or you can pass in the array as a parameter if you want to call it from somewhere else:
function prikazradnomslike($slike)
{
$rezultat = count($slike)-1;
$koliko=rand(0, $rezultat);
$slika=$slike[$koliko];
return $slika;
}
You could have a private property $slike in your class, set it in your slike::skuplanjeslika() and use it in your slike::prikazrandomslike(). Another option is to pass $slike as an argument to slike::prikazrandomslike:
class slike
{
public function __construct($dire)
{
$this->dire=$dire;
}
function skupljanjeslika()
{
$slike = array();
$handler = opendir($this->dire);
while ($file = readdir($handler)) {
if ($file != "." && $file != "..") {
$slike[] = $file;
}
}
closedir($handler);
return $slike; // **Array i want to use!**
}
function prikazradnomslike($slike)
{
$rezultat = count($slike)-1;
$koliko=rand(0, $rezultat);
$slika=$slike[$koliko];
return $slika;
}
}
$photos = new slike('mydir');
$photos->prikazrandomslike($photos->skuplanjeslika());
The issue you're having has to do with "scope" ( http://php.net/manual/en/language.variables.scope.php ). A variable is not accessible outside of the function in which it was originally declared.
If you want access to a variable anywhere within your script there are a number of ways to accomplish this. You can use global variables (not recommended in most cases) or declare them as part of a class (these can be static or not - more on that farther down the post).
A variable declared inside of a class will look something like this:
class myClass {
public $var1;
protected $var2;
private $var3;
public function foo() {
return $this->var1;
}
}
Make a note of public, private and protected, as these are very important keywords.
A private variable within a class is only accessible within that class - it will not be inherited by any children, nor can it be accessed directly by an instance of the object (i.e. $myClassObj->var1)
A protected variable will be inherited by child classes, but has the same access restrictions when using instances of the object.
A public variable is accessible directly and will be inherited.
In order to access any of these variables within the class, simply refer to it using the $this variable.
E.G.:
$this->$var1;
Now, if you declare a variable as static it will be available in memory at all times and accessible via the scope resolution operator (::). HOWEVER private and protected variables will not be directly accessible (same rules apply as before).
myClass::$var1 = 4; // this works fine, and sets $var1 to 4 across ALL instances of myClass
myClass::$var2 = 3; // this WILL NOT WORK - protected variable.
If you need to access a static variable within the class you must refer to it using the scope resolution operator and the keyword self.
class myClass {
public static $var1;
function bar() {
return self::$var1;
}
}
I have a class which contains an array of objects and has methods to return an object from that array by reference. There is also a method to unset an object from the array.
However if I have a variable that references an object from the array, and that element is unset, the variable still has a reference to it. What do I need to do in the remove method that will destroy that object for good, including references to it.
class myClass
{
public $objectList = array();
public function __construct()
{
$objectList[] = new myObject();
}
public function &getObjectByReference()
{
return $this->objectList[0];
}
public function removeObject()
{
unset($this->objectList[0]);
}
}
$myClass = new myClass();
$referencedObject = $myClass->getObjectByReference();
// this can now use the methods from myObject
$myClass-> removeObject();
// supposed to delete the object from memory. However $referencedObject is still
// able to use all the methods from myObject.
So thats the problem I am having, I need to be able to remove from the array and delete the object from memory so variables that reference that object are no longer usable.
Have you tried doing:
$referencedObject = &$myClass->getObjectByReference();
Is $referencedObject still there after putting in that &?
To create a reference from a return value both the function must return by reference (you already do so) and the assignment has to by by reference. So you should write:
$referencedObject =& $myClass->getObjectByReference();
If you do this the reference really will be destroyed.
But if you want to do destroy all variables having this object as value (and which are not references) then this is impossible. You can only remove the real references, not variables having the same value ;)
Php is working with garbage collector : if there is still a reference to the object then the object is not deleted.
unset($this->objectList[0])
Does not delete the object but the value in $this->objectList, the object still exists since he is referenced by $referencedObject.
One solution : when you delete the object, tell him he is being deleted and in that object you have a boolean "isDeleted". Then for every method of that object, check if isDeleted is true and in that case, just do nothing.
This is the nature of PHP's garbage collector. To make sure a caller doesn't maintain a reference to your object you have to ensure they can never touch the original object. Here is an idea:
class myClass
{
public $objectList = array();
public function __construct()
{
$objectList[] = new Wrapper(new myObject());
}
public function getObject()
{
return $this->objectList[0];
}
public function removeObject()
{
$this->objectList[0]->emptyWrapper();
unset($this->objectList[0]);
}
}
class Wrapper {
private $object;
public function __construct($object) {
$this->object = $object;
}
public function __call($method, $args) {
return call_user_func_array(array($this->object, $method), $args);
}
public function __get($attr) {
return $this->object->$attr;
}
public function __set($attr, $value) {
$this->object->$attr = $value;
}
public function emptyWrapper() {
$this->object = null;
}
}
You can use this wrapper idea or you can use forced indirection and handles. I might prefer using forced indirection instead; otherwise, a caller can still keep the wrapper object alive - though it is fairly cheap.
class myClass
{
public $objectList = array();
public function __construct()
{
$objectList[] = new myObject();
}
public function getObjectHandle() {
return 0;
}
public function removeObject($h)
{
unset($this->objectList[$h]);
}
public function call($h, $method, $args) {
call_user_func(array($this->objectList[$h], $method), $args);
}
public function get($h, $attr) {
return $this->objectList[$h]->$attr;
}
public function set($h, $attr, $value) {
$this->objectList[$h]->$attr = $value;
}
}
$myClass = new myClass();
$objectHandle = $myClass->getObjectHandle();
// example method call
$myClass->call($objectHandle, 'some_method', array('arg1', 'arg2'));
$myClass->removeObject($objectHandle);
Does anyone know how to reset the instance variables via a class method. Something like this:
class someClass
{
var $var1 = '';
var $var2 = TRUE;
function someMethod()
{
[...]
// this method will alter the class variables
}
function reset()
{
// is it possible to reset all class variables from here?
}
}
$test = new someClass();
$test->someMethod();
echo $test->var1;
$test->reset();
$test->someMethod();
I know I could simply do $test2 = new SomeClass() BUT I am particularly looking for a way to reset the instance (and its variables) via a method.
Is that possible at all???
You can use reflection to achieve this, for instance using get_class_vars:
foreach (get_class_vars(get_class($this)) as $name => $default)
$this -> $name = $default;
This is not entirely robust, it breaks on non-public variables (which get_class_vars does not read) and it will not touch base class variables.
Yes, you could write reset() like:
function reset()
{
$this->var1 = array();
$this->var2 = TRUE;
}
You want to be careful because calling new someClass() will get you an entirely new instance of the class completely unrelated to the original.
this could be easy done;
public function reset()
{
unset($this);
}
Sure, the method itself could assign explicit values to the properties.
public function reset()
{
$this->someString = "original";
$this->someInteger = 0;
}
$this->SetInitialState() from Constructor
Just as another idea, you could have a method that sets the default values itself, and is called from within the constructor. You could then call it at any point later as well.
<?php
class MyClass {
private $var;
function __construct() { $this->setInitialState(); }
function setInitialState() { $this->var = "Hello World"; }
function changeVar($val) { $this->var = $val; }
function showVar() { print $this->var; }
}
$myObj = new MyClass();
$myObj->showVar(); // Show default value
$myObj->changeVar("New Value"); // Changes value
$myObj->showVar(); // Shows new value
$myObj->setInitialState(); // Restores default value
$myObj->showVar(); // Shows restored value
?>