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();
Related
I have initialized a new instance of a library in the __construct(){} method of a PHP class and equated it to a variable,
but now I want to use this variable to access methods of the library inside another function but PHP is not allowing me do that.
class Demo
{
public function __construct()
{
parent::__construct(new PaymentModel);
$this->api = new Api(config("razorpay", "key_id"), config("razorpay", "key_secret"));
}
public function createOrder()
{
$order = $api->order->create();
echo '<pre>';
var_dump($order); die;
}
}
I looked at the __construct documentation and some other answers here on stack overflow but all they did was confuse me more than helping me out.
Please help me figure this out as I am a starter myself in tech.
To be able to use $this->api in your class, you will need to set it as an attribute.
so :
class Demo
{
private $api;
public function __construct()
{
parent::__construct(new PaymentModel);
$this->api = new Api(config("razorpay", "key_id"), config("razorpay", "key_secret"));
}
public function createOrder()
{
$order = $this->api->order->create();
echo '<pre>';
var_dump($order); die;
}
}
Also, as notified by other, you are to construct a parent class while your class 'Demo' does not extend any other class.
You have defined api as a class variable (property). Use $this->api to acces this class variable (property) in other methods of your class.
// This class probably inherits some base class
class Demo extends BaseDemo
{
public function __construct()
{
parent::__construct(new PaymentModel);
$this->api = new Api(config("razorpay", "key_id"), config("razorpay", "key_secret"));
}
public function createOrder()
{
$order = $this->api->order->create();
echo '<pre>';
var_dump($order); die;
}
}
Also check your class definition - if parent::__construct() is called, then your class probably inherits some base class. If this is not the case, remove parent::__construct() call.
To access object variables you need to use $this. In your case change the first line in createOrder() to $order = $this->api->order->create();
Also you appear to be trying to run the classes parents constructor in your constructor. But the class doesn't have a parent.
you are calling parent::__construct(new PaymentModel); on a class which doeasn't extend any base class.
declare variable $api in a class then only accessible to other function body
Here is my example:
trait FileConfig {
public static function getPathForUploads() {
$paths = static::getPaths();
//etc.
}
abstract public static function getPaths(); //doesn't work. Error: "Static function SharedDefaultConfig::getPaths() should not be abstract"
abstract public function getPaths(); //OK
public static function getPaths() {} //OK
}
Class:
class AppConfig {
use FileConfig;
public static function getPaths() {
return array(...);
}
}
Call:
AppConfig::getPathForUploads();
It's nessessary to make it static and abstract (to force classes using FileConfig to implement getPaths).
I wonder how is it possible to implement method changing it's static property? Is it a good practice or there are better solutions? Will it one day become illegal?
Thank you
This is fixed in php 7, so the following code works:
<?php
error_reporting(-1);
trait FileConfig {
public static function getPathForUploads() {
echo static::getPaths();
}
abstract static function getPaths();
}
class AppConfig {
use FileConfig;
protected static function getPaths() {
return "hello world";
}
}
AppConfig::getPathForUploads();
http://sandbox.onlinephpfunctions.com/code/610f3140b056f3c3e8defb84e6b57ae61fbafbc9
But it does not actually check if the method in AppConfig is static or not during compilation. You will only get a warning when you try to call the non-static method statically: http://sandbox.onlinephpfunctions.com/code/1252f81af34f71e901994af2531104d70024a685
You do not need to make the method static to force classes using it to implement the method. You can simply use interfaces alongside.
trait FileUploadConfig {
public static function getPathForUploads() {
$paths = static::getPaths();
//etc.
}
}
The trait was left as is. I just took away the functions for the interface.
interface PathConfiguration {
public static function getPaths();
}
The interface forces the class to implement the function. I left the static in there to correspond with the trait's specification.
class AppConfig implements PathConfiguration {
use FileUploadConfig;
public static function getPaths() {
return [];
}
}
To force classes using FileConfig to implement getPaths it's not nessessary to make abstract function static. Static means that it belongs to the class that declared it. Make it protected static, add code from trait and then you could change behaviour by inheritance from your AppConfig class.
I have a protected function that is defined within a certain class. I want to be able to call this protected function outside of the class within another function. Is this possible and if so how may I achieve it
class cExample{
protected function funExample(){
//functional code goes here
return $someVar
}//end of function
}//end of class
function outsideFunction(){
//Calls funExample();
}
Technically, it is possible to invoke private and protected methods using the reflection API. However, 99% of the time doing so is a really bad idea. If you can modify the class, then the correct solution is probably to just make the method public. After all, if you need to access it outside the class, that defeats the point of marking it protected.
Here's a quick reflection example, in case this is one of the very few situations where it's really necessary:
<?php
class foo {
protected function bar($param){
echo $param;
}
}
$r = new ReflectionMethod('foo', 'bar');
$r->setAccessible(true);
$r->invoke(new foo(), "Hello World");
That's the point of OOP - encapsulation:
Private
Only can be used inside the class. Not inherited by child classes.
Protected
Only can be used inside the class and child classes. Inherited by child classes.
Public
Can be used anywhere. Inherited by child classes.
If you still want to trigger that function outside, you can declare a public method that triggers your protected method:
protected function b(){
}
public function a(){
$this->b() ;
//etc
}
If the parent's method is protected, you can use an anonymous class:
class Foo {
protected function do_foo() {
return 'Foo!';
}
}
$bar = new class extends Foo {
public function do_foo() {
return parent::do_foo();
}
}
$bar->do_foo(); // "Foo!"
https://www.php.net/manual/en/language.oop5.anonymous.php
You can override this class with another where you make this public.
class cExample2 extends cExample {
public function funExample(){
return parent::funExample()
}
}
(note this won't work with private members)
But the idea of private and protected members is to NOT BE called from outside.
Another option (PHP 7.4)
<?php
class cExample {
protected function funExample(){
return 'it works!';
}
}
$example = new cExample();
$result = Closure::bind(
fn ($class) => $class->funExample(), null, get_class($example)
)($example);
echo $result; // it works!
If you want to share code between your classes you can use traits, but it depends how you want use your function/method.
Anyway
trait cTrait{
public function myFunction() {
$this->funExample();
}
}
class cExample{
use cTrait;
protected function funExample() {
//functional code goes here
return $someVar
}//end of function
}//end of class
$object = new cExample();
$object->myFunction();
This will work, but keep in mind that you don't know what your class is made of this way. If you change the trait then all of your classes which use it will be altered as well. It's also good practice to write an interface for every trait you use.
here i can give you one example like below
<?php
class dog {
public $Name;
private function getName() {
return $this->Name;
}
}
class poodle extends dog {
public function bark() {
print "'Woof', says " . $this->getName();
}
}
$poppy = new poodle;
$poppy->Name = "Poppy";
$poppy->bark();
?>
or one another way to use with latest php
In PHP you can do this using Reflections. To invoke protected or private methods use the setAccessible() method http://php.net/reflectionmethod.setaccessible (just set it to TRUE)
I am using Laravel. i was facing issue while access protected method outside of class.
$bookingPriceDetails = new class extends BookingController {
public function quotesPrice( $req , $selectedFranchise) {
return parent::quotesPrice($req , $selectedFranchise);
}
};
return $bookingPriceDetails->quotesPrice($request , selectedFranchisees());
here BookingController is Class name from which i want to get protected method. quotesPrice( $req , $selectedFranchise) is method that i want to access in different Class.
If I have an abstract class like this:
abstract class MyApp
{
public function init()
{
$this->stuff = $this->getStuff();
}
public function getStuff()
{
return new BlueStuff();
}
}
And then I have a class that extends from this abstract class like this:
class MyExtendedClass extends MyApp
{
public function init()
{
parent::init();
}
public function getStuff()
{
return new RedStuff();
}
}
If I do:
$myobj = new MyExtendedClass();
$myobj->init();
Why does the method getStuff from the child class get called? Isn't $this in the context of the abstract class? If so, shouldn't the method of the abstract class get called?
Thanks!
New answer
In PHP you can use subclasses as if all methods in the parent class that don't exist in the subclass have been copied to the subclass. So your example would be the same as:
class MyExtendedClass extends MyApp {
public function init() {
$this->stuff = $this->getStuff();
}
public function getStuff() {
return new RedStuff();
}
}
Just think of the subclass as having all code of the parent class and you're normally all right. There is one exception to this rule: properties. A private property of a class can only be accessed by that class, subclasses can't access the private properties of parent classes. In order to do that you need to change the private property into a protected property.
Original answer
Abstract classes in PHP are just like regular classes with one big difference: they can't get initiated. This means you can't do new AbstractClass();.
Since they work exactly like regular classes for everything else, this also is the case for extending classes. This means that PHP first tries to find the method in the initiated class, and only looks in the abstract classes if it doesn't exist.
So in your example this would mean that the getStuff() method from MyExtendedClass is called. Furthermore, this means you can leave out the init() method in MyExtendedClass.
I am new to OOP (PHP) and just met the design pattern - singleton.
I have found a DB class which uses mysqli (singleton class). I have added some custom methods to it (insert_id(), query(), fetch_result(), etc).
Then I created a new class called UserTools and I want to extend the database class to use the methods I've created previously (query(), fetch_result(), etc).
But I get this error:
Fatal error: Call to private Database::__construct() from invalid context in (...)
when I try to create instance of the new class (User Tools).
What should I do? Is it a right structure?
There are several way to achieve what you want.
One would be :
class UserTools {
private $db;
function __construct() {
$this->db = Database::db_connect();
}
function login() { /* ... */}
}
Although it would be better to directly pass the database instance to the constructor like this :
class UserTools {
private $db;
function __construct($db) {
$this->db = $db;
}
function login() { /* ... */}
}
// Usage
$userTools = new UserTools(Database::db_connect());
If you're really lazy you could just modify your database class and make the constructor public :
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
But I really discourage you to use the latter one. It's really bad code and it doesn't make sense in a logical point of view. Your UserTools class use a database instance. It is not a database.
It is my understanding that only protected and public methods and variables are inherited through extension, not private ones. Try changing your methods/variables from private to protected. public ones are visible to all.
For more information, See: PHP Visibility (Manual)
Edit
Understand the Singleton pattern. It is called 'singleton' because only one instance of a class is expected. Because of this, most classes implementing the singleton pattern define the constructor as private to restrict you from creating more than one.
To create an instance of a singleton, most classes define some kind of getInstance static method, which is public. This public method calls the private constructor, which probably sets flags indiciating that the class has been instantiated in order to prevent further attempts to instantiate the class. The getInstance method returns the results of calling the constructor, essentially the instance of the class.
You could write something like
class UserTools extends DB {
....
}
A quick example on inheritance in PHP:
class A {
public $a;
public function set_a($new_a) { $this->a = $new_a; return $this; }
public function get_a() { return $this->a; }
}
class B extends A {
public $b;
public function set_b($new_b) { $this->b = $new_b; return $this; }
public function get_b() { return $this->b; }
}
$objb = new B();
$objb->set_a("Some Value")->get_a(); //Some Value
The singleton pattern in most cases prevents instantiating the Singleton class by defining the constructor as private (ie private function __construct()).
So if you try to instantiate either your custom class or the original one that you're extending you will get the message above. You should either create a different class or define and use your function as static (eg public static function query($sql, $dbconnection)).
See http://php.net/manual/en/language.oop5.patterns.php