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
Related
We are moving forward to PHP 8 from PHP 7.4, we are facing Declaration must be compatible Fatal error in our code to custom parameter type, we need a proper solution with less code changes.
Kindly refer below code snippet
ERROR
Fatal error: Declaration of ClientReactieView::getUrlAddData(?ClientReactie $clientReactie = null) must be compatible with Overview\BaseView::getUrlAddData(?Storm\Model $model = null) in /var/www/html/system/tmp/class_client_reactie_view.php on line 102
abstract class file : abstract_class_base_view.php
<?php
namespace Overview;
use Storm;
abstract class BaseView {
public static function getUrlAddData(Storm\Model $model = null){
// ...
return $urlAddData;
}
}
Child class file : class_client_reactie_view.php
<?php
class ClientReactieView extends Overview\BaseView {
public static function getUrlAddData(ClientReactie $clientReactie = null){
// ...
return $urlAddData;
}
}
Custom parameter type class_client_reactie.php
class ClientReactie extends Storm\Model {
// ...
}
Our application is already developed & working fine with PHP 7.4, We require solution to resolve this fatal error with less code changes
The error is telling your code is illogical.
The definition of BaseView makes a promise: you can call getUrlAddData and pass any instance of Storm\Model, or null.
The definition of ClientReactieView says that it extends BaseView, so inherits that promise. But then it changes that promise: you can call getUrlAddData, but you're not allowed to pass anything that's not a ClientReactie.
This is "covariance of input", and has always been forbidden for non-static methods - if $foo instanceof BaseView is true, then $foo->getUrlAddData(...) would have to accept all values that the definition in BaseView allowed.
What's new in PHP 8 is that this is enforced for static methods as well, so that the same guarantee applies to "late static binding" calls such as this:
abstract class BaseView {
public static function getUrlAddData(Storm\Model $model = null){
// ...
return $urlAddData;
}
public static function doSomethingElse(Storm\Model $model = null){
$urlAddData = static::getUrlAddData($model);
// ...
}
}
class ClientReactieView extends Overview\BaseView {
public static function getUrlAddData(ClientReactie $clientReactie = null){
// ...
return $urlAddData;
}
}
ClientReactieView::doSomethingElse(new Storm\Model);
// ERROR! The call goes to BaseView::doSomethingElse, which accepts any Model
// But static::getUrlAddData resolves to ClientReactieView::getUrlAddData
// and that has an incompatible signature
So the correct fix is to honour the promise made by the parent class:
class ClientReactieView extends Overview\BaseView {
public static function getUrlAddData(Storm\Model $model = null){
if ( ! $model instanceof ClientReactie ) {
// Figure out what to do with such calls
}
// ...
return $urlAddData;
}
}
I wanted to have a static closure variable in my class, so that people can change the behavior of a specific part of the code. However, I can't seem to be able to initialize it anywhere.
First I tried this:
public static $logger = function($sql) { print_r($sql); };
But apparently PHP can't handle that. Ok, so I made a static init method:
public static $logger;
static function init() {
/* if (!Base::logger) */
Base::logger = function($sql) { print_r($sql); };
}
And call it at the end of the file, outside class definition. But this also give me a syntax error: Parse error: syntax error, unexpected '=' in [file] on line [line]. Any hints?
The syntax error is right where the error message tells you it is (it would have been even easier to spot if you had given us line numbers...): a missing $-sign.
Base::$logger = function (...)
In addition to that, you migth want to use self:: instead of Base::, this ensure the code will work without any additional changes if you ever rename the class
self::$logger = function (...)
You can improve this code even further, when changing the initializer to a getter that JIT-creates the closure:
private static $logger = NULL;
public static function getLogger () {
if (self::$logger === NULL) {
self::$logger = function ($sql) {print_r($sql);};
}
return self::$logger;
}
[Edit] Based on your comment on this: the clean OOP way of being able to change $logger would be to use a setter:
public static function setLogger ($closure) {
self::$logger = $closure;
}
COmbining this and the getter from above ensures that you always get the value set by the setter, and, if none has been set yet, the default value. Using the setter to set the value back to NULL makes the getter create the default again, which is anoth er plus.
I'm using factory to create an object and the static method to unserialize this object:
public static function factory($idText) {
$fetchedObject = self::fetchStoredObject($idText);
return $fetchedObject;
}
private static function fetchStoredObject($idText) {
$fetchedText = DB::select()
->from(table)
->where('idText', '=', $idText)
->execute()->as_array();
if (!empty($fetchedText)) {
return unserialize(base64_decode($fetchedText[0]['txtContent']));
} else {
return NULL;
}
}
The object is created in this way:
$text = Article::factory($idText);
But I get the following error:
unserialize() [<a href='function.unserialize'>function.unserialize</a>]:
Function spl_autoload_call() hasn't defined the class it was called for
On this line of fetchStoredObject method:
return unserialize(base64_decode($fetchedText[0]['txtContent']));
Why does this error occur?
EDIT
My class has the following structure:
class Article {
private $phpMorphy;
private $words; //contains instances of class Word
...
private function __construct($idText) {
$this->initPhpMorphy(); // $this->phpMorphy gets reference to the object here
}
public function __sleep() {
return Array(
'rawText',
'idText',
'properties',
'words',
'links'
);
}
public function __wakeup() {
$this->initPhpMorphy();
}
}
The Word class doesn't contain the reference to phpMorphy as own property, but uses it in its methods as function parameter.
Here is the part of the serialized string:
" Article words";a:107:{i:0;O:4:"Word":10:{s:5:" * id";O:9:"phpMorphy":7:{s:18:" * storage_factory";O:25:
It appears the phpMorphy is serialized with connectrion to the Word class. Am I right?
The error occurs because inside your serialized string there is a reference to a class that hasn't been included yet - so the PHP autoloading mechanism is triggered to load that class, and this fails for some reason.
Your steps for debugging would be:
Identify which class is included in that serialized string.
Check if you have code for that class somewhere.
Make sure this code can be loaded via autoloading. Alternatively make sure that code is included before unserializing.
What version of PHP did you use? Where did you store your Article class? Try to require() it manually.
The problem is fixed thanks to Sven suggestions. The object of class Word (part of the class Article) contained reference to the phpMorphy class (which happened because I changed parameters order when creating an instance of the word!).
I have a class like this:
// file /models/person.php
class Person
{
public function create_path()
{
self::log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
This is the way how Person is instanciated:
//file /tools/Builder.php
include('/models/Person.php');
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
As you note in Person class, I am calling the object in question with $this reference. But this is not correct because an error is showed:
Message: Undefined variable: this
I suppose that $this reference point to other object or it is unable to work because the object is created from another script. Also, I tried to use self because there was not problem calling methods with that, but as parameter I get:
Message: Use of undefined constant self - assumed 'self'
So, can you guide me to the right direction?
I tested your code out for myself, with a few minor changes. It appears to work properly.
Changed self::log() to $this->log()
Added global function path_helper (I have no idea what this does)
PHP
function path_helper(Person $object)
{
var_dump($object);
}
class Person
{
public function create_path()
{
$this->log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
$Build = new Builder();
$Build->build();
Result
trying to create a path
object(Person)[2]
Your code is correct and your going in the right direction.
You should call the log method like this:
$this->log();
because using self:: is reserved for static methods.
Also, try calling the path_helper function like this:
path_helper(self);
Hope I could help you. Couldn't test it, but it should work.
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()