Does Laravel 5.3019 database Transaction method work? - php

I've use Larvel 5.0 with Database transaction all the method in my previous web application it work as well and we are really love it because this application help me much more than our estimated
so we have create another webs application by using this newest version of this framework and used the same Database structure but finaly it would not work for me and another one to.
I have as more peoples and post on some toturial website for asking any belp but not yet get any solution so I record this video for sure about this case.
Issue: My issue I've disabled (//commit()) method all data still can insert into Database.
final function Add()
{
if ($this->request->isMethod('post')) {
//No you will see this method use with Try Catch and testing again
//DB::beginTransaction(); // Ihave testing with outside of try and inside again
Try{
DB::beginTransaction();
$cats = new Cat();
$catD = new CategoryDescriptions();
$cats->parent_id = $this->request->input('category_id');
$cats->status = ($this->request->input('status')) ? $this->request->input('status') : 0;
if (($res['result'] = $cats->save())== true) {
$catD->category_id = $cats->id;
$catD->language_id = 1;
$catD->name = $this->request->input('en_name');
if (($res['result'] = $catD->save()) === true) {
$catD2 = new CategoryDescriptions();
$catD2->category_id = $cats->id;
$catD2->language_id = 2;
$catD2->name = $this->request->input('kh_name');
$res['result'] = $catD2->save();
}
}
if(!empty($res)) {
//DB::commit();
}
return [$res,($res['result'] = $catD->save())];
}catch(\Exception $e){ // I have already try to use Exception $e without backslash
DB::rollback();
}
}
$cat = Cat::with(['CategoryDescriptions', 'children'])->where('status', 1)->get();
return view('admin.categories.add', ['cat' => $cat]);
}
You can check on my video to see that .
Check on my video

I don't know why your code did not work. But you can try with this code I think it's will work. Laravel transaction documentation
try{
DB::transaction(function)use(/*your variables*/){
// your code
});
}catch(\PDOException $exception){
//debug
}
If any exception occurs it will automatically rollback. If you want manual rollback then inside transaction you can throw a manual exception based on your logic.

Related

doctrine2 flush() silently crashes for no apparent reason

I'm writing a converter that takes a document from database (mongo db), does some magic with its fields and writes it back. Repeat for all relevant docs.
The problem is, after successful processing EntityManager#flush() just silently crashes not committing any changes to db or returning an error code.
I encountered this crash before but I've been able to evade it by reducing quantity of entities to flush(). Now it won't work even with one.
The code goes like this:
public function convertTagsAction() {
$result = [];
$result['docs processed'] = 0;
$result['tags added'] = 0;
$repo = $this->getRepo('Portal');
$cnt = 0;
$dm = $this->getDM();
$docs = $repo->findBy([...]);
$result['docs to process'] = count($docs);
foreach($docs as $doc) {
....//executing just for ONE doc at the moment
$result['docs processed']++;
//file_put_contents('1.txt', print_r($doc, true));
//Everything is ok in the file
$dm->persist($doc);
echo $dm->getUnitOfWork()->size();
// returns 6087 which I deem strange
//this helped me before to manage this problem
$cnt++;
if ($cnt >= 20) {
$dm->flush();
$cnt = 0;
}
}
try {
$dm->flush();
} catch (Exception $e) {
echo $e->getMessage(); //Nah, won't tell me anything
}
return $this->success($result);
}
So now, whenever flush() is called, the script just quits and not even returns any output (should do so in the last line). Any ideas how to solve it?

Laravel DB::transaction exception PDO There is no active transaction

i have the following code:
$new_models = DB::transaction(function () use ($supplier, $address, $addressDetail) {
$new_supplier = $this->setNewSupplier($supplier);
$new_address = $this->setNewAddress($address);
$new_addressDetail = $this->setNewAddressDetail($addressDetail,$new_address->id);
$this->syncSupplierAddress($new_supplier->id,$new_address->id);
$this->updateControlAp($new_supplier->supplier_id);
return [$new_supplier, $new_address, $new_addressDetail];
});
The set methods are basically creating the models object with save() at the end;
Now this works perfectly fine if 2nd...nth fails BUT NOT if the first one fails.
If $this->setNewSupplier($supplier);
fails than i get
"PDOException in Connection.php line 541:
There is no active transaction"
Am i doing something wrong here ? Also if i comment $this->rollBack(); from the catch in vendor Connection.php it actually gives me the SQL error. Important part here is that this isn't working only if first save() fails
PS. I am using PostgreSQL not MySQL but i don't think its related
There are different ways to make transactions in Laravel, another one could be this:
...
$new_models = [];
try {
DB::beginTransaction();
$new_supplier = $this->setNewSupplier($supplier);
$new_address = $this->setNewAddress($address);
$new_addressDetail = $this->setNewAddressDetail($addressDetail,$new_address->id);
$this->syncSupplierAddress($new_supplier->id,$new_address->id);
$this->updateControlAp($new_supplier->supplier_id);
$new_models = [$new_supplier, $new_address, $new_addressDetail];
DB::commit();
} catch(\Exception $e) {
DB::rollback();
// Handle Error
}
...

Handling $resource request from PHP backend using SLIM

I'm having problems accessing my PHP backend from AngularJS.
I have followed:
http://coenraets.org/blog/2012/02/sample-application-with-angular-js/
Routing with AngularJS and Slim PHP
Some other's too but those are similar. I've tackled the problem for a few days now and still can't get it working.
First way to call my php script
app.controller('PhoneDetailCtrl',function($scope, $modal, $resource) {
var request_Id = 1;
var Request = $resource('http://mobiiltelefonid24.ee/api/kasutatud_telefonid/'+request_Id);
$scope.request = Request.get();} //this way I get code 200 but 119 empty chars.. So I figure routing should be correct?
Second way I tried
app.controller('PhoneDetailCtrl',function($scope, $modal, Service) {
$scope.request = Service.get({id:1});} //this gives me code 200 but 119 empty chars...
app.service('Service', function ($resource) {
return $resource('api/kasutatud_telefonid/:id', {}, {
update: {method:'PUT'}
});});
PHP code (using mysql db)
require 'Slim/Slim.php';
$app = new Slim();
$app->get('/', 'getPopularPhones');
$app->get('/uued_telefonid','getNewPhones');
$app->get('/kasutatud_telefonid','getUsedPhones');
$app->get('/uued_telefonid/:id', 'getPhoneDesc');
$app->get('/kasutatud_telefonid/:id', 'getPhoneDesc');
$app->run();
/*Other get methods are exactly the same but with different name*/
function getPhoneDesc($id) {
$sql = "SELECT * FROM Phone";
try {
$db = getConnection();
$stmt = $db->query($sql);
$wines = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo json_encode($wines);
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
getConnection() is implemented as shown in wine app tutorial. There is one row in db that has 21 colums so it should return something. Also tried to pass string $wine="teststring" but that also arrived as jibbrjabbre.
Is routing wrong or is there problems with querying from db? (I can query just fine from phpMyAdmin). Out of ideas...
Solved! Slim was falsely configured and meekroDB worked just fine (Thanks mainguy). On top of that there were some issues on webhosts side.

Reverting object property changes in php

I have a bunch of Doctrine php objects and I'm calling things like
$myObj = $query->execute()->getFirst();
$myObj->setName('a new name');
$myObj->setAge('40');
$myObj->save();
etc...
etc...
And at some point, if encounter an error, I'd like to revert all those property changes since I've already called the save() function and that propagates the new properties to the database.
I'd like to come up with a way to store the old value of the object as well as which method to call to revert it. Something like:
$undoCollection = array();
$undoObject = array();
$undoObject['revertFunction'] = $myObj->setName;
$undoObject['revertValue'] = 18;
array_push($undoCollection,$undoObject)
So that later on, if something goes wrong, I can loop through the $undoCollection:
foreach($undoCollection as $undoObj)
{
$undoObj['revertFunction']($undoObj['revertValue']);
}
Is this something that's possible in PHP? Or is there something else that can provide that functionality?
You should use transactions. E.g.:
$myObj = $query->fetchOne();
if ($myObj)
{
$conn = $myObj->getTable()->getConnection();
try
{
$conn->beginTransaction();
$myObj->setName('Asd')->save();
// do other stuff...
// if an exception is thrown before calling commit
// nothing in this try block will be saved
$conn->commit();
}
catch(Exception $e)
{
$conn->rollback();
}
}

PHP Exceptions in Classes

I'm writing a web application (PHP) for my friend and have decided to use my limited OOP training from Java.
My question is what is the best way to note in my class/application that specific critical things failed without actually breaking my page.
My problem is I have an Object "SummerCamper" which takes a camper_id as it's argument to load all of the necessary data into the object from the database. Say someone specifies a camper_id in the query string that does not exist, I pass it to my objects constructor and the load fails. I don't currently see a way for me to just return false from the constructor.
I have read I could possibly do this with Exceptions, throwing an exception if no records are found in the database or if some sort of validation fails on input of the camper_id from the application etc.
However, I have not really found a great way to alert my program that the Object Load has failed. I tried returning false from within the CATCH but the Object still persists in my php page. I do understand I could put a variable $is_valid = false if the load fails and then check the Object using a get method but I think there may be better ways.
What is the best way of achieving the essential termination of an object if a load fails? Should I load data into the object from outside the constructor? Is there some sort of design pattern that I should look into?
Any help would be appreciated.
function __construct($camper_id){
try{
$query = "SELECT * FROM campers WHERE camper_id = $camper_id";
$getResults = mysql_query($query);
$records = mysql_num_rows($getResults);
if ($records != 1) {
throw new Exception('Camper ID not Found.');
}
while($row = mysql_fetch_array($getResults))
{
$this->camper_id = $row['camper_id'];
$this->first_name = $row['first_name'];
$this->last_name = $row['last_name'];
$this->grade = $row['grade'];
$this->camper_age = $row['camper_age'];
$this->camper_gender = $row['gender'];
$this->return_camper = $row['return_camper'];
}
}
catch(Exception $e){
return false;
}
}
A constructor in PHP will always return void. This
public function __construct()
{
return FALSE;
}
will not work. Throwing an Exception in the constructor
public function __construct($camperId)
{
if($camperId === 1) {
throw new Exception('ID 1 is not in database');
}
}
would terminate script execution unless you catch it somewhere
try {
$camper = new SummerCamper(1);
} catch(Exception $e) {
$camper = FALSE;
}
You could move the above code into a static method of SummerCamper to create instances of it instead of using the new keyword (which is common in Java I heard)
class SummerCamper
{
protected function __construct($camperId)
{
if($camperId === 1) {
throw new Exception('ID 1 is not in database');
}
}
public static function create($camperId)
{
$camper = FALSE;
try {
$camper = new self($camperId);
} catch(Exception $e) {
// uncomment if you want PHP to raise a Notice about it
// trigger_error($e->getMessage(), E_USER_NOTICE);
}
return $camper;
}
}
This way you could do
$camper = SummerCamper::create(1);
and get FALSE in $camper when the $camper_id does not exist. Since statics are considered harmful, you might want to use a Factory instead.
Another option would be to decouple the database access from the SummerCamper altogether. Basically, SummerCamper is an Entity that should only be concerned about SummerCamper things. If you give it knowledge how to persist itself, you are effectively creating an ActiveRecord or RowDataGateway. You could go with a DataMapper approach:
class SummerCamperMapper
{
public function findById($id)
{
$camper = FALSE;
$data = $this->dbAdapter->query('SELECT id, name FROM campers where ?', $id);
if($data) {
$camper = new SummerCamper($data);
}
return $camper;
}
}
and your Entity
class SummerCamper
{
protected $id;
public function __construct(array $data)
{
$this->id = data['id'];
// other assignments
}
}
DataMapper is somewhat more complicated but it gives you decoupled code which is more maintainable and flexible in the end. Have a look around SO, there is a number of questions on these topics.
To add to the others' answers, keep in mind that you can throw different types of exceptions from a single method and handle them each differently:
try {
$camper = new SummerCamper($camper_id);
} catch (NoRecordsException $e) {
// handle no records
} catch (InvalidDataException $e) {
// handle invalid data
}
Throwing an exception from the constructor is probably the right approach. You can catch this in an appropriate place, and take the necessary action (e.g. display an error page). Since you didn't show any code, it's not clear where you were catching your exception or why that didn't seem to work.
try {
$camper = new SummerCamper($id);
$camper->display();
} catch (NonexistentCamper $ex) {
handleFailure($ex);
}

Categories