Overriding the default controller method using restfull Yii extension - php

I am building on an application in which i need to built the API's and then i found this extenison : Link below ->
https://github.com/evan108108/RESTFullYii
But i was wondering that how to override the existing methods present in the controller.
For eg.
I have my actionView method as follows:
public function actionView($id) {
$this->render('view', array(
'model' => $this->loadModel($id),
));
}
And this outputs me the all the fields from the database. But the thing i want is that i should write some logic and the output should be generated according to my logic.
Please help me. I am stuck???

Related

How to make the controller data override view controller in Laravel?

To build a sidebar that has a lot of dynamic data on it I learned about View composers in Laravel. The problem was that View Composers trigger when the view loads, overriding any data from the controller for variables with the same name. According to the Laravel 5.4 documentation though, I achieve what I want with view creators :
View creators are very similar to view composers; however, they are
executed immediately after the view is instantiated instead of waiting
until the view is about to render. To register a view creator, use the
creator method:
From what I understand, this means if I load variables with the same name in the controller and the creator, controller should override it. However this isn't happening with my code. The view composer:
public function boot()
{
view()->creator('*', function ($view) {
$userCompanies = auth()->user()->company()->get();
$currentCompany = auth()->user()->getCurrentCompany();
$view->with(compact('userCompanies', 'currentCompany'));
});
}
And here is one of the controllers, for example:
public function name()
{
$currentCompany = (object) ['name' => 'creating', 'id' => '0', 'account_balance' => 'N/A'];
return view('companies.name', compact('currentCompany'));
}
the $currentCompany variable in question, for example, always retains the value from the creator rather than being overridden by the one from the controller. Any idea what is wrong here?
After some research, I realized my initial assumption that the data from the view creator can be overwritten by the data from the controller was wrong. The creator still loads after the controller somehow. But I found a simple solution.
For those who want to use View composers/creators for default data that can get overwritten, do an array merge between the controller and composer/creator data at the end of the boot() method of the composer/creator, like so:
$with = array_merge(compact('userCompanies', 'currentCompany', 'currentUser'), $view->getData());
$view->with($with);

How to custom render function of Yii2 framework

I want to change views folder of yii2 to structure bellow
views
----default
----site
----index.php
----error.php
----login.php
In the siteController i'm using code bellow
public function actionIndex(){
return $this->render('default/index');
}
and error
The view file does not exist: D:\wamp\www\yii2\backend\views\site\default/index.php
Please help me
With your current code, the Site Controller search the view file under his view's folder /views/site, you need to get the right path:
$this->render('../default/site/index');
I suggest to create an alias for be more flexible, like #default_views in your main-local file:
'aliases' => [
'#default_views' => '../default/',
So, the function:
public function actionIndex(){
return $this->render(Yii::getAlias('#default_views') . 'site/index');
}

Laravel 4 RESTful API - resource controller - deeper request hierarchy

I'm building my frontend part of the API system.
Using default Resource Controller's by Laravel you can achieve this type of requests:
http://superapi.com/v1/soccer/10
Which will call the:
/app/controllers/SoccerController.php # show($id) method
I need at least one more level of depth, to be able to do it like this:
http://superapi.com/v1/soccer/player/10
So it will resolve to:
/app/controllers/SoccerController.php # show() method having both, "player" and "10" arguments.
public function show($model)
{
return Response::json(array('success' => true, 'message' => 'Test ' . $model));
}
Laravel passes only 1 parameter to method, and I cannot find anything about how to pass more.
I'm doing this basically because my 1 controller is responsible for talking to a few Models, not just one. Either SoccerPlayer or SoccerTeam or SoccerSchedule, it all should be nicely put under
/v1/<controller>/<type>/<id>
Advices?
Thanks!
You can have the best of both worlds anyway, by placing a custom route before the resource route:
Route::get('soccer', 'SoccerController#show');
Route::resource('soccer', 'SoccerController', array('except' => array('show')));
Now the show() method will be escluded from the resource controller control (thus calling soccer/10 or soccer/player will lead to a NotFoundHttpException), and placed into your custom route.
You'll need to edit the show() method to accept the second parameter though:
public function show($type, $id)
{
}
you can use route prefixing
Route::group(array('prefix' => 'soccer'), function()
{
Route::resource('player', 'PlayerController');
});
then, you can put all soccer relavant controllers in the same namespace (and same folder) like Soccer. in this case, change the above route to
Route::resource('player', 'Soccer\PlayerController');

How to implement Zend routing with Ajax

i am new to zend and i could not find a way to implement Ajax in zend.
In general php, its pretty easy to make an ajax request and show the response in the desired part of our page. But coming to zend, i have no clue how to do it.
Suppose in my index controller's index.phtml file, i have a button, and when i click on it, i have to make an ajax request to a particular controller and action, and load the related controller action's view in my page.
But what i could not understand is how to specify the urls for the ajax request and how the routing works.
Currently, i made ajax request to load the view statically like this:
xmlhttp.open("GET","../application/views/scripts/register/register.phtml",true);
FYI, i am using regex routing in my application, so would it be better to use curl to route the requests?
First things first, you don't request the view directly. You need to request the specific controller action, eg
/register/register
Zend comes with a great action helper called AjaxContext. This helper lets you respond with a different view based on the type of request (XmlHttpRequest) and a format parameter, disabling any layouts normally present.
To set it up, place something like this in your controller's init() method
public function init()
{
$this->_helper->ajaxContext->addActionContext('register', 'html')
->initContext();
}
Then, add a view script with the ajax suffix, eg register/register.ajax.phtml.
Construct your AJAX GET request to include the format=html parameter, eg
xmlhttp.open('GET', '/register/register/format/html', true);
or
xmlhttp.open('GET', '/register/register?format=html', true);
What will be returned is the rendered contents of register.ajax.phtml, without any layouts.
Apart from what the other answers stated, there's also a URL view helper function that can be useful to call a specific action on a controller. So you could just use $this->url(array('controller' => 'your_controller', 'action' => 'your_action'), 'default', true); to get the link to "your_action" action on the "your_controller" controller (using the default route). You could also specify a specific route instead of 'default' if you have one defined.
So for your example you would use something like the following in your view phtml file (if you're using the default routing) :
xmlhttp.open("GET","<?php echo $this->url(array('controller' => 'register', 'action' => 'register'), 'default', true);?>");
For more information refer to Zend Framework - View Helpers.
You should never be requesting the view directly. That's just wrong. Request URI like this:
xmlhttp.open("GET","/register/register");
Which means "I am looking for default module, register controller and register action", or in other words RegisterController::registerAction().
It's the same as:
xmlhttp.open("GET","/default/register/register");
Which is the same, the default module can be omitted.
Zend Framework knows where to look for the view script (unless you are using some unusual directory structure).
You can just create a blank layout and use it for your ajax controller actions (or what Phil suggested, AjaxContent is probably better for this).
I'll write here an almost complete "how to" guide to implement AJAX calls in Zendframework 3.
We need:
A route declaration
A controller
Some javaScript (is out of skope, perhaps I'll show it in other place)
The route declaration:
<?php
// editing a module.config.php in your project
// typical lines:
namespace Ajax2l; // my ajax module name
use Zend\Router\Http\Segment;
// ...
'router' => [
// ... other routes
'ajax2lsajaxcall' => [
'type' => Segment::class,
'options' => [
'route' => '/ajax2l/ajaxrequest[/:action][/:garbage]',
// the :action wildcard is a place to have extra parameters
// the :garbage wildcard is a place to send random strings
// to ensure you break cache to get real process for
// all your calls, since every call will be different
'defaults' => [
'controller' => Controller\AjaxController::class,
'action' => 'ajaxrequest'
]
],
'may_terminate' => true,
'child_routes' => [
// other ajax routes if needed
]
],
// I only use one ajax route and one controller for all my sites' ajax
// calls because they fire small db actions and reflect them on small
// parts of my pages. So I think I do not need a route and a controller
// for each ajax call. Instead, I use a Library and some services to get
// sets of elementary components and to perform tasks.
The Controller
My Ajax2l module is located under "myzend_project/module" directory.
<?php
// Filename: /module/Ajax2l/src/Controller/AjaxController.php
namespace Ajax2l\Controller
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
// No more components are needed
class AjaxController extends AbstractActionController {
public function ajaxrequestAction(){
$request = $this->getRequest();
$content = $request->getContent();
$isHttpRequest = $this->ifIsValidHttpRequest();
// if you have a real ajax call you must disable the normal output
$viewmodel = new ViewModel();
$viewmodel->setTerminal($is_xmlhttprequest);
// If not an Ajax call (perhaps from untrusted eyes) serve a forgiven
// page message
if(!$isHttpRequest){
return $this->forgivenPage();
}
// Now prepare a response and responds
$requestParams = $this->preProcessRequest($content);
// call the logics to process your params
$output = $this->processRequestParams($requestParams);
// and send a response
$response = $this->getResponse();
$response->setContent($output);
return $response;
}
private function ifIsValidHttpRequest($content){
// I use a small token string to verify if posted data matches
// perhaps not the proper way but is fast and works
$token = 'my_secure_visitor_session_token_identifier';
return (strpos($content, $token) > 2) ? 1 : 0;
// the validation is simplified here it has some more
// complex logics. To ensure validation of requesting source
}
private function preProcessRequest($content){
// The logics to know what to do
// ...
// here you can identify and set properly the post params
}
function processRequestParams($requestParams){
// some logics to process your data
// ...
// some logics to create a Json output
// ...
return $jsonObject;
}
protected function forgivenPage(){
$view = new ViewModel([]);
// set a forgiven message page as output
$view->setTemplate('ajax2l/messages/forgiven.phtml');
// note: the views directory uses lowercase for module names
return $view;
}
}
Hope it helps. I lost a lot of time reading on zend ajax without results. So I hope I was the last losing his time on this topic.
Luis

Zend Framework: Controllers in separate directories

I'm quite new in Zend framework, but quickly learning. I've encountered the following problem, but I don't really know if my solution is good :)
I've created an application which uses widgets. Widget is a class which implements Widget_Interface and is executed by Widget_Manager.
Widgets can be loaded via WidgetController (which calls Widget_Manager, etc). Now the problem I encountered is: widgets can also be configured, and to make the code more transparent, I'd like a widget to have its own controller (currently, it is only a class). But the problem is, I'd like all widget configurations to be addressed via WidgetController, and then passed to specific widget controller.
An example: let's say I've got a widget named 'scrobbler'. Now when configuring it in the UI, I'd like to make Ajax request with updated settings. I could make a request like http://myapp.com/scrobbler/update-info/, so the framework would run ScrobblerController and I'd process the information from here on.
My idea is to make a request on http://myapp.com/widget/update/scrobbler/, so the framework runs WidgetController. WidgetController would then call ScrobblerController and pass other parameters.
I'm aware of _forward() function in Zend_Controller, but I'd like to have widget controllers and my application's controllers separated (let's say application controllers in /application/controllers and widget controllers in /application/controllers/widgets).
Is it possible to make this and what do I have to add to the Zend framework configuration? Hope I didn't complicate too much :)
Nice day
Edit:
Solved this using modular structure, and moved common classes into root directory.
You coud probably utilize Controller helpers instead of controllers in this case. So let's say that WidgetController is responsible for updating all types of widgets. The updateAction would need to find information on which widget type you wish to configure, this is the scrobbler parameter. You would need to name this parameter so it can be accessed easily. This can be done by either adding a route or adding the name before scrobbler in the uri.
Solution 1: Add a route:
In Bootstrap:
public function __initRoutes () {
$route = new Zend_Controller_Router_Route(
'widget/update/:type',
array (
'controller' => 'widget',
'action' => 'update'
),
array (
'type' => '[a-z_-]*'
)
);
/* #var $fc Zend_Controller_Front */
$fc = $this->bootstrap('FrontController')->getResource('FrontController');
/* #var $router Zend_Controller_Router_Rewrite */
$router = $fc->getRouter();
$router->addRoute('update-widget', $route);
}
Solution 2: Add the parameter name in the uri:
Make requests to /widget/update/type/widgetName instead.
Now, in the WidgetController::updateAction, you can fetch the widget to update using $this->_getParam('type').
So the code could look something like:
class WidgetController extends Zend_Controller_Action
{
public function updateAction ()
{
$widgetName = $this->_getParam('type');
$this->view->result = $this->_helper->Widgets->update($widgetName);
}
}
class App_Controller_Helper_Widgets extends Zend_Controller_Action_Helper
{
public function update($widgetName)
{
$widgetManager = new App_Model_WidgetManager();
$widget = $widgetManager->load($widgetName);
$widget->setOptions($this->getRequest()->getParams());
return $widget->save();
}
}

Categories