View variable is not accessible in template - php

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.

Related

MVC indexController not using the correct action

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"

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

How to save embedded forms in symfony 1?

I have a form which represnts single answer object (this is standard propel generated form I have not changed much there only some validation rules) and another form that represents a collection of answers code as below:
class BbQuestionAnswersForm extends sfForm {
public function __construct($defaults = array(), $options = array(), $CSRFSecret = null) {
parent::__construct($defaults, $options, $CSRFSecret);
}
public function configure() {
if (!$questions = $this->getOption('questions')) {
throw new InvalidArgumentException('The form need array of BbExamQuestion objects.');
}
if (!$taker = $this->getOption('taker')) {
throw new InvalidArgumentException('The form need BbExamtaker object.');
}
if (!$user = $this->getOption('questions')) {
throw new InvalidArgumentException('The form need sfGuardUser object.');
}
foreach($questions as $question) {
$answer = new BbExamAnswer();
$answer->setBbExamQuestion($question);
$answer->setBbExamTaker($taker);
$answer->setCreatedBy($user);
$answer->setUpdatedBy($user);
$form = new BbExamAnswerForm($answer, array('question' => $question));
$this->embedForm($question->getId(), $form);
}
$this->widgetSchema->setNameFormat('solve[%s]');
}
}
Everything(validation, display) goes fine with this form until I try to save it. Part of action which trying to save the form:
...
$this->form = new BbQuestionAnswersForm(null, array('questions' => $this->questions, 'taker' => $this->taker, 'user' => $this->getUser()->getGuardUser()));
if($request->isMethod('post')) {
$this->form->bind($request->getParameter($this->form->getName()));
if($this->form->isValid()) {
if($this->form->save()) {
$this->getUser()->setFlash('success', 'Save goes fine.');
$this->redirect($this->generateUrl('#bb'));
} else {
$this->getUser()->setFlash('error', 'Upps an error occurred.');
}
}
}
When I send valid form I receive "Call to undefined method BbQuestionAnswersForm::save()" error.
I tried to write this method like this:
public function save() {
$conn = Propel::getConnection(ZlecPeer::DATABASE_NAME);
$conn->beginTransaction();
try{
foreach($this->getEmbeddedForms() as $form) {
$form->save();
}
$conn->commit();
} catch(Exception $e) {
$conn->rollback();
echo 'upps something goes wrong';
die($e->getMessage());
return false;
}
return true;
}
but it doesnt work, I receive exception without any message.
What am I doing wrong, how to make save method work?
I believe your BbQuestionAnswersForm is extending the wrong object. It should extend BaseFormDoctrine or possibly BaseBbQuestionAnswersForm if you are using the framework correctly.
Edit: Just noticed you are using propel but it should be the same thing. Try:
class BbQuestionAnswersForm extends BaseBbQuestionAnswersForm
and less likely:
class BbQuestionAnswersForm extends BaseFormPropel
Save method should looks like this:
public function save($con = null) {
if (null === $con) {
$con = Propel::getConnection(BbExamAnswerPeer::DATABASE_NAME);
}
$con->beginTransaction();
try{
foreach($this->embeddedForms as $name => $form) {
if(!isset($this->values[$name]) || !is_array($this->values[$name])) {
continue;
}
if($form instanceof sfFormObject) {
$form->updateObject($this->values[$name]);
$form->getObject()->save($con);
$form->saveEmbeddedForms($con);
} else {
throw new Exception('Embedded form should be an instance of sfFormObject');
}
}
$con->commit();
} catch(Exception $e) {
$con->rollBack();
throw $e;
return false;
}
return true;
}

CakePHP - call_user_func_array() looses $this->request->data?

I need to call Controller-methods dynamically. For this purpose I wrote the following code:
if(isset($method['postParams'])) {
foreach($method['postParams'] as $index => $param) {
$this->request->data[ $index ] = $param;
}
}
App::import('Controller', $method['controller']);
// get result
$method['controller'] = $method['controller'] . 'Controller';
$Controller = new $method['controller']();
try {
if(count($method['params'])) {
$varVal = call_user_func_array(array($Controller, $method['method']), $method['params']);
} else {
$varVal = call_user_func(array($Controller, $method['method']));
}
} catch(Exception $e) {
$varVal = $e;
}
$this->set($varName, $varVal);
Now I debug the function being called and see that $this->request->data is NULL.
How to solve this?
For the sake of completeness I'll post the answer to this problem for anyone having a similar issue to find the solution more easily.
Instead of:
$this->request->data
Use:
$Controller->request->data
After instanciating the $Controller object.

Facebook php sdk: getSessionFromRedirect returns null

I am using Phalcon. The following function is called when accessing route: /registration/facebook/access:
public function facebookAccess()
{
$app = new FacebookApp($this->config);
$app->initialize();
$loginUrl = $app->getRegistrationLink($this->fbRedirectUrl);
$this->view->setVar('loginUrl', $loginUrl);
}
$app->initialize() calls session_start() and FacebookSession::setDefaultApplication with my app id and secret. The link appears correctly. When I click on the link, I get redirected to /registration/facebook/process:
public function facebookProcess()
{
$app = new FacebookApp($this->config);
$app->initialize();
if (!$app->startSession($this->fbRedirectUrl))
{
if ($app->getSessionError())
$this->dispatchError($app->getSessionError());
else
$this->dispatchErrorStub('FACEBOOK_SESSION_INVALID');
return;
}
$fbData = $app->getUser();
if (!$fbData->save())
{
$this->dispatchErrorOn($fbData);
return;
}
$this->view->setVar('fbData', $fbData);
}
where startSession is defined as follows:
public function startSession($redirectUrl)
{
$helper = new FacebookRedirectLoginHelper($redirectUrl);
try
{
$this->session = $helper->getSessionFromRedirect();
$this->sessionError = false;
if (!$this->session)
return false;
return true;
}
catch(Exception $ex)
{
$this->session = false;
$this->sessionError = $ex->getMessage();
return false;
}
}
But the returned session is always true. The code worked fine yesterday, I just did some refactoring. Cannot figure out the problem.
It resolved itself without doing nothing... still I don't know what went wrong.

Categories