How to auto complete methods from Symfony 2 DI in netbeans - symfony

I am starting to develop with symfony 2 and it uses a lot dependency injection. I would like to know if is there any way that makes netbeans detect the type of object based on the string and auto complete with their methods?
For example, $this->container->get('doctrine') returns a Doctrine\Bundle\DoctrineBundle\Registry instance. In the container, the key doctrine corresponds to Doctrine\Bundle\DoctrineBundle\Registry.
Something like it, could be useful for zendframework 2 also.
I don't want to create new methods in the controller and nor use /* #var $var Symfony...*/, I would automatic detection.

As far as I know, there's no way for an IDE to detect the type of the object your container returns. My solution is to wrap those calls to the container into private getter functions. IMHO this improves code readability as well – especially, if you do this call more than once per class.
/**
* #return \Doctrine\Bundle\DoctrineBundle\Registry
*/
private function getDoctrine()
{
return $this->container->get('doctrine');
}

The IDE "PhpStorm" permits to suggest "use" declarations.
And this IDE propose specific features for Symfony2 and Drupal !
edited by JetBrains : http://www.jetbrains.com/phpstorm/
Not free but power full enough to reduce time developpement time (and time is money...)
Enjoy : )

phpStorm:
$foobar= $this->get('foobar'); //returns mixed
/* #var \MyNamespace\FooBar $foobar*/
or
$foobar= $this->get('foobar'); //returns mixed
/* #var FooBar $foobar*/
You can do this with eclipse PDT:
$foobar= $this->get('foobar'); //returns mixed
/* #var $foobar \MyNamespace\FooBar*/

( Walk around ) When comes to Symfony services:
Instead of
$doctrine = $this->container->get('doctrine');
use
$doctrine = $this->getDoctrine();
As you can see, Symfony allows you to access most of it services directly from $this variable. NetBeans will know what auto completion to use.
Lets have a look why this works (inside Controller class)
It is possible because Controller class imports Registry class with USE statement,
use Doctrine\Bundle\DoctrineBundle\Registry;
and then in method comment annotation it declares the returning object type with
/*
* #return Registry
*/
If you call $this->container->get('doctrine'); directly then auto completion will be get omitted and you will have to use whats below.
( Answer ) No magic auto completion works so far. Use Php Storm (it does what you request). For those who pick to stick with NetBeans you need to use manual annotation like in example below:
We can point NetBeans to a class it should be using for auto completion.
1) In terminal from project directory search for service you want to import:
php bin/console debug:container
If you know what you looking for use this instead:
php bin/console d:container | grep doctrine
...
doctrine --------------------------------------------------------
Doctrine\Bundle\DoctrineBundle\Registry
...
2) If this is not a service use get_class() PHP build in function to get class name of the object it particular variable. Or use reflection class. It's up to you.
3) Once you know the class name declare USE statement for better readability
use Doctrine\Bundle\DoctrineBundle\Registry;
4) Now wen we know what is the class name of the object instance in particular variable we are ready to inform NetBeans about what we know by using comment annotations so that it can enable auto completion.
/**
* #var $doctrine Registry
*/
$doctrine = $this->container->get('doctrine');
Now auto completion is enabled. Type
$doctrine->|
then press Ctrl+Space. See the image below:

Related

PhpStorm doesn't show autocomplete even after Ctrl+Space

I am learning to code with Symfony in symfonycasts.com and am using PhpStorm.
Doctrine\ORM\EntityManagerInterface service doesn't load getRepository()-> suggestions.
This is what I should see typing getRepository():
This is what I see:
Other autocomplete libraries seems to be working well.
Found one way to fix it : it's possible to hint IDE which class is that object can by using #var annotation above the variable, e.g.:
/** #var \App\Repository\QuestionRepository $repository */
$repository = $entityManager->getRepository(Question::class);
$repository-> // now you should have autocomplete here :)
Phpstorm seems to have issue with the EntityManagerInterface, when I use the specific type EntityManager instead of interface, the suggestions start working again.

Doctrine: Allow extending STI entities from within 3rd party code

Background
I've got an entity A with single table inheritance set up and class Foo extending it like so:
/**
* #ORM\Entity()
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap(
* "foo" = Foo
* )
*/
abstract class A
{
// ...
}
/**
* #ORM\Entity()
*/
class Foo extends A
{
// ...
}
This works with no problems. However, I need to be able to let 3rd party code extend A as well. Problem: I don't know the discriminator mappings that would be needed to wire this up beforehand as this is a property of the base class.
My current solution
I'm in Symfony land, so I can make use of the dependency injection container and decorate the annotation_reader* (that processes the discriminator map class annotations) with my own one.
This reader delegates most of the calls to the original one but can extend found discriminator map annotations. It does so based on an 'extension registry' which itself is filled by a compiler pass looking for a special service tag. Anyone wanting to extend the core entity A with Bar can now tag Bar with this service tag (that also includes the identifier for the mapping; the column type in this example).
*) this will probably also work within the loadClassMetadata event - which would be preferable instead of decorating the reader
/**
* #ORM\Entity()
* #DiscriminatorMapExtension("bar")
*/
class Bar extends A
{
// ...
}
(I'm using service annotations in the above example to be able to write the tags directly beneath the entity annotation. But how exactly the classes will be registered in the end doesn't matter right now. I'm more interested in the general concept.)
So if it's working, what's the problem?
I'd really love to hear some feedback from experienced Doctrine devs on this approach, especially:
Is there a better way to achieve a 'shared entity' across bundles?
Why could this pattern be a problem?
Thanks a lot in advance!

Using htmlpurifier with annotations in symfony 2.8

I would like to use the htmlpurifier not as a form data transformer, but rather as an annotation in the entities property.
The problem: In the Symfony 2.8 project we use a lot of different types of forms, some using symfonies formbuilder, some via sonata-admin, some using twig and ajax etc ..
So using a transformer and a custom field type is not the way to go.
Also, editing every single create or update action would be overkill.
I've been playing with the idea of an event listener on prePersist, but with such a large amount of different entities in our project we would most likely incur a performance hit if this were to be called on every persist() action. Limiting it to only specific object types would also be painstaking.
Is it possible to use the htmlpurifier bundle as an annotation only on the properties that matter?
eg:
/**
* #var string
*
* #ORM\Column(name="uprename", length=20, nullable=true)
* #htmlpurifier('default')
*/
private $firstName;
Where default would be the default configuration.
bundle: https://github.com/Exercise/HTMLPurifierBundle

Behat stopped generating regular expressions for method stubs

I've started working with Behat for behavioural testing.
I managed to set behat up for my Symfony2 project, started writing scenarios. I was happy with Behat giving me method stubs with regexp to fill in that'd correspond to the steps in my scenarios.
However, after a while, Behat stopped generating regular expressions and is giving me stub methods like this:
/**
* #Given I am on the page :arg1 <-- this is what I get
*/
public function iAmOnThePage($arg1)
{
throw new PendingException();
}
I'd rather have it work like befor, e.g.:
/**
* #Given /^I open "([^"]*)"$/ <--- I'd expect this
*/
public function iOpen($arg1, $sessionName=null)
{
$this->getSession($sessionName)->visit($arg1);
}
I must have messed somtehing up as I went, but have no idea why the default behaviour changes all of a sudden.
Any suggestions?
Did you update your version of Behat ?
In version 3 it's with the :arg and in v2.5 it's with the regex expressions.
If you like the old way of working you can follow the manual .
Implementing the SnippetAcceptingContext interface tells Behat that
your context is expecting snippets to be generated inside it. Behat
will generate simple pattern snippets for you, but if regular
expressions are your thing, Behat can generate them instead if you
implement Behat\Behat\Context\CustomSnippetAcceptingContext interface
instead and add getAcceptedSnippetType() method returning string
"regex":
public static function getAcceptedSnippetType()
{
return 'regex';
}

Doctrine lifecycleCallbacks strange behaviour

I have defined lifecycleCallbacks in yaml as follows:
lifecycleCallbacks:
prePersist: [setCreatedAtValue]
preUpdate: [setUpdatedAtValue]
The above has generated entities with the respective functions as follows:
/**
* #ORM\PrePersist
*/
public function setCreatedAtValue()
{
if($this->created_at == null)
{
$this->created_at = new \DateTime();
}
}
Which looks all fine, right? However, when I try to open the sonata admin page, I get the following error
[Semantical Error] The annotation "#ORM\PrePersist" in method AppBundle\Entity\Article::setCreatedAtValue() was never imported. Did you maybe forget to add a "use" statement for this annotation?
I have never encountered this before and a bit confused about what to do. I am using symfony 2.7.6, Doctrine ORM version 2.5.1, Sonata Admin 2.3.7
Any help will be greatly appreciated
Since you defined your callbacks using yaml, you don´t need to define them again using annotations. Just remove the comments with the #ORM\PrePersist block before the function and everything will be fine.
If you wanted to use annotations to define your doctrine properties, you would need to import them before you can use them. To do so you would need to add this line at the beginning of your file:
use Doctrine\ORM\Mapping as ORM;
Same issue came with me.
In my case everything worked well until I did not Serialize my object in JsonResponse.
So problem was that previously I was not using that entity class (which was giving error) for sending JsonResponse, as soon as I tried to prepare JsonResponse containing that class, JsonResponse failed to serialize my class as it hadn't implemented Serializable interface.
This will happen if you will fetch objects with methods like findAll or findBy which returns Entity objects instead of php array.
So I just skipped those native methods and write doctrine query for fetching data.
You can also implement Serializable interface.

Resources