I'm trying to return the result of a task from a subcontroller with the following url:
index.php?option=com_example&task=subctrl.test&format=json
but I keep getting the 500 View not found Error...
class ExampleControllersSubctrl extends JControllerForm
{
public function test()
{
$result= array("val1","val2");
echo json_encode($result);
}
}
I've tried naming the subcontroller file both Subctrl.php & Subctrl.json.php but neither worked. I believe I shouldn't need a view to render the result based on other SO posts I've read but maybe that is incorrect.
This setup will eventually be used to return an Ajax call when I get it working.
What am I doing wrong here?
Add an exit statement after the echo statement or Joomla will continue processing the component and will try to call a view. Since no view value was set, no view will be found and the system will redirect to an error page. Full code below:
class ExampleControllerSubctrl extends JControllerForm
{
public function test()
{
$result= array("val1","val2");
echo json_encode($result);
exit();
}
}
Joomla also some other methods that you can use such as call jexit() or JFactory::getApplication()->close(). The general idea is to get the application to stop here. Continuing is a waste.
Also, had to make sure the class name is set right. Middle work should be Controller not Controllers.
The problem is that you're extending JControllerForm which will try and guess the view for your form if one isn't provided.
On Joomla 2.5 you can change JControllerForm to JController and that will resolve the problem.
As you have a JSON controller that Joomla is routing you to via format=json you don't need an exit on your test() method either.
Related
I am developing an Api in Cakephp. I need to handle the exception if android app calls wrong function or wrong controller. I need to know how can I can handle that and return the response in json to my android app. I mean I know I can write something in my beforefilter function because this function will execute first But I don't know how I can catch first the exception or how can I detect the event. By Googling I come to some solution but still it is not working. Here is my code below which I have tried.
App/Lib/AppErrorHandler.php
class AppErrorHandler extends ExceptionRenderer{
public static function handleException($error) {
if ($error instanceof MissingActionException) {
echo "incorrect controller action name";
exit;
}
}
}
?>
in bootstrap.php
App::uses('AppErrorHandler', 'Lib');
I didn't do anything in my Api regarding exception. Please let me know if I have to write some code in Api class too
You are extending ExceptionRenderer for your custom ExceptionHandler, which is the right way. Now you are trying to override method handleException which basically is not present in the baseClass. So Its wrong to do that..
Now for your solution:
You need to override function render() from ExceptionRenderer class. The way you do it is below:
class AppErrorHandler extends ExceptionRenderer{
public function render() {
if ($this->method) {
if($this->error instanceof MissingActionException) {
// echo here whatever you want..
}
call_user_func_array(array($this, $this->method), array($this->error));
// this line is required to render the normal page as per the error code.. 400 or 500 or similar..
}
}
}
P.S: in lib/Cake/Error you will find the files which handle the default exceptions. Here in exceptions.php you will find the different errors which are thrown or can be thrown.
I have a PHP class where I have to invoke PHP header function to show a webpage. As pointed out from this post, header should be followed by exit callback. Since this situation is very common in my classes, I've defined a method in parent class:
class ParentClass
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
I would like to invoke this method from children classes:
class ChildClass extends ParentClass
{
public function someFunc()
{
$this->header($some_url);
}
}
PHP documentation says that exit terminates the current script. My question is: does the exit function terminate child script even if it is contained in parent class?
EDIT
In my specific situation, I am using a MVC design pattern and ChildClass is a controller. Inside it, sometimes I need to show a view, sometimes I need to redirect to another url. Let me explain it with a practical example.
Suppose to have a website with a login section. When login page is displayed to users (login data not submitted), login controller should show login view. This view contains a form with an action like action="login.html". When data is submitted, login controller is invoked and checks login data: if login is successful, user is redirected to his admin section.
class UsersController extends BaseController
{
public function login()
{
try
{
if(isset($_POST['submit']))
{
// check login data, throw exception in case of error
// if success, redirect to admin section
$this->header('admin.html');
}
else
{
// show login view
}
}
catch(Exception $e)
{
// show login view (with error)
}
}
}
class BaseController
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
Since this situation is quite common in my controllers, I've preferred to define a header method in BaseController instead of typing everytime
header('Location:someURL.html');
exit;
In my OP, I only wanted to be sure that $this->header('admin.html'); callback would terminate current login method, even if it is defined in BaseController script.
Hope it's a little clearer now.
As already descripted in the comment, exit will terminate everything, i.e. the webpage immediately stops executing, including clean up functions and finally blocks.
So, you should consider using exit very carefully because many things might happen: data doesn't get written to the database when you're not using auto-commit (unless you commit the data before calling exit). Auto-commit is not enabled by default in PHP's MySQL module (as far as I know).
Here is an example:
class B extends A {
public function someFunc() {
# you might wanna use partent instead as
# pointed out by Ding in the comments, but
# maybe someFunc does more that just doing
# the redirect.
$this->header("http://google.com");
}
}
try {
print("Ok...");
$obj = new B();
$obj->someFunc();
print("Nahh..."); # doesn't get called/
} finally {
print("Cleaning up."); # doesn't get called, either.
}
Instead of calling the exit method, you should rather implement a clear MVC design pattern. Here is a very quick example:
<?php
class Response {
# use private here and use appropriate
# getters and setters.
public $status_code = 200;
public $content = "";
public $headers = array();
}
class HomeView extends View {
# called when a get request is made.
public function get() {
$response = new Response();
$response->content = "Hello world."
}
}
class RedirectionView {
public function get() {
$response = new Response();
$response->status_code = 301; # use 302 if moved only temporarily.
$response->headers["Location"] = "http://google.com";
}
}
function processRequest() {
# load appropriate view programatically
$view = new RedirectionView();
$response = $view->get();
http_response_code($response->status_code);
foreach ($response->headers as $headerName => $headerValue) {
header(sprintf("%s: %s", $headerName, $headerValue));
}
print($view->content)
}
?>
Note that this is not really a MVC design pattern (the model is missing and, well, it's not clear what the controller, however, that's what django (a Pyhton framework) uses, too). You might wanna check out PHP MVC frameworks (a quick google search will do the trick) or implement your own (my example might be a good start).
Edit 1:
Using exit is probably ok (but I wouldn't use it because I believe it is bad practice). If you're able to edit the design approach you're using, I'd make your View BaseClass get/post method (or whatever you're the method that returns response object. Note: if you're using prints to show the response to the user, try to add a Response which contains all the data you're request needs to show. This is better than having prints (or echos) everywhere in your code).
Using the response object, your code would then be able to either just set the location header (if it's a redirect) or show the message. So you don't need to "kill" any part of the webpage and it will terminal when the execution ends. But again: you're probably good to go with an exit call in your method (unless you're encountering any issues with your code (database transactions that aren't committed, statistic data that is not updated (because its after the exit statement). Exit will simply terminate your script completely.
I'm relatively new to the laravel framework and i noticed a pretty disturbing issue with laravel controllers. I dont know if its me but it doesnt seem to work at all. Lets say i have a controller and i want to split the logic contained in the method called when the request hits a route tied to the controller.
class SomeController extends BaseController
{
function doSomething()
{
$this->doSomethingExtra();
}
function doSomethingExtra()
{
return "Something Extra Done";
}
}
And lets say a have to route defined like so
Route::get('main/dashboard','SomeController#doSomething');
the second method called from the first never returns the string "Something Extra Done" to the browser. infact it returns an empty 200 response. However this seems to work when you return response from the doSomething() as usual. Anyone know why this is behaving this way? is there anyway to breakup a controller logic into several Methods that actually return responses to the client?
Change this
$this->doSomethingExtra();
to this.
return $this->doSomethingExtra();
I am calling one controller method from another controller's method. I can confirm that the method is being called because when I do a print_r on the passed data, I see everything I expect. My problem is that when I call $this->Log->save($this->data) nothing is written to the DB. I am a .NET developer, hence I know preciously little about cakePHP, but I know that this is the way one is supposed to save stuff to the DB, hence I am majorly stumped.
<?php
//The calling controller
App::import('Controller', 'Logs');
class othAuthComponent extends Object //I noticed this inherits from Object,
//but it doesn't seem to be a problem
{
function SomeFunction()
{
//create instance of our Logs controller as per example
$Logger = new LogsController;
$Logger->constructClasses();
$Logger->cms_addlog($user['User']['name'].' Logged in', $user['User']['id']);
}
}
?>
And the offender:
<?php
//the called controller
class LogsController extends AppController
{
function cms_addlog($note,$ba_id)
{
$this->Log->create();
$curDateTime = getdate();
$this->data['LogTime'] = $curDateTime;
$this->data['Note'] = $note;
$this->data['brandactivatorid'] = $ba_id;
//print_r($this->data);
//die();
$this->Log->save($this->data);
}
}
?>
The correct way to do this is to make the cms_addlog function part of the Log model.
Then call
$this->Log->cms_addlog($user['User']['name'].' Logged in', $user['User']['id']);
You're not supposed to call Controller actions/methods from anywhere in your code. Controller actions are meant to be directly accessed from the browser.
The clean way is to implement a addLog method in your model and call that one either from the controller, or from the component.
Please read http://book.cakephp.org/2.0/en/getting-started/cakephp-structure.html and http://book.cakephp.org/2.0/en/cakephp-overview/understanding-model-view-controller.html for further reference.
I am performing the jquery POST correctly, however I would like to call another PHP function inside the controller. EDIT The code below works fine....I'm just an idiot. Someone close this please.
Here is the setup:
class controller extends CI_Controller {
function con1() {
//retrieve post variable
$this->con2()
}
function con2() {
//do something
$this->my_model->get_results() //fails
}
}
Jquery POSTS to con1, however it will fail when i do $this->con2(). Is there anyway I can get this to work? Also, is it possible to call a model once jquery posts the data?
Thanks
It's not really clear what you aren't able to do, but why are you juggling with controller's methods, when model are done just for that?
The purpose of a Model is being something re-usable, so why don't you call it right in con1() method?
class Controller extends CI_Controller {
function con1() {
$this->load->model('my_model');
//retrieve post variable
echo $this->my_model->get_results();
}
}
Also, post variable are available to Models also, if you want to grab their values there.
If you expand your answer with further details I'll edit and update my question, so far it's just a bit of a guessing on what's wrong. The code I showed should work, provided the get_result() method actually returns something (which you need to echo out).
If by "how do I call a function within a model" means how you call a model's method inside another model's method, well, it works like any php class method's call, $this->other_method();
Haven't used codeigniter but I suspect redirecting to con2 within con1 with the post array would fix the issue.