in my Symfony2.8 app I got the following controller:
public function changetariffAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $this->container->get('security.context')->getToken()->getUser();
$userid = $user->getId();
$tariff = $user->getTariff();//tariff1 here
$paymentForm = $this->createPaymentForm($user);
$paymentForm->handleRequest($request);
if($tariff != 'tariff2') {
$query = $em->createQuery('UPDATE My\UserBundle\Entity\User u SET u.tariff = :tariff2 WHERE u.id = :userid');
$query->setParameter('userid', $user->getId());
$query->setParameter('tariff2', 'tariff2');
$query = $query->getResult();//returns 1 here, tariff field in DB is set to tariff2 as expected
$query = $em->createQuery('SELECT u FROM My\UserBundle\Entity\User u WHERE u.id = :userid');//getting once again user entity but it did not change
$query->setParameter('userid', $user->getId());
$user = $query->getResult();
$tariff_upd = $user[0]->getTariff();//tariff1 here but I need tariff2!
//Also I tried to persist and flush user entity here but it did not work
return $this->render('MyBundle:Pages:tariffchangesuccess.html.twig', array(
'user' => $user,
'form' => $paymentForm->createView(),
'tariff' => $tariff_upd //still tariff1 but I need tariff2
));
}
return $this->render('MyBundle:Pages:tariffchangesuccess.html.twig', array(
'user' => $user,
'form' => $paymentForm->createView(),
'tariff' => $tariff
));
}
My Controller works ok and all the values are updated in my DB as expected but new values (tariff2) are not rendered in my twig template. New values are rendered only when I update the page in my browser (hit F5), but this is not an expected behavior. Any ideas how to fix that? Thank you.
Doctrine use something similar as cache and maybe your use of queries instead of natives methods short-circuit this system. Docrtine can handle your entities and know what to record and has been changed etc. But you have to use Doctrine functions or repositories for that, and not do it througt custom queries... The Doctrine way should be something like:
$em = $this->getDoctrine()->getManager();
$userid = $this->container->get('security.context')->getToken()->getUser()->getId()
// Get object user from DB values
$user = $em->getRepository('My\UserBundle:User')->findOneById($userid );
// Update tarif in the user object
$user->setTariff('tariff2');
// Let Doctrine write in the DB. The persist() may not be necesary as Doctrine already manage this object, but it's a good practise.
$em->persist($user);
$em-> flush();
// Doctrine should already have update the $user object, but if you really really want to be sure, you can reload it:
$user = $em->getRepository('My\UserBundle:User')->findOneById($userid );
You can use the refresh method of the EntityManager in order to:
Refreshes the persistent state of an entity from the database,
overriding any local changes that have not yet been persisted.
So add the refresh call, as example:
$query = $em->createQuery('SELECT u FROM My\UserBundle\Entity\User u WHERE u.id = :userid');//getting once again user entity but it did not change
$query->setParameter('userid', $user->getId());
$user = $query->getResult();
// Force refresh of the object:
$em->refresh($user);
$tariff_upd = $user[0]->getTariff();//tariff1 here but I need tariff2!
Hope this help
Related
I'm trying save user IP adress after login on website. I'm using laravel 5.2 framework. I got user table and login_ip row. My code looks like that:
$user = User::where('login_ip', Request::getClientIp());
$user->save();
But it does not saving. What i'm doing wrong? Sorry for my bad english :)
If you want to save IP for current user, you can do this:
auth()->user()->update(['login_ip' => Request::getClientIp()]);
This will not create additional query as code in shoieb0101, Amit and Ronald answers.
Don't forget to add login_ip to the $fillable array in User model:
protected $fillable = ['login_ip'];
If you want to save IP for only logged in users and ignore guests, you can do a check:
!auth()->check() ? : auth()->user()->update(['login_ip' => Request::getClientIp()]);
Try
$user = User::find(auth()->user()->id);
$user->login_ip = Request::getClientIp();
$user->save();
//assuming $userid is also requested
$user = User::where('id', $userid);
$user->login_ip = Request::getClientIp();
$user->save();
You can try it as:
auth()->user()->login_ip = Request::getClientIp();
auth()->user()->save();
OR
auth()->user()->save(['login_ip' => Request::getClientIp()]);
Note - It will update the user's login_ip in single query.
You dont have to get logged user form db, all info about your user you have in Auth::user() so:
Auth::user()->login_ip = Request::getClientIp();
Auth::user()->save();
or
Auth::user()->login_ip = $request->ip();
Auth::user()->save();
but you need to have Request $request as parameter of your method.
I am probably stating the obvious, but your first line...
$user = User::where('login_ip', Request::getClientIp());
... returns an Eloquent query builder, right?
So, a save() on this will never work?
$user = User::where('login_ip', Request::getClientIp())->first();
... will return an actual User (if in the DB), which makes save() also possible.
Or did you make a typo in your OP?
I have a problem with phalcon model magic getter and setter.
I want to update like this tutorial :
https://docs.phalconphp.com/en/latest/reference/models.html#storing-related-records
But the thing is my proj is multi module and separated models folder.
So I have to use alias for hasOne and belongsTo
$this->hasOne('user_id', '\Models\UserProfile', 'user_id', array('alias' => 'UserProfile'));
and
$this->belongsTo('user_id', '\Models\CoreUser', 'user_id', array('alias' => 'CoreUser'));
What i want to do is like this.
$CoreUser = new CoreUser();
$user = $CoreUser->findFirst(array(
//...condition here to find the row i want to update
));
$user->assign($newUserData);
$user->setUserProfile($newProfileData);
$user->update();
But above this code only save user data and don't save Profile data at all. (have profile data -- confirmed)
So do you have any idea what the error is? if u know, Please help me or give me a tip.
I got it now.. when assigning like $user->UserProfile = $newUserProfile;
$newUserProfile should b a Model Object.
So my new code is
$CoreUser = new CoreUser();
$user = $CoreUser->findFirst(array(
//...condition here to find the row i want to update
));
$profile = $user->UserProfile; //$profile is now model object which related to $user
//assign new array data
$profile->assign($newProfileData);
$user->assign($newUserData);
/*
* can also assign one by one like
* $user->first_name = $newProfileData['first_name'];
* but cannot be like $profile = $newProfileData or $user->UserProfile = $newProfile
* since it's gonna override it the model with array
*/
$user->UserProfile = $profile;
$user->update(); // it's working now
Thanks to #Timothy for the tips too .. :)
Instead of doing
$profile = $user->UserProfile;
You should instantiate a new UserProfile object
// find your existing user and assign updated data
$user = CoreUser::findFirst(array('your-conditions'));
$user->assign($newUserData);
// instantiate a new profile and assign its data
$profile = new UserProfile();
$profile->assign($newProfileData);
// assign profile object to your user
$user->UserProfile = $profile;
// update and create your two objects
$user->save();
Note that this will always create a new UserProfile. If you want to use the same code to update and create a UserProfile, you can maybe do something like:
// ...
// instantiate a (new) profile and assign its data
$profile = UserProfile::findFirstByUserId($user->getUserId());
if (!$profile) {
$profile = new UserProfile();
}
$profile->assign($newProfileData);
// ...
I am writing a Symfony3 appusing Doctrine ORM.
SO what i am trying to do is to find if a given email address exists in a table (every email is unique). so i have a user repository with some attributes I can easily persist data to the db but failing to retrive data.
/**
* #param $email
*/
public function findUserByEmail($email)
{
$user = $this->getDoctrine()
->getRepository('TestBundle:TestUser')
->find($email);
if (!$user) {
echo 'Error';die();
}
}
I know the var passed to the function contains a email string, but what i get in return is error and when i var_dump $user before the if statment i get null.
I followed the Symfony docs
Your User probably has a separate primary key field. the find() method on a repo only retrieves by primary key.
Repositories use __call to dynamically process findBy* and findOneBy* methods, so you could call it like this:
$repo = $this->getDoctrine()->getRepository('TestBundle:TestUser');
// magic find method
$user = $repo->findOneByEmail($email);
// explicit find method
$user = $repo->findOneBy(['email' => $email]);
// custom QueryBuilder
$user = $repo->createQueryBuilder('user')
->where('user.email = :email')
->setParameter('email', $email)
->getQuery()
->getSingleResult();
BTW: If you are validating this for a submitted form, there is a contraint that does this check for you: UniqueEntity
I think the problem is because you forgot to call getManager().
So the code would be:
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestBundle:TestUser')->findOneBy(['email' => $email]);
Hope it would help you!
I have self-referencing one-to-many relationship (I did it in accordance with Documentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-self-referencing )
Now I want flush new element to Entity, but how can I use ID of new flush element to put it in referencing place?
I try with:
$newProject->setSubprojectId($newProject);
and with:
$newProject->setSubprojectId($newProject->getId());
but I think that it's impossible to get ID of object before flush it. I'm right?
My code looks like:
/**
* #Route("/project/manage", name="project_edit");
*/
public function registerAction(Request $request)
{
$user = $this->get('security.token_storage')->getToken()->getUser();
$newProject = new Project();
$newProject->setIsActive(1);
$newProject->setOwner($user);
$newProject->setCreateDate( new \DateTime() );
$newProject->setSubprojectId($newProject);
$formProject = $this->createForm(AddProject::class, $newProject);
$formProject->handleRequest($request);
if($formProject->isSubmitted() && $formProject->isValid()){
$em = $this->getDoctrine()->getManager();
$em->persist($newProject);
$em->flush();
return $this->render('xxx/projectEdit.html.twig', array(
'form' => $formProject->createView(),
));
}
return $this->render('xxx/projectEdit.html.twig', array(
'form' => $formProject->createView(),
));
}
EDIT
I found different solutions but the question remains valid - it's possible to get this id before flush or to flush id for two columns in the same time?
You could try setting cascade persist, however why not just do:
$em = $this->getDoctrine()->getManager();
$em->persist($newProject);
$em->flush();
$newProject->setSubProject($newProject); // *why* do you want to do this?
$em->persist($newProject);
$em->flush();
You shouldn't need to mess about with setting ids directly. You should be able to accomplish this by using the setter on your object and doctrine should take care of the ids for you.
In Doctrine2 using some thing like:
$user = array('username' => 'example', 'passsword' => 'changeme');
$conn->insert('users', $user);
How would I then get the last ID of the user I just inserted? If it is not possible to do this then how do you gen a id so that you can the following:
$id = //something here.
$user = array('username' => 'example', 'passsword' => 'changeme', 'id' => $id);
$conn->insert('users', $user);
If you are using the ORM
$em->persist($object);
$em->flush();
$object->getId();
if you are using the DBAL:
$conn->lastInsertId();
http://www.doctrine-project.org/api/dbal/2.5/class-Doctrine.DBAL.Connection.html#_lastInsertId
One can use the Doctrine\DBAL\Connection::lastInsertId() method.
It can be used with native queries as well as manually written inserts.
Example case:
$query = 'INSERT INTO blabla...';
$connection->executeUpdate($query, $params);
var_dump($connection->lastInsertId());
If using the ORM, you can obtain an instance of the connection from the entity manager:
$connection = $em->getConnection();
Note:
Aside from the technical details, I agree with #Layke for using an entity for your specific case.
$conn->lastInsertId();will get you the last inserted ID when only using Doctrine's DBAL (sans ORM).
Providing that your Entity which are you are trying to set has
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
Then when you persist your object, the entity manager will populate the Entity which you are trying to persist with the ID.
Some caveats however, is that you can't do this with composite keys post obviously, and you obviously have to flush all Entities. So if you detach an Entity which has an association to the persisted entity that you are trying to get the ID for, then you won't be able to retrieve the ID.
Aside from that Flask's answer is bang on.
$em->persist($object);
$em->flush();
$object->getId();