Using $this when not in object context - php

maybe it is to early in the morning or I'm totally blind, but why to I get a 'Fatal error: Using $this when not in object context' in the following code. There is nothing static in there.
The class:
<?php
class Property
{
/**
* #var string[]
*/
private $values;
public function __contruct($file)
{
$this->values = parse_ini_file($file, false);
}
/**
* #return string
*/
public function get($key, $default = null)
{
if (key_exists($key, $this->values)) { //<-- error
return $this->values[$key];
}
return $default;
}
}
The test:
<?php
class PropertyTest extends Test
{
public function testGet()
{
$prop = new Property($this->getResource('test.properties'));
$this->assertEquals('foo', $prop->get('test.entry', 'xyz'));
$this->assertEquals('bar', $prop->get('test.entry2', 'xyz'));
$this->assertEquals('xyz', $prop->get('test.entry3', 'xyz'));
$this->assertEquals(null, $prop->get('test.entry3'));
}
}
Edit
The error comments indicating the trace. The error occures while running the PropertyTest->testGet() on the the first $prop->get() caused by the first line of the Property->get() method.
Solution
Beside the typo xdazz found, and the deprecation Phil pointed at, user985935 was right. :)
To make it short, my class loader used the static get and the phpUnit error mislead my investigations and my information I offer you for finding my problem. Sorry.

There is a typo in your code.
public function __contruct($file)
which should be
public function __construct($file)

'Fatal error: Using $this when not in object context'
The $this keyword points to methods that are inside an object only you can't use $this outside an object I think this is what causing your problem

Related

I need this class to return a string value "error25" if it fails is it possible? - PHP [duplicate]

This question already has answers here:
Throw exception if value not passed to method
(2 answers)
PHP Error handling missing arguments
(3 answers)
Closed 7 months ago.
Hello everyone I have this class in php
<?php
namespace ExternalImporter\application\libs\pextractor\parser;
defined('\ABSPATH') || exit;
class Product {
public $link;
public $domain;
public $title;
public $description;
public $price;
public $currencyCode;
public $image;
public $oldPrice;
public $manufacturer;
public $inStock;
public $availability;
public $category;
public $condition;
public $ratingValue;
public $reviewCount;
public $features = array();
public $images = array();
public $reviews = array();
public $paused;
public $categoryPath = array();
public $extra = array();
}
However when this is called with a null value it gives me a fatal error.
I need that when this error occurs it returns the result: error25
I call the class like this in a function
public static function update(Product $newProduct, $product_id)
{
//code
}
In this example, $newProduct has the value of NULL, which is why it would generate an error in the function.
If I can return the error string error25 I could handle it.
Note: If the solution is to call the function, it is much better than editing the class itself.
My goal is to achieve something like this, but I'm not sure you can in PHP
public static function update(Product $newProduct ?: "error25", $product_id)
{
//code
}
Edit Possible solution
public static function update($newProduct, $product_id)
{
if (empty($newProduct)) {
# CALL Product $newProduct how to do it?
}
else {
$newProduct = NULL;
}
}
First of all your error occurs not because of your parameter $newProduct is null and not an instance of Product. It occurs because you have logic in your method definition. You can 't do that.
public static function update(Product $newProduct ?: "error25", $product_id)
This should never work. It 's a syntax error. It results in: PHP Parse error: syntax error, unexpected token "?", expecting ")". Please set your error reporting to the highest level, so that such basic errors are visible to you.
Checking against null or instance of a class
<?php
declare(strict_types=1);
namespace Marcel;
use Exception;
use stdClass;
class Foo
{
public static function bar(?stdClass $yadda): void
{
if ($yadda === null) {
throw new Exception('$yadda is not an instance of stdClass', 25);
}
// or ...
if (!$yadda instanceof stdClass) {
throw new Exception('$yadda is not an instance of stdClass', 25);
}
// everything okay at this point
$yadda->someProperty = 'I am a valid stdClass instance';
}
}
What happens here? Your static method takes a parameter that can either be an instance of stdClass or null. If $yadda is null an exception will be thrown with a message and a code.
Catching type errors
With PHP 8 you can catch type errors. That 's another solution to your problem.
<?php
declare(strict_types=1);
namespace Marcel;
use stdClass;
use TypeError;
class Test
{
public static function foo(stdClass $yadda): void
{
// some logic here
}
}
try {
Test::foo(null);
} catch (TypeErrror $error) {
var_dump($error->getMessage());
// Marcel\Test::foo(): Argument #1 ($bar) must be of type stdClass, null given
}
You can catch type errors in a try/catch block. If $yadda is something different than an instance of stdClass a type error will be thrown. You can handle this error in a catch block. With this solution you don 't have to declare your parameters as null or an instance of some class. You can just declare the type hint of a specific class and catch a type error when calling the static method.

PHPUnit - ReturnValueMap of Mocks not finding Mocked Class Methods

I'm new to unit testing and have come across something I don't understand when using returnValueMap() in PHPUnit. I've been googling for days now ...
Consider this code under test;
public function __construct(EntityManager $entityManager, AuditLog $auditLog) {
$this->entityManager = $entityManager;
$this->auditLog = $auditLog;
}
public function updateSomeId($oldId, $newId)
{
$repositories = ['repo1', 'repo2', 'repo3'];
foreach ($repositories as $repository) {
try {
$this->entityManager->getRepository($repository)
->updateSomeId($oldId, $newId);
} catch (RepositoryException $e) {
throw new SomeOtherException($e->getMessage(), $e->getCode(), $e);
}
}
}
The unit test code;
... code removed for brevity
$repoMaintenance = new RepoMaintenance(
$this->getEntityManagerMock(),
$this->getAuditLogMock()
);
$this->assertTrue($repoMaintenance->updateSomeId(
$this->oldId,
$this->newId
));
/**
* #return EntityManager
*/
private function getEntityManagerMock()
{
$entityManagerMock = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
$entityManagerMock
->method('getRepository')
->willReturn($this->returnValueMap($this->getEntityManagerReturnValueMap()));
return $entityManagerMock;
}
/**
* #return array
*/
private function getEntityManagerReturnValueMap()
{
return [
['repo1', $this->getRepo1Mock()],
['repo2', $this->getRepo2Mock()],
['repo3', $this->getRepo3Mock()],
];
}
/**
* #return Repo1
*/
private function getRepo1Mock()
{
return $this->getMockBuilder(Repo1::class)
->disableOriginalConstructor()
->getMock();
}
... Code removed for brevity
When the unit test is run, the following fatal error is returned;
PHP Fatal error: Call to undefined method PHPUnit_Framework_MockObject_Stub_ReturnValueMap::updateSomeId()
I've previously used mocks in return value maps with no issue accessing methods in a public context. The difference is I'm attempting to mock __construct() variables, which are set to private access within the SUT.
What am I missing? The problem (I would naively guess) is with the private access level of the members being mocked.
Is there a way to unit test this code? I don't want to hit the database at any point and this is the reason for mocking the calls to it.
You should have will($this->returnValueMap... instead of willReturn($this->returnValueMap...

Strict standards non static method

I want to fix this error:
Strict Standards: Non-static method
Gpf_Settings_Regional::getInstance() should not be called statically,
assuming $this from incompatible context on line 39
The code producing it:
$this->addValue(Gpf_Settings_Gpf::REGIONAL_SETTINGS_DECIMAL_SEPARATOR,
Gpf_Settings_Regional::getInstance()->getDecimalSeparator());
I know this is method for PHP 5.3, but I have 5.4 on shared hosting and need to call static on PHP 5.4
Problem:
You are accessing a non-static method statically with strict standards error reporting switched on.
Solutions:
You can update Gpf_Settings_Regional class
change
public function getInstance()
to
public static function getInstance()
If you are unable to change that class you can change error reporting and switch of reporting of strict standards errors, but it would be better to improve the code.
How to eliminate php5 Strict standards errors?
if i see good it's already made it by script
*/
private static $instance;
public static function create(Gpf_Application $application) {
setlocale(LC_ALL, 'en.UTF-8');
self::$instance = $application;
self::$instance->registerRolePrivileges();
self::$instance->initLogger();
self::$instance->addSmartyPluginsDir();
$timezone = Gpf_Settings_Gpf::DEFAULT_TIMEZONE;
try {
$timezone = Gpf_Settings::get(Gpf_Settings_Gpf::TIMEZONE_NAME);
} catch (Gpf_Exception $e) {
Gpf_Log::error('Unable to load timezone: %s - using default one.', $e->getMessage());
}
if(false === #date_default_timezone_set($timezone)) {
Gpf_Log::error('Unable to set timezone %s:', $timezone);
}
}
public function getDefaultLanguage() {
return 'en-US';
}
/**
* #return Gpf_Application
*/
public static function getInstance() {
if(self::$instance === null) {
throw new Gpf_Exception('Application not initialize');
}
return self::$instance;
}
and this is part where problem is
abstract class Gpf_ApplicationSettings extends Gpf_Object {
/**
* #var Gpf_Data_RecordSet
*/
private $recordSet;
const CODE = "code";
const VALUE = "value";
protected function loadSetting() {
$this->addValue("theme", Gpf_Session::getAuthUser()->getTheme());
$this->addValue("date_time_format", 'MM/d/yyyy HH:mm:ss');
$this->addValue("programVersion", Gpf_Application::getInstance()->getVersion());
$this->addValue(Gpf_Settings_Gpf::NOT_FORCE_EMAIL_USERNAMES, Gpf_Settings::get(Gpf_Settings_Gpf::NOT_FORCE_EMAIL_USERNAMES));
$quickLaunchSettings = new Gpf_Desktop_QuickLaunch();
$this->addValue(Gpf_Desktop_QuickLaunch::SHOW_QUICK_LAUNCH, $quickLaunchSettings->getShowQuickLaunch());
$this->addValue(Gpf_Settings_Gpf::REGIONAL_SETTINGS_THOUSANDS_SEPARATOR,
Gpf_Settings_Regional::getinstance()->getThousandsSeparator());
$this->addValue(Gpf_Settings_Gpf::REGIONAL_SETTINGS_DECIMAL_SEPARATOR, Gpf_Settings_Regional::getInstance()->getDecimalSeparator());
$this->addValue(Gpf_Settings_Gpf::REGIONAL_SETTINGS_DATE_FORMAT, Gpf_Settings_Regional::getInstance()->getDateFormat());
$this->addValue(Gpf_Settings_Gpf::REGIONAL_SETTINGS_TIME_FORMAT, Gpf_Settings_Regional::getInstance()->getTimeFormat());
Gpf_Plugins_Engine::extensionPoint('Core.loadSetting', $this);
}

Cannot override final method Exception::getPrevious()

I got CMS and trying to install it, but when i try to login i got error
Cannot override final method Exception::getPrevious()
Fatal error: Cannot override final method Exception::getPrevious() in C:\wamp\www\uis-online\application\exceptions\applicationException.php on line 41
Does anyboy have idea what cause this error
code in this file is
class ApplicationException extends Exception
{
protected $innerException;
/**
* Konstruktor
* #return unknown_type
*/
public function __construct($message, $code = 0, Exception $innerException = null)
{
parent::__construct($message, $code);
if (!is_null($innerException))
{
$this->innerException = $innerException;
}
}
public function getPrevious()
{
return $this->innerException;
}
// custom string representation of object
public function __toString() {
$exceptions_message = "";
if($this->innerException != null && $this->innerException->getMessage() != "") {
$exceptions_message = $this->innerException->__toString();
}
return $exceptions_message .__CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
}
As shown in the documentation the method you're trying to override is a final one.
final public Exception Exception::getPrevious ( void )
http://php.net/manual/en/exception.getprevious.php
According to the PHP manual you can't override final methods.
PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.
http://php.net/manual/en/language.oop5.final.php

Mock private method in a test function by PHPUnit

Writing unit tests for code which is already written is fun sometimes.
I am writing a test case for the following code (an example):
<?php
class mockPrivate {
public static function one($a){
$var = static::_two($a);
return $var;
}
private static function _two($a){
return $a+1;
}
}
?>
The test class is like this:
<?php
require_once 'mockPvt.php';
class mockPrivate_test extends PHPUnit_Framework_TestCase {
public $classMock;
protected function setUp(){
$this->classMock = $this->getMock('mockPrivate', array('_two'));
}
public function test_one(){
$a = 1;
$retVal = 2;
$classmock = $this->classMock;
$classmock::staticExpects($this->once())
->method('_two')
->with($a)
->will($this->returnValue($retVal));
$value = $classmock::one($a);
$this->assertEquals($value, $retVal);
}
}
?>
After running by $ phpunit mockPrivate_test.php I got this error:
PHP Fatal error: Call to private method Mock_mockPrivate_531a1619::_two() from context 'mockPrivate' in /data/www/dev-sumit/tests/example
s/mockPvt.php on line 6
But if I change the
private static function _two()
to
public static function _two() or
protected static function _two()
it works totally fine. Since this is a legacy code I can't change the private to public/protected. So is there any way I can test the function one or Is this a limitation of phpunit?
Another option is to create a class that extends mockPrivate, allowing accessibility to the object you wish to test. Your engineers should be thinking long and hard about why something is private (because that means the class is not easily extensible). Also remember that you can mock the test class if you need to override what it returns.
class Test_MockPrivate extends MockPrivate
{
/**
* Allow public access to normally protected function
*/
public static function _two($a){
return parent::_two($a);
}
}
// Code to force the return value of a now public function
$mock = $this->getMock('Test_MockPrivate', array('_two'));
$mock->expects($this->any())
->method('_two')
->will($this->returnValue('Some Overridden Value');
You can use reflection for changing visibility of methods. You can find more info in
PHP object, how to reference?
Use mock and reflection... (posted this solution, since this is the top google result)
$oMock = $this->getMock("Your_class", array('methodToOverride'));
$oMock->expects( $this->any() )
->method('methodToOverride')
->will( $this->returnValue( true ) );
$oReflection = new ReflectionClass("Your_Class");
$oMethod = $oReflection->getMethod('privateMethodToInvoke');
$oMethod->setAccessible( true );
$oMethod->invoke( $oMock );

Categories