Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds method_exists check to Model->__call() avoiding recursion issues for non-existent methods #75

Closed
wants to merge 7 commits into from

Conversation

michaelward82
Copy link
Contributor

Re: Issue #74

I'll try to find some time to add a regression test for this.

@treffynnon
Copy link
Collaborator

You'll need to get a newer version of PHPUnit to run the tests. They require 3.7+. I use the phar file downloadable from the PHPUnit site as it is much easier than mucking around with the packages in Linux repositories or from PEAR.

@michaelward82
Copy link
Contributor Author

Same thing with 3.7:

PHPUnit 3.7.26 by Sebastian Bergmann.

Configuration read from /web/other/paris2/phpunit.xml

PHP Fatal error:  Call to a member function getAttribute() on a non-object in /web/other/paris2/test/idiorm.php on
line 327
PHP Stack trace:
PHP   1. {main}() /usr/local/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/local/bin/phpunit:612
PHP   3. PHPUnit_TextUI_Command->run() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:129
PHP   4. PHPUnit_TextUI_TestRunner->doRun() phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:176
PHP   5. PHPUnit_Framework_TestSuite->run() phar:///usr/local/bin/phpunit/phpunit/TextUI/TestRunner.php:349
PHP   6. PHPUnit_Framework_TestSuite->run() phar:///usr/local/bin/phpunit/phpunit/Framework/TestSuite.php:705
PHP   7. PHPUnit_Framework_TestSuite->runTest() phar:///usr/local/bin/phpunit/phpunit/Framework/TestSuite.php:745
PHP   8. PHPUnit_Framework_TestCase->run() phar:///usr/local/bin/phpunit/phpunit/Framework/TestSuite.php:775
PHP   9. PHPUnit_Framework_TestResult->run() phar:///usr/local/bin/phpunit/phpunit/Framework/TestCase.php:783
PHP  10. PHPUnit_Framework_TestCase->runBare() phar:///usr/local/bin/phpunit/phpunit/Framework/TestResult.php:648
PHP  11. ModelPrefixingTest->tearDown() phar:///usr/local/bin/phpunit/phpunit/Framework/TestCase.php:870
PHP  12. ORM::set_db() /web/other/paris2/test/ModelPrefixingTest.php:17
PHP  13. ORM::_setup_identifier_quote_character() /web/other/paris2/test/idiorm.php:282
PHP  14. ORM::_detect_identifier_quote_character() /web/other/paris2/test/idiorm.php:303

When I hit the error producing line 327 of idiorm.php, I get the following evaluation in debug:

$_db[$connection_name] = null

which causes this call to fail:

self::$_db[$connection_name]->getAttribute(PDO::ATTR_DRIVER_NAME)

It seems a null db is passed in at step 11 as part of the tearDown function, but said db is required to not be null at a later point.

In case it is relevant, the machine is running Ubuntu 13.04, with PHP 5.4.9-4.

@treffynnon
Copy link
Collaborator

That is really weird. I am running the tests locally just fine and Travis-CI is also running the tests successfully.

simon@Treffynnon:~/paris [master] $ php ../phpunit.phar 
PHPUnit 3.7.24 by Sebastian Bergmann.

Configuration read from /home/simon/paris/phpunit.xml

.....................................................

Time: 78 ms, Memory: 4.50Mb

OK (53 tests, 61 assertions)

@michaelward82
Copy link
Contributor Author

Bizarre. Must be something funky with my setup.

I'll log on to my home mac os x install and try it from there!

@michaelward82
Copy link
Contributor Author

And from my mac it works fine! Has to be an env problem - I'll just have to do the work from the mac!

PHPUnit 3.7.26 by Sebastian Bergmann.

Configuration read from /Users/michael/dev/paris/phpunit.xml

.....................................................

Time: 183 ms, Memory: 4.50Mb

OK (53 tests, 61 assertions)

@michaelward82
Copy link
Contributor Author

I tried adding the following test to ParisTest.php, but when this is present I get a segmentation fault.

public function testInvalidFunctionCallDoesNotRecurse() {
    $result = Model::factory('Simple');
    $result = $result->findNone();
    $this->assertEquals(false, $result);
}

Clearly I am looking for false as the return value from the non-existent method call.

Any suggestions?

@michaelward82
Copy link
Contributor Author

I think I've got the regression test working correctly, though I do get a segmentation fault rather than an assertion error when i remove the bug fix from the code and retest.

@treffynnon
Copy link
Collaborator

I would suggest that it should throw an exception rather than return false:

throw new Exception("Method $name() does not exist in class " . get_class($this));

…nction call to the class, updates regression test to expect the same
@treffynnon
Copy link
Collaborator

The reason why the original test was not working is because you are not getting an instance of Model when calling Model::factory(), but an instance of ORMWrapper. ORMWrapper extends Idiorm's ORM class, which has an __call() method in it. That __call() method in there does not have any method_exists() protection. As soon as I add in a similar method_exists() protection your code works as expected with your original regression test.

So this pull request needs to be accompanied with change/pull request in Idiorm itself as well.

@michaelward82
Copy link
Contributor Author

Yeah, I realised that in the end :)

The protection can exist independently in the Model class, though we obviously need to place it in any class that uses this type of functionality.

Is it just the ORM class that needs the fix or will I find it elsewhere?

I'll sort out the code and send a pull request this evening.

Is everything in order with this patch now?

@treffynnon
Copy link
Collaborator

Yes, looks good. Although I would like to have the original regression test included again as well.

It should just be ORM that needs the patch I think.

@michaelward82
Copy link
Contributor Author

Ok, I'll add a test for idiorm when I fix ORM, and will restore the previous regression test to the Paris test suite when the idiorm work is done.

@michaelward82
Copy link
Contributor Author

Do we need a custom exception class to satisfy the old version of PHPUnit being used for PHP 5.2 testing by Travis?

See sebastianbergmann/phpunit#454 for further details.

@ghost ghost assigned treffynnon Sep 16, 2013
@treffynnon
Copy link
Collaborator

Aside from that one file mentioned above this looks good. Thanks!

@michaelward82
Copy link
Contributor Author

Sorry, it was an unintended PHPStorm project file that shouldn't have been checked in.

@shdwp
Copy link

shdwp commented Sep 30, 2013

I think you just need to trigger fatal error, just like PHP without __call does.

@treffynnon
Copy link
Collaborator

I don't like throwing uncatchable fatal errors from within a library as I feel this is something that should be an implementers decision. They can ignore it, allow the exception to halt proceedings or handle the exception in another way.

@amerker
Copy link

amerker commented Nov 25, 2013

I also get infinite recursions when trying to access nullable DB fields from Twig, via {{ object.field }}, that actually have NULL as value. When accessing the corresponding method, breakage ensues. This is when building the object using find_one(), or find_many() plus Twig loop. It's interesting that the Twig test "is defined" always returns true regardless of whether the field is NULL or has data.

When using find_array() I can access the NULL field from Twig as expected.

@gwn
Copy link

gwn commented Dec 3, 2013

Hey @treffynnon . What is the fate of this pull request? Will it be merged? Is there anything that is still missing?

@treffynnon
Copy link
Collaborator

@Cal127 it is earmarked for the 1.5.0 release milestone which is currently scheduled for the end of January. I have recently assigned all outstanding pull requests to a milestone.

@gwn
Copy link

gwn commented Dec 3, 2013

Thanks

@treffynnon
Copy link
Collaborator

Merged in develop

@treffynnon treffynnon closed this Dec 26, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants