Interacting with multiple PHP classes - php

I am learning on PHP classes. I can write a basic PHP classes but having trouble when accessing variables and functions from other classes.
My first class
Class First_class
{
public $options;
function __construct()
{
$this->options = get_option('theme_options'); //wordpress fn
}
function my_function() {
add_menu_page(...)
}
}
Class Second_class
{
public $first_class_object;
function __construct()
{
$this->first_class_object = new First_class();
//Trying to access $this->options here
}
}
new Second_class();
Class Third_class
{
public $first_class_object;
function __construct()
{
$this->first_class_object = new First_class();
//Trying to access $this->options here
}
}
new Third_class();
I am trying to access public variables from Class First_class using $first_class_object = new First_class(); in the second class and third classes. You see when I initiate new First Class in other classes add_menu_page() triggers two times. I am not sure how to access the variables and functions properly. May be constructors?
Sorry may be I am something wrong here?
I am looking for an experts suggestion.

Extend your classes.
An example is below using your code as an example. 3v4l demo is here and php extends docs are here.
<?php
class FirstClass
{
public $options;
public function __construct()
{
$this->options = ['yay']; //get_option('theme_options'); //wordpress fn
}
public function myFunction()
{
//
}
}
class SecondClass extends FirstClass
{
}
class ThirdClass extends FirstClass
{
}
$secondClass = new SecondClass();
var_dump($secondClass->options);
$thirdClass = new ThirdClass();
var_dump($thirdClass->options);

if you try accessing other class Properties, you could use className::propertyName
OR
if you wanna access properties within the class you can use self:: or $this.
know more about accessing properties and traverses under classes.
http://php.net/manual/en/language.oop5.paamayim-nekudotayim.php

try extend class
class Third_class extends First_class
{
public $first_class_object;
function __construct()
{
$this->first_class_object = new First_class();
//Trying to access $this->options here
}
}
or use this construction for access to you class
$this->first_class_object->option

Related

How to use one function variable to another function in abstract class

abstract class Dropboxapi {
protected $webAuth;
protected function abi() {
require __DIR__.'/app/Dropbox/autoload.php';
self::start();
self::dropbox_auth();
}
public function start() {
$webAuth = new Dropbox\WebAuth($appInfo,$appName,'path',$csrfTokenStore);
}
public function dropbox_auth() {
$authUrl = $webAuth->start();
}
}
Dropboxapi::abi();
Here i have $webAuth object in start function. When I use this in dropbox_auth it shows Undefined variable: webAuth.
When i use $this->webAuth i'm getting Using $this when not in object context
i tried like self::webAuth also. This is showing Access to undeclared static property:. So I don't understand how to use that.
if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private.
Many example are there for abstract class.Just check how you can or not.As you asked without abstract just define the class and function like below.Here all the variable and methods are $this context.
class Dropboxapi {
public $this->webAuth='';
public function abi() {
require __DIR__.'/app/Dropbox/autoload.php';
$this->webAuth = new
Dropbox\WebAuth($appInfo,$appName,'path',$csrfTokenStore);
}
public function dropbox_auth() {
$authUrl = $this->webAuth->start();
}
}
$dropbox = new Dropboxapi();
$dropbox->dropbox_auth();
You are defining things wrong. Abstract class, similar with interface, are tend to be used as "blueprint" class. It means they need to be extended by another classes to be used, and cannot be used by itself as is. Using $this in abstract class is fine, as in documentation of abstract by php.net: http://php.net/manual/en/language.oop5.abstract.php.
What you need to do, is to have another class that inherit / extends that DropBoxApi class of yours, ex:
class DropBoxApi2 extends DropBoxApi
{
}
As class DropBoxApi2 is inherited, then it already has functions and property of it's parent (DropBoxApi). And you can use it like (example):
$api = new DropBoxApi2();
$api->start();
Additionally, the double colon that you use is static operator. Which is far far different concept than abstract.
Sample Code. Replace with your requirement.
you have to make everything as static
abstract class Dropboxapi {
protected static $webAuth;
public static function abi() {
self::start();
self::dropbox_auth();
}
public static function start() {
self::$webAuth = new Stdclass();
}
public static function dropbox_auth() {
var_dump(self::$webAuth);
}
}
Dropboxapi::abi();

Initiating a class globally

To be specific, i have a two class Request and Utils,
class Request
{
public function __construct()
{
//constructor method
}
public function request()
{
$utils=new Utils;
$consolidated_errors=$utils->array_remove_empty($all_params_error);
}
public function process()
{
$utils=new Utils;
$consolidated_errors=$utils->another_method($all_params_error);
}
}
And class Utils,
class Utils
{
public function __construct()
{
//constructor method
}
public function array_remove_empty()
{
//returns a variable.
}
public function another_method()
{
//returns a variable.
}
}
you can see that i am initializing the class two times in request class , and my question is that any way initializing the class globally and using through out the class?
You are looking for Singleton pattern
Following demonstrate very basic Singleton example for your class
public class Utils {
private static Utils uniqInstance;
private Utils() {
}
public static synchronized Utils getInstance() {
if (uniqInstance == null) {
uniqInstance = new Utils();
}
return uniqInstance;
}
// other useful methods here
}
get the instance using static-factory pattern
The above code does not look like Java to me, but anyway,
You could create the class at a class level private Utils myUtuils = new Utils ();
or
have the class as a static class and then just use it directly in your method
public function process()
{
consolidated_errors= Utils.another_method($all_params_error);
}
}

Difficulty referring to class function

I need to call a function someFunction() how do I refer to it when it is in the following class structures?
abstract class A
{
protected $session;
protected $model;
public function __construct()
{
$session = new classSession;
$model = new classModel;
}
}
class classModel
{
$this->session->someFunction();
}
I've tried using $this->session->someFunction() but it does not work!
Firstly, you need to put it within the context of a function - code cannot exist on its own within a class body. Secondly, for anything in classModel to access $session, classModel has to extend class A. You end up with something like this:
class classModel extends A
{
public function foo()
{
$this->session->someFunction();
}
}
So for $this->session->someFunction(); to execute, you'd do this:
$model = new classModel();
$model->foo();

Changing the Privacy Scope of PHP Class Functions

I have an abstract class that extends classes to provide a basic orm function. All the functions it provides are protected to the class so it can decide what fields are made publicly available to outside objects. But recently, I have started working with some smaller data classes that do not require such complexity, and would benefit from having the orm editing functions publicly available and no special functions.
As the naming convention for the functions is sufficient and compact, is there a way to change the existing functions to public (without needing the same class, or an interim extends), or would I have to use the new traits feature of php to add an existing class, which contains public versions of the functions that act as an abstraction layer for the internal protected functions?
EDIT:
For the traits method, I was thinking that it would help like this:
abstract class ORMClass {
public function __construct($pk) {}
protected function __get($k) {}
protected function __set($k,$v) {}
protected function save() {}
}
trait publicORM {
public function __get($k) { return parent::__get($k); }
public function __set($k,$v) { return parent::__set($k,$v); }
public function save() { return parent::save(); }
}
class myOrm extends ORMClass {
use publicORM;
protected static $table = 'myTable';
}
so then I could use myOrm like:
$myOrm = new myOrm(1);
$myOrm->foo = 'alice'
echo $myOrm->bar;
$myOrm->save();
without needing the:
public function __get($k) { return parent::__get($k); }
public function __set($k,$v) { return parent::__set($k,$v); }
public function save() { return parent::save(); }
to be listed in the class myOrm
Since this was never answered properly, I'm adding Charles answer.
This can be done using PHP's Reflection library, built in to PHP since version 5. This particular method is fairly hacky:
<?php
abstract class BaseClass {
protected function testMe() {
echo 'I WORK!';
}
}
class ConcreteClass extends BaseClass {
// Class Code
}
$method = new ReflectionMethod('BaseClass', 'testMe');
$method->setAccessible(true);
$method->invoke(new ConcreteClass()); // Prints 'I WORK!'
And here is the better method using an interim abstract class that extends the base class but uses public methods:
<?php
abstract class BaseClass {
protected function testMe() {
echo 'I WORK!';
}
}
abstract class PublicBaseClass extends BaseClass {
public function testMe() {
parent::testMe();
}
}
class ConcreteClass extends PublicBaseClass {
// Class Code
}
$obj = new ConcreteClass();
$obj->testMe();

PHP Object Extension $this->some_object->method

I am trying to make a script in which different classes (e.g. Database, Utilities, Config) are all used to form one central Main class. I have tried extending a chain of them:
Main -> Utilities -> Database -> Configuration
But how can I set the different parts so that they can be called like this:
<?php
$this->db->select("WAFFLES");
echo($this->config->app_path);
?>
You could create a global class that does you basic initializing
class Base {
$var1, var2;
public function __construct() {
$this->var1 = new DB();
$this->var2 = new Config();
....
}
}
Then your classes can extend the base class and have access to the data
class Foo extends Base {
public function bar() {
$this->var1->someOpertaion();
}
}
You need to declare each new object as variable in your Main Class like:
class Main{
private $db = NULL;
private $config = NULL;
$this->db = new Database;
$this->config = new Config;
}
etc.
While i'm not a professional coder i'll considering a better approach than this. This kind of object-handling can cause a bloated main class and in the worst case you may face some performance issues.
1) use __autoload or spl_autoload_register to load classes
2) use magic methods, to call function when getting unknown property. Following examples demonstrates how to use __get and dynamicaly initialize object only when you use them.
//use __autoload to load db and config class when they are called.
class db{
function lol(){
echo 'Hello from db->lol() <br />';
}
}
class config{
function lol(){
echo 'Hello from config->lol() <br />';
}
}
//Manager class to use with classes where you want to access other object trough $this
class Manager{
private $_instances=array();
function __get($name){
//if instance does not exists, create one
if (!isset($this->_instances[$name])){
$this->_instances[$name]=new $name();
}
//return instance
return $this->_instances[$name];
}
}
class Some extends Manager{
function f1(){
$this->db->lol();
$this->config->lol();
}
}
$some=new Some();
$some->f1(); //echoes 'Hello from db->lol()' and 'Hello from config->lol()'
But for accessing global class instances I prefer using following method:
Use singleton pattern to access global class trough GloballClass::i() and if global class is not defined use autoload to load that class.
class db extends mysqli{
private static $_i;
//Access to singleton instance
public static function i() {
return (self::$_i instanceof self)?self::$_i:self::$_i = new self();
}
//class functions
function q($q){
echo 'Hello from db->q()';
}
}
class config{
private static $_i;
//Access to singleton instance
public static function i() {
return (self::$_i instanceof self)?self::$_i:self::$_i = new self();
}
//class functions
function somefunction(){
echo 'Hello from config->somefunction()';
}
}
db::i()->q('SELECT * FROM users');
config::i()->somefunction();
Following is solution inspired by Gordons comment:
It uses GlobalClassFactory class to define only one instance of global classes.
class db{
function lol(){
echo 'Hello from db->lol() <br />';
}
}
class config{
function lol(){
echo 'Hello from config->lol() <br />';
}
}
class GlobalClassFactory{
private static $_classes=array();
public static function getInstance($name){
if (!isset(self::$_classes[$name])){
self::$_classes[$name]=new $name();
}
return self::$_classes[$name];
}
}
class Base{
function __get($name){
return GlobalClassFactory::getInstance($name);
}
}
class Some extends Base{
function f1(){
$this->db->lol();
$this->config->lol();
}
}
$some=new Some();
$some->f1();
Here is the sample prototype:
include 'db.php'; // include db class
include 'config.php'; // include config class
class main{
public $db = NULL;
public $config = NULL;
function __construct() {
$this->db = new db;
$this->config = new config;
}
}
Creating a composite object with instances of everything that might be needed during code execution up front is a complete waste of resources. You want to create instances only when needed. One way to achieve this would be to add a magic __get method to the class:
public function __get($name) {
// if self::$instances (or main) contains instance of $name, return instance
// else if class_exists $name, create, store and return instance
// else throw exception
}
But even then, chances are you are creating a God Object and magic methods are somewhat slower than regular accessors. If you need to create instances this way, have a look at the Symfony Dependency Injection Container or implement a Registry.

Categories