PHPStorm generate phpdoc - phpstorm

I have method like this:
public function connect (Application $app)
{
$controller = $app['controllers_factory'];
$controller->get('/login', function () {
return 'test';
});
return $controller;
}
Everything works fine, but I would like to save $app in private field, like this
private $app;
public function connect (Application $app)
{
$this->app = $app;
$controller = $this->app['controllers_factory'];
$controller->get('/login', function () {
return 'test';
});
return $controller;
}
In this case PHPStrom throws error "method get not found in class". I tried phpdoc but it didn't work (As you see i use SILEX micro-framework)

The autocomplete gets stuck at this step, because it's unclear whats the value coming from array (even if it's an object that acts like an array).
$controller = $this->app['controllers_factory'];
There are two possibilities. First, if you have an array that consist of elements that share a single type, you can specify the type like this:
/**
* #var Application[]
*/
private $app;
An alternate method is to specify the type of a variable inline:
/** #var Application $controller */
$controller = $this->app['controllers_factory'];
Both options are supported by PHPStorm.

Related

How to add custom parameter to Doctrine Column type

I am trying to make a custom column type, but the SQL need to depend on a custom parameter.
Default types handle those parameters without issues eg. string type has length.
How can I add one for my type.
Example of what I am trying to do:
class EnumType extends Type
{
const ENUM = 'enum';
public function getName(): string
{
return self::ENUM;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
{
$class = $fieldDeclaration['class'];
if (!is_subclass_of($class, Enum::class)) {
throw new \Exception('You must specify a valid enum class');
}
$values = call_user_func([$class, 'getValues']);
return "ENUM('" . implode("', '", $values) . "')";
}
public function convertToPHPValue($value, AbstractPlatform $platform): ?Point
{
return $value;
}
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{
return $value;
}
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
}
}
So far I tried:
/**
* #var string
* #ORM\Column(type="enum", class="App\Enums\OrderStatus")
*/
protected $status;
/**
* #var string
* #ORM\Column(type="enum", options={"class":"App\Enums\OrderStatus"})
*/
protected $status;
First one did not work at all showing an error that class field is not defined.
Second one did work fine, but then it always tried to remake the column since it was not detecting class when loading definition from database.
Did you forget configure types in config/packages/doctrine.yaml ?
It must look like:
doctrine:
dbal:
types:
enum: 'App\Doctrine\Types\EnumType' #Change it to valid class
and in connection section add a mapping_types:
doctrine:
dbal:
connections:
default:
mapping_types:
enum: enum

Adding withCount to collection json

So i've got two models, Client and Project, and Client has a hasMany relationship with projects. I'm just trying to add the project count for the client into the JSON response but I can't get it to work.
My controller just returns all the projects;
public function index(Client $client)
{
return $client->all();
}
And my model contains the below;
protected $appends = ['client_projects_count'];
/**
* Create a relationship between this client and it's projects
*/
public function clientProjects() {
return $this->hasMany('App\Project');
}
public function getClientProjectsCountAttribute()
{
return $this->withCount('clientProjects');
}
This just adds client_projects_count to the response but it's an empty array. I'm close, if I dd($this->withCount('clientProjects')->get()) I can see the client_projects_count with the correct count, but if I remove the dd and keep the ->get() then I get an internal server error.
Also, it is possible to only load this for the index() method rather than every one?
From the Documentation
$clients = Client::withCount('projects')->get();
foreach ($clients as $client) {
echo $client->projects_count;
}
So I managed to resolve it myself, although I'm sure their must be a nicer way.
Client.php
protected $appends = ['client_projects_count'];
/**
* Create a relationship between this client and it's projects
*/
public function clientProjects() {
return $this->hasMany('App\Project');
}
public function clientProjectsCount()
{
return $this->clientProjects()->selectRaw('client_id, count(*) as aggregate')->groupBy('client_id')->get();
}
public function getClientProjectsCountAttribute()
{
return isset($this->clientProjectsCount()[0]) ? $this->clientProjectsCount()[0]->aggregate : 0;
}

Show usage of dynamic generated callable function name

Is there any posibility in PhpStorm to map usage of dynamic generated fucntion between it declaration an usage?
Assume I have next code:
<?php
class TestExample {
public function __construct($component) {
$component_parts = $this->get_dynamic_component_part_list($component);
$this->load_component_parts($component, $component_parts);
}
private function get_dynamic_component_part_list($component){
//Complex logic to get attached parts by $component
$component_parts = array('part1', 'part2');
return $component_parts;
}
private function load_component_parts(&$component, $component_parts) {
foreach ($component_parts as $component_part) {
$component[$component_part] = $this->{'load_' . $component_part}($component['id']);
}
}
private function load_part1($id) {
//Loading and prepare condition from one source
$part1 = new Part1($id);
// Complex algorithm
return $part1;
}
private function load_part2($id) {
//Loading and prepare condition from another source
$part2 = new Part2($id);
// Complex algorithm
return $part2;
}
}
class Part1 {
}
class Part2 {
}
I want to see usage of load_part1 and load_part2.
Is there any way to do it by usage phpDoc or in some other way?
At this moment PhpStorm notice me that this function doesn't have usage but realy it used in load_component_parts method.
You can use the phpDoc annotation #see.
For example:
$className = 'SomeClass';
$method = 'methodToCall';
$anArgument = 'bar';
/** #see SomeClass::someMethod() */
$foo = call_user_func([$className, $method], $anArgument);
This annotation will create at least a reference to this code, so that you know to come back here when you review SomeClass::someMethod() before throwing the "unused" method away.

How do you assign roles to users with the basic template in Yii2?

http://www.yiiframework.com/doc-2.0/guide-security-authorization.html#role-based-access-control-rbac
In the documentation, it says that you can assign the role to the user in the advanced template by using this code:
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false);
// the following three lines were added:
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
The problem is that I am using the basic template. Is there a way of doing this inside the basic template?
I thought about using the afterSave method; however, I am not sure how to do this.
public function afterSave($insert)
{
}
Any idea on how it can be done?
public function afterSave($insert)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->Id());
}
I am thinking this could work, but I am not totally sure.
It does not depend on used template.
Your example is correct, except few things.
$this->Id() should be replaced with $this->id (assuming primary key of users table is named id).
Note that you need also call parent implementation of afterSave() method and you missed $changedAttributes parameter:
/**
* #inheritdoc
*/
public function afterSave($insert, $changedAttributes)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->id);
parent::afterSave($insert, $changedAttributes);
}
For further improvements, you can wrap saving in transaction, so if something is failed in afterSave(), model is not saved (afterSave() event handler is executed after model is saved in database).
Also you can move assigning role logic to separate method.
Note that with this logic every registered user will have that role. You can wrap it with some condition, however it's better to assign role through admin interface.
You can see how it's implemented for example in this extension. For example you can create separate form, action and extend GridView ActionColumn with additional icon for assigning role.

How can I find out what argument was given to a mocked method?

If I write something like this:
verify().that( mockPromise.handleFault( any() ))
it works fine to tell me that 'handleFault' was invoked.
But later I want to invoke the fault handler function that was passed in. The handler will be a private function so there isn't another way to access it.
In Java Mockito, the feature you're looking for is called ArgumentCaptor. In short, it's a special kind of Matcher (like any()) that matches any type of object and keeps the object it "matches" in a variable.
Unfortunately, it looks like it's not available in Flex yet.
The good news is that if you feel like it, you can probably write an implementation of the Matcher interface that does exactly that--save its most recent value and return true--in fifteen minutes or so. :)
Good luck!
Based on Jeff's answer, I did this:
import org.mockito.api.Matcher;
class ArgumentCaptor implements Matcher
{
private var _value:*;
public function ArgumentCaptor()
{
}
public function get value():*
{
return _value;
}
public function describe():String
{
return "";
}
public function matches(value:*):Boolean
{
_value = value;
return true;
}
}
which can be used like:
var argCaptor:ArgumentCaptor = new ArgumentCaptor();
verify().that( mockPromise.handleFault( argThat(argCaptor) ));
argCaptor.value; // the argument