I wonder how i can call a method of a class inside of a method in other classes that called method is in a class that declared after the classes that use inside.
Let me show you an example:
Database.php:
class Database{
modifyUser($field,$change){
global $logging;
if($database->query('MYSQL QUERY')){
$logging->modifyUser($field,$change);
}
}
}
$database = new Database;
Logging.php:
class Logging{
modifyUser($field,$change){
global $database;
$database->query('Mysql Query for Logging');
}
}
$logging = new Logging;
now problem is if use top classes in included file like this:
user.php
include('database.php');
include('logging.php');
php shows an error that you use $logging variable which is not declared as class yet.
and if I change like this:
user.php
include('logging.php');
include('database.php');
same error but for $database; I don't know how to use it that PHP doesn't conflict for sequences.
I don't think it is possible, if you run the following code with command line you'll get "Segmentation fault" error;
class A
{
private $b;
public function __construct()
{
$b = new B();
}
}
class B
{
private $a;
public function __construct()
{
$a = new A();
}
}
$x = new A();
it is like an infinite loop.
First of all you can use include_once / require_once, so only the first time the file is needed, it will be loaded
Also, you can use autoloading
And instead of using global variables, either pass the instance or provide some sort of factory. Relying on global variables is bad for your encapsulation and it's ugly in an OO code
Related
I have a class like the following:
class game {
public $db;
public $check;
public $lang;
public function __construct() {
$this->check = new check();
$this->lang = DEFAULT_LANG;
if (isset($_GET['lang']) && !$this->check->isEmpty($_GET['lang']))
$this->lang = $_GET['lang'];
}
}
As you can see I have a public variable $lang that is also defined via the contructor.
The proble is that I want to access the result of this variable from other classes that are not directly related to this class, since I don't want to redeclare it for each different class.
So for example how can I call the result of that variable from another class, lets call it class Check ?
if you mark the public $lang; as static:
public static $lang;
you can access it via game::$lang;
if not static, you need to make an instance of game and directly access it:
$game = new game;
$game->lang;
static call inside of (current) class:
self::$lang;
late static bound call (to inherited static variable):
static::$lang;
call from child class to parent:
parent::$lang;
normal call inside of an instance (instance is when you use new Obj();):
$this->lang;
BTW:
variables defined by define('DEFAULT_LANG', 'en_EN'); are GLOBAL scope, mean, can access everywhere!
<?php
define('TEST', 'xxx');
class game {
public function __construct() {
echo TEST;
}
}
//prints 'xxx'
new game;
you can make it static variable, so you will be able to call it anytime anywhere, the diff is that instead of
$this->lang;
when editing it(Works inside class game only) you do :
self::$lang;
and when you call/edit it (Works everywhere) from anther class you do :
game::$lang
the idea of static class is that its exist only in one instance, so only one $lang exist in your program. but there is no need to load the whole class to get acsess to it.
How can I call the result of that variable from another class, lets call it class Check?
A variable doesn't have a result. If you mean to retrieve the state of that variable on a specific object $obj of class game then you can simply do:
$obj->lang
On a side note if $lang is publicly only read only you should protect it by defining it private or protected and create a getter method instead.
If you mean that you want to use the same variable name in another class I'd suggest you to consider inheritance:
class Check extends game { /* now Check has $lang */ }
but the variable of the two objects will be different.
Since the property is public, you can access it from outside the class as $objInstance->property. It doesn't matter if you're calling it from a function, procedural script, in another object. As long as you have the instance, you can call it's public property. Ex:
function foo($c) {
echo $c->lang;
}
foo($check);
Also, some advice on working with objects and such: It's considered better code if you don't create instances of objects in the other objects, but rather pass them in someway (either a setter method or through the constructor). This keeps the classes loosely coupled and results in code that is more reusable and easier to test. So:
class Game
{
...
public function __construct($check, $defaultLang, $get) {
$this->check = $check;
$this->lang = $defaultLang;
if (isset($get['lang']) && !$this->check->isEmpty($get['lang']))
$this->lang = $get['lang'];
}
...
$game = new Game(new Check(), DEFAULT_LANG, $_GET);
echo $game->check;
The first half of this article is an accessible explanation of what is known as Dependency Injection.
Been searching all around but still cannot find a solution for this problem.
My problem is that i got these snips of code(Examples):
Core file
class Core {
public $DB = null;
public $Handler = null;
function run() {
$this->DB = "somedatabase";
include_once('handler.php');
$this->Handler = new Handler;
$this->Handler->run();
}
}
This is the helper.php example
class Handler extends Core {
function run() {
echo "<pre>"; print_r($this); echo "</pre>"; die();
}
}
Even tho i defined the DB variable before i include the helper then it is still empty inside the helper class. It's defined yes but it's empty. Which means it properly doesn't share the same memory as the Core class.
Keep in mind that the Core class it self is instanced too.
-
Thanks for all suggestions
Edit
PhpMyCoder got it right. Thank you for the detailed and well written reply.
For over 2 years i been seeing PHP scopes as being the same or sorta the same as JavaScript's scope. Now i realize that if i extend my "Core" class i get all the methods and properties within it. But the values is private to my class and my class alone.
This is great. Finally i got it.
From what I gather here you are talking about public instance variables. They are performing as OOP would require. Each time you instantiate a class with
$core = new Core(); // or
$handler = new Handler();
Each of them gets a fresh space in memory to store their instance variables. Instance variables are unique to each instance of a class, as the name would suggest. So, two separate instances of Core and Handler do not share instance variables. However since Handler extends Core, two instances of Core are created. One instance is the one that I created on the first line. The other is created so that Handler can extend it on the second line. These two instances of Core are not the same object. To have the same values for Core across all core objects you will need to use static (class) variables.
class Core {
public static $hello = 'World';
}
var_dump(Core::$hello); //string('Word')
In my example, $hello will always be available to everyone by accessing it with the scope resolution operator, ::. So Handler could access it with either Core::$hello or parent::$hello. If you wanted to only expose this static variable to Core and its subclasses, then you would need to make it protected and access it from within Core with self::$hello and from its subclasses with parent::$hello.
class Core {
protected static $hello = 'World';
public function sayHello() {
echo 'Hello '.self::$hello; //from within Core, access with `self`
}
}
class Handler extends Core {
public function myParentSays() {
echo 'My parent says: Hello '.parent::$hello;
}
}
$core = new Core();
$core->sayHello(); // 'Hello World'
$handler = new Handler();
$handler->myParentSays(); // 'My parent says: Hello World'
Check the PHP docs for more on the static keyword and the scope resolution operator.
EDIT
I believe your confusion lies in a misunderstanding of how inheritance works in OOP so let me give you a little real-world-ish example. Let's say you create a class for employees called Employee. This class has a public instance variable (that is, one that can be accessed with ->) for the name of the person. In PHP this would be:
class Employee {
public $name;
public __construct($name) {
$this->name = $name;
}
}
Now let's create a new employee:
$tim = new Employee('Tim');
Let's say that we need a new class, Intern, that should subclass Employee. That should be easy enough:
class Intern extends Employee {
public function makeCoffee(Employee $receiver) {}
}
If we create a new intern now, should his name be Time just because we have already created another employee named Tim? No. That doesn't make sense.
$intern = new Intern();
var_dump($intern->name); //string(0) ""
Now say that setting the name was some complicated and arduous process and we'd rather not have to code it again. With a little modification to our Intern class we can leave the name setting to its superclass, Employee.
class Intern {
public function __construct($name) {
parent::__construct($name);
}
public function makeCoffee(Employee $receiver) {}
}
Now we can create a new intern and set his or her name. Notice how the other Employee keeps his name.
$intern = new Intern('Something Forgettable');
var_dump($intern->name); // string(21) "Something Forgettable"
var_dump($employee->name); // string(3) "Tim"
Now why is this? In OOP, a subclass/superclass is an "is a" relationship. The Intern "is an" Employee. The Intern has all the same properties and methods as an Employee but because each Intern and Employee are distinct they have their own values for these properties.
With this in mind, I suggest you rethink your strategy for your classes. Does it really make sense that Handler is a Core? Does it make sense that MainController is a Handler?
Classes don't share memory unless you pass a reference to them. When you make an instance of a class (an object), it is unique. You could have:
$a = new Core();
$b = new Core();
$a->var1 = 'foo';
$b->var1 = 'bar';
echo $a->var1; // 'foo'
echo $b->var1; // 'bar'
The same holds for extending a class. It doesn't explicitly share the values of the fields, it just shares their existence/visibility.
To share the value, you would do something more like this:
$a = new Core();
$b = new Core();
$c = 'foo';
$a->var1 = &$c;
$b->var1 = &$c;
echo $a->var1; // 'foo'
$b->var1 = 'bar';
echo $a->var1; // 'bar'
$c = 'baz';
echo $a->var1; // 'baz'
Variables are only set on objects (class instances). Don't confuse classes with objects.
If you want to have variables bound to classes, use the static keyword:
class Core {
public static $static = 'abc';
public $instance = 'xyz';
}
Core::$static = 'x';
$core = new Core();
$core->instance = 'a';
In PHP, classes are extended, not objects. This is class:
class SomeClass{
// ...
}
And this is object:
$object = new SomeClass();
So, when your are extending some class, all its protected/public properties are become available to child class.
So I have this class:
class A{
public function do_a(){ return 'a_done';};
public function do_b(){ return 'b_done';};
}
So I require the php file and create an instance of the class:
require_once("A_class.php");
$System = new A();
require_once("user_calls.php"); //here I import the user file with the function calls.
user_calls.php contents:
echo 'this was the result of '.$System->do_a();
echo 'this was the result of '.$System->do_b();
So, that does work, but I don't want the user to have to use $System->do_a();, but only do_a();.
Any solutions?
EDIT: I also want to limit the functions the user could call in the user_calls.php file, to basic native php functions and those in class A.
DISCLAIMER: While this code works, and does what you requested, that doesn't mean that I advocate coding like this. It's very hard to follow for other developers (and maybe even you in the future...), and it also makes use of eval(), which is almost always A Bad Thing(tm). That said, here you go:
<?php
class A {
public function do_a() {
return __METHOD__;
}
public function do_b() {
return __METHOD__;
}
}
$aRef = new ReflectionClass('A');
$aPublicMethods = $aRef->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($aPublicMethods as $method) {
$php = <<<PHP
function {$method->name}() {
global \$System;
return \$System->{$method->name}();
}
PHP;
eval($php);
}
$System = new A();
echo 'this was the result of ' . do_a();
echo 'this was the result of ' . do_b();
Please also note that if your methods use arguments, things get even more hairy. Also, if you name any of your methods the same as a function in the global namespace (ex. substr()), this will attempt to redefine them, and you'll probably get a Fatal Error.
Methods of a class are either instance methods (they act on a particular instance of a class defined by $this) or they are class methods (They aren't tied to any one particular instance of a class, but provide services that fall within the remit of the class.
An instance method is defined as follows:
public function foo()
{
}
whereas a class method is defined with the STATIC keyword.
static public function bar()
{
}
In the instance method you can use $this to get access to the state of the instance on which the method was called. This is not available in the class method because it's not tied to any one instance. It can access other members of the class (provided they're not tied to an instance) with the self keyword though.
Instance methods are called as follows:
$a = new ObjType ()
$output = $a -> foo ();
Class methods are called as follows:
$output = ObjType::bar ();
No matter which approach you use you either have to provide an instance (for instance methods) or a class (for class methods) to call the method. Calling just foo() or bar() will not work.
You'll have to use a closure. Note that it's calling directly from the class definition, not the object:
class test {
function method() {
echo 'method was called';
}
}
$method = function(){call_user_func('test::method');};
$method();
$method();
$method();
//output:
//method was calledmethod was calledmethod was called
To call the method from the object, rather than the class, you'll have to pass the object into the closure:
class test {
var $count = 0;
function method() {
$this->count++;
echo $this->count . "|<br />";
}
}
$obj = new test;
$obj2 = new test;
$method = function($object){call_user_func(array($object, 'method'));};
$method($obj);
$method($obj);
$method($obj);
$method($obj2);
//output:
//1|
//2|
//3|
//1|
But that's not any prettier or simpler, is it?
If you don't want to clutter up your page, just name the object something short:
$pco = new page_controller_object_with_a_long_name_that_is_annoying;
$pco->do_a();
$pco->do_b();
//etc.
Moving it outside the class as suggested by #LucM sounds the easiest way.
I'm attempting to define a __invokeable global instance of a class that contains my application's functions.
Basically I'm trying to create a namespace for my library, and therefore I'm attempting to use a class to hold all my functions/methods.
I don't want to have to include global $class_instance at the top of all my files, because that is ugly.
Also I don't to have to reference the variable like $GLOBALS['myvar'] everywhere.
Personally I find this a real oversight in php.
It appears I can't define super globals like $myFunctionsGlobal
And I can't define variables (well actually constants) in php like myvar=$classInstance.
Namespaces
If namespaces are supposed to solve this issue, why aren't they more widely used?
For example Kohana doesn't use namespaces, along with many other php libraries.
One I'm after:
class _namespace{
public $_function;
function __invoke($arg){
// Function body
echo $arg;
}
function method(){
;
}
}
$N = new _namespace;
$N('someValue');
$N->method();
function myFunc(){
// I don't want global $N;
// I don't want $N = $_GLOBALS['N'];
// I don't want $N = get_instance();
$N('some other value');
}
Solution:
In most other languages like c and js you can only have one object/function per variable name. PHP seems to special allowing you to have namespaces,functions and classes with the same name. I was trying to group all of my functions under one central variable for simplicity and still have the functionality of it being __invokable. In fact a class and a function named the same thing would have provided this functionality.
<?
class R{
static function static_method(){
;
}
function method(){
;
}
}
function R(){;}
R();
R::static_method();
$instance = new R();
$instance->method();
In php5.3 you can emulate a invokable constant with methods by defining a function with the same name as your namespace.
namespace.php
<? namespace Z;
function init($arg=''){
echo $arg;
}
function method(){
echo 'method';
}
function method(){
echo 'method2';
}
othefile.php
include('namespace.php');
function Z($a=null,$b=null){
return Z\init($a,$b);
}
Z('test');
Z\method();
Z\method2();
Here's my new answer for you it works
class _bidon {
static function __invoke($arg){
// Function body
echo $arg;
}
}
$b = new _bidon;
$b('eee');
function myFunc(){
// I don't want global $N;
// I don't want $N = $_GLOBALS['N'];
// I don't want $N = get_instance();
_bidon::__invoke('some other value');
}
myFunc();
but the function will be specific to the class not the object
------ Previous post :
Hi i did not clearly understand but if you have a class created just do :
public static $myFunctionsGlobal;
and whene you want to use it outer than your class you do :
myclassname::$myFunctionsGlobal
and it will be accessible as soon as you include your class
you don't need to create an object because it's a static var you just need to have the class included
You can use a service container.
An example you can find here: Which pattern should I use for my unique instance of the User class? and to deepen If Singletons are bad then why is a Service Container good?
Also namespaces can't help you if you need to have one single instance for your helper objects like you are asking.
Addendum
With the service container I suggest you can still use __invoke.
$obj = app('CallableClass');
$obj(5);
i have 2 classes
for DB
for language
i want to use my language things in the DB
so it outputs the result
ex :
class db_control{
var $db_connection, $lang_var;
//create the function for the connection
function db_connect(){
//define some variables
global $db_host, $db_username, $db_password, $db_name, $lang_var;
$this->db_connection = mysql_connect("$db_host","$db_username","$db_password")or die("can't connect to server with these informations");
//checl that the connection is established
if($this->db_connection){
echo $lang_vars->getvar("$langvals[lang_con_est]");
}
but this
$lang_vars->getvar("$langvals[lang_con_est]");
doesn't work
i mean it outputs many problems
and am sure my problem is that i didn't define my variables and classes correctly
P.S : the language class is in file called language.php and this part is in DB.MySQL.php
EDIT :
this is the language class
class lang_vars{
public static function getvar($variable){
return $variable;
}
}
i want the DB class to display text from the language class
thats why i used
echo $lang_vars->getvar("$langvals[lang_con_est]");
but it doesn't work
cuz when i declare the language class
$lang_vars = new lang_vars;
inside the db_control it shows error unexpected T_something expected T_Function
and when i declare it outside nothing up
hope i made things more clear now
Any reason why you are still using PHP4 syntax?
When creating an instance of the db_control class, pass the object to be stored as $lan_var into the constructor or set it via a dedicated setter. See Dependency Injection.
class DBControl
{
protected $_lang;
public function __construct($lang = NULL)
{
if($lang !== NULL) {
$this->_lang = $_lang;
}
}
public function setLang($lang)
{
$this->_lang = $lang;
}
}
Then do either
$dbControl = new DBControl(new LangThing);
or
$dbControl = new DBControl;
$dbControl->setLang(new LangThing);
Also, get rid of the globals. Pass those in via Dependency Injection too.
Make your language class methods static . Read more here.
class LangClass
{
public static function getvar()
{
// your code here
}
}
Then, you can use its functions without creating objects like this:
$LangClass::getvar("$langvals[lang_con_est]");
This can do the trick.
$lang_vars = new LanguageClassOrWhateverItIsCalled();
$lang_vars->getvar($langvals[lang_con_est]);
But maybe you should think of making it a static method. In that case you can call it with:
LanguageClassOrWhateverItIsCalled::getVar($langvals[lang_con_est]);
You can define the method static like:
public static function getVar() {
// Do something
}
Edit: #SAFAD
You should use the static method for this. To make this work, be sure your class language.php is loaded. To do so just add in the DB.MYSQL.php file the following line:
require_once('language.php');
class db_control {
...
Make sure you have the right path to the language.php file.
Then you should call the method in db_control class like this:
if($this->db_connection){
echo lang_vars::getvar("$langvals[lang_con_est]");
}
Besides, what is the use of a function like this? You should either do:
if($this->db_connection){
echo $langvals[lang_con_est];
}
or change your static getvar method to:
public static function getvar($variable){
return $langvals[$variable];
}
and your function call to:
if($this->db_connection){
echo lang_vars::getvar("lang_con_est");
}