I want to use some ajax, but I don't know how to use function as the same as setNoRender() in zend framework 2 to disable for render view.
How to disable rendering view in zend framework 2?
To disable your view :
public function myactionAction()
{
// your code here ...
return false;
}
"return false" disables the view and not the layout! why? because the accepted types are:
ViewModel
array
null
so "false" disable the view.
To disable layout and view, return a response object:
public function myactionAction()
{
// your code here ...
return $this->response;
}
To disable layout:
public function myactionAction()
{
// your code here ...
$view = new ViewModel();
$view->setTerminal(true);
return $view;
}
If you're using JSON, then look at the view's JsonStrategy and return a JsonModel from you controller. See this article.
Alternatively, you can return an Response from your controller and the whole view layer is skipped:
public function testAction()
{
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent('foo');
return $response;
}
Proper and simple solution to do this
public function testAction()
{
$data = array(
'result' => true,
'data' => array()
);
return $this->getResponse()->setContent(Json::encode($data));
}
Details: http://cmyker.blogspot.com/2012/11/zend-framework-2-ajax-return-json.html
I found some answer.
Though $this->layout()->getLayout() returns the name/path of the newly selected layout... The layout does not change with any of the following commands...
within a controller
$this->getLocator()->get('view')->layout()->setLayout('layouts/ajax.phtml');
$this->getLocator()->get('view')->layout()->setLayout('ajax');
$this->getLocator()->get('view')->layout()->disableLayout();
within a view PHTML file
$this->layout()->setLayout('layouts/ajax.phtml');
$this->layout()->setLayout('ajax');
$this->layout()->disableLayout();
$view = new ViewModel();
$view->setTerminate(true);
...
use Zend\View\Model\JsonModel;
public function myAction() {
...
$view = new JsonModel($myArray);
$view->setTerminal(true);
return $view;
}
Related
How to access Model from Views in Codeigniter.
I have a Model with a function, i need to call this function from view
Please Read the CI documentation First:
If You are using a MVC Structured Framework then you should be following the way it works.
You Need the Controller:
public function your_controller_function(){
// To load model
$this->load->model ('your_model');
//To Call model function form controller
$data = $this->your_model->model_function($ex_data);
//TO Send data to view
$this->load->view('your_view',['data'=>$data]);
}
Inside your model:
public function model_function($ex_data){
// Your Querys
// user return to send you query result to the controller anything
// Sample Example of query and return
$query = $this->db->select('*')
->where('your_column',$data['column_name'])
->get('your_table');
$your_result = $query->row_array();
if($this->db->affected_rows() > 0){
return your_result;
} else {
return FALSE;
}
}
Inside your view you can write :
<?php
$this->load->model('your_model');
$this->your_model->some_function();
?>
For example in User_controller load User Model $this->load->model('Users_model');
Then User View page $viewpage = this->Users_model->somefunction($id);
I'm using codeigniter, for make an api rest, with the library that provide the oficial web site.
The problem is: the file routes.php doesn't redirect well. When i put localhost/API/1 into my browser apear the 404 error.
Here my controller "Apicontroller":
public function __construct() { //constructor //no tocar
parent::__construct();
$this -> load -> model("Modelocontrolador");
}
public function index_get() { //get all the info
$datos_devueltos = $this->Modelocontrolador->getPrueba(NULL, "Usuarios");
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}
public function find_get($id){ //select where
$datos_devueltos = $this->Modelocontrolador->getPrueba($id, "Usuarios");
if($id != NULL){
if(!is_null($datos_devueltos)){
$this->response(array("response" => $datos_devueltos), 200);
}else{
$this->response(array("response" => "No date"), 200);
}
}else{
$this->response(array("response" => "No dates for search"), 200);
}
}
public function index_post() { //insert in la table
if(! $this -> post("dato")){
$this->response(array("response" => "No enought info"), 200);
}else{
$datoID = $this -> Modelocontrolador -> save($this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => $datoID), 200);
}else{
$this->response(array("response" => "No found it"), 200);
}
}
}
public function index_put($id) { //"update"
if(! $this -> post("dato") || ! $id){
$this->response(array("response" => "No ha mandado informacion correcta para el update"), 200);
}else{
$datoID = $this -> Modelocontrolador -> update("Uid",$id,$this -> post("dato"),"UsuariosJJ");
if(!is_null($datoID)){
$this->response(array("response" => "Dato actualizado"), 200);
}else{
$this->response(array("response" => "Error modify"), 200);
}
}
}
public function index_delete($id) {
if(! $id){
$this->response(array("response" => "Not enought info"), 200);
}else{
$delete = $this-> Modelocontrolador -> delete("Uid",$id,"UsuariosJJ");
}
if(!is_null($delete)){
$this->response(array("response" => "Date delete"), 200);
}else{
$this->response(array("response" => "Error delete"), 200);
}
}}
And my routes file:
$route['default_controller'] = 'Apicontroller';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
/*sub-rutas*/
/*---------*/
$route["Apicontroller"]["get"] = "Apicontroller/index"; //basico
$route["Apicontroller/(:num)"]["get"] = "Apicontroller/find"; //select
$route["Apicontroller"]["post"] = "Apicontroller/index"; //insert
$route["Apicontroller/(:num)"]["put"] = "Apicontroller/index/$1"; //update
$route["Apicontroller/(:num)"]["delete"] = "Apicontroller/index/$1"; //delete
If the browser request literally uses /API then routing needs to 'see' exactly that. Also, the route rules must be explicit with the method to be called. (Hopefully the code shown reflects the mapping you had in mind.)
/*sub-rutas*/
/*---------*/
$route["API"]["get"] = "Apicontroller/index_get"; //basico
$route["API/(:num)"]["get"] = "Apicontroller/find_get/$1"; //select
$route["API"]["post"] = "Apicontroller/index_post"; //insert
$route["API/(:num)"]["put"] = "Apicontroller/index_put/$1"; //update
$route["API/(:num)"]["delete"] = "Apicontroller/index_delete/$1"; //delete
Using the above routes I created some test code. Here are those files.
The much simplified Apicontroller.
class Apicontroller extends CI_Controller
{
function __construct()
{
parent::__construct();
}
function index_get()
{
echo "API index";
}
public function find_get($id)
{ //select where
echo "API find_get $id";
}
public function index_post()
{
echo 'API index_post';
}
public function index_put($id)
{ //"update"
echo "API put $id";
}
}
I don't believe that because your Apicontroller is extending a different Class the results would change. That may be a drastic assumption.
In order to test POST calls I used these two files.
First a Testpost.php controller
class Testpost extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->helper('form');
}
public function index()
{
$this->load->view("test");
}
}
The very simple view (test.php) loaded by the above.
<?php
echo form_open("API");
echo form_submit('mysubmit', 'Submit Post!');
echo form_close();
Directing the browser to localhost/testpost shows a page with a single submit button. Pressing the button results in a screen with the text "API index_post".
Sending the browser to localhost/API/3 produces a screen with the text "API find_get 3".
localhost/API produces "API index".
Now the interesting thing (not related to your problem, but interesting).
Given the default
$route['default_controller'] = 'Apicontroller';
and the route
$route["API"]["get"] = "Apicontroller/index_get";
I expected that directing the browser to the home page localhost would produce "API index". But it doesn't. It results in a 404. Due to that behavior it might be wise to be more explicit with default_controller
$route['default_controller'] = 'Apicontroller/index_get';
Or add an index() function to Apicontroller that calls $this->index_get().
I did not test PUT or DELETE as my server isn't setup to handle them. But as GET and POST seem to function, in a righteous world, they will work.
seems like you are using PHil's REST_Controller library with CI 2.x, correct ?
If so, I would recommend you to use what I like to call an "index gateway" because you can't do per-Method routing with CI2:
class Apicontroller extends REST_Controller
{
function index_gateway_get($id){
$this->get_get($id);
}
function index_gateway_put($id){
$this->put_put($id);
}
// This is not a "gateway" method because POST doesn't require an ID
function index_post(){
$this->post_post();
}
function get_get($id = null){
if(!isset($id)){
// Get all rows
}else{
// Get specific row
}
}
function put_put($id = null){
if(!isset($id)){
// a PUT withtout an ID is a POST
$this->post_post();
}else{
// PUT method
}
}
function post_post(){
// POST method
}
}
The routing to make this work is really easy:
$route["API/(:num)"] = "Apicontroller/index_gateway/$1";
That's all you need. Phil's REST Library will redirect to the correct index_gateway_HTTPMETHOD depending on which method is used.
Each index_gateway_HTTPMETHOD will then redirect to the correct method.
As far as I know, this trick is the only way to have CI2 use a single /API/ entry point that works for all HTTP Methods.
Accessors will do their job on a single attribute perfectly, but I need a way to have a method to do an Accessor/Getter job on all attributes and automatically.
The purpose is that I want to replace some characters/numbers on getting attributes and then printing them out. I can do it from within controller and manually but I think it would be great to have it from model side and automatically.
Like overriding getAttributes() method:
public function getAttributes()
{
foreach ($this->attributes as $key => $value) {
$this->attributes[$key] = str_replace([...], [...], $value);
}
return $this->attributes;
}
But I have to call it every time on model $model->getAttributes();
Any way to do it automatically and DRY?
Try something like:
public function getAttribute($key)
{
if (array_key_exists($key, $this->attributes) || $this->hasGetMutator($key)) {
if($key === 'name') return 'modify this value';
return $this->getAttributeValue($key);
}
return $this->getRelationValue($key);
}
It's fully overriding the default method so be a bit careful.
EDIT
Also check out: http://laravel.com/docs/5.1/eloquent-mutators
I would go with following approach and override the models __get method:
public function __get($key)
{
$excluded = [
// here you should add primary or foreign keys and other values,
// that should not be touched.
// $alternatively define an $included array to whitelist values
'foreignkey',
];
// if mutator is defined for an attribute it has precedence.
if(array_key_exists($key, $this->attributes)
&& ! $this->hasGetMutator($key) && ! in_array($key, $excluded)) {
return "modified string";
}
// let everything else handle the Model class itself
return parent::__get($key);
}
}
How about running it with each Creating and Updating events. So you can do something like that:
public function boot()
{
Model::creating(function ($model)
return $model->getAttributes(); //or $this->getAttributes()
});
Model::updating(function ($model)
return $model->getAttributes(); //or $this->getAttributes()
});
}
I'm new to cakePHP. Needless to say I don't know where to start reading. Read several pages about AJAX and JSON responses and all I could understand is that somehow I need to use Router::parseExtensions() and RequestHandlerComponent, but none had a sample code I could read.
What I need is to call function MyController::listAll() and return a Model::find('all') in JSON format so I can use it with JS.
Do I need a View for this?
In what folder should that view go?
What extension should it have?
Where do I put the Router::parseExtension() and RequestHandlerComponent?
// Controller
public function listAll() {
$myModel = $this->MyModel->find('all');
if($this->request->is('ajax') {
$this->layout=null;
// What else?
}
}
I don't know what you read but I guess it was not the official documentation. The official documentation contains examples how to do it.
class PostsController extends AppController {
public $components = array('RequestHandler');
public function index() {
// some code that created $posts and $comments
$this->set(compact('posts', 'comments'));
$this->set('_serialize', array('posts', 'comments'));
}
}
If the action is called with the .json extension you get json back, if its called with .xml you'll get xml back.
If you want or need to you can still create view files. Its as well explained on that page.
// Controller code
class PostsController extends AppController {
public function index() {
$this->set(compact('posts', 'comments'));
}
}
// View code - app/View/Posts/json/index.ctp
foreach ($posts as &$post) {
unset($post['Post']['generated_html']);
}
echo json_encode(compact('posts', 'comments'));
// Controller
public function listAll() {
$myModel = $this->MyModel->find('all');
if($this->request->is('ajax') {
$this->layout=null;
// What else?
echo json_encode($myModel);
exit;
// What else?
}
}
You must use exit after the echo and you are already using layout null so that is OK.
You do not have to use View for this, and it is your wish to work with components. Well all you can do from controller itself and there is nothing wrong with it!
Iinjoy
In Cakephp 3.5 you can send json response as below:
//in the controller
public function XYZ() {
$this->viewBuilder()->setlayout(null);
$this->autoRender = false;
$taskData = $this->_getTaskData();
$data = $this->XYZ->getAllEventsById( $taskData['tenderId']);
$this->response->type('json');
$this->response->body(json_encode($data));
return $this->response;
}
Try this:
public function listAll(){
$this->autoRender=false;
$output = $this->MyModel->find('all')->toArray();
$this->response = $this->response->withType('json');
$json = json_encode($output);
$this->response = $this->response->withStringBody($json);
}
I have this code in my controller (admin):
function save(){
$model = $this->getModel('mymodel');
if ($model->store($post)) {
$msg = JText::_( 'Yes!' );
} else {
$msg = JText::_( 'Error :(' );
}
$link = 'index.php?option=com_mycomponent&view=myview';
$this->setRedirect($link, $msg);
}
In model I have:
function store(){
$row =& $this->getTable();
$data = JRequest::get('post');
if(strlen($data['fl'])!=0){
return false;
}
[...]
And this is working - generate error message, but it return to items list view. I want to stay in edit view with entered data. How to do it?
In your controller you can:
if ($model->store($post)) {
$msg = JText::_( 'Yes!' );
} else {
// stores the data in your session
$app->setUserState('com_mycomponent.edit.mymodel.data', $validData);
// Redirect to the edit view
$msg = JText::_( 'Error :(' );
$this->setError('Save failed', $model->getError()));
$this->setMessage($this->getError(), 'error');
$this->setRedirect(JRoute::_('index.php?option=com_mycomponent&view=myview&id=XX'), false));
}
then, you will need to load the data from session with something like:
JFactory::getApplication()->getUserState('com_mycomponent.edit.mymodel.data', array());
normally this is loaded in the method "loadFormData" in your model. Where to load that data will depend on how are you implementing your component. If you are using the Joomla's form api then you can add the following method to your model.
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_mycomponent.edit.mymodel.data', array());
if (empty($data)) {
$data = $this->getItem();
}
return $data;
}
EDIT:
BUT please note, that Joomla's API already can do all this for you if you controller inherits from "JControllerForm", you don't need to rewrite the save method. The best way to create your component is copying what is in Joomla's core components, com_content for example
It is not recommended to rewrite save or any method.
If you really want to override something and want to update something before or after save, you should use JTable file.
For Example:
/**
* Example table
*/
class HelloworldTableExample extends JTable
{
/**
* Method to store a node in the database table.
*
* #param boolean $updateNulls True to update fields even if they are null.
*
* #return boolean True on success.
*/
public function store($updateNulls = false)
{
// This change is before save
$this->name = str_replace(' ', '_', $this->name);
if (!parent::store($updateNulls))
{
return false;
}
// This function will be called after saving table
AnotherClass::functionIsCallingAfterSaving();
}
}
You can extends any method using JTable class and that's the recommended way to doing it.