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

[WIP]Added Phalcon\Mvc\Model\Binder #12341

Merged
merged 1 commit into from
Nov 19, 2016
Merged

Conversation

Jurigag
Copy link
Contributor

@Jurigag Jurigag commented Oct 20, 2016

PR with model binding changes in dispatcher, moving code to separated class, as well add more abilities, caching of reflection, and make binding working for micro handlers, controllers and lazy controllers

  • Make sure that the PR passes in Travis CI to make the process more efficient.
  • Only use tabs for indentation.
  • if needed, rebase to the proper branch before submitting your pull request.
    If it doesn't merge cleanly with master you may be asked to rebase your changes.
  • Don't put submodule updates in your pull request unless they are to landed commits.
  • Add tests relevant to the fixed bug or new feature. See our testing guide for
    more information.
  • Phalcon 2 is written in Zephir, please do not submit commits that modify C generated
    files directly or those whose functionality/fixes are implemented in the C
    programming language
  • Remove any change to ext/kernel / *.zep.c / *.zep.h files before submitting the PR

@Jurigag Jurigag changed the title Added Phalcon\Mvc\Model\Binder [WIP]Added Phalcon\Mvc\Model\Binder Oct 20, 2016
@Jurigag Jurigag force-pushed the 3.1.x-binding branch 15 times, most recently from 3947a6f to 44cb0ff Compare October 21, 2016 07:53
*/
public function setModelBinding(boolean value)
public function setModelBinding(boolean value, var cache = null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deprecated public function setModelBinding(boolean value, var cache = null)

/**
* Enable model binding during dispatch
*
* @param \Phalcon\Mvc\Model\BinderInterface modelBinder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if not needed, zephir-lang/zephir#1331 Does it for 100% correctly generate stubs in this case ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not Phalcon issue.

*
* @param \Phalcon\Mvc\Model\BinderInterface modelBinder
*/
public function setModelBinder(<BinderInterface> modelBinder, var cache = null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public function setModelBinder(<BinderInterface> modelBinder, var cache = null) -> <DispatcherInterface>

abstract static function getModelName() -> var;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> string | array

?


if realHandler instanceof Controller {
let methodName = handler[1];
let bindCacheKey = "binding_" . get_class(realHandler) . "_" . methodName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"binding_" => "_PHMB_"


return this->getParamsFromReflection(handler, params, cacheKey, methodName);
}
else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else not needed. just throw Exception if handler is not Closure and methodName is null


/**
* Sets cache instance
* @param \Phalcon\Cache\BackendInterface cache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

* Sets cache instance
* @param \Phalcon\Cache\BackendInterface cache
*/
public function setCache(<BackendInterface> cache)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> ...


/**
* Gets cache instance
* @return Phalcon\Cache\BackendInterface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's needed, otherwise in generated stubs it would return Phalcon\Mvc\Model\BackendInterface

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just use -> ...

}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cyclomatic complexity

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see a way to solve it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this?:

for paramKey, methodParam in methodParams {
    let reflectionClass = methodParam->getClass();

    if !reflectionClass {
        continue;
    }

    let className = reflectionClass->getName();

    if typeof className != "string" {
        continue;
    }

    // ...
}

Also, what value could reflectionClass->getName() be if it's not a string?

Copy link
Contributor Author

@Jurigag Jurigag Oct 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea, thanks Sid :) well i think that we don't even need check type of className, not sure though.

# [3.1.0](https://github.com/phalcon/cphalcon/releases/tag/v3.1.0) (2016-XX-XX)
- Added `Phalcon\Mvc\Model\Binder`, class used for binding models to parameters in dispatcher, micro, added `Phalcon\Dispatcher::getBoundModels` and `Phalcon\Mvc\Micro::getBoundModels` to getting bound models
- Deprecated `Phalcon\Dispatcher::setModelBinding`, use `Phalcon\Dispatcher::setModelBinder`
- Deprecated `Phalcon\Mvc\Controller\BindModelInterface`, use `Phalcon\Mvc\Model\Binder\BindableInterface`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be in 3 PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So i should change it to one line ? Or what ?

Copy link
Contributor

@sergeyklay sergeyklay Oct 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about split this work to 3 pr?

@Jurigag
Copy link
Contributor Author

Jurigag commented Oct 21, 2016

Any way to have IntegrationTester and UniTester in one tester method ? :C I don't know why but it trying to execute method from IntegrationTester anyway.

@Jurigag Jurigag force-pushed the 3.1.x-binding branch 8 times, most recently from 07edb29 to 789ea1b Compare October 21, 2016 11:23
@Jurigag Jurigag closed this Oct 21, 2016
@Jurigag Jurigag reopened this Oct 21, 2016
@Jurigag Jurigag force-pushed the 3.1.x-binding branch 5 times, most recently from edf337b to 6670663 Compare October 21, 2016 23:50
@Jurigag
Copy link
Contributor Author

Jurigag commented Oct 22, 2016

Finally passed tests, had some weird seg fault. I needed to add some useless variable to store callMethod result and then set it to returnedValue, pretty weird @virgofx can you look here ? If it's related somehow to other try catch problems ? Or some other kind of issue

Also DON'T merge it yet, want to refractor somehow tests, also tbh there is no action executing after cache is added so need to do this too.

What is even MORE weird that without this returnedValue hack on PHP 7 catch(\TypeError $e) was not working at all !

*/
public function setModelBinding(boolean value)
public function setModelBinding(boolean value, var cache = null) -> <Dispatcher>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add PHPDoc with example here

/**
* Enable model binding during dispatch
*/
public function setModelBinder(<BinderInterface> modelBinder, var cache = null) -> <Dispatcher>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here

@@ -737,6 +748,22 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac
}

/**
* Returns bound models from binder instance
*/
public function getBoundModels() -> array
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same

/**
* Sets model binder
*/
public function setModelBinder(<BinderInterface> modelBinder, var cache = null) -> <Micro>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example please

@sergeyklay
Copy link
Contributor

I think we need detailed description for some public methods

@Jurigag
Copy link
Contributor Author

Jurigag commented Oct 22, 2016

Yea when there will be time i will add phpdoc examples.

Copy link

@DavertMik DavertMik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed tests, they look pretty nice. But some small changes still required. I'd recommend you to break long tests into smaller ones but name them better so anyone looking into name of a test (without lookint into its code) would understand what exactly it tests, what feature of a method is that.

*
* @param IntegrationTester $I
*/
public function testDispatcher(IntegrationTester $I)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you name it in a bit more meaningful way? I'd really like to know what actual functionality is tested

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's in BinderCest so it's obviously testing binding with dispatcher :) I think name is fine.

$dispatcher->setActionName('multiple');
$dispatcher->setParams(['people' => $people->cedula, 'robots' => $robot->id]);

$dispatcher->dispatch();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the second time you perform action. It is a good idea to make test to have 3 steps: arrange, act, assert. You already did assertion in this test, so this can be made as another test.

This is important because smaller tests are easier to read, understand, and fix. If setup part of those tests are similar you can move it to separate method and call it using @before annotation

$dispatcher->setActionName('view');
$dispatcher->setParams(['people' => $people->cedula]);

$dispatcher->dispatch();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to separate test

$dispatcher->setActionName('multiple');
$dispatcher->setParams(['people' => $people->cedula, 'robots' => $robot->id]);

$dispatcher->dispatch();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to separate test

$dispatcher->setParams(['people' => $people->cedula]);

try {
$dispatcher->dispatch();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to separate test... Probably it should named like "testDispatcherInstanceException" also you can use something

$I->expectException()

method in this test

*
* @param IntegrationTester $I
*/
public function testMicroHandler(IntegrationTester $I)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public function testMicroHandlerAndModelBinder

anyway I think you can make the test name even more verbose and specific

$I->assertEquals([
'people' => 'Phalcon\\Test\\Models\\People',
], $this->cache->get('_PHMB_/{people}'));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this test can be split into few as well

*
* @param IntegrationTester $I
*/
public function testMicroController(IntegrationTester $I)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testMicroControllerAndModelBinder

$I->assertEquals([
'people' => 'Phalcon\\Test\\Models\\People',
], $this->cache->get('_PHMB_Test9Controller_viewAction'));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be split into few tests... each action section should make its test

$I->assertEquals([
'people' => 'Phalcon\\Test\\Models\\People'
], $this->cache->get('_PHMB_Test9Controller_viewAction'));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just the same: split it!

@Jurigag
Copy link
Contributor Author

Jurigag commented Oct 27, 2016

Yea on weekend i will try to refactor tests. Most of work is done but don't have time to finish it :)

@Jurigag
Copy link
Contributor Author

Jurigag commented Oct 29, 2016

@DavertMik @sergeyklay something like this tests now ?

Well need to clean $this->cache->flush() because im unnecessary calling it two times in some places.

@Jurigag Jurigag force-pushed the 3.1.x-binding branch 3 times, most recently from 634b121 to dc4807d Compare October 29, 2016 12:05
@@ -43,25 +47,48 @@ class LazyLoader
/**
* Initializes the internal handler, calling functions on it
*
* @todo move code to callMethod method in 4.0.0 and remove this method
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs: #12098

+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2016 Phalcon Team (https://phalconphp.com) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please fix indents?

/**
* Return the model name or models names and parameters keys associated with this class
*/
abstract function getModelName() -> string|array;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string | array

/**
* Gets cache instance
*/
public function setCache(<BackendInterface> cache) -> <Binder>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> <BinderInterface>

@Jurigag
Copy link
Contributor Author

Jurigag commented Nov 19, 2016

I removed this @todo comment and added comment in proper issue. I think it's ready to merge @sergeyklay

Those tests are fine now ? You meant something like this ? @DavertMik

@sergeyklay sergeyklay merged commit a4bfbc2 into phalcon:3.1.x Nov 19, 2016
@sergeyklay
Copy link
Contributor

Thanks

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.

4 participants