Cakephp 2 validation message on beforesave model callback - cakephp-2.0

I am using CakePhp 2.5 and in a beforeSave model Callback i do return false if some information (MyIndex) is not provided.
How can i display the error message ?
I try :
$this->validationRuleErrors = 'You need to choose MyIndex';
But did not see any error message.
if( in_array( 'MyIndex', array_keys( $this->data) ) == FALSE )
{
$this->validationRuleErrors = 'You need to choose MyIndex';
debug($this->validationErrors);
return false;
}

The validationErrors property set in your beforeSave can be accessed from your controller.
Example controller:
try {
$this->Model->save($data);
if (!empty($this->Model->validationErrors)) {
// just echo $this->Model->validationErrors if you don't want to use an exception
throw new Exception($this->Model->validationErrors);
}
} catch (Exception $e) {
$this->data = [
'success' => false,
'message' => $e->getMessage()
]
}

Related

internal error undefined index

I am getting internal error
in AdminController.php line 85
at HandleExceptions->handleError('8', 'Undefined index: name', 'C:\wamp64\www\laravel\dev.oasis-portal.my\app\Http\Controllers\AdminController.php', '85', array('data' => array())) in AdminController.php line 85
when I run
public function courseDelete()
{
$data = Input::all();
$student = Course::where('name', '=', $data["name"]);
if($student->delete()) {
User::find($data["name"])->delete();
return json_encode(array('success' => true));
} else {
return json_encode(array('success' => false, 'errors' => "Unable to remove student."));
}
}
My route is: Route::get('/course/delete/', 'AdminController#courseDelete');
$data["name"] is not set, and therefore an exception is thrown. A better solution would be to get parameters by using the request() shorthand:
ie. request()->get('name'); //will return null if not set

how to show an array using Ajax and Symfony

i am trying to show a consult which have an array with arrays in symfony using Ajax and json, this is my ajax's script :
<script>
var boton=document.getElementById("form_Boton");
function ajax() {
var nombre=$('#form_nombre').val();
$.ajax({
type: 'POST',
url: "{{ path('buscar_porCriterio') }}",
data: ({nombre: nombre}),
dataType:"json",
beforeSend:function () {
alert("enviará a: "+nombre);
},
success:function (resp) {
if(resp!=""){
$('#resultados').html(resp["nombre"]+" "+resp["apellido"]+" "+resp["residencia"]);
}
if(resp==""){
alert("NO SE ENCONTRO NADA");
}
}
})
}
boton.addEventListener("click",ajax);
</script>
And this is my controller:
public function PorCriterioAction(Request $request){
if(!$request->isXmlHttpRequest())
{
throw new Exception("Error, NO ES AJAX");
}
$nombre=$request->request->get('nombre');
$em=$this->getDoctrine()->getManager();
$encontradas=$em->getRepository('FormulariosBundle:persona')->findBynombre($nombre);
if ($encontradas == null) {
$response = new Response("VACIO " . $nombre . " Sorry");
return $response;
}
else{
$persona_encontrada = (array("id" => $encontradas->getId(),
"nombre" => $encontradas->getNombre(),
"apellido" => $encontradas->getApellido(),
"residencia" => $encontradas->getResidencia()
));
$response= new JsonResponse($persona_encontrada);
return $response;}}
what i need is get all data from my DB whose name be $nombre, and show every data in my div 'resultados'. but. when i realize my search, symfony show me this exception:
Exception
my question is: How can i do to pass every data of that consult to my div 'resultados'?
as you see, i want to show such consult in a div whose id is "resultados" but does not work, can you help me please? i am a beginner in symfony and i have to make this University Proyect and finish my study, thanks for your answer
EDIT # 2
this is the change to my controller:
public function PorCriterioAction(Request $request){
if(!$request->isXmlHttpRequest())
{
throw new Exception("Error, NO ES AJAX");
}
$nombre=$request->request->get('nombre');
$em=$this->getDoctrine()->getManager();
$encontradas=$em->getRepository('FormulariosBundle:persona')->findBynombre($nombre);
if ($encontradas == null) {
$response = new Response("VACIO " . $nombre . " Sorry");
return $response;
}
else{
foreach ($encontradas as $Item){
$persona_encontrada = (array("id" => $Item->getId(),
"nombre" => $Item->getNombre(),
"apellido" => $Item->getApellido(),
"residencia" => $Item->getResidencia()
));
array_push($persona_encontrada,$Item);
}
$response= new JsonResponse($persona_encontrada);
return $response;
}
}
is this what you need? responseText
I believe $encontradas is a results set so try this:
foreach( $encontradas as $item){
$persona_encontrada = (array(
"id" => $item->getId(),
"nombre" => $item->getNombre(),
"apellido" => $item->getApellido(),
"residencia" => $item->getResidencia()
));
}
Let us know the result.
EDIT #2
I see the problem. Since it iterates through the array, you want $persona_encontrada to be an array and then use the PHP array_push to add array elements to it. You could do it like so:
$persona_encontrada = array();
foreach( $encontradas as $item){
$element = array(
"id" => $item->getId(),
"nombre" => $item->getNombre(),
"apellido" => $item->getApellido(),
"residencia" => $item->getResidencia()
);
array_push( $persona_encontrada, $element);
}
By the way, although this will work for you, it might not be the best way to do something like this. But it will work.

Balanced-Payments Try Catch response

I've attempting to learn how to set up credit card payments and using a Balanced Payments test marketplace. I haven't ever set up a try catch statement before and I am having some trouble with processing the response.
Here is my controller try/catch statement:
try{
$card->debits->create(array(
"amount" => $amount,
"appears_on_statement_as" => "test",
"description" => $invoiceId,
"order" => $order,
));
} catch (Balanced\Errors\Declined $e) {
$this->arrResponse['status'] = $e->getMessage();
return Response::json($this->arrResponse);
}
$invoice->save();
// send email function...
//redirect
$this->arrResponse['status'] = SUCCESS;
return Response::json($this->arrResponse);
I can see the error on chrome developer tools, but I can't make it appear on my view.
Chrome dev tools 500 internal server error statement:
error: {type: "Balanced\Errors\Declined", message: "",…}
file: "/Applications/MAMP/htdocs/testcc/vendor/balanced/balanced/src/Balanced/Errors/Error.php"
line: 42
message: ""
type: "Balanced\Errors\Declined
processpayment.js file:
jQuery.post(baseURL+'/processPayment', {
uri: fundingInstrument.href,
amount: amount,
invoiceId: invoiceId,
}, function(r) {
// backend response
if (r.status === 200) {
$('#msgSection').empty().removeClass('alert-error alert-success').addClass('alert-success').text(' payment has been received').show();
} else {
// failure from backend
$('#msgSection').empty().removeClass('alert-success').addClass('alert-warning').text('error').show();
}
});
When test card is processed successfully, everything works and success message appears on my view. However, when I use a test card that is declined, no message is sent to my view. Anyone see what I am doing wrong?
try to check balanced-php client testsuite to see how they use try catch block from here
so your code would be like.
try{
$card->debits->create(array(
"amount" => $amount,
"appears_on_statement_as" => "test",
"description" => $invoiceId,
"order" => $order,
));
} catch (Balanced\Errors\Declined $e) {
$this->arrResponse['status'] = $e->category_code;
return Response::json($this->arrResponse);
}
$invoice->save();
// send email function...
//redirect
$this->arrResponse['status'] = SUCCESS;
return Response::json($this->arrResponse);
$e->category_code will be either funding-destination-declined or authorization-failed or card-declined

Cakephp Render XML errors in custom Exception.renderer

Based on the information here: Using a custom renderer with Exception.renderer to handle application exceptions
I'm creating a custom error renderer that renders in XML format.
Below is the sample code for the render function in app/Lib/Error/AppExceptionRenderer:
public function render() {
if (isset($this->controller->request->params['xml'])) {
$this->controller->viewClass = "MyXml";
$error = array(
'app' => array(
'error' => 'An unexpected error has occured.'
)
);
$this->controller->set('error', $error);
$this->controller->set('_serialize', 'error');
}
}
However nothing gets returned. I have done some echo within the if condition and that shows.
So is it because the viewClass is not initialized while its in AppExceptionRenderer::render() stage?
There were no errors either.
"MyXml" viewClass works perfectly in normal controllers too.
So apparently I was missing the render and send methods.
Here's the full working example.
<?php
class AppExceptionRenderer extends ExceptionRenderer {
public function __construct($exception) {
parent::__construct($exception);
}
public function render() {
// Handle errors
if (isset($this->controller->request->params['xml'])) {
Cakelog::error($this->error->getMessage());
$this->controller->viewClass = "MyXml";
$error = array(
'app' => array(
'error' => 'An illegal operation has been detected.'
)
);
$this->controller->set('error', $error);
$this->controller->set('_serialize', 'error');
$cakeResponseObject = $this->controller->render();
$this->controller->response->send($cakeResponseObject);
} else {
if ($this->method) {
call_user_func_array(array($this, $this->method), array($this->error));
}
}
}
}

Override Model::save() or Implement Before/After Events? How Do I Fatten my Cake Models?

I find my edit actions in CakePHP controllers get messy pretty quickly, and I'd like to pull most of that crap into the Model. Let me give you a scenario.
I have an users/edit action in my Users controller. I want to let users reset a password (or not reset the password) in my form. If they provide a new password then I pass the three password fields into save() using the fields list parameter of save(). If they don't provide those fields I don't want to pass those fields in using the fields list.
The code to check these fields is currently in my controller, what would be a good way to move this into the model?
Here's what my controller's edit action looks like:
function edit($id = null) {
if ($this->Session->check('Auth.User') && $this->Session->read('Auth.User.id') == $id) {
if (!$id && empty($this->data)) {
$this->Session->setFlash('Invalid Account','default',array('class'=>'flash_error'));
$this->redirect(array('controller'=>'directories', 'action' => 'index'));
}
if (!empty($this->data)) {
// take out the following and an error occurs in parentNode()
$this->data['User']['group_id'] = 2;
if (empty($this->data['User']['old_password'])) { //TODO: pass in a field list for every publicly available save() call.
//dont update the password fields if they aren't passing in the old password
if ($this->User->save($this->data,true,array('first_name', 'last_name', 'email', 'username'))) {
$this->Session->setFlash('Your changes have been saved','default',array('class'=>'flash_ok'));
$this->redirect(array('controller'=>'directories','action'=>'index'));
} else {
$this->Session->setFlash('Your changes could not be saved. Please, try again.','default',array('class'=>'flash_error'));
}
} else {
//update the passwords
if ($this->User->save($this->data,true,array('first_name', 'last_name', 'email', 'username', 'password', 'password_confirm', 'old_password'))) {
$this->Session->setFlash('Your changes have been saved','default',array('class'=>'flash_ok'));
$this->redirect(array('controller'=>'directories','action'=>'index'));
} else {
$this->Session->setFlash('Your changes could not be saved. Please, try again.','default',array('class'=>'flash_error'));
}
}
}
if (empty($this->data)) {
$this->data = $this->User->read(array(
'first_name', 'last_name', 'email', 'username'
), $id);
}
$this->set('user_id',$id);
$this->set('current_subscription', $this->User->Subscription->currentSubscription($id));
} else {
//redirect to not authorized
$this->Session->setFlash('Invalid Account','default',array('class'=>'flash_error'));
$this->redirect(array('controller'=>'directories', 'action' => 'index'));
}
}
A more graceful style would be
function edit($id = null)
{
if($id && $this->Modelname->isValidLoginUser($id) && $this->data)
{
$login_tag = $this->Modelname->resetPass($id,$this->data);
switch($login_tag)
{
case 0: $this->Session->setFlash();$this->redirect();break;
case 1: $this->Session->setFlash();$this->redirect();break;
....
}
}
else
{
$this->Session->setFlash("missing arguments.");
}
}
And the function Modelname->resetPass() in the model looks like
function resetPass($id,$data)
{
$user = $this->findById($id);
$oldpasswd = $user[modelname]['password'];
$newpasswd = $data[modelname][passwd1];
$confirmpasswd = $data[modelname][passwd2];
if($newpasswd=="" || $confirmpasswd=="")
{
return 0;
}
if($newpasswd != confirmpasswd)
{
return 1;
}
....//perhaps other invalid situations
if($newpasswd == $oldpasswd)
{
$this->saveField("password",$newpasswd);
return N; //N is an int meaning success.
}
}

Resources