in zf1, we can get controller and action name using
$controller = $this->getRequest()->getControllerName();
$action = $this->getRequest()->getActionName();
How we can achieve this in zf2?
UPDATE:
I tried to get them using
echo $this->getEvent()->getRouteMatch()->getParam('action', 'NA');
echo $this->getEvent()->getRouteMatch()->getParam('controller', 'NA');
But I am getting error
Fatal error: Call to a member function getParam() on a non-object
I like to get them in __construct() method;
Ideally I would like to check if there is no Action is defined it will execute noaction() method. I would check using php method method_exists.
Even simpler:
$controllerName =$this->params('controller');
$actionName = $this->params('action');
you can't access these variables in controller __construct() method, but you can access them in dispatch method and onDispatch method.
but if you would like to check whether action exist or not, in zf2 there is already a built in function for that notFoundAction as below
public function notFoundAction()
{
parent::notFoundAction();
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent("Action not found");
return $response;
}
but if you still like to do it manually you can do this using dispatch methods as follow
namespace Mynamespace\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;
use Zend\Mvc\MvcEvent;
class IndexController extends AbstractActionController
{
public function __construct()
{
}
public function notFoundAction()
{
parent::notFoundAction();
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent("Action not found");
return $response;
}
public function dispatch(Request $request, Response $response = null)
{
/*
* any customize code here
*/
return parent::dispatch($request, $response);
}
public function onDispatch(MvcEvent $e)
{
$action = $this->params('action');
//alertnatively
//$routeMatch = $e->getRouteMatch();
//$action = $routeMatch->getParam('action', 'not-found');
if(!method_exists(__Class__, $action."Action")){
$this->noaction();
}
return parent::onDispatch($e);
}
public function noaction()
{
echo 'action does not exits';
}
}
You will get module , controller and action name like this in Zf2 inside your controller...
$controllerClass = get_class($this);
$moduleNamespace = substr($controllerClass, 0, strpos($controllerClass, '\\'));
$tmp = substr($controllerClass, strrpos($controllerClass, '\\')+1 );
$controllerName = str_replace('Controller', "", $tmp);
//set 'variable' into layout...
$this->layout()->currentModuleName = strtolower($moduleNamespace);
$this->layout()->currentControllerName = strtolower($controllerName);
$this->layout()->currentActionName = $this->params('action');
$controllerName = strtolower(Zend_Controller_Front::getInstance()->getRequest()->getControllerName());
Related
Heres the code for the route:
<?php
use app\controllers\Home;
use app\core\App;
$app = new App();
$app->router->get('/', function(){
echo "hello there";
});
$app->router->get('user/', 'user');
$app->router->get('/contact', [Home::class,'contacts']);
$app->router->post('/contact', function(){
echo "handlecontact";
});
$app->run();
Heres the code for the router core class:
<?php
namespace app\core;
class router{
public Request $request;
public Response $response;
protected array $routes = [];
public function __construct(Request $request,Response $response)
{
$this->request = $request;
$this->response = $response;
}
public function get($path, $callback){
$this->routes['get'][$path] = $callback;
}
public function post($path, $callback){
$this->routes['post'][$path] = $callback;
}
public function resolve(){
$path = $this->request->getpath();
$method = $this->request->getmethod();
$callback = $this->routes[$method][$path] ?? false;
if($callback == false){
$this->response->setstatuscode(404);
return "not found";
}
if(is_array($callback)){
$callback[0] = new $callback[0]();
}
return call_user_func($callback,$this->request);
}
I want to be able to declare a route and pass a parameter to it. If i do it so like that it tells me route not found.
Like i want to be able to write the route like this:
$app->router->get('/contact/{id}', function(){
echo $id; // to echo it out like this from the controller
});
Can someone be of good help or also add something to the idea. Thanks in advance
I am very new to PHP (did some small projects a few years back, but nothing since) and trying to get familiar with it again by creating a RESTful API project. Coming from a C# background, I'm trying to setup the boiler plate stuff to be similar to that of .NET, where controllers handle the request and attributes help determine which function should handle the request.
The problem I'm running into is retrieving the attributes from a method within the Controller class. I create an instance of ReflectionClass, call getMethods() then attempt to iterate the methods to retrieve the attributes by calling $method->getAttributes(HttpGet::class) but the $method->getAttributes() call is throwing the following error
'PHP message: PHP Fatal error: Uncaught Error: Call to undefined method ReflectionMethod::getAttributes() in /var/www/*********/api/base/ApiController.php:36\
Here is the code
-Running on Apache2 / Linux with PHP 7.4.28
The Controller
require './base/ApiController.php';
require './base/attributes/RouteAttributes.php';
class SessionController extends ApiController
{
#[HttpGet('')]
public function OnGet()
{
parent::OK("GET Called - Returned 200 OK");
}
#[HttpPost('')]
public function OnPost()
{
parent::Created("POST called - Returned 201 CREATED");
}
}
$controller = new SessionController();
ApiController::HandleRequest($controller);
?>
The ApiController base class
/* Base class for all API controllers, provides basic functionality like
* returning common statuses, conversion of data to JSON and formatting
* appropriate headers
*/
require "HttpStatusCode.php";
class ApiController
{
//Return Types
public static function StatusCode(int $status, $data)
{
header('X-PHP-Response-Code: $status->value', true, $status);
if(isset($data))
{
header("Content-type: application/json");
echo json_encode($data);
}
exit;
}
public static function HandleRequest($controller)
{
$routePath = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : NULL;
$requestMethod = strtoupper($_SERVER['REQUEST_METHOD']);
$controllerInfo = new ReflectionClass($controller);
$methodFound = false;
switch($requestMethod)
{
case 'GET':
foreach($controllerInfo->getMethods() as $method)
{
echo $method;
$getAttribute = $method->getAttributes(HttpGet::class);
if(count($getAttribute))
{
$method.invoke($controller, NULL);
$methodFound = true;
}
}
break;
case 'POST':
break;
}
if($methodFound == false)
ApiController::StatusCode(HttpStatusCode::NotFound, "Method Not Found");
}
public function OK($data)
{
ApiController::StatusCode(HttpStatusCode::OK, $data);
}
public function Created($data, $createdAtRoute)
{
if(isset($createdAtRoute))
header('Location: $createdAtRoute');
StatusCode(HttpStatusCode::Created, $data);
}
public function Accepted($data)
{
StatusCode(HttpStatusCode::Accepted, $data);
}
public function NoContent()
{
StatusCode(HttpStatusCode::NoContent, NULL);
}
public function BadRequest($data)
{
StatusCode(HttpStatusCode::BadRequest, $data);
}
public function Unathorized($data)
{
StatusCode(HttpStatusCode::Unathorized, $data);
}
public function Forbidden($data)
{
StatusCode(HttpStatusCode::Forbidden, $data);
}
}
?>
The Attribute definitions
#[Attribute]
class HttpGet
{
public string $Route;
public function __construct(string $route)
{
$this->Route = $route;
}
}
#[Attribute]
class HttpPost
{
public string $Route;
public function __construct(string $route)
{
$this->Route = $route;
}
}
#[Attribute]
class HttpPut
{
public string $Route;
public function __construct(string $route)
{
$this->Route = $route;
}
}
#[Attribute]
class HttpPatch
{
public string $Route;
public function __construct(string $route)
{
$this->Route = $route;
}
}
#[Attribute]
class HttpDelete
{
public string $Route;
public function __construct(string $route)
{
$this->Route = $route;
}
}
?>
The project is very much still in the infancy stages and going to be a functional 'learner' project to get my feet wet. I just haven't been able to get past this error. Any help or insight would be greatly appreciated.
Your issue is with the PHP version. PHP Annotations have been supported since PHP 8.0
I'm trying to create a class function which resembles how we used to fetch database listing and convert into a dropdown listing.
eg: DB::table()->where()->get()
what i would like to achieve in laravel custom class or through model is this
Dropdown::fetch()->toArray()
Dropdown::fetch()->toDropdown()
I tried to figure out how this can be done through google. But couldn't find any solution to it.
I'm using laravel 5.8
--
Edit - Sample Code added
Code tried:
namespace App\Http\Models;
use DB;
use Closure;
use BadMethodCallException;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Database\Eloquent\Model;
class Dropdown extends Model
{
private $result = [];
private $default;
public function _cities(){
$tbl_cities = config("tables.TBL_meta_cities");
$result = DB::table($tbl_cities)->select('id', 'cityname')
->orderBy('id')->get()->toArray();
$this->result = $result;
}
public function _select(){
}
public function _list(){
return $this->result;
}
public function _setDefault($def=''){
}
public static function __callStatic($method, $parameters)
{
$action = '_'.$method;
if(method_exists(get_called_class(), $action))
self::$action(...$parameters);
else echo 'not found';
}
public function __call($method, $parameters)
{
$action = '_'.$method;
if(method_exists($get_called_class(), $action))
self::$action(...$parameters);
else echo 'not found';
}
}
and i tried
Dropdown::cities()->list()
but ended with bugs
Well i figured it out myself.
class Dropdown extends Model
{
private static $result = [];
private function getCities(){
$result = City::select('id', 'cityname')
->orderBy('id')->get()->toArray();
self::$result = $result;
}
public function toArray(){
return self::$result;
}
public function toDropdown(){
// Do the dropdown works
}
/**
* Dynamically handle calls to the class.
*
* #param string $method
* #param array $parameters
* #return mixed
*
* #throws \BadMethodCallException
*/
public function __callMethod($method, $parameters){
// Check with inclusive
$class = get_called_class();
$avail = false;
$action = '';
// Check method availability - direct
if(!$avail){
$action = $method;
$avail = method_exists($class, $action);
}
// Check method 2
if(!$avail){
$action = 'get'.ucwords($method);
$avail = method_exists($class, $action);
}
if($avail){
// Call the method
$return = self::$action(...$parameters);
if(!empty($return)) return $return;
} else {
// Throw error if method not found
throw new BadMethodCallException("No such method exists: $name");
}
return new self;
}
public static function __callStatic($method, $parameters){
return (new self)->__callMethod($method, $parameters);
}
public function __call($method, $parameters){
return (new self)->__callMethod($method, $parameters);
}
}
All i need to do is return new self which does the trick instead of return $this so that the trailing function can be called easily.
Now i can able to call that function like this
Dropdown::cities()->toArray();
Reference:
https://stackoverflow.com/a/41631711/1156493
Thank you #Joseph for your time & support.
I've been handed a PHP class, and I'm not interested in fully restructuring it. (it works!)
But I'd like to add a slight modification inside a few methods.
Here is one of the many methods inside the class:
<?php
class SomeFunClass {
public function getAccountInfo()
{
$request = $this->prepareRequest('get_account_info');
$response = $this->execute($request);
return $response;
}
}
?>
The return $response is a string value.
I've come to a point that I need to return the $request string, which happens to be a json string.
The prepareRequest() method always returns a json string, which is then passed to the exec() method, which simply sends the data via cURL to a domain.
I'd like to extract the $request string (when I call the getAccountInfo() method), for later review.
Here's what I'm doing now:
<?php
$api = new SomeFunClass();
$curlresponse = $api->getAccountInfo();
?>
Obviously, the example immediately above only gives me back what the cURL response would be.
Would be nice to call a method that lets me see what the $request looks like.
I'm open to suggestions.
Just return an array with the request and the response:
<?php
class SomeFunClass {
public function getAccountInfo()
{
$request = $this->prepareRequest('get_account_info');
$response = $this->execute($request);
return array('request' => $request, 'response' => $response);
}
}
?>
You can modify those methods to store the last request into an attribute of the current class :
<?php
class SomeFunClass {
$last_request;
...
public function getAccountInfo()
{
$request = $this->prepareRequest('get_account_info');
$last_request = request;
$response = $this->execute($request);
return $response;
}
public function getLastRequest()
{
return $this -> last_request;
}
}
?>
Or, better, if prepareRequest is a method of yours, then just modify this one to store the last request.
You can do something like this:
<?php
class SomeFunClass {
public $request;
public $response;
public function getAccountInfo()
{
$this->request = $this->prepareRequest('get_account_info');
$this->response = $this->execute($this->request);
return $this->response;
}
}
?>
Now, you can do something like this:
<?php
$api = new SomeFunClass();
$curlresponse = $api->getAccountInfo();
$request = $api->request;
?>
Ideally, you can do implement your class like this to take actual advantage of OOP (so that these instance variables request and response are auto-set for all your methods):
<?php
class SomeFunClass {
public $request;
public $response;
public function getAccountInfo()
{
$this->prepareRequest('get_account_info');
return $this->execute();
}
public function anotherMethod()
{
$this->prepareRequest('another_method', 'some', 'args');
return $this->execute();
}
public function prepareRequest()
{
$args = func_get_args(); // contains your arguments
$method = array_shift($args); // contains your method name
...
...
$this->request = $return // value returned by this method
}
public function execute()
{
$request = $this->request;
...
...
$this->response = $return // value returned by this method
}
}
?>
You could also do this:
<?php
class SomeFunClass {
public function reviewRequest($request)
{
return $this->prepareRequest($request);
}
}
And then:
<?php
$api = new SomeFunClass();
$request = $api->reviewRequest('get_account_info');
i wrote a small plugin, so i will be able to get the name of the controller in each view.
but idk how to "pass" a parameter to the view (do sumth like $this->view->foo =...;).
class Zend_Extension_Controller_Plugin_GetControllerName extends Zend_Controller_Plugin_Abstract
{
public function __construct()
{
}
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$this->view->controllerName = $request->getControllerName();
}
}
what can i write instead of $this->view->controllerName so it will work?
Try this:
$view = Zend_Layout::getMvcInstance()->getView();
$view->controllerName = $request->getControllerName();
You can use the helper broker to get an instance of the view. Something like this should work:
Zend_Controller_Action_HelperBroker::getExistingHelper('ViewRenderer')->view->foo = 'bar';
Take this example as basis:
class Plugin_Sidebar extends Zend_Controller_Plugin_Abstract {
public function postDispatch(Zend_Controller_Request_Abstract $request)
{
if($request->getModuleName() == 'admin')
{
return;
}
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
if (null === $viewRenderer->view) {
$viewRenderer->initView();
}
$view = $viewRenderer->view;
$Categories = new Model_DbTable_Categories();
$view->menuItens = $Categories->getMenu();
}
}