Getting the last User ID in Zend Framework - mysql

Using MySQL query browser, I manually made a table called users and input some date in the fields. I set the primary key to id and set it to auto increment. There are 3 rows, the highest id is 3.
I then made the following class in the method directory to call upon the data in the table etc.
class Application_Model_DbTable_User extends Zend_Db_Table_Abstract
{
protected $_name = 'user';
public function getLatestUserId()
{
$id = $this->getAdapter()->lastInsertId();
return $id;
}
}
In the controller I do the following which gets the value generated by the method and lets the view access it:
$usersDbModel = new Application_Model_DbTable_User();
$lastUserId = $usersDbModel->getLatestUserId();
$this->view->lastUserId = $lastUserId;
In the view I then echo it to display it to the user:
echo $this->lastUserId;
However, even though my last id in the users table is 3. It displays 0.
I have also tried:
public function getLatestUserId()
{
$sql = 'SELECT max(id) FROM user';
$query = $this->query($sql);
$result = $query->fetchAll();
return $result;
}
But this just throws out a server error.
What have I done wrong?
Am I missing something?
Is there another way of doing this?

The answer was:
$sql = 'SELECT max(id) FROM user';
$query = $this->getAdapter()->query($sql);
$result = $query->fetchAll();
return $result[0]['max(id)'];

If you queried like "SELECT id FROM USERS SORT BY id DESC LIMIT 0,1"
You would get nothing but the id of the newest user, no?

if you use a select statement like
SELECT max(id) FROM USERS;
If you haven't tried having a function in the controller try something like this.
class IndexController extends Zend_Controller_Action {
public function init() {
}
public function indexAction() {
}
public function getLatestUserId()
{
$bootstrap = $this->getInvokeArg('bootstrap');
$resource = $bootstrap->getPluginResource('db');
$db = $resource->getDbAdapter();
$sqlrequest = "select max(id) as Idmax from user";
$rows = $db->fetchAll($sqlrequest);
foreach ($rows as $row)
echo $maxId = $row['Idmax'];
return $maxId;
}
}
and your bootstrap file would look something like
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
return $config;
}
}
Hopefully something like that works, hope it helped

The problem is that Mysql doesn't really support lastInsertId() it will in some cases return the last id of an auto incrementing primary key.
Several solutions have been presented here and most will return the last id of the primary key, which may or may not be what you really need.
This method will also do the same using the select() object.
public function getlastInsertId(){
$select = $this->select();
$select->from($this->_name, "id");
$select->order('id DESC');
$select->limit(0, 1);
$result = $this->fetchAll($select)->current();
return $result->id;
}
I think that over time you may find these kinds of methods unreliable if what you're really after is the last id you inserted. Over time as records are added and deleted the database may or may not fill in vacant id's depending on which database you are currently using and how that database is set up.
In most cases we need the id of the last item inserted very soon after inserting it, usually to update a view script. In this instance I usually just make the whole row object part of the return.
Here is an example of what I mean:
/**this method will save or update a record depending on data present in the array*/
public function saveUser(array $data) {
/**cast data array as std object for convience*/
$dataObject = (object) $data;
/**if id exists as array and has a non null value*/
if (array_key_exists('id', $data) && isset($data['id'])) {
/**find row if updating*/
$row = $this->find($dataObject->id)->current();
} else {
/**create new row*/
$row = $this->createRow();
}
$row->first_name = $dataObject->first_name;
$row->last_name = $dataObject->last_name;
$row->email = $dataObject->email;
/**save or update row*/
$row->save();
/**return the $row you just built or you can return $result = $row->save(); and get*/
/** just the primary key. Save() will throw an exception if table is marked read only*/
return $row;
}

Related

Laravel Model get next increment ID when the Table linked with Model is Non-AutoIncrement

As I mentioned in Question, the current Laravel 6.0 project I am working on has bit weird DB setup, where the Model's(the MainModel here) MySQL table has been set with AutoIncrement as NULL. And client won't allow to change the Table's definition at all.
I want to reliably find the next and previous IDs of the Model(since I can't find from table as AutoIncrement is set to NULL) before inserting record, so that I can make an entry of relevant record(for eg. image(s) of a testimonial/faq or any WYSIWYG content field) into another referential table first, by correctly inserting the main Model's ID into the refrential ID field of that another table.
Currently I have this in my main Model, but the next method doesn't reliably return the exact incremented ID consistently:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Te7aHoudini\LaravelTrix\Traits\HasTrixRichText;
class [MainModel] extends Model
{
use HasTrixRichText;
protected $guarded = [];
public $timestamps = false;
protected $primaryKey = 'id';
protected $connection = '[connection1]';
protected $table = '[main_table]';
protected $fillable = ['id', '[titlefield]', '[wysiwyg_field]'];
/**
* Setup model event hooks
*/
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->id = $model->max('id') + 1;
});
}
/**
* Get next available Faq Id
*/
public function next()
{
return ++$this->id;
}
}
Any help is appreciated...
As I understand you are confused about how to call statically model queries. You can achieve the same logic by using a static self-reference static.
public static function next()
{
return static::max('id') + 1;
}
This would be equivalent to.
MainModel::max('id');
Bonus to make it a transaction to avoid id clashing. This can lock the database in fun ways, but will avoid you have the same ids, something similar to this, very simple example.
DB::transaction(function () {
$id= MainModel::next();
$newModel = MainModel::create(['id' => $id]);
});
As I understanding, in order to get the next increment id, you need to call the following line.
Model::lastest()->first()

How to exchange values between 2 records at unique column

How to exchange the values in the Unique column of two records?
like below Model
User
id
name
code // this is unique
What I want to do is like...
$user1 = User::find(1);
$user2 = User::find(2);
DB::Transaction();
try {
$user1->code = $user2->code;
$user2->code = $user1->code;
$user1->save();
$user2->save();
} catch()...
of course, I know this code doesn't work by constraint violation error.
Anyway,I want to exchange UserA's code and UserB's code.
But I don't know the best way.
Any one knows?
I tried this code,and it worked.but it seems little dirty.
$user1 = User::find(1);
$user2 = User::find(2);
DB::Transaction();
try {
$user1_code_temp = $user1->code;
$user2_code_temp = $user2->code;
$user1->code = rand();
$user1->save();
$user2->code = $user1_code_temp;
$user2->save();
$user1->code = $user2_code_temp
$user1->save();
} catch()...
What you are doing is correct. And I personally would prefer it being this way as it is more readable what you are doing. You could disable unique checks in mysql temporarily but I would not recommend that.
To clean up the code, you can add this as a method in users model :
<?php
// Inside User.php model
/**
* Exchange user code
*
* #param User $user
*
* #return void
*/
public function exchangeCode(User $user){
$code1 = $this->code;
$code2 = $user->code;
$this->setCode(rand(6));
$user->setCode($code1);
$this->setCode($code2);
return $this;
}
/**
* Set Code
*
* #param string $code
*
* #return void
*/
public function setCode($code)
{
$this->code = $code;
$this->save();
return $this;
}
// And then in controller
$user1->exchangeCode($user2);
On your model define a
protected $primaryKey = 'code';

Doctrine - delete all entities

I have problem with deleting all rows in database. I can't find out how to do it. I'm using Symfony and Doctrine. Somewhere I read, that it isn't possible "normal" way, but I can do it by DQL (createQuery), but I don't know syntax.
public function resetDatabase(EntityManagerInterface $em)
{
$query = $em->createQuery('DELETE ???');
$query->execute();
return new Response('', Response::HTTP_OK);
}
public function resetDatabase(EntityManagerInterface $em)
{
$query = $em->createQuery(
'DELETE FROM App\Entity\YourEntity e WHERE e.age > :ageparameter'
)->setParameter('ageparameter', 10)->execute();
return new Response('', Response::HTTP_OK);
}
Ou... I have find out, how to do it.
/**
* #Route("/resetdatabase")
*/
public function resetDatabase(EntityManagerInterface $em)
{
$repository = $em->getRepository(MoneyDatabase::class);
$entities = $repository->findAll();
foreach ($entities as $entity) {
$em->remove($entity);
}
$em->flush();
return new Response('', Response::HTTP_OK);
}
But sometimes it must run twice, because somehow after 30 seconds entities return (but there are only compulsory columns, others are null). And after second run it disappear completely. It's strange, that it does only sometimes. Why it does at all?

Laravel - Update dynamic form fields in database

I have a dynamic form where the user should be able to add or remove fields while editing.
I am able to update the exact number fields that are in the database table. But what I want is if a user clicked a 'Delete Subject' and 'Update' buttons, I want that entire row deleted from the database.
And, if he added a subject by clicking 'Add another Subject' the form and clicked 'Update' I want those subjects added. What am I missing here?
Note: I built a One-to-Many relation between New and Subjects, where a New has many subjects and many subjects belong to a New (It works fine).
My form looks like this
New Model
protected $fillable = ['name', 'address'];
public function subjects() {
return $this->hasMany(Subjects::class, 'new_id');
}
Subjects Model
protected $fillable = ['new_id', 'sub_code', 'sub_name', 'sub_img'];
public function subs(){
return $this->belongsTo(New::class, 'new_id');
}
Create Method
public function create(Request $request, New $new){
$new = New::FindorFail($id)
$subjects= [];
$sub_images = $request->file('sub_img');
$sub_name = $request->sub_name;
for ($i=0; $i < count(request('sub_code')); ++$i)
{
$subjects = new Subjects;
$subjecs->sub_code = request('sub_code')[$i];
$subjects->sub_name = request('sub_name')[$i];
$sub_img_name = uniqid() . '.' . $sub_images[$i]->getClientOriginalExtension();
$sub_images[$i]->move(public_path('/images/'), $sub_img_name);
$subjects->sub_img = '/images/'.$sub_img_name;
$new->subjects()->save($subjects);
}
}
Update Method
public function update(Request $request, $id){
$new=New::FindOrFail($id)
$subjects = Subjects::with(['subs'])->where('new_id', $new->id)->get();
$new->update($request->all());
$i=0;
foreach( $subjects as $new_subjects)
{
$sub_images =request()->file('sub_img');
$sub_name = request('sub_name');
if(isset($sub_images[$i]))
{
$pathToStore = public_path('images');
if($request->hasFile('sub_img') && isset($sub_images[$i]))
{
$sub_img_name = uniqid() . '.' . $sub_images[$i]->getClientOriginalExtension();
$sub_images[$i]->move(public_path('/images/'), $sub_img_name);
$new_subjects->sub_img = '/images/'.$sub_img_name;
$new_subjects->sub_code = request('sub_code')[$i];
$new_subjects->sub_name = request('sub_name')[$i];
$new_subjects->sub_img = "images/{$sub_img_name}";
$i++;
$new->subjects()->save($new_subjects);
}
}
}
}
Subjects Database
I want this table row be updated (added or deleted) after user edit the form.
From my experience with Laravel, I think the problem is that you call the Product model instead of the New model so maybe you need to fix it.
you reference the New model :
public function subs(){
enter code herereturn $this->belongsTo(New::class, 'new_id');
}
then you use the wrong model Product :
$new=Product::FinOrFail($id)
Another thing is to double check the fillable attribute within the Subject model also you can write the update action and do something like

Yii2 pass query result to a action in another controller

I'm trying to insert record into my audit table upon update of record in any other table. For example, if a user update his profile I want to store the old record and the newly updated record in my audit table. For this in my user model I'm trying to use beforeSave() and pass the value to my audit controller
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Yii::$app->runAction('audit-trial/createaudit', ['query' => $query]);
return true;
}
}
And the action code in audit controller for now
public function actionCreateaudit($query)
{
$model = new Audit();
$model->old = '';
foreach($query as $name => $value){
//$temp = $name .': '. $value.', ';
//$contentBefore[] = $temp;
$audit->old = $audit->old.$name .': '. $value. ', ';
}
// I've not yet any other code for now I'm trying to get the old value
$model->save();
}
I'm getting 404 not found error. What do I need to change in my code to make it work? Thank you!
instead of runAction() . If you want to perform operation on another model, prefer to create a static function in that model (in your case Audit model) to save the data
public function beforeSave($insert)
{
if((parent::beforeSave($insert))){
// Place your custom code here
$query = DepCustomer::findOne($this->customer_id);
Audit::saveOldDetails($query);
return true;
}
}
and write saveOldDetails function in Audit Model
public static saveOldDetails($query){
// your business logic here
}
Refer this link
http://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail