How to see variables from another class function in a PHP class? - php

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;
}
}

Related

PHP - Getting the class, which has called method

I would like to generate an log file. Therefor I have created a static class called log with an method called write:
class log {
public static function write($info) {
// file writing
}
}
In this function i would like to know from which class the method write is called (automatically):
log::write("Testinformation");
I have already tried with: get_called_class - but this gives me only "log" instead of the "real" called class...
Is there any way to automatically retrieve the called class?
$offset = 1;
$backtrace = debug_backtrace();
$caller = array();
if(isset($backtrace[$offset])) {
$backtrace = $backtrace[$offset];
if(isset($backtrace['class'])) {
$caller['class'] = $backtrace['class'];
}
if(isset($backtrace['function'])) {
$caller['function'] = $backtrace['function'];
}
}
No you have info about calling class and method or function. You can also use function I wrote long time ago
<?php
function getCaller($offset = 0) {
$baseOffset = 2;
$offset += $baseOffset;
$backtrace = debug_backtrace();
$caller = array();
if(isset($backtrace[$offset])) {
$backtrace = $backtrace[$offset];
if(isset($backtrace['class'])) {
$caller['class'] = $backtrace['class'];
}
if(isset($backtrace['function'])) {
$caller['function'] = $backtrace['function'];
}
}
return $caller;
}
?>
You can't retrieve the class that called it.
use something like:
define("log_tag", "myclass")
at the start of the file, and through out the rest of the file call:
log::write(log_tag, "testinformation");`
I think it would be easier to add the class name at the call of the method :
class Foo
{
public function bar()
{
// do something ...
log::write(get_called_class().': blablabla...');
}
}

PHP If Statement in Class to set protected variable

I'm trying to set a class Variable dependent on an if statement in PHP that's available to all the functions in the class. Just setting the variable works fine, but as soon as I attempt to set from an IF statement everything is breaking.
Examples:
Works
class Default_Service_NewSugar {
protected $base_url = "http://url1";
function test() {
return $this->base_url;
}
}
Doesn't work
class Default_Service_NewSugar {
if($_SERVER['APPLICATION_ENV']=="development"){
protected $base_url = "http://url1";
} else {
protected $base_url = "https://url2";
}
function test() {
return $this->base_url;
}
}
Is this not possible in a class? If not is there an alternative way I should be approaching this?
The main problem is that you are putting procedural code inside a class. Referencing to the PHP.net documentation:
A class may contain its own constants, variables (called "properties"), and functions (called "methods").
php.net
I would recommend reading the PHP manual on how to work with OOP, and read many of the OOP tutorials available on the web.
As mentioned in other answers you should do the initializing work inside the class constructor.
class Default_Service_NewSugar
{
protected $base_url;
public function __construct()
{
$this->base_url = ($_SERVER['APPLICATION_ENV'] == "development")
? "http://url1"
: "https://url2";
}
function test()
{
return $this->base_url;
}
}
A more OOP like approach would be to set the URL inside a configuration file and pass the variable to the class when initiating the class.
class Default_Service_NewSugar
{
protected $base_url;
public function __construct($base_url)
{
$this->base_url = $base_url;
}
function test()
{
return $this->base_url;
}
}
//usage would then be:
$default_service = new Default_Service_NewSugar($url_from_configuration_file);
$default_service->test(); //outputs the given URL
You should write that conditional statement inside the constructor. And also, no need to specify the access specifier every time the variable is being initialized, you can specify once and in the initialization part just assign the value. And also optimize your code as well.
class Default_Service_NewSugar {
protected $base_url = "http://url";
function __construct() {
$this->base_url .= $_SERVER['APPLICATION_ENV']=="development" ? 1 : 2;
}
function test() {
return $this->base_url;
}
}
You have lots of typos and that's not the perfect way to work around variables within class
class Default_Service_NewSugar {
protected $base_url;
public function __construct() {
$this->base_url = ($_SERVER['APPLICATION_ENV'] == "development") ? "http://url1" : "http://url2";
}
public function test() {
return $this->base_url;
}
}
As already mentioned, you may initiate your variable inside constructor. Another approach to achieve your goal is to use property access function instead of direct object field access. In this way, you may add additional conditions easily and the code will look like this:
class Default_Service_NewSugar {
public function __construct() {
}
public function getBaseURL($env = null) {
$env = $env ? $_SERVER['APPLICATION_ENV'] : $env;
return ($env == "development") ? "http://url1" : "http://url2";
}
}
$obj = new Default_Service_NewSugar();
print $obj->getBaseURL();

How do i get my class to use an array from outside the class?

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.

initilize array in class constructor or when defined?

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.

Error message Strict standards: Non-static method should not be called statically in php

I have the following php. However when I see the index.php I get the following error message.
Strict standards: Non-static method
Page::getInstanceByName() should not
be called statically in
/var/www/webworks/index.php on line 12
I am hoping someone can tell me how to fix the problem.
index.php
// { common variables and functions
include_once('ww.incs/common.php');
$page=isset($_REQUEST['page'])?$_REQUEST['page']:'';
$id=isset($_REQUEST['id'])?(int)$_REQUEST['id']:0;
...
// { get current page id
if(!$id){
if($page){ // load by name
$r=Page::getInstanceByName($page);
if($r && isset($r->id))$id=$r->id;
}
if(!$id){ // else load by special
$special=1;
if(!$page){
$r=Page::getInstanceBySpecial($special);
if($r && isset($r->id))$id=$r->id;
}
}
}
// { load page data
if($id){
$PAGEDATA=(isset($r) && $r)?$r : Page::getInstance($id);
}
else{
echo '404 thing goes here';
exit;
}
...
...
ww.incs/common.php
<?php
require dirname(__FILE__).'/basics.php';
...
...
ww.incs/basics.php
session_start();
if(!function_exists('__autoload')){
function __autoload($name) {
require $name . '.php';
}
}
...
...
Page.php
class Page{
static $instances = array();
static $instancesByName = array();
static $instancesBySpecial = array();
function __construct($v,$byField=0,$fromRow=0,$pvq=0){
# byField: 0=ID; 1=Name; 3=special
if (!$byField && is_numeric($v)){ // by ID
$r=$fromRow?$fromRow:($v?dbRow("select * from pages where id=$v limit 1"):array());
}
else if ($byField == 1){ // by name
$name=strtolower(str_replace('-','_',$v));
$fname='page_by_name_'.md5($name);
$r=dbRow("select * from pages where name like '".addslashes($name)."' limit 1");
}
else if ($byField == 3 && is_numeric($v)){ // by special
$fname='page_by_special_'.$v;
$r=dbRow("select * from pages where special&$v limit 1");
}
else return false;
if(!count($r || !is_array($r)))return false;
if(!isset($r['id']))$r['id']=0;
if(!isset($r['type']))$r['type']=0;
if(!isset($r['special']))$r['special']=0;
if(!isset($r['name']))$r['name']='NO NAME SUPPLIED';
foreach ($r as $k=>$v) $this->{$k}=$v;
$this->urlname=$r['name'];
$this->dbVals=$r;
self::$instances[$this->id] =& $this;
self::$instancesByName[preg_replace('/[^a-z0-9]/','-',strtolower($this->urlname))] =& $this;
self::$instancesBySpecial[$this->special] =& $this;
if(!$this->vars)$this->vars='{}';
$this->vars=json_decode($this->vars);
}
function getInstance($id=0,$fromRow=false,$pvq=false){
if (!is_numeric($id)) return false;
if (!#array_key_exists($id,self::$instances)) self::$instances[$id]=new Page($id,0,$fromRow,$pvq);
return self::$instances[$id];
}
function getInstanceByName($name=''){
$name=strtolower($name);
$nameIndex=preg_replace('#[^a-z0-9/]#','-',$name);
if(#array_key_exists($nameIndex,self::$instancesByName))return self::$instancesByName[$nameIndex];
self::$instancesByName[$nameIndex]=new Page($name,1);
return self::$instancesByName[$nameIndex];
}
function getInstanceBySpecial($sp=0){
if (!is_numeric($sp)) return false;
if (!#array_key_exists($sp,$instancesBySpecial)) $instancesBySpecial[$sp]=new Page($sp,3);
return $instancesBySpecial[$sp];
}
Your methods are missing the static keyword. Change
function getInstanceByName($name=''){
to
public static function getInstanceByName($name=''){
if you want to call them statically.
Note that static methods (and Singletons) are death to testability.
Also note that you are doing way too much work in the constructor, especially all that querying shouldn't be in there. All your constructor is supposed to do is set the object into a valid state. If you have to have data from outside the class to do that consider injecting it instead of pulling it. Also note that constructors cannot return anything. They will always return void so all these return false statements do nothing but end the construction.
I think this may answer your question.
Non-static method ..... should not be called statically
If the method is not static you need to initialize it like so:
$var = new ClassName();
$var->method();
Or, in PHP 5.4+, you can use this syntax:
(new ClassName)->method();
If scope resolution :: had to be used outside the class then the respective function or variable should be declared as static
class Foo {
//Static variable
public static $static_var = 'static variable';
//Static function
static function staticValue() { return 'static function'; }
//function
function Value() { return 'Object'; }
}
echo Foo::$static_var . "<br/>"; echo Foo::staticValue(). "<br/>"; $foo = new Foo(); echo $foo->Value();
Try this:
$r = Page()->getInstanceByName($page);
It worked for me in a similar case.
use
className->function();
instead
className::function() ;
return false is usually meant to terminate the object creation with a failure. It is as simple as that.
Instead of using the instance with the scope resolution operator :: because it wasn't defined like static function.
$r=Page::getInstanceByName($page);
change it to :
$r=Page->getInstanceByName($page);
And it will work like a charm.

Categories