I am calling function form library in codeigniter and it's giving me below error
PHP Fatal error: Cannot access property started with '\0' in /system/core/Exceptions.php on line 85
Code:
$this->load->library('test_library');
TEST_LIBRARY::first();
Class file:
class TEST_LIBRARY
{
public function first(){
return "here";
}
}
However, when I call the function using this method $this->test_library->first(); it's working fine.
It was working both ways before not sure what's going on. There is no other log messages in error.log file. How can I debug further and fix this issue?
Function first is not static but you called as if it is. Change test_libaray.php to :
class TEST_LIBRARY {
public function __construct() {}
public function first() {
return "here"; // i suggest to use __METHOD__ or __LINE__ instead
}
}
And then try:
$test_library = new TEST_LIBRARY();
$test_libaray->first();
instead of:
TEST_LIBRARY::first();
Or you can just change first static.
Whenever I include the beforeAction function event with something simple I get an error saying it has to be compatible. This does not happen on my live server only on my local one. The only difference I can think of is my local server is running PHP7 and my live one is running PHP5.6. Is that what is causing the issue? The only thing I have found that will fix it is removing it completely.
This is what my beforeAction looks like
public function beforeAction()
{
if(Yii::$app->user->isGuest){
return $this->redirect(['site/login']);
} else {
if(strtotime(UserInfo::findOne(Yii::$app->user->Id)->active_until) < strtotime(date("Y-m-d H:i:s"))){
Yii::$app->session->setFlash('warning', 'You need an active subscription to access events.');
echo("<script>location.href = '".Url::toRoute('site/subscription')."';</script>");
exit;
//return $this->redirect(['site/subscription']);
}else {
return true;
}
}
}
I also tried this simple one to check and got the same issue
public function beforeAction()
{
if (!parent::beforeAction($action)) {
return false;
}
return true;
}
Here is the error message I get
Declaration of frontend\controllers\EventController::beforeAction() should be compatible with yii\web\Controller::beforeAction($action)
See this error message :
should be compatible with yii\web\Controller::beforeAction($action)
Your override function must be compatible with parent. So, valid code :
public function beforeAction($action)
{
....
}
Just explaining
If you get this problem, it means that you have a function in your parent class and a function in your child class that have the same name but not the same input variable declaration.
Parent Class
beforeAction($action) {
....
}
Child Class
beforeAction() {
....
}
As you can see, the child class is missing the $action variable. This creates a warning in PHP E_Strict. All you have to do is make sure that the child class function is exactly the same as the parent.
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.
class Testme()
{
public function testMe ($a)
{
if ($a == 1)
{
throw new Exception ('YAY');
}
}
}
so its easy to test if it threw exception
/**
* #expectedException Exception
*/
public function test()
{
new Testme(1);
}
but what if it didn't do anything?
public function test()
{
new Testme(2);
?? ? ? ? ?
}
Scenarios
You have two possible scenarios for a function to do nothing:
Scenario 1: No return statement
Your function does nothing because you do not perform actions in it and you do not include the return keyword in it:
public function doNothing()
{
// Do nothing.
}
Scenario 2: With return statement
Your function does nothing because you do not perform actions in it and you do include the return keyword in it without expressing any return value:
public function doNothing()
{
// Do nothing.
return;
}
Other scenarios
I will leave out of the cases to treat the following scenarios:
Case in which you do not return anything but you perform significant actions that can be tested on other objects. In this case you must unit-test the resulting states of the modified objects.
Case in which you do nothing but return something, then you should unit-test the return value.
Exploring the documentation in the PHP manual
For the first case, the PHP manual documents that the evaluated expression of the function will be null. It says here: http://php.net/manual/en/functions.returning-values.php in a note:
If the return is omitted the value NULL will be returned.
For the second case, the PHP manual documents that the evaluated expression of the funcion will also be null. It says here: http://php.net/manual/en/function.return.php in a note:
If no parameter is supplied, then the parentheses must be omitted and NULL will be returned. [...]
Conclusion
It is therefore clearly documented that a function that "does nothing" necessarily evaluates to null.
How to test a function that does nothing
Just assert your expectations:
$this->assertNull( $sut->doNothing() );
This way you "exercise" your function, you run over it making the code-coverage complete all the lines, and you "expect" that "nothing happened" by testing the null value of its evaluation as an expression, as documented.
How to test a constructor that does nothing
Nevertheless to test a constructor... well... common sense: What's the purpose of a constructor? Create an object (instance) of a certain type (class), right?
So... I prefer to start the 100% of my unit tests by checking that the $sut has been created. This is the VERY first test I write when I'm writing the code of a new class. This is the test I write even before the class exists. At the end, this is what the constructor is for. Red bar. Then I create the class. Green bar.
Let's say I have an Email class that takes a string and will be only created if a valid email is passed and throws exception otherwise. this is very similar to your question. A constructor that just "allows the creation" or "denies it by exploding the system".
I usually would do something like this:
//-------------------------------------------------//
// Tests //
//-------------------------------------------------//
/** #dataProvider validEmailProvider **/
public function testCreationIsOfProperClass( string $email )
{
$sut = $this->getSut( $validEmail );
$this->assertInstanceOf( Email::class, $sut );
}
/** #dataProvider invalidEmailProvider **/
public function testCreationThrowsExceptionIfEmailIsInvalid( string $invalidEmail )
{
$this->expectException( EmailException::class );
$this->getSut( $invalidEmail );
}
//-------------------------------------------------//
// Data providers //
//-------------------------------------------------//
public function validEmailProvider() : array
{
return
[
[ 'alice#example.com' ],
[ 'bob.with-several+symbols#subdomain.another.subdomain.example.verylongTLD' ],
]
}
public function invalidEmailProvider() : array
{
return
[
[ 'missing_at_symbol' ],
[ 'charlie#cannotBeOnlyTld' ],
]
}
//-------------------------------------------------//
// Sut creators //
//-------------------------------------------------//
private function getSut( string $email ) : Email
{
return new Email( $email );
}
As I use PHP 7.0 and I put types everywhere, both entering the parameters and also in the return types, if the created object was not an Email, the getSut() function would fail first.
But even if I wrote it omitting the return type, the test tests what it is expected to happen: new Email( 'valid#example.com' ); is itself an expression that shoud evaluate to "something" of class Email::class.
How to test a constructor that does something
Code smell. The constructor probably should not do work. If any, just store parameters. If the constructor "does work" other than storing parameters consider lazy-processing on getters, or delegating that work in a factory or so.
How to test a constructor that "does nothing but store parameters"
Just like before + then get the data.
Test in your first test that the creation is an instance of something.
Then in another different test, exercise something like a getter that gets you what entered in the constructor even if the constructor did not anything (other than storing it).
Hope that this helps.
In PHPUnit 7.2+ you can also use TestCase::expectNotToPerformAssertions()
public function test()
{
// ...
$this->expectNotToPerformAssertions();
}
This has the same behaviour as the #doesNotPerformAssertions annotation.
2018+
Nowadays the best practice is annotation exactly for these cases:
/**
* #doesNotPerformAssertions
*/
public function testSomething()
{
$someService = new SomeObject();
$someService->shallNotFail();
}
Example pull-request
PHPUnit documentation (poor)
It's not possible. Add return statement and assert the result.
class Testme()
{
public function testMe ($a)
{
if ($a == 1)
{
throw new Exception ('YAY');
}
return true;
}
}
and then
$object = new Testme();
$this->assertTrue($object->testMe(2));
Note: The credits for this solution go to this related answer. The context may seem a little different, but the solution / workaround works the same way. Testing that an exception is not thrown is just the same as testing a method with no return value.
According to this issue thread, there is no built in solution for testing something like DoesNotThrowException in PHPUnit (yet).
So yes, one solution would be to return some dummy value from your method, like
public function testMe ($a)
{
if ($a == 1) { throw new Exception ('YAY'); }
return true;
}
and then assert it in your test. But if you don't want to change the code just for the test, you can work around it:
public function testExceptionIsNotThrown()
{
try {
new Testme(2);
}
catch(Exception $e) {
/* An exception was thrown unexpectedly, so fail the test */
$this->fail();
}
/* No exception was thrown, so just make a dummy assertion to pass the test */
$this->assertTrue(true);
}
It may seem hacky and not very intuitive, but if it's stupid but it works, it's not stupid.
This is an very interesting question, although lot of answers were written, none of them seems to properly answer the question, since you have asked using the class let me explain this way.
Please keep in mind that an instance method you have created in class should have only 2 intentions.
It can alter the state of a class ( change the class properties like private variables )
It returns the state of the class ( getters )
any thing other than this is meaningless unless it is a static method. for example
if you have class like this
class Foo {
private $prop = null;
public function fooMethod() {
$this->prop = "string";
}
public function getProp() {
return $this->prop;
}
}
the method fooMethod() does not return any thing, but it affects the state of $prop property in the class, you can test the method by
$this->assertNotNull( $instance->getProp() );
because you knew if this method is run then the prop $prop should be affected and state of that variable is changed.
Miscellanous Scenario: My method doesn't alter the state and also won't return any state variables.
Then the method is static. It should not be an instance method, and the static methods usually have return type, because they cant affect the state of the class and also can't return state variables. This constraints the static methods from storing a result somewhere (unless you store them globals, don't do that ), so it should definitely return some output. If you don't want to return output, then you could consider returning a boolean from static method.
public function testThrowingException()
{
$this->expectException(Exception::class);
$this->expectExceptionMessage('YAY');
(new Testme())->testMe(1);
}
public function testNotThrowingException()
{
$this->expectNotToPerformAssertions();
(new Testme())->testMe(2);
}
I stumled upon the same problem. To ensure "nothing" has happened it's enough to just call you the method in your unit test. If it fails the test will fail anyway.
If you just call your method without the #expectedException annotation like this
public function test()
{
new Testme(1);
}
you'll get an error
There was 1 error:
1) Testme::testMe
Exception: YAY
I have faced a curious condition and maybe you can help me understand that.
$object = array('controller' => 'frontend_shop', 'method' => 'category');
include_once(PATH.'controllers/'.$object['controller'].'.php');
$controller = new $object['controller']($object);
class Frontend_shop extends Controller {
public $controller;
public function __construct($object)
{
// Works
$this->$object['method']();
//DonĀ“t work
$this->controller = $object;
$this->controller['method']();
}
public function category()
{
echo 'hello';
}
}
This works and 'hello' is displayed
$this->$object['method']();
But when I assign this array to a class variable like:
$this->controller = $object;
$this->controller['method']();
I get:
Fatal error: Call to undefined function category() in /usr/lib/app/application/controllers/frontend_shop.php on line 10
Of course I know that I can use the first method, but maybe you can explain whats could be wrong in the class variable way of do it. Thanks
you would need something like
$this->{$this->controller['method']}();
$this->controller['method'] resolves to a string(the method name). but methods must be called upon an object(otherwise they're functions, not methods), and thats where the other $this-> resolution comes in.
I prefer
$callable = array($this, $this->controller['method']);
call_user_func($callable);
I don't like the litteral call syntax, as you have to look closely at the code to see whats really going on.
http://php.net/manual/en/function.call-user-func.php
http://www.php.net/manual/en/language.types.callable.php