There is no active transaction' - php

having problems with this function wipe_data
this wipe_data function my DB cleanup and admin data inserting
but this function shows error:
There is no active transaction
This is my code:
function wipe_data() {
DB::beginTransaction();
$adminData = User::where('role', 'admin')->first();
try {
User::truncate();
User_details::truncate();
User_kyc::truncate();
Token::truncate();`enter code here`
$auto_id = date('Y');
DB::statement("ALTER TABLE ls_users AUTO_INCREMENT = $auto_id");
$admin = new User();
$admin->username = $adminData->username;
$admin->email = $adminData->email;
$admin->password = $adminData->password;
$admin->role = $adminData->role;
$admin->save();
$user_id = User::where('role', 'admin')->value('id');
DB::commit();
} catch (\Exception $ex) {
DB::rollback();
return false;
}
return true;
}

There are some statements that caused implicit commit, including the ALTER TABLE statement you are using.
Therefore, your statement has already been committed before you called DB::commit(), hence an error occurred.

Related

php pdo cant excute alter statment

public function
updateOrderno($neworderid){
$updateData = array($neworderid);
$stmt = $this->pdo->prepare("ALTER TABLE `order` AUTO_INCREMENT=?");
try {
if ($stmt->execute($updateData)){
return true;
}else{
return false;
}
} catch (PDOException $e){
return false;
}
}
Here is my code , I call this with $post data and then
it keep retruning false when I execute the alter statement any help?

How can I use db transaction in laravel?

I try this :
public function destroy($id)
{
DB::beginTransaction();
try {
$product = $this->product_repository->find($id);
$result = $product->categories()->detach();
if($result) {
list($status,$instance) = $this->product_repository->delete($id);
}
DB::commit();
return ['status'=>true,'data'=>$status];
} catch (\Exception $e) {
DB::rollback();
return ['status'=>false, 'message'=>$e->getMessage()];
}
}
If the code executed, $this->product_repository->delete($id) not work / not success delete.
But this : $product->categories()->detach();, it works / success deleted.
How to if delete product failed, delete category also failed?
You can't add return statement inside transaction that halts entire process and DB::rollback() is executed.
To switch the return, You can define a boolean variable and make false while you catch exception.
Like this:
public function destroy($id)
{
$success = true;
DB::beginTransaction();
try{
// Your Code
$product = $this->product_repository->find($id);
$result = $product->categories()->detach();
if($result) {
list($status,$instance) = $this->product_repository->delete($id);
}
DB::commit();
}catch(\Exception $e){
DB::rollback();
$success = false;
}
if($success){
// Return data for successful delete
}
else{
// Return data for unsuccessful delete
}
}
Hope you understand.
You can use it like this:
$returnResult = [];
DB::beginTransaction();
try {
...
DB::commit();
$returnResult['status'] = true;
$returnResult['data'] = $status;
} catch (...) {
...
DB::rollback();
$returnResult['status'] = true;
$returnResult['message'] = $e->getMessage();
}
return $returnResult;

2 table in 1 form Laravel

I had 2 tables . driver and part_time_available, when I select driver type parttime it'll show part_time_available field. the problem is I can't save.
it throws this error : Integrity constraint violation: 1048 Column 'driver_id' cannot be null
here's my save controller code so far :
public function save(Request $request, $obj = null) {
if (!$obj) {
$obj = new Driver;
}
$obj->active = TRUE;
$obj->counter = 0;
return $this->saveHandler($request, $obj);
}
public function saveHandler(Request $request, $obj)
{
try {
DB::beginTransaction();
$obj->fill($request->all());
if (!$obj->save()) {
throw new ValidationException($obj->errors());
}
foreach($request->parttimeAvailabilities as $pta) {
if (empty($pta['id'])) {
$parttimeAvailability = new ParttimeAvailability();
}
else {
$parttimeAvailability = ParttimeAvailability::find($pta['id']);
}
$parttimeAvailability->Driver()->associate($obj);
$pta['driver_id'] = isset($pta['driver_id']) ? $pta['driver_id'] : null;
$driver = Driver::find($pta['driver_id']);
$parttimeAvailability->driver()->associate($driver);
$parttimeAvailability->day = $pta['day'];
$parttimeAvailability->start_time = $pta['start_time'];
$parttimeAvailability->end_time = $pta['end_time'];
$parttimeAvailability->available = isset($pta['available']);
$parttimeAvailability->save();
};
$obj->save();
if (!$parttimeAvailability->save()) {
throw new ValidationException($parttimeAvailability->errors());
}
DB::commit();
return $this->sendSuccessResponse($request);
} catch (ValidationException $e) {
DB::rollback();
\Log::error($e->errors);
return $this->sendErrorResponse($request, $e->errors);
} catch (Exception $e) {
DB::rollback();
\Log::error($e->getMessage());
return $this->sendErrorResponse($request,'Unable to process. Please contact system Administrator');
}
}
any idea ??
Take a look here:
$pta['driver_id'] = isset($pta['driver_id']) ? $pta['driver_id'] : null;
$driver = Driver::find($pta['driver_id']);
From this code chunk we can see that driver_id can be null. In that case there is no driver to find. You should only search for a driver if you have an id.

MySQL's session handler difficulties

Watching this online tutorial about MYSQL's session handler and got really confused about this part:
table_XXX == Table XXX;
col_XXX == Column XXX;
sid == Session id
Read method:
public function read($session_id)
{
$this->db->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
$this->db->beginTransaction();
/**
* the data is selected and no other ppl can interfere
* the writing process until COMMIT is reached
*/
$sql = "SELECT $this->col_expiry, $this->col_data
FROM $this->table_sess
WHERE $this->col_sid = :sid FOR UPDATE";
$selectStmt = $this->db->prepare($sql);
$selectStmt->bindParam(':sid', $session_id);
$selectStmt->execute();
$results = $selectStmt->fetch(\PDO::FETCH_ASSOC);
if ($results) {
if ($results[$this->col_expiry] < time()) {
// return empty if data out of date
return '';
}
return $results[$this->col_data];
}
return $this->initializeRecord($selectStmt);
}
Protected method:
protected function initializeRecord(\PDOStatement $selectStmt)
{
try {
$sql = "INSERT INTO $this->table_sess
($this->col_sid, $this->col_expiry, $this->col_data)
VALUES (:sid, :expiry, :data)";
$insertStmt = $this->db->prepare($sql);
$insertStmt->bindParam(':sid', $session_id);
$insertStmt->bindParam(':expiry', $this->expiry); // expiry is defined
$insertStmt->bindValue(':data', '');
$insertStmt->execute();
return '';
} catch(\PDOException $e) {
$this->db->rollBack();
throw $e;
}
}
Write method:
public function write($session_id, $data)
{
try {
$sql = "INSERT INTO $this->table_sess ($this->col_sid,
$this->col_expiry, $this->col_data)
VALUES (:sid, :expiry, :data)
ON DUPLICATE KEY UPDATE
$this->col_expiry = :expiry,
$this->col_data = :data";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':expiry', $this->expiry, \PDO::PARAM_INT);
$stmt->bindParam(':data', $data);
$stmt->bindParam(':sid', $session_id);
$stmt->execute();
return true;
} catch (\PDOException $e) {
if ($this->db->inTransaction()) {
$this->db->rollback();
}
throw $e;
}
}
In 'Protected method', line 8, there is a $session_id, and clearly no $session_id is passed to the protected method, so bindParam() for that line simply binded nothing?
So initializeRecord() simply initiated a row that has expiry time but nothing else? And then the sid and data is inserted after write method is called?
This is doing a lot of string-construction trickery with WHERE $this->col_sid = :sid and so forth, as it creates SQL statements.
You might try echoing or dumping those SQL statements to see what they contain right before you run ->execute() on them. That will help you troubleshoot.
It's pretty clear your protected method is missing $session_id. Is it possible there's a value for $this->sid you could use there?

Can you have two instances of a model in one test function in phpunit?

I'm trying to test that a duplicate user cannot be inserted. To do this, I am creating 2 user objects with the same details, just changing account name - since this is something that is also unique.
However, my setter doesn't seem to be setting the company name second time around. When I echo from the model, the property I am trying to set is still the same from the previous object I created. My test fails as it throws the account already exists exception I set up
Failed asserting that exception of type "Models\AccountAlreadyExistsException" matches expected exception "Models\UserAlreadyExistsException".
public function testCantInsertDuplicateUser ()
{
$user = new \Models\User();
$user->first_name = 'John';
$user->surname = 'Smith';
$user->email = 'myemail#gmail.com';
$user->password = 'password';
$user->password_confirmation = 'password';
$user->setCompanyName('Star');
$user->setPackageId(2);
$this->assertTrue($user->signUp());
$user2 = new \Models\User();
$user2->first_name = 'John';
$user2->surname = 'Smith';
$user2->email = 'myemail#gmail.com';
$user2->password = 'password';
$user2->password_confirmation = 'password';
$user2->setCompanyName('cross');
$user2->setPackageId(2);
$this->setExpectedException('Models\UserAlreadyExistsException');
$user2->signUp();
}
//user model
public function setCompanyName ($company_name)
{
$this->company_name = $company_name;
}
private function insertAccount ()
{
$account = new \Models\Account;
$account->setCompanyName($this->company_name);
$account->setPackageId($this->package_id);
$this->account_message_bag = new \Illuminate\Support\MessageBag();
if (!$account->insert()) {
$this->account_message_bag = $account->getValidationErrors();
}
return $account;
}
private function insertUser ()
{
$save_user = $this->save(self::$rules, array(), array(), function ($model)
{
//this is all performed before save
$existing_email = User::where('email', "=", $this->email)->count();
if ($existing_email) {
//delete account that was created in previous step
//as the signup hasn't been successful
$this->account->delete();
throw new UserAlreadyExistsException();
}
//are there any account validation errors?
if (count($this->account_message_bag->getMessages()>0)) {
return false;
}
});
return $save_user;
}
public function signUp ()
{
$this->account = $this->insertAccount();
$this->account_id = $this->account->getId();
if (!$this->insertUser()) {
//delete the company created in previous step
$this->account->delete();
$user_message_bag = Ardent::errors();
//combine user and account validation eerrors
$message_array = array_merge($user_message_bag->getMessages(), $this->account_message_bag->getMessages());
$this->validation_errors = new \Illuminate\Support\MessageBag($message_array);
throw new GenericValidationException();
}
//TODO - does this return false on failure?
$sent = $this->sendConfirmEmail();
if (!$sent) {
throw new WelcomeEmailNotSent();
}
//sende confirm email
return true;
}
//Account model
public function insert ()
{
$result = $this->save(self::$rules, array(), array(), function()
{
$existing_company_name = \Models\Account::where('company_name', '=', $this->company_name)->count();
if ($existing_company_name) {
throw new AccountAlreadyExistsException();
}
});
if (!$result) {
$this->validation_errors = Ardent::errors();
return false;
}
return true;
}
check the way you validate the AccountAlreadyExistsException
may be you should change the email
Your namespaces are likely the problem.
You create the class in \Models, but use Models (without the backslash) for the exception. Maybe your code is throwing \Models\UserAlreadyExsitsException, not Models\UserAlreadyExistsException.
$user2 = new \Models\User();
...
$this->setExpectedException('Models\UserAlreadyExistsException');
Maybe this should be '\Models\UserAlreadyExistsException'
$user2 = new \Models\User();
...
$this->setExpectedException('\Models\UserAlreadyExistsException');

Categories