Symfony, getters and setters vs magic methods - php

I don't like having "stupid" getters and setters for every property on my entity classes so I am thinking on using magic methods to get/set those properties instead of creating every single getter and setter. The idea is to create an specific getter or setter when its logic is diffefent from the typical "return $name" or "$this->name=$name". Moreover this magic method would be created on a different class and every entity would extend it (I have not thought very much about this step)
Anyway, what do you think about replacing getters/setters with magic methods?? Would it penalize too much the performance? Any other problems that I am not taking into account?

The problem with that is that e.g. the default template engine of symfony2 twig needs these methods. Twig translates the statement {{ object.property }} to $object->getProperty() so instead of using the very nice dot notation you would have to call properties in twig like this: {{ object.__get("property") }}.
I know that doctrine also uses magic methods in it's entity manager. So when you make a repository query for an object you can use:
$repository->findOneByProperty($value);
instead of
$repository->findOneBy(array(
'property' => $value
));
I would highly suggest that you do not use magic methods but instead use a get and set method for each property separately. This will also give you higher control about the state of that property.
Also be sure to checkout this Answer. It pretty much answers your question aswell.

If you are referring to Doctrine Entity and you have nothing against code generation, you can use the doctrine:generate:entities command, eg.:
$ php app/console doctrine:generate:entities Acme/StoreBundle/Entity/Product
as explained in the documentation.
Therefore you would only need to specify the fields.

Code completion in IDE will not work in this case.
Also you will be not able to make type hinting for object and arrays, and also not with the doc block.
Performance will be slower but depending your project (server hardware and count of useres) you will probably don't see any differences

Related

How to configure PHPStan to avoid false positives caused by specific classes and/or magic methods?

While using PHP RedBean on a project, PHPStan reports problems like this one:
87 Access to an undefined property RedBeanPHP\OODBBean::$token.
This is happening because RedBean's OODBBean class uses magic methods to logically bind class attributes with database table columns. AFAIK, there is nothing wrong with the way RedBean is implementing that feature.
Is there a way to configure PHPStan to ignore problems from RedBean (or any other class)? Or to ignore what might be being caused by magic methods?
You have several options depending on what you exactly need. For magic properties:
If your class can dynamically contain any property, similarly to stdClass, you can put the class name into universalObjectCratesClasses config parameter. See README.
If your class always contains the same magic properties, you can define them by adding #property annotations above the class.
You can create a so-called class reflection extension that describes what your __get and __set method logic for the static analyser. This is a robust way to define what exact properties will exist on an object in every situation. This makes PHPStan very powerful by avoiding false negatives - it will still report accessed properties that are not defined even in a magic way. See README for more details.
For magic methods, the same thing in 3. applies - you can write an extension that describes logic in __call for the static analyser. See README for more details.

Symfony: Using global variables

I know... stay away from globals.
The thing is I really, really, need to have a value that is accessible and, most important modifiable from different parts of the application. It's a counter for some actions that I need to watch for debug purposes. Googling for anything related to Symfony and globals, always got me to results that suggests using the Container parameters or Twig globals, but the thing is that according to Symfony documentation:
You can only set a parameter before the container is compiled: not at run-time.
The Twig globals are pretty much out of scope given that I need them in controller, not in view.
IMHO, both of these solutions are more like constants than variables.
So, the question is: Is there a best practice to obtain what I need using Symfony or should I just use the PHP globals?
Thank you!
Create a service (e.g: ApplicationGlobals) with a private property $counter and public setter and getter to read and write the value. A service class will be instantiated automatically and can be reached from everywhere where you can use the container (get it in the controller or pass it as an argument to other services).
Latter you will be able to add multiple variables, when needed, with their proper getters and setters and use them in your project.
I think you could even write a destructor that stores the new value when Symfony terminates. http://symfony.com/doc/current/service_container.html#creating-configuring-services-in-the-container
Why not use the parameters section in services.yaml ?
It seems that you can also define/modify variables programmatically :
$container->parameters()->set('app.admin_email', 'something#example.com');
https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
https://symfony.com/doc/current/configuration.html#configuration-parameters

symfony form with only getter methods in entity

i want to create a forms with only getter methods in the entity... Since I am working on already existing database which does not require to store or manipulate the data.
Hence I have created Entities for the products with only Getter methods and no Setter method.
However when i create form( like search query with some dropdowns etc) it always looking for set or Add methods. Is there a possibility if i can only use getters to get the data from the database.
And I do not want data to be modified at anytime in the future.
i tried with "read_only" but it still gives an error about setter and addMethod()
http://symfony.com/doc/current/reference/forms/types/form.html#read-only
EDIT:
I want to create a drop down ProductGroupcategory-> productSubcategory -> Product
like this(advance search): http://www.buycarspares.co.uk/
Complete Code:
https://gist.github.com/anonymous/8b2e576e69b1588e4f21
Relationships require add- and get-methods simply because it is about an array or arrayCollection of an object and not about the getters or setters for normal entity properties like strings.
Yes you can though some people might consider the solution to be worse than the problem. You could of course just declare your entity properties to be public. That would avoid not only setters but getters as well. Doctrine 2's lazy loading functionality would not work.
A more advanced approach it to realize that the form component uses a property access object to transfer data to and from your entity. That is where the 'add' and 'set' messages are coming from. Property access objects are also what allows you to use arrays as well as entities. http://symfony.com/doc/current/components/property_access/introduction.html
The form component allows you to plug in your own property access object which means that you can create your own access object which can write directly to private/protected variables using Reflection. This, by the way, is the same technique that Doctrine 2 uses to hydrate your entities using database information.
Of course I can already hear howls of protest of this approach mostly about violating encapsulation. But think about it for a moment before down voting. The form component really is just persisting and retrieving the state of an entity to and from an html document. Exactly what Doctrine 2 does. As long as you don't misuse the technique then there is no violation.
I routinely use this approach to avoid writing endless getters and setters. Seems to work fine in practice.

Is it good to use magic find methods from Doctrine EntityRepository?

I'm asking in context of symfony framework.
I am wondering if this is a good practice to use magic find methods (like find($id), findByField($value) etc...).
Those methods neither has return type nor are defined at all. This leads my IDE to mark warnings around them. Also I have to mark type of returned value all the time I use those methods, to make code completion working on those variables.
As a solution I am usually writing getters inside custom repository classes. In symfony docs there is example of such getter, that overload an variant of magic findBy method.
I have a bad feelings about such overloading magic find methods too, because it kind of mixes my own repo implementation with the parent EntityRepository one.
So I end up with writing custom getters that uses "get" prefix instead of "find".
Now, can someone tell me whats the best practice and why ?
EDIT
Recently i was looking for some ways to optimize doctrine, and I have found advise not to use magic finders, so its another argument against magic finders.
I have also read doctrine docs about magic finders and found that:
http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/dql-doctrine-query-language.html#magic-finders
These are very limited magic finders and it is always recommended to expand your queries to be manually written DQL queries. These methods are meant for only quickly accessing single records, no relationships, and are good for prototyping code quickly.
So I have finally worked out my own opinion (and use case) for magic finders. Use them only for speed up coding, and always mark them with TODO, to rewrite them into custom repository methods while cleaning up code.
In my opinion it's a bad practise too. I would suggest you to use findBy([]) and findOneBy([]) methods. I believe when I started learning symfony I had a case when magic methods didn't work at all because properties of my entity was named using underscores.

Confused About Objects and Classes in CodeIgniter?

I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?

Categories