So, I'm setting up relationships with PhalconPHP and then trying to access those relationships from an object.
When I do:
Companies::find()[0]->companyTitles
it works fine. But when I add fields to it, it doesn't:
Companies::find(array('fields'=>'id,name'))[0]->companyTitles
// Gives: Undefined property: Phalcon\Mvc\Model\Row::$companyTitles
I know I'm getting back a partial object when I specify fields, but does that mean that I'm unable to use some of the "more advanced" features? (I am asking for the id). I'd just rather not have to pull back everything from the database if I don't need everything (performance and all...).
Is there a way to overcome this?
As you can see, the type of the returned object is \Phalcon\Mvc\Model\Row. When you limit the fields, the type of the returned object is not your model, and that means you don't have access to all the extra functionality on your model, and you can only use the properties to have access to the values you have previously noted.
TL;DR: No, you can't, because what you get is not an instance of Companies.
Related
I have a laravel Model with a one to many relationship which the user can edit via a multiple select tag.
Before exporting the model as a JSON, I use the "pluck" method to get an array of related IDs instead of an array of models, so that they can be used in the select tag and later be synced again with the "sync" method of Laravel.
However the result of "pluck()" seemingly doesn't persist over serialization. The following code doesn't work -upon serialization, "relationship" becomes again an array of objects-
$model->relationship = $model->relationship->pluck('id');
This one, however, does what it should: somePropertyIHaveJustCameUpWith is an array of IDs
$model->somePropertyIHaveJustCameUpWith = $model->relationship->pluck('id');
1) Why does this happen?
2) I have seen there is this resources way in the documentation, but creating an entire new class for something that could be solved with a single line of code feels like a bit overkill. Isn't there a cleaner way to do that?
I think this is likely a result of the way the model implements toArray().
The you can trace the steps taken, but eventually the relations are read from the $this->relations property on the Model, not from each individual relationship.
So, instead of setting the value of your relation directly like:
$model->relationship = $newValue
... you could try setting it using:
$model->setRelation('relationship',$newValue)
This will update the $model->relations property.
This should allow the toArray() method to get the new value that you set when serializing.
Note that the toJson() method in turn calls the toArray() method when serializing. So either approach will be the same result.
i want to load an entity in my Controller, but dont want that the entity contains all fields. I did that before with the Jms-Serializer, where you can use the Groups Annotations, to avoid loading special fields. But i there you have to serialize your object to json/xml etc.
And i dont want it serialized, i just want that groups function. I searched this site and the internet, but didnt found any solution for my problem.
Hope that someone understand what i mean and got an idea :)
There are a couple of possibilities:
Use partial objects (which will deliver objects where only specified attributes will be filled during hydration): http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/partial-objects.html#partial-objects
This is dangerous and you should be extra careful, because it looks like a fully loaded entity from all perspectives. You have to know why a field is null - just because it's null or because it simply hasn't been filled during hydration.
Don't hydrate objects but query for an array as hydration result (by that again you can specify which array keys you would like to get back): http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#array-hydration
Use this for performance-sensitive queries where you need a lot of read-only data and complex joins. But be aware that you don't have any entities you can manage with Doctrine (e.g. updating, deleting etc.).
Use DTOs which are objects but non-Doctrine-managed entities, there again you can specify what you would like to get hydrated with the NEW syntax: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#new-operator-syntax
Basically the same advise as in 2) but this time you'll get objects. So you can use all your OOP wisdom.
Create your own custom hydration mode - there you can define on your own how entities should be hydrated: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes
Very advanced level. Only useful if you need a special hydration mode for several entities and really no other option delivers at performance and quality as you require it.
You can use partial objects, but you should be careful. For example:
$q = $em->createQuery("select partial u.{id,name,otherField} from MyApp\Entity\User u");
You can read more here: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/partial-objects.html
I'm writing an API where I have a Controller that POSTs a new object, GETs it back and can PUT/PATCH updates to it. The problem is that there's a difference in properties between the two different actions. For example, when I POST a new object I want to ensure that the 'id' of it is returned so that it can be used to identify it for the GET/PUT/PATCH endpoints. It doesn't matter if it comes back via the GET (it's just a duplication of data at that point) but I certainly don't want it passed for the PUT or PATCH as the id is immutable.
So what's the best way to mark this up in swagger so that I can have different versions of the same Definition? I've seen that you can use 'allOf' to add Definitions to other properties, but I'm wondering if there's a way of saying 'not these properties in the definition'?
If I could do the latter I could make one Definition of the object as a whole and simply knock out the things that aren't required to be returned or submitted when referencing it at the Controller. Is this possible? Am I making sense?
(Just to make things more interesting, my swagger.json file is being generated by swagger-php based on Annotations in my controller and entity files)
I am facing the same issue while writing our spec file, and didn't know how to fix it but what I used is the property "readOnly":true, this way the documentation says that this is a readonly property, you can only read it through GET/POST methods but you cannot send it via PATCH/ PUT.. hope this helps
Using Doctrine, is it possible to map to properties which don't actually exist using magic methods?
I'm doing the mapping with YAML.
For example, if I wanted to map to a property named "demo", but SomeClass::$demo didn't actually exist. I'd want to some combination of __get(), __set(), __isset() and __call() to handle $demo (and getDemo() and setDemo()) and do something else with them.
I've tried setting this up, but I'm getting an error:
Uncaught exception 'ReflectionException' with message 'Property My\Bundle\DemoBundle\Entity\SomeClass::$demo does not exist'
I'm not sure if there is something special with the ReflectionProperty that causes it to miss my magic methods, or if I'm maybe missing a magic function. However, as far as I can tell, ReflectionProperty should interact with them.
Any ideas?
UPDATE:
Upon further investigation, it looks like the ReflectionProperty constructor will throw an exception and won't trigger the magic methods.
Does anyone else know of means to map Doctrine to dynamic properties?
Thanks.
UPDATE 2:
To example what I'm trying to accomplish.
Basically, I have a generic User object which just contains the base properties needed to handle actually being a user (roles, password, salt, username, etc.). However, I want to be able to extend this object to add application-and-user-specific meta data.
So, say I create a Forum bundle. I could then I could dynamically hook up meta data related to the user for use with the Forum. I don't want to put it directly in the User bundle, because then the User bundle becomes less flexible.
If I could somehow dynamically inject new data in to the user, it could all be loaded in a single query with the user, instead of having to be loaded in a separate query. I know there are some other methods to do this, which I've already explored and even used to a limited extend. However, it'd be much nicer if I could dynamically create these associations, which really shouldn't be that difficult of a leap.
If you don't need to search on these dynamic properties then just add a property called data to your entity and map it to a doctrine array type. Now do your majic stuff and store the dynamic properties in the data array.
A second approach might be along these lines: http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html. For each installation you might be able to give the administrators of making a custom entity.
But as long as you don't need to directly query on your dynamic properties then the first method works well.
I got an old PHP system integrated with a new CakePHP one. The problem is when displaying data I occasionally get index undefined errors meaning the models aren't related to where they're supposed to be maybe because there's no validation. There are gaps resulting into models loosing their relationship with a model I'm expecting hence te index undefined error.
What do you guys think is the best way to remedy this issue if let's say I can't touch the old PHP system?
You can use if (isset($post['Comment'])) style checks before using indexes that may or may not exist as well.
First, I think empty() is now preferred to isset() as empty checks for nulls, zeroes, and empty strings, as well as whether or not something is set.
Second, if your issue is relating the models then debug($this->model1->model2) is your best friend. It will show you if the models are properly related (It should state model2 object in bold if all is well, anything else and your relations aren't working.).
If you can't touch the old system, you can still make it work and look like cake by creating a cake model for it. Set the model to use no table, and build functions that will shape the resulting arrays and objects into cakephp arrays. Essentially, create a cake wrapper for the old functions. You can use the inflector class to help automate that a bit
You could potentially use the model's afterFind callback to massage your data into the correct form.