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

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);
}

Related

Laravel with() together Table or Variable Name

I was reading a blog related Repository Pattern. I saw use of withBlogs method.
public function index()
{
$blogs = $this->blogRepository->all();
return view('blog')->withBlogs($blogs);
}
I never see something like this before. What is the purpose of it or what it's doing?
it is laravel's magic methods
you can name the method anything you want with with() in laravel
let me explain you by example, the following code you write in your controller method
return view('index')->withName('Name')->withFullName('Full Name')->withaddress('Your address')->withcountryName('CountryName');
then you can access the values in view explained below
withName('Name') in view it becomes $name
withFullName('Full Name') in view it becomes $fullName
withaddress('Your address') in view it becomes $address
withcountryName('CountryName') in view it becomes $countryName
It is used for passing data into views. The with method returns an instance of the view object so that you can continue chaining methods before returning the view. All of the syntax below archives the same thing:
return view('blog')->withBlogs($blogs);
return view('blog')->with('blogs', $blogs);
return view('blog')->with(compact('blogs'));
return view('blog', compact('blogs'));

Laravel 4: Responding to AJAX requests from controller

I'm trying to generate ajax specific responses from my controllers by using the Request::ajax() method, which is working just fine. The only problem is that the way I have it set up right now isn't really a nice looking solution.
My controller:
class HomeController extends BaseController {
protected $layout = 'layouts/main';
public function __construct()
{
$this->beforeFilter('auth');
}
public function getIndex()
{
$view = View::make('content.home.index');
if(Request::ajax()) return $view; //For ajax calls we only want to return the content to be placed inside our container, without the layout
$this->layout->menu = 'content.menu';
$this->layout->content = $view;
}
}
So right now, for every method I define within my controllers I need to add the code snippet that checks for an AJAX request and returns a single view if the statement returns true.
This leads to my question that is probably more PHP related than it is to the framework;
Is there a way of executing my AJAX check on every method call, without actually placing it inside the method? Or is there some other solution to keep my code DRY?
Thanks in advance!
PS: This is my first post on stackoverflow, so feel free to correct me if I made any mistakes
Create a new barebone layout named 'layouts/ajax' (or any name you like).
<?php echo $content ?>
In your Base controller, override this setupLayout() function.
protected function setupLayout()
{
if ( ! is_null($this->layout))
{
$layout = Request::ajax() ? 'layouts/ajax' : $this->layout;
$this->layout = View::make($layout);
}
}
Change your getIndex() function to this.
public function getIndex()
{
$view = View::make('content.home.index');
$this->layout->menu = 'content.menu';
$this->layout->content = $view;
}
Now non-ajax requests will be rendered using layout set in the controller, where as ajax requests will receive whatever set to $this->layout->content.
Note : Controller will neglect the layout setup in setupLayout(), if the called method returns truthy value. So this method will not work for functions like below.
public function getIndex()
{
return View::make('content.home.index');
}
You could just change the layout property, in the constructor, if it's an ajax request:
public function __construct()
{
$this->beforeFilter('auth');
if(Request::ajax()) {
$this->layout = '';
}
}
If it doesn't work try setting it to NULL instead.
Why would you return a VIEW via ajax? Are you using it to create a SPA? If so there are better ways. I'm generally against returning HTML via AJAX.
The route I'd go in your position is probably opposite of how you're doing it. Render the view no matter what, if the request is ajax, pass the extra data back and have JS render the data on the page. That's essentially how most Javascript MVC frameworks function.
Sorry if I am totally missing the point here, just going on an assumption of your end goal with the info you provided.

How can I debug $Model after 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());

Should I call redirect() from within my Controller or Model in an MVC framework?

I'm using the MVC PHP framework Codeigniter and I have a straight forward question about where to call redirect() from: Controller or Model?
Scenario:
A user navigates to www.example.com/item/555. In my Model I search the item database for an item with the ID of 555. If I find the item, I'll return the result to my controller. However, if an item is not found, I want to redirect the user somewhere. Should this call to redirect() come from inside the model or the controller? Why?
No your model should return false and you should check in your controller like so:
class SampleModel extends Model
{
//Construct
public function FetchItem($id)
{
$result = $this->db->select("*")->from("table")->where("item_id",$id)->get();
if($result->num_rows() == 0)
{
return false;
}
//return result
}
}
and within your controller do:
function item($id)
{
$Item = $this->SampleModel->FetchItem($id);
if(!$Item)
{
redirect("class/error/no_item");
}
}
Models are for data only either return a standard result such as an key/value object or a boolean.
all logic should be handled / controlled by the Controller.
Models are not page specific, and are used globally throughout the whole application, so if another class / method uses the model, it might get redirect to the incorrect location as its a different part of your site.
It seems like the controller would be the best place to invoke your redirect because the controller typically delegates calls to the model, view, or in your case, another controller.
However, you should use whatever makes the most sense for your application and for what will be easier to maintain in the future, but also consider that rules do exist for a reason.
In short, if a coworker were to try to fix a bug in your code, what would the "reasonable person" standard say? Where would most of them be most likely to look for your redirect?
Plus, you said you're returning the result to your controller already... perhaps that's where you should make your redirect...

Codeigniter: Calling a method from a view

Here's my model, what it does is pulls a particular post from a user. Each post may also have comments, which are stored in an array called comments. I have everything working and I'm able to display the post along w/ the comments. The issue is, each comment has a post_date that displays when the comment was made. I need to call the function that "converts" the date into something like "3 weeks ago." The method TimeAgo is located in my user_model.php page. The excerpt shows a variable called data that's actually for the post, the comment is embedded inside the array and I loop through that in my view.
So the question is, is there a better way of handling this or do I have to call the TimeAgo method from within the view page?
Note, I'm using mongodb but it shouldn't matter if it's mongodb or mysql. Same thing ...
user_model.php
$query = array("_id" => new MongoId($plan_id), "username" => $username);
$fields = array("plan_title", "comments", "post_date");
$data = $collection_plans->findOne($query, $fields);
$data['date'] = self::TimeAgo($data['post_date']->sec);
$data['username'] = $username;
return $data;
If my understanding is correct I'd put the TimeAgo method inside a library or helper, then (auto)load whenever necessary and process the date before passing it to the view from within the controller.
this would allow you to access that method from within another model if required, or indeed any other part of your CI app, rather than from just within user_model.php
You call the model method from the controller and put it into a variable. You then pass the var to the view.

Resources