MVC indexController not using the correct action - php

I have two Actions in my IndexController.
public function indexAction()
{
$this->view->setVars([
'name' => 'Stefan',
]);
}
public function testAction()
{
$this->view->setVars([
'name' => 'testOutput',
]);
}
When going to call my index page
https://localhost/index/
It does output the name that i set in my views/index/index.php
<h1>Hello <?php echo $name ?></h1>
And i do get the output
Hello Stefan
Problem:
If i got to
https://localhost/index/test
I also get the same output even tho i cleary stated something else in my testAction
So he Acces the indexAction even if im in not calling the Action in my browser.
What i would want is, since i have echo $name; in my test.php file.
That i get the output
testOutput
Here would be my Autoloader.
Thank you in advance.
<?php
// simple autoloader
spl_autoload_register(function ($className) {
if (substr($className, 0, 4) !== 'Mvc\\') {
// not our business
return;
}
$fileName = __DIR__.'/'.str_replace('\\', DIRECTORY_SEPARATOR, substr($className, 4)).'.php';
if (file_exists($fileName)) {
include $fileName;
}
});
// get the requested url
$url = (isset($_GET['_url']) ? $_GET['_url'] : '');
$urlParts = explode('/', $url);
// build the controller class
$controllerName = (isset($urlParts[0]) && $urlParts[0] ? $urlParts[0] : 'index');
$controllerClassName = '\\Mvc\\Controller\\'.ucfirst($controllerName).'Controller';
// build the action method
$actionName = (isset($urlParts[1]) && $urlParts[1] ? $urlParts[1] : 'index');
$actionMethodName = $actionName.'Action';
try {
if (!class_exists($controllerClassName)) {
throw new \Mvc\Library\NotFoundException();
}
$controller = new $controllerClassName();
if (!$controller instanceof \Mvc\Controller\Controller || !method_exists($controller, $actionMethodName)) {
throw new \Mvc\Library\NotFoundException();
}
$view = new \Mvc\Library\View(__DIR__.DIRECTORY_SEPARATOR.'views', $controllerName, $actionName);
$controller->setView($view);
$controller->$actionMethodName();
$view->render();
} catch (\Mvc\Library\NotFoundException $e) {
http_response_code(404);
echo 'Page not found: '.$controllerClassName.'::'.$actionMethodName;
} catch (\Exception $e) {
http_response_code(500);
echo 'Exception: <b>'.$e->getMessage().'</b><br><pre>'.$e->getTraceAsString().'</pre>';
}
EDIT:
It really doesnt matter what i action i call after the index. it can be index/asdsad
And he still goes to the main indexAction.
It doesnt even say that he can't find the action.
EDIT2:
Output from var_dump($url,$urlParts,$controllerName,$actionMethodName)
string(0) ""
array(1) {
[0]=>
string(0) ""
}
string(5) "index"
string(11) "indexAction"

Related

How to call binance api class in php construtor?

I am trying to call binance api class in construct method in my controller so that I can access that api class instance throught entire controller. Problem lies that I need to pass $key and $secret variables to binance class in order to get that object, but I can not do that in construct method. I tried making config.ini file and calling it with parse_ini_file but that returned error that I can not use that function inside class. Here is my code. Any help is appreciated or if someone has other idea on how to make this work.
controller
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
require 'vendor/autoload.php';
class BinanceController
{
private $api;
private $key = 'some long string 1';
private $secret = 'some long string 2';
$api = new Binance\API($key,$secret); // SOMEHOW I NEED LIKE THIS!!!
public function __construct()
{
$this->api = new Binance\API($this->key,$this->secret);
}
public function getAllBinancePairs()
{
$exchangeInfo = $this->api->exchangeInfo(); // HERE IS SOURCE OF ERROR!!!
$results = [];
foreach($exchangeInfo['symbols'] as $info) {
$results[] = $info['symbol'];
}
json_response($results);
}
}
index.php
<?php
require 'vendor/autoload.php';
$router = new AltoRouter();
$router->map( 'GET', '/fbinance', function() {
require __DIR__ . '/fbinance.php';
});
$router->map('GET','/get-all-binance-pairs', array('c' => 'BinanceController', 'a' => 'getAllBinancePairs'));
$match = $router->match();
if(!isset($match['target']['c']))
{
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Server Error', true, 404);
}
switch($match['target']['c']) {
case "BinanceController":
include 'controllers/BinanceController.php';
if( $match && is_callable("BinanceController::" . $match['target']['a']) ) {
call_user_func_array("BinanceController::" . $match['target']['a'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Server Error', true, 404);
exit;
}
break;
default:
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Server Error', true, 404);
break;
}
If the arguments to the constructor for that API are not public, you can only instantiate it within the constructor of BinanceController like:
class BinanceController
{
private $api;
private $key = 'some long string 1';
private $secret = 'some long string 2';
public function __construct()
{
$this->api = new Binance\API($this->key,$this->secret);
}
}

View variable is not accessible in template

in my PagesController::display() i have this code :
class PagesController extends AppController {
public function display(...$path) {
$count = count($path);
if (!$count) {
return $this->redirect('/');
}
if (in_array('..', $path, true) || in_array('.', $path, true)) {
throw new ForbiddenException();
}
$page = $subpage = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
$this->set(compact('page', 'subpage'));
try {
$this->render(implode('/', $path));
} catch (MissingTemplateException $exception) {
if (Configure::read('debug')) {
throw $exception;
}
throw new NotFoundException();
}
$test = "abc";
$this->set(compact('test'));
}
}
That's almost the same as the standard pages controller, I added the last two lines.
My home.ctp template contains:
<?php
var_dump($test);
...
When I access the site, this outputs:
C:\wamp64\www\site\src\Template\Pages\home.ctp:322:null
Which is confusing because debug kit shows that this variable was set:
Why is the test variable not available in the home.ctp template?
Render is being called before set
try {
$this->render(implode('/', $path)); <----
} catch (MissingTemplateException $exception) {
if (Configure::read('debug')) {
throw $exception;
}
throw new NotFoundException();
}
$test = "abc";
$this->set(compact('test')); <-----
}
The call to set is simply too late - it is after the template has already been used.
To have any effect the set call must be before calling render i.e.:
$test = 'abc';
$this->set(compact('page', 'subpage', 'test')); <---
try {
$this->render(implode('/', $path)); <---
...
Why does the variable show up in DebugKit?
DebugKit interrogates the controller instance to obtain the view variables used - But this runs right at the end of the request. This is the reason it is found by debug kit even though it was not available in the template.

Too many redirects PHP MVC

class Core {
protected $currentController = '';
protected $currentMethod = '';
protected $params = [];
public function __construct() {
$url = $this->getUrl();
$pages = [
"" => ["controller" => "Pages", "method" => "index"],
"profile" => ["controller" => "Pages", "method" => "profile"],
"help" => ["controller" => "Pages", "method" => "help"],
"signin" => ["controller" => "Pages", "method" => "signin"]
];
// cant access controller
$noaccess = ["pages"];
if (in_array($url[0], $noaccess)) {
redirect("/");
}
if (isLoggedIn()) {
if (!in_array($url[0], $noaccess)) {
if (!array_key_exists($url[0], $pages)) {
if (file_exists('../app/controllers/' . ucwords($url[0]) . '.php')) {
// If exists, set as controller
$this->currentController = ucwords($url[0]);
$this->currentMethod = "index";
// Unset 0 Index
unset($url[0]);
} else {
// 404
$this->currentController = "Pages";
$this->currentMethod = "error404";
unset($url[0]);
}
} else {
foreach ($pages as $page => $options) {
if ($url[0] == $page) {
$this->currentController = $options['controller'];
$this->currentMethod = $options['method'];
//unset($url[0]);
}
}
}
}
} else {
redirect("signin");
}
// Require the controller
require_once '../app/controllers/' . $this->currentController . '.php';
// Instantiate controller class
$this->currentController = new $this->currentController;
// Check for second part of url
if (isset($url[1])) {
// Check to see if method exists in controller
if (method_exists($this->currentController, $url[1])) {
$this->currentMethod = $url[1];
// Unset 1 index
unset($url[1]);
}
}
// Get params
$this->params = $url ? array_values($url) : [];
// Call a callback with array of params
call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
}
public function getUrl() {
if (isset($_GET['url'])) {
$url = rtrim($_GET['url'], '/');
$url = filter_var($url, FILTER_SANITIZE_URL);
$url = explode('/', $url);
return $url;
}
}
}
I'm learning how to make my own MVC framework for PHP. I'm trying to redirect the user in the core class that instantiates a controller based on the url.
example.com/posts/ will instantiate the Post Controller.
I want to redirect them to /signin/ if they're not logged in. No page will be accessible if the user isn't signed in.
I have a basic function called isLoggedIn() which checks for a $_SESSION variable. I'm able to test if it works with a die() command.
Everything works, but I get an error saying too many redirects. My redirect regarding the $noaccess works without this issue, but I can't get the loggedIn one to work. I'm not sure why it's having this issue.
If every page creates a new Core object, including the sign in page, then whenever you try to sign in (access the sign in page), it will keep redirecting to itself in a never-ending loop.
Adding a condition or simply not checking for login data in the constructor should do the trick. There are many ways to do it, but that’s the general idea.
In the end, all pages run the same logic except the login page, which reverses it.
Thanks to Zeke: https://stackoverflow.com/users/3654197/zeke
Whenever I was redirecting to /signin/, that was also trying to redirect which caused a loop.
I put a condition to only redirect if the the url wasn't /signin/
if ( !isLoggedIn()) {
if ($url[0] == "signin") {
$this->currentController = "Pages";
$this->currentMethod = "signin";
} else {
redirect('signin');
}
unset($url[0]);
}

PHP - ZF2 - render template from string variable

i have problem with rendering template in ZF2, where template is in string in variable. There is simple example:
$template = "<div>easy</div>";
$view = new \Zend\View\Model\ViewModel();
$view->setTemplate($template);
$renderer = new \Zend\View\Renderer\PhpRenderer();
$html = $renderer->render($view);
This code fail on rendering, the renderer think that the template is a path to file. And iam reallz not sure how to tell rendere its a string.
Thx for your time and respond.
You have to extend the PhpRenderer class and override the render method, in such a way that will use the string in the $template as the actual template:
class MyPhpRenderer extends PhpRenderer {
public function render($nameOrModel, $values = null)
{
if ($nameOrModel instanceof Model) {
$model = $nameOrModel;
$nameOrModel = $model->getTemplate();
if (empty($nameOrModel)) {
throw new Exception\DomainException(sprintf(
'%s: received View Model argument, but template is empty',
__METHOD__
));
}
$options = $model->getOptions();
foreach ($options as $setting => $value) {
$method = 'set' . $setting;
if (method_exists($this, $method)) {
$this->$method($value);
}
unset($method, $setting, $value);
}
unset($options);
// Give view model awareness via ViewModel helper
$helper = $this->plugin('view_model');
$helper->setCurrent($model);
$values = $model->getVariables();
unset($model);
}
// find the script file name using the parent private method
$this->addTemplate($nameOrModel);
unset($nameOrModel); // remove $name from local scope
$this->__varsCache[] = $this->vars();
if (null !== $values) {
$this->setVars($values);
}
unset($values);
// extract all assigned vars (pre-escaped), but not 'this'.
// assigns to a double-underscored variable, to prevent naming collisions
$__vars = $this->vars()->getArrayCopy();
if (array_key_exists('this', $__vars)) {
unset($__vars['this']);
}
extract($__vars);
unset($__vars); // remove $__vars from local scope
while ($this->__template = array_pop($this->__templates)) {
$this->__file = $this->resolver($this->__template);
try {
if (!$this->__file) {
$this->__content = $this->__template; // this line does what you need
}else{
ob_start();
$includeReturn = include $this->__file;
$this->__content = ob_get_clean();
}
} catch (\Exception $ex) {
ob_end_clean();
throw $ex;
}
if ($includeReturn === false && empty($this->__content)) {
throw new Exception\UnexpectedValueException(sprintf(
'%s: Unable to render template "%s"; file include failed',
__METHOD__,
$this->__file
));
}
}
$this->setVars(array_pop($this->__varsCache));
if ($this->__filterChain instanceof FilterChain) {
return $this->__filterChain->filter($this->__content); // filter output
}
return $this->__content;
}
}
and then you code should look like:
$template = "<div>easy</div>";
$view = new \Zend\View\Model\ViewModel();
$view->setTemplate($template);
$renderer = new MyPhpRenderer();
$html = $renderer->render($view);
Try by replacing '\' with _ underscore as Zend_View_Renderer_PhpRenderer

altorouter routes doesn't work

i'm trying to use altorouter for set routing map of my php project, at this moment the file routes.php is this
<?php
$router = new AltoRouter();
$router->setBasePath('/home/b2bmomo/www/');
/* Setup the URL routing. This is production ready. */
// Main routes that non-customers see
$router->map('GET','/', '', 'home');
$router->map( 'GET', '/upload.php', 'uploadexcel');
$match = $router->match();
// call closure or throw 404 status
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
?>
i have 2 files in the principal directory of my project, index.php and upload.php, what's wrong?
have you modified your .htaccess files to rewrite as per the altorouter site?
your routes look wrong. try like this:
// 1. protocol - 2. route uri -3. static filename -4. route name
$router->map('GET','/uploadexcel', 'upload.php', 'upload-route');
as it looks like you are wanting a static page (not a controller) try this (allows for both):
if($match) {
$target = $match["target"];
if(strpos($target, "#") !== false) { //-> class#method as set in routes above, eg 'myClass#myMethod' as third parameter in mapped route
list($controller, $action) = explode("#", $target);
$controller = new $controller;
$controller->$action($match["params"]);
} else {
if(is_callable($match["target"])) {
call_user_func_array($match["target"], $match["params"]); //call a function
}else{
require $_SERVER['DOCUMENT_ROOT'].$match["target"]; //for static page
}
}
} else {
require "static/404.html";
die();
}
which is pretty much from here: https://m.reddit.com/r/PHP/comments/3rzxic/basic_routing_in_php_with_altorouter/?ref=readnext_6
and get rid of that basepath line.
good luck
you car run class#function via "call_user_func_array":
if ($match) {
if (is_string($match['target']) && strpos($match['target'], '#') !== false) {
$match['target'] = explode('#', $match['target']);
}
if (is_callable($match['target'])) {
call_user_func_array($match['target'], $match['params']);
} else {
// no route was matched
header($_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
die('404 Not Found');
}
}

Categories