How to create a model object in yii2 by string name? - yii2

I need to create a model by string name that it is a variable.
function($modelName){
$modelName= "backend\\models\\".$modelName;
$modelClass = Yii::createObject([
'class' => $modelName,
]);
$model = $modelClass::find();
}
when I pass Book(it is extracted form DB) as modelName to function, it throws an error: Class backend\models\Book does not exist.
but when I write $modelName= "backend\\models\\Book"; it works fine.
I know it is because of run time and compile time. but I don't know how to solve it. because $modelName is Characterized at run time.

You are accessing to a static method using an object. You should access to the static method just using the class name eg:
$modelName = 'backend\models\\' . $modelName;
$model = $modelName::find();
And remember that $modelName::find() don't return a model but just the query object for a model. To obtain a model you should use eg: $modelName::find()->where(['id'=>$your_value])->one();

Related

laravel 5.5 model relation in json

I'm trying to understand, if in laravel 5.5 there is a method that given a model linked to another with an external key, I can obtain the result of the complete join of the attributes of both models. I wanto to avoid to return two models and merge them.
Below the code of my model:
class Event extends Model {
public function location(){
return $this->hasOne('App\Location');
}
}
In the controller I obtain the location information of the respective Event, but in the result I would like to see information of both Event and Location.
In the controller If I call the model with the ORM:
$event = Event::where('name',$name)->first()->location;
$model=$eventLocation->getModel();
return $model;
And obtain this json with
{"id":12,"created_at":null,"updated_at":null,"name":"location_test","event_id":"1"}
That contains only the attributes of the location and not for the Event! How can I show both?
thanks
Try with:
$event = Event::with('location')->where('name', $name)->first();
$location = $event->location;
In this way you will get the event itself and the complete related location as location field.
See the Eager Loading section on the docs.
Try this :
$event = Event::with('location')->where('name', $name)->first();
return $event->toJson();
You will have access to your event with data.location
You can use:
$event = Event::with('location')->where('name',$name)->first();
or:
$event = Event::where('name',$name)->first();
$event->load('location');
Then when you just return model or call $event->toJson() you will have your location relationship loaded.
If you want to get details about loading relationships you can look at laravel eager loading using with() vs load() after creating the parent model

Yii2 how can an model attribute is modified after load method? (like the afterFind method)

I have an attribute of the model which should be modified after it's loaded from the database.
I could extend the afterFind method, which could the convert the varchar value to a php array. So it works find.
But when the model is loaded I have no idea how to convert that varchar to the php array.
I have tried with rules but does not works:
[['languages'], 'each', 'rule' => ['string']],
or this one
[['languages'], 'safe'],
So this one works afterFind:
public function afterFind()
{
$this->languages = $this->convertToPHPArray($this->languages);
parent::afterFind();
}
By the way I have tried to extend the init or the __constructor method with this conversation, but no success, after load method the languages attribute is still a string instead of a php array.
If I understood your question, I think that you could use a property in the model:
public class Model {
public function getLanguagesArray()
{
return $this->convertToPHPArray($this->languages);
}
}
Then, use it:
$arr = $model->languagesArray;

serialize an entity that extends FOS user model

I have a user entity that extends the entity model of FOsUserBundle (FOS\UserBundle\Entity\User), as they recommend it.
Then I'd like to get all the users I have and pass them to twig as a json:
$em = $this->getDoctrine()->getManager();
$user_array = em->getRepository('MyBundle:user')->findByCustomer($customerID);
So I have an array which contains objects.
if I do:
json_encode($user_array);
or
json_encode($user_array[0]);
I get an empty string {}. I was at least expecting to get the array defined in the FOS User class
public function serialize()
{
return serialize(array(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id,
));
}
but it seems actually FOS doesn't implements Jsonserialize so it doesn't work.
When I change the FOS user class to implement Jsonserialize, it stops working (I can't connect anymore for example...).
Is there any way to get this work with FOS ?
All fields in the FriendsOfSymfony User entity are protected.
Which means you can simply reference them in the User class that is extending it just as you would a normal field.
This also means you can add another method in your own User class that will return an json encoded array containing all the values of the User.
Example of this would be:
public function json_encode()
{
return json_encode(array(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id,
));
}
You can't just simply json encode the whole array so the way to do it is:
$jsonEncodedUserArray = array();
foreach($user_array as $user) {
$jsonEncodedUser = $user->json_encode();
array_push($jsonEncodedUserArray, $jsonEncodedUser);
}

Propel toArray Mechanics in Doctrine?

I was using Propel for a long time and now I want to try Doctrine.
In My Propel days I used PropelObjectCollection::toArray (for a collection) or PropelObject::toArray() for a single record to convert the PropelObject via array to json.
In my company we override the toArray method to store virtual columns in the array and then the json string.
For example:
public function toArray() {
$arr = parent::toArray();
$arr['full_name'] = $this->getFullName(); // full_name isnt part of the table, it's just a getter
return $arr;
}
When I turn this into json i have my full_name property in my json and then in my Extjs store Object (we use extjs).
Now I wanna try doctrine, but doctrine doesn't seem to allow this.
Can i override a function or property in my doctrine class, or can I do this by annotations, is it possible to generate a json with propertys ('first_name', 'last_name', 'full_name') if my Doctrine class only has the properties $first_name, $last_name and no $full_name
or is there a work around to achieve the same?
Thanks for your help
Edit:
I found something in JMSSerializerBundle if you use Annotations:
#VirtualProperty
use JMS\Serializer\Annotation\VirtualProperty;
at the top of my Doctrine Entity File and an example method
/**
*
* #VirtualProperty
* #return string
*/
public function getFullName() {
return $this->getName(). " mylastname";
}
my json then contains the virtual property full_name

Doctrine 2 namespace issue

I'm using Zend Framework 1 with the Bisna library to integrate Doctrine 2. I generated my Entities from my database model with the Doctrine 2 CLI. This is all working fine, except for the setter methods for associated records. The argument they accept must be of a specific namespace (\Category here).
class Article
{
public function setCategory(\Category $category = null) {
$this->category = $category;
return $this;
}
}
However, when I do this:
$article = $this->em->getRepository('\Application\Entity\Article')->find(1);
$category = new \Application\Entity\Category();
$category->SetName('New Category');
$article->setCategory($category);
I get the following fatal error: Argument 1 passed to Application\Entity\CategoryField::setCategory() must be an instance of Category, instance of Application\Entity\Category given.
When I change the setter method to accept \Application\Entity\Category objects, it's working of course. Should I do this for every generated method, or are there other options? This is the first time I'm using namespaces, so it might be something simple.
You can always add this to the top of your class file: use \Application\Entity\Category; and then simply reference it later like so: public function setCategory(Category $category = null)
Check out: http://php.net/manual/en/language.namespaces.importing.php for more info about use
Otherwise you would have to reference the full namespace otherwise your application does not know that \Category is a reference to \Application\Entity\Category