I am trying to call method getDetails() from another class which in turns calls to methods from its own class(i.e, called class) and it does so by
$this->getAccount() and $this->getAddress() and in called class we have methods like $this->getAccount() and $this->getAddress() function but when I call
them I get fatal error message as call to undefined method, but when I try calling that method using CalledClassName::getAddress() and
CalledClassName::getAddress() than it works fine.
My question is that class which am calling(i.e, calledClass ) will always have use $this->getAddress() and $this->getAccount() as am getting this class
information from other team and there are 3 teams that would be calling functions getDetails() which would internally call getAccount() and getAddress()
functions and so how should I deal with the issue of $this on myside when am calling getDetails() function.
Code Example
Calling Class:
CalledClass::getDetails() // Call to getDetails function in CalledClass
CalledClass::
public function postalAddress()
{
return array(
'addressId' => $address->addressId,
'city' => $address->city,
'country' => $address->country,
'postcode' => $address->postcode,
'stateOrProvince' => $address->stateOrProvince,
'street' => $address->streetName,
'streetNumber' => $address->streetNrFirst,
'streetSuffix' => $address->streetNrFirstSuffix
);
};
public function getAddress()
{
return $this->postalAddress();
}
public function setAccount($account)
{
$this->account = $account;
}
public function getAccount()
{
return $this->find('account = 1311143','');
}
public function getDetails()
{
$data = array();
$data[$address] = $this->getAddress();
$data[$account] = $this->getAccount();
return $data;
}
So now using the above method it gives me error and so if am using CalledClass::getAddress() and CalledClass::getAccount() and it works fine but I cant chang e the code in the calledclass as am calling this function from another team.
Any guidance or suggestions ?
If the function you are trying to call from another class is static, you need to use the :: (scope resolution operator) to call on it. It is also the same way when trying to access static properties.
Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
Taken from PHP: Static Keyword
In the meantime for your method call to work without having the ability to modify the other member's code is to use CalledClass::getAddress()
Related
I looked a lot and didn't find a similar question so please bear with me I am still learning OOP.
I read that in a class, a protected function can be accessed from any other function, but it has to be within the same class. So why does the following code not work when I make the
register_scripts() function as protected? I mean, since setup_hooks() function is holding the action that will trigger the register_scripts() callback, and both these functions are in the same Assets class, so why the error on making it protected?
class Assets{
protected function __construct(){
// Load all classes
$this->setup_hooks();
}
// define hooks for the plugin here
protected function setup_hooks(){
// Actions
add_action( 'wp_enqueue_scripts', [ $this, 'register_scripts' ] );
}
public function register_scripts(){
wp_enqueue_script( 'mono_script', MY_DIR_URL . '/assets/script.js', array(), '1.0', true );
}
}
I get the following error:
Fatal error: Uncaught TypeError: call_user_func_array(): Argument #1 ($callback) must be a valid callback, cannot access protected method MWS_PLUGIN\Inc\Assets::register_scripts()
As #disinfor showed, this comes down to scope, and it isn't really a WordPress issue, but a PHP one. WordPress's hook system obviously doesn't live in your class, it lives in the global namespace (although that's not part of the issue) and that's the important distinction.
To your note about setup_hooks "holding the action", that isn't true, it is only referencing it. Whoever actually calls that reference must have the proper scope.
You can get around this, however, by using closures. Here's a sample of a class and a couple of ways to pass, along with the failure that you noticed.
class Thing {
public function publicFunction() {
echo __METHOD__, PHP_EOL;
}
protected function protectedFunction() {
echo __METHOD__, PHP_EOL;
}
public function __construct() {
// This works as expected
test([$this, 'publicFunction']);
// This all works because it is a closure
test(
function() {
$this->protectedFunction();
}
);
// This is a shorter version of the previous
test( fn() => $this->protectedFunction() );
// This does not work
test([$this, 'protectedFunction']);
}
}
function test(callable $func){
$func();
}
new Thing;
Demo: https://3v4l.org/mdiX0
Ok so my question is, i have a Facebook call back function that I'm using. The callback function uses an instance as an argument facebookCallBack(LaravelFacebookSdk $fb)
The function works great,I'm using this in my auth controller in larvel , but now I want to reuse this function within the same controller something like $this>facebookReusableCallBack(LaravelFacebookSdk $fb)
I'm having issues ,i get this error facebookReusableCallBack() must be an instance of SammyK\LaravelFacebookSdk\LaravelFacebookSdk, none given.
here's a sample of my code:
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack();
}
public function facebookReusableCallBack() {
//All my code here
}
how can I reuse this function within my controller?
i've tried :
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack(LaravelFacebookSdk $fb);
}
but the argument doesn't get passed as an instance?
You don't need to define the type of a variable when you pass it in.
Method definition:
public function facebookReusableCallBack(LaravelFacebookSdk $fb) {
//some code
}
Execution within another method:
function myMethod() {
$var = new LaravelFacebookSdk();
$this->facebookReusableCallBack($var);
}
What you have done is define the type of the variable in your function definition (good) to force the type. However these are only needed in the definition.
So for your explicit example:
public function facebookCallBack(LaravelFacebookSdk $fb) {
$this->facebookReusableCallBack($fb);
}
Because $fb must be an instance of LaravelFacebookSdk when calling facebookCallBack it will be fine for facebookReusableCallBack.
I have a private function as written below in the Controller.
private function GetProjects($ProjectStatus) {
return \App\Models\Project\Project_Model
::where('ProjectStatusID', $ProjectStatus)
->where('WhoCreatedTheProject', auth()->user()->UserID)->get();
}
Below is the action method that is using this private function.
public function ClientCancelledProjects() {
$ProjectStatus = \App\Enumeration\Project\ProjectStatus::Cancelled;
$MyProjects = GetProjects($ProjectStatus);
return view("Project.Client.MyProject", array("Projects" => $MyProjects));
}
Below is the Error coming when running the controller.
Call to undefined function App\Http\Controllers\Project\GetProjects()
Somebody knows why this is happening ? I am trying to reuse some lines of code as they are written many times in the Controller.
To access functions in a controller from a function in the same controller, use self:::
public function ClientCancelledProjects() {
$ProjectStatus = \App\Enumeration\Project\ProjectStatus::Cancelled;
$MyProjects = self::GetProjects($ProjectStatus);
return view("Project.Client.MyProject", array("Projects" => $MyProjects));
}
Note: Self:: (uppercase) will work depending on the version of php installed, but for older versions, self:: is preferred.
Please check this link for more info: PHP - Self vs $this
Functions inside of a class are not global functions, and cannot be called that way. You need to use $this->GetProjects() instead.
I'm stuck probably at a fairly simple question... I'm working on a implementation with YAML to enable the duplication of the application.
However, setting up the config model is the part where I'm stuck.
class ConfigModel {
public $configSection = null;
private $configArray = array();
public function loadYML(){
$this->configArray = Spyc::YAMLLoad('../config/config.yml');
}
public function setConfigSection($configSection){
$this->configSection = $configSection;
}
public function getConfig($configSection){
$this->loadYML(); //Line 33
}
}
Through a test script I request the specific contents of the YML file:
$mysqlSettings = ConfigModel::getConfig('mysql');
But then I'm getting the error:
Fatal error: Using $this when not in object context in Line 33
The loadYML works and outputs a Array. And to my onderstanding the this->loadYML(); is allowed to be used there...
You trying to call ConfigModel::getConfig() as static method. It is is wrong to use $this in static method. You must declare $configArray as static property and loadYML() and getConfig() as static methods if you need to call getConfig() as static
Please explain execution flow of the below statement
$this->setPageID()
->paginate()
->sendCacheHeaders();
in below code
protected function main()
{
$this->setPageID()
->paginate()
->sendCacheHeaders();
}
public function setPageID()
{
$this->pageID = (int)$this->Router->getRealPageID();
return $this;
}
protected function paginate()
{
d('paginating with $this->pagerPath: ' . $this->pagerPath);
$Paginator = Paginator::factory($this->Registry);
$Paginator->paginate($this->Cursor, $this->PER_PAGE,
array('currentPage' => $this->pageID,
'path' => '{_WEB_ROOT_}/' . $this->pagerPath));
$this->pagerLinks = $Paginator->getLinks();
return $this;
}
protected function sendCacheHeaders()
{
return $this;
}
What is the flow of this methods execution?, Is there any data transfer/communication b/w these methods?
I call this chaining. Basically, your functions are part of a class and that class has an instance ($class = new class()).
Your functions are returning that instance. While not a best practice per se, it does mean that you can chain the calls back to back.
$this->setPageID() ->paginate() ->sendCacheHeaders();
Note how each function returns $this. So it's the same as writing
$this->setPageID();
$this->paginate();
$this->sendCacheHeaders();
They're not communicating with each other explicitly. They all belong to the same class instance so they can access any variables belonging to that class (or any parent classes). So when paginate() sets $this->pagerLinks, any function in that class can access that value.
$this
->setPageID() // sets class variable $pageID from Router class. Returns current class.
->paginate() // Setup of Paginator class, assigns links to $pagerLinks. Returns current class
->sendCacheHeaders(); // does nothing. Returns current class
Because every function return $this so it's possible to chain method calls. Without returning $this your call will look like this:
$this->setPageID();
$this->paginate();
$this->sendCacheHeaders();