How can I debug $Model after validation? - validation

I want to see the content of validationErrors => array(???) of the $Model after a failed validation, but there is no "afterValidation()" method.
Does anyone know how can I see that or at least how would it look exactely?
Thank's!

On Controller, you can validate data before you trying save:
$this->ModelName->set($this->request->data);
if ($this->ModelName->validates()) {
// success
} else {
// failed
$errors = $this->ModelName->validationErrors;
}
Reference:
Validating Data from the Controller

Use $this->ModelName->invalidFields() after you have made the save/whatever you're doing:
For example:
debug($this->ModelName->invalidFields());
If you have a redirect at some point after that call, you might not see the data in your view. In this case, you can always do die(); either right after or wrapped around your call like so:
die(debug($this->ModelName->invalidFields());

Related

How to load a CodeIgniter view in $promise->then() in a controller?

In my CodeIgniter 2 controller I call a model method which returns a ReactPHP promise, and I want to load a CodeIgniter view in the function called by that promise's ->then() method. How can I do this? What happens instead is the controller method returns nothing, so I get a blank page in the browser.
Here is a simplified example illustrating what I'm trying to do:
class My_class extends My_Controller {
function my_method() {
$this->my_model->returns_a_promise()->then(function ($data) {
// How can I pass the promise's resolved value to the template here?
// It seems this never gets called, because my_method() returns
// before we get here. :(
$this->load->view('my_view', $data);
});
}
}
Is there any way to tell the controller method not to send output to the browser until after the promise has resolved?
I'm not sure what are you trying to do but if you want to stop view from outputting and return it as a string then output it with echo yourself you can do this:
$view = this->load->view('my_view', $data, TRUE);
Now you have the view as a var string you can use it to do what you are trying to do.
It turns out the code in my original question does work. So the question is the answer. But the reason it wasn't working for me was that returns_a_promise() was not returning a resolved promise, so ->then() was not called and the view was not rendered. In order to make it return a resolved promise, I had to call $deferred->resolve(); in the code that returned the promise.
The upshot of this is that this code example demonstrates it is possible to run asynchronous PHP (via ReactPHP in this case) in CodeIgniter controller methods. My particular use case is to run many database queries concurrently in the CodeIgniter model.
try this:
function my_method() {
$data = array();
$data['promise'] =$this->my_model->returns_a_promise();
$data['view'] = 'my_view';
$this->load->view('my_view', $data);
}

Handling Failed eloquent methods

I'm calling a product's information field, as you can see below:
$product->attributes->first()->attributeValues->where('locale',$iso);
Basically in the $product variable already have information regarding the product.
I use $product->attributes->first() to get his attributes, and after getting them I go get his values with ->attributeValues->where('locale',$iso) with the specific language.
The data it outputs is good, but only if attributes exist, because in case there isn't any it doesn't and because of the attributeValues method the page fails.
How can I handle in this situation?
You may check it with a simple empty() or even count() if you prefer.
$attributes = $product->attributes->first()->attributeValues->where('locale',$iso);
if (count($attributes) == 0) {
// There is no attribute, do something
}
Split up your line
$attributes = $product->attributes->first(); // placeholder
if(isset($attributes) { // check if we have one
$attributes->attributeValues->where('locale',$iso); // if so.. do the dance
} else {// go home }

How to send a response from a method that is not the controller method?

I've got a Controller.php whose show($id) method is hit by a route.
public function show($id)
{
// fetch a couple attributes from the request ...
$this->checkEverythingIsOk($attributes);
// ... return the requested resource.
return $response;
}
Now, in checkEverythingIsOk(), I perform some validation and authorization stuff. These checks are common to several routes within the same controller, so I'd like to extract these checks and call the method everytime I need to perform the same operations.
The problem is, I'm unable to send some responses from this method:
private function checkEverythingIsOk($attributes)
{
if (checkSomething()) {
return response()->json('Something went wrong'); // this does not work - it will return, but the response won't be sent.
}
// more checks...
return response()->callAResponseMacro('Something else went wrong'); // does not work either.
dd($attributes); // this works.
abort(422); // this works too.
}
Note: Yes, I know in general one can use middleware or validation services to perform the checks before the request hits the controller, but I don't want to. I need to do it this way.
As of Laravel 5.6 you can now use for example response()->json([1])->send();.
There is no need for it to be the return value of a controller method.
Note that calling send() will not terminate the output. You may want to call exit; manually after send().
You are probably looking for this:
function checkEverythingIsOk() {
if (checkSomething()) {
return Response::json('Something went wrong');
}
if(checkSomethingElse()) {
return Response::someMacro('Something else is wrong')
}
return null; // all is fine
}
And in the controller method:
$response = $this->checkEverythingIsOk();
if($response !== null) { // $response instanceof Response
return $response;
}
It's probably overkill, but I will throw it in anyway. You might want to look into internal requests. Also this is just pseudoish code, I have not actually done this, so take this bit of information with caution.
// build a new request
$returnEarly = Request::create('/returnearly');
// dispatch the new request
app()->handle($newRequest);
// have a route set up to catch those
Route::get('/returnearly', ...);
Now you can have a Controller sitting at the end of that route and interpret the parameters, or you use multiple routes answered by multiple Controllers/Methods ... up to you, but the approach stays the same.
UPDATE
Ok I just tried that myself, creating a new request and dispatching that, it works this way. Problem is, the execution does not stop after the child-request has exited. It goes on in the parent request. Which makes this whole approach kind of useless.
But I was thinking about another way, why not throw an Exception and catch it in an appropriate place to return a specified response?
Turns out, thats already built into Laravel:
// create intended Response
$response = Response::create(''); // or use the response() helper
// throw it, it is a Illuminate\Http\Exception\HttpResponseException
$response->throwResponse();
Now usually an Exception would be logged and you if you are in Debug mode, you would see it on screen etc. etc. But if you take a look into \Illuminate\Foundation\Exceptions\Handler within the render method you can see that it inspects the thrown Exception if it is an instance of HttpResponseException. If it is then the Response will be returned immediately.
To me the most simple and elegant way is:
response()->json($messages_array, $status_code)->throwResponse();
(you don`t need return)
It can be called from a private function or another class...
I use this in a helper class to check for permissions, and if the user doesn`t have it I throw with the above code.

CakePHP validation error messages - how to pass them around?

Please note: I'm not trying to do this anymore, because I found an alternative, but it may be useful in the future to know the answer.
I have a form that is in a view (index.ctp) associated with the index() action on a controller. That form should post data to another action, contact(), in the same controller. This second action doesn't have a view, it's just to process the information and redirect the user according to the outcome. This action is doing the validation and redirecting the user to the referer (index in this case) in case of an error, and then the error should be displayed in index. Note that the model doesn't use a database table, but it's used only to define validation rules.
The validation is taking place correctly and reporting the expected errors. In order to retrieve the errors after the redirect, it writes the $this->ModelName->invalidFields() array to a session variable that is retrieved on the index() action after the redirection.
This array is passed on to the $errors variable to the view. Now comes the problem. The errors, although being passed correctly between redirects, aren't getting attached to the respective forms. How can I accomplish this? The form has all the conventional names, so it should be automatic, but it isn't.
Here's part of the relevant code:
Index view:
echo $this->Form->create('Contact', array('url' => '/contacts/contact'));
echo (rest of form) ...
echo $this->Form->end(__('send message', true));
Contacts controller:
function index() {
if ($this->Session->check('Contact.errors')) {
$this->set('errors', $this->Session->read('Contact.errors'));
}
}
function contact() {
if (!empty($this->data)) {
$this->Contact->set($this->data);
if ($this->Contact->validates()) {
(send the email)
}
else {
$this->Session->write('Contact.errors', $this->Contact->invalidFields());
$this->redirect($this->referer);
}
}
}
I don't think it's a good idea to write the validation errors in a session variable. I'm no CakePHP expert, but I don't think that's the way you are supposed to do it. All your forms should point to the same url you are on, so the data that the user has entered will not be lost.
Could you add some code to your question?

Need help figuring out how to write my zend view helper

I'm fairly new to Zend Framework and MVC in general so I'm looking for some advice. We have a base controller class in which we have some methods to obtain some user information, account configurations, etc.
So I'm using some of those methods to write out code in various controllers actions, but now I want to avoid duplicating this code and further more I would like to take this code outside of the controller and in a view helper as it is mainly to output some JavaScript. So the code in the controller would look like this:
$obj= new SomeModel ( $this->_getModelConfig () );
$states = $obj->fetchByUser ( $this->user->getId() );
//Fair amount of logic here using this result to prepare some javascript that should be sent to the view...
The $this->_getModelConfig and $this->user->getId() are things that I could do in the controller, now my question is what is the best way to pass that information to the view helper once i move this code out of the controller ?
Should I just call these methods in the controller and store the results into the view and have the helper pick it up from there ?
Another option I was thinking of was to add some parameters to the helper and if the parameters are passed then I store them in properties of the helper and return, and when called without passing the parameters it performs the work. So it would look like this:
From controller:
$this->view->myHelper($this->user->getId(), $this->_getModelConfig());
From view:
<?= $this->myHelper(); %>
Helper:
class Zend_View_Helper_MyHelper extends Zend_View_Helper_Abstract
{
public $userId = '';
public $config = null;
public function myHelper ($userId = null, $config = null)
{
if ($userId) {
$this->userId = $userId;
$this->config = $config;
} else {
//do the work
$obj = new SomeModel($this->config);
$states = $obj->fetchByUser($this->userId);
//do the work here
}
return $this;
}
}
Any advice is welcomed!
Firstly the ASP style ending tag here at "$this->myHelper(); %>" is bad practice, with that said it is more advisable to keep the logic in the model and the controller just being used to call the model, get the results and spit that to the view for viewing.
what I would do is, if i simply want to pass a bunch of values to the view, i stuff them in an associative array and send them over.
anyway you should not be doing your ...
"//Fair amount of logic here using this result to prepare some javascript that should be sent to the view..."
part in the controller, I would advice you to make a new model that does that logic stuff for you, and you just call your model in the controller pass it what ever arguments that are needed and then spit the result of that to the view.
The best way is to get the data from your model throught your controller, and then pass to the view. But if you really need a custom helper to echo the view parts, we only will know if you say exactly what you're trying to do.
If you already have this logic in a helper, try to just pass the parameters in your view myhelper($this->params); ?>
You may want take a look at this approach too:
// In your view to put javascript in the header
// You can loop trought your data and then use it to generate the javascript.
<?php $this->headScript()->captureStart(); ?>
$().ready(function(){
$('#slideshow').cycle({
fx: 'fade',
speed: 1000,
timeout: 6500,
pager: '#nav'
});
});
<?php $this->headScript()->captureEnd() ?>

Resources