I ll reframe my question based on some research I have done?
I need to store lot of errors separately like $_SESSION['client_error'],$_SESSION['state_error'] etc.
According to zend documentation do I have to store it like this for each error?
$client_error = new Zend_Session_Namespace(''client_error);
$state_error = new Zend_Session_Namespace('state_erro'); and so on?
This is my code in the controller.
I am storing it as
$this->view->state_error_message=$state_error;
After I echo $this->state_error in the view I want to unset it.
Ok here are few more things I tried:
In the controller in policyInfoAction:
session_start();
$error_message = new Zend_Session_Namespace('error_message');
$error_message="TEST";
$this->view->error_message=$error_message;
$this->_redirect('/pdp/client-info/');
In the view in client-info:
session_start();
<?php echo $this->error_message; ?>
This returns nothing.
Ok this is my updated code:
public function clientInfoAction()
{
$errors = new Zend_Session_Namespace('errors');
// get the error arrays
$client_errors = (isset($errors->client_error)) ? $errors->client_error : array();
$state_errors = (isset($errors->state_error)) ? $errors->state_error : array();
unset($errors->client_error, $errors->state_error); // delete from the session
// assign the values to the view
$this->view->client_errors = $client_errors;
$this->view->state_errors = $state_errors;
}
public function policyInfoAction()
{
if (count($arrErrors) > 0)
{
// The error array had something in it. There was an error.
$strError="";
foreach ($arrErrors as $error)
{
$strError="";
$errors->client_error = array();
$errors->state_error = array();
foreach ($arrErrors as $error)
{
$strError .= $error;
// to add errors to each type:
$errors->client_error['client_error'] = $strError;
$errors->client_error[] = $strError;
$this->_redirect('/pdp/client-info/');
}
}
}
When i echo $this->client_errors I get 'Array'
Here is some advice and suggestions that can hopefully get you on the right track.
First, when using Zend_Session and/or Zend_Session_Namespace, you never want to use PHP's session_start() function1. If you start a session with session_start(), and then try to use Zend_Session, it will throw an exception that another session already exists.
Therefore, remove all session_start() calls from your Zend Framework application.
Second, you mentioned you had a lot of messages you need to store, so this may not be the right thing for you, but see the FlashMessenger action helper. This allows you to set a message in a controller, and then access it on the next page request. The messages only live for one page hop, so after the next page load, they are deleted. You can store many messages with the FlashMessenger, but your access to them is not very controlled. You could use multiple flash messengers each in differen namespaces also.
To solve your problem in particular, you could just do something like this:
// in controller that is validating
$errors = new Zend_Session_Namespace('errors');
$errors->client_error = array();
$errors->state_error = array();
// to add errors to each type:
$errors->client_error['some_error'] = 'You had some error, please try again.';
$errors->client_error['other_error'] = 'Other error occurred.';
$errors->client_error[] = 'Other error, not using a named key';
$errors->state_error[] = MY_STATE_PARSING_0;
What is happening here is we are getting a session namespace called errors creating new properties for client_error and state_error that are both arrays. You don't technically have to use multiple Zend_Session_Namespaces.
Then to clear the messages on the next page load, you can do this:
// from controller again, on the next page load
$errors = new Zend_Session_Namespace('errors');
// get the error arrays
$client_errors = (isset($errors->client_error)) ? $errors->client_error : array();
$state_errors = (isset($errors->state_error)) ? $errors->state_error : array();
unset($errors->client_error, $errors->state_error); // delete from the session
// assign the values to the view
$this->view->client_errors = $client_errors;
$this->view->state_errors = $state_errors;
See also the source code for Zend_Controller_Action_Helper_FlashMessenger which can give you some idea on managing data in session namespaces.
I don't know if this will help you or not but here is the code for a controller that just takes an id from a form a gathers data based on that id an assigns that data to the session (to be used throughout the module) and then unsets that data when appropriate. and Never leaves the Index page.
<?php
class Admin_IndexController extends Zend_Controller_Action
{
//zend_session_namespace('location')
protected $_session;
/**
*set the layout from default to admin for this controller
*/
public function preDispatch() {
$this->_helper->layout->setLayout('admin');
}
/**
*initiaize the flashmessenger and assign the _session property
*/
public function init() {
if ($this->_helper->FlashMessenger->hasMessages()) {
$this->view->messages = $this->_helper->FlashMessenger->getMessages();
}
//set the session namespace to property for easier access
$this->_session = new Zend_Session_Namespace('location');
}
/**
*Set the Station and gather data to be set in the session namespace for use
* in the rest of the module
*/
public function indexAction() {
//get form and pass to view
$form = new Admin_Form_Station();
$form->setAction('/admin/index');
$form->setName('setStation');
$this->view->station = $this->_session->stationName;
$this->view->stationComment = $this->_session->stationComment;
$this->view->form = $form;
try {
//get form values from request object
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = (object)$form->getValues();
//set session variable 'station'
$this->_session->station = $data->station;
$station = new Application_Model_DbTable_Station();
$currentStation = $station->getStation($this->_session->station);
$this->_session->stationName = $currentStation->station;
$this->_session->stationComment = $currentStation->comment;
//assign array() of stations to session namespace
$stations = $station->fetchAllStation();
$this->_session->stations = $stations;
//assign array() of bidlocations to session namespace
$bidLocation = new Application_Model_DbTable_BidLocation();
$bidLocations = $bidLocation->fetchAllBidLocation($this->_stationId);
$this->_session->bidLocations = $bidLocations;
$this->_redirect($this->getRequest()->getRequestUri());
}
}
} catch (Zend_Exception $e) {
$this->_helper->flashMessenger->addMessage($e->getMessage());
$this->_redirect($this->getRequest()->getRequestUri());
}
}
/**
*Unset Session values and redirect to the index action
*/
public function changestationAction() {
Zend_Session::namespaceGet('location');
Zend_Session::namespaceUnset('location');
$this->getHelper('Redirector')->gotoSimple('index');
}
}
just to be complete i start the session in the bootstrap. On the theory that if I need it great if not no harm.
protected function _initsession() {
//start session
Zend_Session::start();
}
this is all the view is:
<?php if (!$this->station): ?>
<div class="span-5 prepend-2">
<?php echo $this->form ?>
</div>
<div class="span-10 prepend-2 last">
<p style="font-size: 2em">Please select the Station you wish to perform Administration actions on.</p>
</div>
<?php else: ?>
<div class="span-19 last">
<?php echo $this->render('_station.phtml') ?>
</div>
<?php endif; ?>
Related
There is one view, and one controller, it is necessary, with the use of the get parameter, to change the path by the link. So in the end it turned out like this:
Upcoming -> http://mywebsite.com/tournaments?type=upcoming
Finished -> http://mywebsite.com/tournaments?type=finished
Here is the controller which will process your GET variable
Controller
<?php
class Demo_controller extends CI_Controller
{
public function demo($id)
{
echo $id; //the id which you will get in URL string
}
}
?>
View File where you will pass the Variable
<?php
$id = "1";//dyanmic id which will be pased with the form
echo form_open('demo/demos-function'.$id);
//in between your code
echo form_close
?>
Routes
Inside routes.php
$route['demo/demos-function/(:any)] = Demo_controller/demo/$1
No need to change the $1 it will explain the routes that it is having URL paramater.
So Ultimately Your link will be
https://localhost/demo/demos-function/1
https://localhost/demo/demos-function/2
In Codeigniter Url like this :
Upcoming -> http://mywebsite.com/controller/method/upcoming
Finished -> http://mywebsite.com/controller/method/finished
public function method_name()
{
$type = $this->uri->segment(3); // third level value of URL - Segment(1) is controller and followed by method and query string
if($type == 'upcoming')
{
echo $type;
$this->load->view('upcoming');
}
else
{
echo $type;
$this->load->view('finished');
}
}
I'm using Zend Framework 2 with ZfcUser, BjyAuthorize and Doctrine for the database. Registration etc. works very well so far. My problem is, that registered users have no role assigned, so i want to add the role "user" to the user during registration.
I think i could attach this to the "register" event, but i don't know how to do that.
I hope someone can help me ...
(i used this tutorial for setting up zfcuser etc. http://samminds.com/2013/03/zfcuser-bjyauthorize-and-doctrine-working-together/)
public function onBootstrap(MvcEvent $e)
{
$zfcServiceEvents = $e->getApplication()->getServiceManager()->get('zfcuser_user_service')->getEventManager();
$zfcServiceEvents->attach('register', function($e) {
$user = $e->getParam('user');
// probably the role must be added here, with $user->addRole();
// but how do i get the user Role Entity to add from DB?
});
Building on DangelZM's answer, and using another reference (see link at end of my post) about the Event Manager, I came up with this solution which organizes the potential ZfcUser event listeners out into a user listener object.
Note: I created my own user module called NvUser, so depending on the name of your module you'll have to replace all references of NvUser to your user module name.
Summary
I created an NvUserListener object that can itself attach event listeners to the shared event manager, and house the event listener callbacks.
Inside NvUser/Module.php:
<?php
namespace NvUser;
use Zend\Mvc\MvcEvent;
use NvUser\Listener\NvUserListener;
class Module
{
public function onBootstrap(MvcEvent $mvcEvent)
{
$em = $mvcEvent->getApplication()->getEventManager();
$em->attach(new NvUserListener());
}
}
Inside NvUser/src/NvUser/Listener/NvUserListener.php:
<?php
namespace NvUser\Listener;
use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\Event;
class NvUserListener extends AbstractListenerAggregate
{
public function attach(EventManagerInterface $events)
{
$sharedManager = $events->getSharedManager();
$this->listeners[] = $sharedManager->attach('ZfcUser\Service\User', 'register', array($this, 'onRegister'));
$this->listeners[] = $sharedManager->attach('ZfcUser\Service\User', 'register.post', array($this, 'onRegisterPost'));
}
public function onRegister(Event $e)
{
$sm = $e->getTarget()->getServiceManager();
$em = $sm->get('doctrine.entitymanager.orm_default');
$user = $e->getParam('user');
$config = $sm->get('config');
$criteria = array('roleId' => $config['zfcuser']['new_user_default_role']);
$defaultUserRole = $em->getRepository('NvUser\Entity\Role')->findOneBy($criteria);
if ($defaultUserRole !== null)
{
$user->addRole($defaultUserRole);
}
}
public function onRegisterPost(Event $e)
{
$user = $e->getParam('user');
$form = $e->getParam('form');
// Do something after user has registered
}
}
Inside NvUser/config/module.config.php:
<?php
namespace NvUser;
return array(
'zfcuser' => array(
'new_user_default_role' => 'user',
),
);
References:
Understanding the Zend Framework 2 Event Manager
Maybe it's not the best solution, but it works for me.
Add user_role_id option in config scope.
public function onBootstrap(MvcEvent $mvcEvent)
{
$zfcServiceEvents = $mvcEvent->getApplication()->getServiceManager()->get('zfcuser_user_service')->getEventManager();
$zfcServiceEvents->attach('register', function($e) use($mvcEvent) {
$user = $e->getParam('user');
$em = $mvcEvent->getApplication()->getServiceManager()->get('doctrine.entitymanager.orm_default');
$config = $mvcEvent->getApplication()->getServiceManager()->get('config');
$defaultUserRole = $em->getRepository('SamUser\Entity\Role')->find($config['user_role_id']);
$user->addRole($defaultUserRole);
});
}
Maybe someone will offer better solution.
This work too.
public function onBootstrap(MvcEvent $mvcEvent)
{
$zfcServiceEvents = $mvcEvent->getApplication()-getServiceManager()->get('zfcuser_user_service')->getEventManager();
$zfcServiceEvents->attach('register', function($e) use($mvcEvent) {
$user = $e->getParam('user');
$em = $mvcEvent->getApplication()->getServiceManager()-get('doctrine.entitymanager.orm_default');
$defaultUserRole = $em->getRepository('SamUser\Entity\Role')-find('id_of_your_role_on_table_role_for_example: '2'');
$user->addRole($defaultUserRole);
});
}
I just used a MySQL trigger
DROP TRIGGER IF EXISTS `user_role_after_insert_trig`;
DELIMITER //
CREATE TRIGGER `user_role_after_insert_trig` AFTER INSERT ON `user`
FOR EACH ROW begin
insert into user_role_linker (user_id,role_id) values (new.user_id, 5);
end
//
DELIMITER ;
I'm having a difficult time understanding how Zend_Session_Namespace is integrated with Zend_Auth. I have this method I'm using as the action to Authenticate my login page-it is working correctly and redirecting to the /monthly view:
public function authAction(){
$request = $this->getRequest();
$registry = Zend_Registry::getInstance();
$auth = Zend_Auth::getInstance();
$DB = $registry['DB'];
$authAdapter = new Zend_Auth_Adapter_DbTable($DB);
$authAdapter->setTableName('users')
->setIdentityColumn('UserName')
->setCredentialColumn('Password');
// Set the input credential values
$uname = $request->getParam('UserName');
$paswd = $request->getParam('Password');
$authAdapter->setIdentity($uname);
$authAdapter->setCredential($paswd);
// Perform the authentication query, saving the result
$result = $auth->authenticate($authAdapter);
// TRYING TO SET THE NAMESPACE
$this->session = new Zend_Session_Namspace('UserName');
if($result->isValid()){
$data = $authAdapter->getResultRowObject(null,'password');
$auth->getStorage()->write($data);
$this->_redirect('/monthly');
}else{
$this->_redirect('/login');
}
}
But I need to be able to store UserName as a Zend_session and call it from monthly controller. I'm not doing things right because I just get a blank screen when I try and do this:
public function indexAction()
{
$this->view->userName = Zend_Session_Namespace('UserName');
}
With the lines:
$data = $authAdapter->getResultRowObject(null,'password');
$auth->getStorage()->write($data);
You're writing all the user's information, except the password, which is OK. Where ever you need to access the logged in user's details, you can do something like (updated as per your comment):
public function indexAction() {
$auth = Zend_Auth::getInstance();
if($auth->hasIdentity()) {
$userData = $auth->getIdentity();
$this->view->user = $userData;
}
}
in the view file (index.phtml) just: echo $this->user->firstname
That's it. If one day you decide to change the storage for Zend_Auth from session, to, for example, database, this piece of code will still work.
Youre not useing the correct namespace. Zend_Auth use the Zend_Auth namespace. The namespace is the structure, not the key for a value. so your session looks something like this:
Array('Zend_Auth' => array ('UserName' => 'myname')
Well thats not accurate exactly because you havent stored the user name unless youve provided for this directly in your adapter. youll need to do something like:
$auth->getStorage()->UserName = 'myusername';
Then you can access with $authData = new Zend_Session_Namespace('Zend_Auth'); $username = $authData->UserName;.
Take a closer look at how the Zend_Auth_Adapter_Db works.
This is my approach and it s working nice:
1-i start by defining an init function in the bootstrap
protected function _initSession()
{
$UserSession = new Zend_Session_Namespace('UserSession');
$UserSession->setExpirationSeconds(/* you may fix a limit */);
Zend_Registry::set('UserSession', $UserSession);
}
/* in the Login action,after correct username & pwd */
// Create session
$UserSession = Zend_Registry::get('UserSession');
// Get the user from database or just from fields
//you have to make sure that the psswd is encrypted use MD5 for example..
$db = Zend_Db_Table::getDefaultAdapter();
$user = $db->fetchRow("SELECT * FROM user_table WHERE user_email = '".$user_email."'");
//then you assign to $user to $UserSession variable :
$UserSession->user = $user;
//finaly don't forget to unset session variable in the Logout action ...
I've seen this question asked already - but none of the answers really gelled for me, so I'm asking again: I want to embed a persistent login form (which will change into a nav bar if logged in) in the header bar for a site. Effectively, I want to be able to inject some controller logic into the layout.
After much research, I can see several ways that might achieve this - none of which seem ideally suited.
View Helpers seem suited to adding a suite of methods to the Zend_View object - but I don't want to write conditional code in the layout.phtml to trigger a method. Action helpers would help me remove that functionality and call it from a Controller - but that seems to be in poor favour from several quarters. Then there are plugins, which might be well suited in the dispatch/authentication loop.
So, I was hoping someone might be able to offer me some guidance on which way might best suit my requirements. Any help is greatly appreciated.
For those of you with a similair issue, this is how I ended up solving it (I'm using layout btw)
I registered a view helper in the Bootstrap:
protected function _initHelpers(){
//has to come after view resource has been created
$view = $this->getResource('view');
// prefix refers to the folder name and the prefix for the class
$view->addHelperPath(APPLICATION_PATH.'/views/helpers/PREFIX','PREFIX');
return $view;
}
Here's the view helper code - the actual authentication logic is tucked away in model code. It's a bit clumsy, but it works
class SB_UserLoginPanel extends Zend_View_Helper_Abstract {
public function __construct() {
$this->user = new SB_Entity_Users();
$this->userAccount = new SB_Model_UserAccount();
$this->request = Zend_Controller_Front::getInstance()->getRequest();
$this->form = $this->makeLoginForm();
$this->message='';
}
//check login
public function userLoginPanel() {
if(isset($_POST['loginpanel']['login'])) {
$this->processLogin();
}
if(isset($_POST['loginpanel']['logout'])) {
$this->processLogout();
}
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$this->loginPanel = $this->getUserNav();
} else {
$this->loginPanel = $this->getLoginForm();
$this->loginPanel .= $this->getMessages();
}
return $this->loginPanel;
}
private function processLogin() {
if($this->form->isValid($_POST)){
$logindata = $this->request->getPost('loginpanel');
if($this->user->login($logindata['email'],$logindata['password'])) {
Zend_Session::rememberMe();
$redirect = new Zend_Controller_Action_Helper_Redirector();
$redirect->goToUrl('/account/');
return $this->getUserNav();
}else {
$this->message = '<p id="account_error">Account not authorised</p>';
}
}else {
$this->form->getMessages();
}
}
private function processLogout() {
if(isset($_POST['loginpanel']['logout'])) {
$this->user->logout();
$request_data = Zend_Controller_Front::getInstance()->getRequest()->getParams();
if($request_data['controller']=='notallowed') {
$redirect = new Zend_Controller_Action_Helper_Redirector();
$redirect->goToUrl('/');
}
}
}
private function makeLoginForm() {
}
private function getLoginForm(){
return $this->form;
}
private function getMessages(){
return $this->message;
}
private function getUserNav(){
//return partial/render
}
}
I then call this from the relevant part of the markup in the layout.phtml file.
<?php echo $this->doctype(); ?>
<head>
<?php
echo $this->headLink() ."\n";
echo $this->headScript() ."\n";
echo $this->headMeta() ."\n";
?>
<title><?php echo $this->escape($this->title) ."\n"; ?></title>
</head>
<div id="masthead">
<div id="userLoginPanel">
<?php echo $this->userLoginPanel(); ?>
</div>
</div>
<!--rest of layout-->
In principle, this should be an action helper, but after reading some less than favourable articles regarding Zend Action Helper - I opted for this method which did the trick.
Hope that helps!
I have coded a simple admin module with ability to paginate records and sort them by some column. And when I sort and then call some other action on the records it should redirect the user back to index page with the same sort parameters as there were before. But after I call the indexAction() with parameters like this /admin/users/index/column/num_orders/order/ASC and then call the toggleActiveAction() I am redirected to page /admin/users/index/column/num_orders/order/CSS.
The same story with .../index/page/2 => .../index/page/css.
Why "CSS"? My session data never used in other context than you see below.
In my bootstrap I have the following:
protected function _initSession()
{
Zend_Session::start();
}
Controller init():
...
$this->_session = new Zend_Session_Namespace('Admin_Users');
...
I have a following function in my controller:
public function redirectToIndex()
{
$options = array();
if (isset($this->_session->curPage) && $this->_session->curPage != 1)
$options['page'] = $this->_session->curPage;
if (isset($this->_session->curColumn) && $this->_session->curColumn)
$options['column'] = $this->_session->curColumn;
if (isset($this->_session->curOrder) && $this->_session->curOrder)
$options['order'] = $this->_session->curOrder;
$this->_helper->redirector('index', 'users', 'admin', $options);
}
In index action:
$curColumn = $this->_getParam('column', '');
$curOrder = strtoupper($this->_getParam('order', ''));
$page = $this->_getParam('page', 1);
...
$this->_session->curPage = $page;
$this->_session->curColumn = $curColumn;
$this->_session->curOrder = $curOrder;
Then in toggleActiveAction() I call
$this->redirectToIndex();
I guess there is a unexisted css file on your page (on js or img) which is handled with Zend Framewok froncontroller. Youd should enable log for all requests that are handled with ZF and you will find there a request like "/theme/supersite/css/thisFileNotExists.css" (or similar :)