I've got a problem. I'm using zfcuser in my project, and now i want to create profile pages. I'have created the showAction() in UserController, but when i put the url to webbrowser, i will got 404.
public function showAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('zfcuser', array(
'action' => 'register'
));
}
try {
$user = $this->zfcUserAuthentication()->getIdentity()->getUser($id);
}
catch (\Exception $ex) {
return $this->redirect()->toRoute('zfcuser', array(
'action' => 'register'
));
}
return new ViewModel(array(
'user' => $user));
}
I also created custom function to get User info all in one row.
It looks like this:
public function getUser($id){
$rowset = $this->tableGateway->select(array('user_id' => $id));
$row = $rowset->current();
return $row;
}
And it is in Entity/User.php
This is my showAction() in zfc UserController.php
I thought its wrong module.config, but its not working anyway. I changed my module.config to this:
'show' => array(
'type' => 'Literal',
'options' => array(
'route' => '/show[/][:id]',
'defaults' => array(
'controller' => 'zfcuser',
'action' => 'show',
),
),
),
My problem is, i can not even get to url to show this controller action.
Where can be problem. I want to make simple user profile page.
The problem is in my opinion your route 'Literal'. A literal route can't have params.
You have to use Segment instead
But it's not the only problem i think.
ZfcUser comes with a packaging, profile page already exist :
Take a look to this complete slideshare :
Zf2 Zfc-User
Related
Here is my route:
'router' => array(
'routes' => array(
'upload' => array(
'type' => 'segment',
'options' => array(
'route' => '/products/upload[/:products]',
'defaults' => array(
'controller' => 'Products\Controller\Upload',
'action' => 'index'
),
),
'may_terminate' => true,
'child_routes' => array(
'uploadsuccessful' => array(
'type' => 'literal',
'options' => array(
'route' => '/uploadsuccessful',
'defaults' => array(
'controller' => 'Products\Controller\Upload',
'action' => 'successful'
),
),
),
),
),
),
);
I am trying to call this route several times from different view scripts giving different [/:products] parameter.
Upload Shoes Product Image
Upload Trainers Product Image
Upload Hat Product Image
Here is my Controller code.
<?php
namespace Products\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Products\Form\UploadForm;
class UploadController extends AbstractActionController
{
protected $_dir = null;
public function indexAction()
{
$products = $this->params()->fromRoute('products');
$config = $this->getServiceLocator()->get('Config');
$fileManagerDir =$config['file_manager']['dir'];
$this->_dir = realpath($fileManagerDir) .
DIRECTORY_SEPARATOR .
$products;
if (!is_dir($this->_dir)) {
//read, write, execute
mkdir($this->_dir, 0777);
}
$form = new UploadForm($this->_dir, 'upload-form');
$request = $this->getRequest();
if ($request->isPost()) {
$post = array_merge_recursive(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($post);
if ($form->isValid()) {
$data = $form->getData();
$this->setFileNames($data);
return $this->redirect()->toRoute('upload/uploadsuccessful', array('products' =>$products));
}
}
return new ViewModel(array('form' => $form));
}
public function successfulAction()
{
$file = array();
$flashMessenger = $this->flashMessenger();
if ($flashMessenger->hasMessages()) {
foreach($flashMessenger->getMessages() as $key => $value) {
$file = $value;
}
}
return new ViewModel(array('file' => $file));
}
protected function setFileNames($data)
{
unset($data['submit']);
foreach ($data['image-file'] as $key => $file) {
rename($file['tmp_name'], $this->_dir . DIRECTORY_SEPARATOR . $file['name']);
}
}
}
I think the idea is clear: for each [/:products] parameter I tried to make separate folder with given name in $fileManagerDir.
But, there is a problem. When I click on button upload ($request->isPost() == true) parameter $products becomes null and uploaded files don't go to appropriate folders. Also I am not able to redirect to successful action - the error appears "missing parameter" because $products is null.
In your view script the upload buttons are href links. This will result in a GET REQUEST being sent to the controller and not a POST and no FILES will be present either. Unless that is, you are intercepting the click event with external JS which you haven't mentioned here. The route url's should be in the form action attribute. The submit buttons should be buttons not links (unless you are using JS not mentioned here). Make sure the form method is set to POST.
Something like:
<form action="<?php echo $this->url('upload', array('products' =>'shoes')); ?>" method="post" enctype="multipart/form-data">
You'll need to deal with the dynamic action using JS or redesign your routing.
I want to use REST controllers in my website to map to routes similar to the following:
GET /article
GET /article/1
GET /article/create
GET /article/1/update
GET /article/1/delete
POST /article
PUT /article/1
DELETE /article/1
My controller is:
namespace Article\Controller;
// use Zend\Mvc\Controller\AbstractActionController;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\ViewModel;
use Article\Form\ArticleForm;
use Article\Model\Article;
class ArticleController extends AbstractRestfulController
{
protected $articleTable;
public function getList()
{
return new ViewModel(array(
'articles' => $this->getArticleTable()->fetchAll(),
));
}
public function get($id)
{
return new ViewModel(array(
'article' => $this->getArticleTable()->getArticle($id),
));
}
public function create()
{
$form = new ArticleForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$article = new Article();
$form->setInputFilter($article->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$article->exchangeArray($form->getData());
$this->getArticleTable()->saveArticle($article);
// Redirect to list of articles
return $this->redirect()->toRoute('article');
}
}
return array('form' => $form);
}
public function update()
{
//...
}
public function delete()
{
//...
}
public function getArticleTable()
{
if (!$this->articleTable) {
$sm = $this->getServiceLocator();
$this->articleTable = $sm->get('Article\Model\ArticleTable');
}
return $this->articleTable;
}
}
My module.config.php routes are as following:
'router' => array(
'routes' => array(
'article' => array(
'type' => 'segment',
'options' => array(
'route' => '/article[/:id]',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Article\Controller\Article',
),
),
),
With the AbstractRestfulController I can achieve the first two GETs, POST and DELETE; but, I don't know how to get the following routes (which will render as forms):
GET /article/create .. maps to ArticleController::create
GET /article/1/update .. maps to ArticleController::update
GET /article/1/delete .. maps to ArticleController::delete
I read in the docs: "Additionally, you can map “action” methods to the AbstractRestfulController, just as you would in the AbstractActionController; these methods will be suffixed with “Action”, differentiating them from the RESTful methods listed above. This allows you to perform such actions as providing forms used to submit to the various RESTful methods, or to add RPC methods to your RESTful API." .. but I can't see an example, and I tried adding a createAction but route not found. I guess my router configuration needs modified?
I'm running a 2.2.2 CakePHP Application, everything works as desired. Now I'm developing a Android App for it and therefore need to create the interfaces between those two apps. That's why I need to login users manually. So I created a whole new controller, the AndroidController, in order to bundle everything at one place. First thing to do would be the Login-Action. So I setup the following controller:
<?php
App::uses('AppController', 'Controller');
/**
* Android Controller
*
* #package app.Controller
*/
class AndroidController extends AppController {
public $components = array('RequestHandler','Auth');
public $uses = array('User');
public function beforeFilter() {
$this->Auth->allow();
}
public function login() {
//For testing purposes
$postarray = array('_method' => 'POST','data' => array('User' => array('email' => 'user#gmail.com', 'password' => 'THISisDEFINITELYaWRONGpassword')));
$id = $this->tryToGetUserID($postarray['data']['User']['email']);
if($id == 0){
//return Error json, unknown User
$this->set('result', array(
'tag' => 'login',
'success' => 0,
'error' => 1,
'error_msg' => 'Unknown User'
));
}else{
// if ($this->request->is('post')) {
$postarray['data']['User'] = array_merge($postarray['data']['User'], array('id' => $id));
$this->User->id = $id;
if ( $this->Auth->login($postarray['data']['User'])) {
// Login successfull
$this->User->saveField('lastlogin', date(DATE_ATOM));
$user = $this->User->find('all', array(
'recursive' => 0, //int
'conditions' => array('User.id' => $id)
));
$loggedInUser = array(
'tag' => 'login',
'success' => 1,
'error' => 0,
'uid' => '??',
'user' => array(
'name' => $user['0']['User']['forename'].' '.$user['0']['User']['surname'],
'email' => $user['0']['User']['email'],
'created_at' => $user['0']['User']['created'],
'updated_at' => $user['0']['User']['lastlogin']
)
);
$this->set('result', $loggedInUser);
} else {
// Login failed
$this->set('result', array(
'tag' => 'login',
'success' => 0,
'error' => 2,
'error_msg' => 'Incorrect password!'
));
}
// }
}
}
public function tryToGetUserID($email = null) {
$user = $this->User->find('list', array(
'conditions' => array('User.email' => $email)
));
if(!empty($user)){
return array_keys($user)['0'];
}else{
return 0;
}
}
}
You need to know that this method will be called as a POST request, but for testing purposes I manually created a post-array. In future I will use the $_POST array.
So, what happens: The Login with a registered user works, but it works every time! Even though the password is wrong or missing! The program never reaches the part in code with the "Login failed" comment.
Am I missing something here..?
Thank you!
If you take a closer look at the documentation you will notice that AuthComponent::login() will ...
In 2.x $this->Auth->login($this->request->data) will log the user in with whatever data is posted
I've put a considerable amount of digging into this but I haven't been able to figure out what the best method would be.
I have an employee management system where everyone who logs in is either an "employee", a "supervisor" or a "manager".
At the moment, I display different versions of pages just fine depending on what their rank is. However, regular "employees" can still get to pages they shouldn't if they manually enter the URL. According to CakePHP's documentation, it says all pages are restricted by default, and you have to grant access to each one. But I haven't granted access and it seems all the pages are accessible.
What is the best method for page access?
Thanks!
Edit: Here is the configuration of the AppController:
public $components = array(
'DebugKit.Toolbar',
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'Employee'
)
),
'loginAction' => array(
'controller' => 'employees',
'action' => 'login',
//'plugin' => 'users'
),
'loginRedirect' => array('controller' => 'employees', 'action' => 'dashboard'),
'logoutRedirect' => array('controller' => 'employees', 'action' => 'login'),
'authError' => 'You must be logged in to see that.'
)
);
And then there is the isAuthorized() method which always is set to return false:
public function isAuthorized($user = null) {
// Any registered user can access public functions
/*if (empty($this->request->params['admin'])) {
return true;
}*/
// Only admins can access admin functions
/*if (isset($this->request->params['admin'])) {
return (bool)($user['role'] === 'admin');
}*/
// Default deny
return false;
}
Crete two tables in database
resources (id, controller, action) (This will contain controller names and action names.)
permission (roll_id, resource_id)
In isAuthorized() function
If roll is admin, then return true.
Else Check the following.
using $this->request->controller Get current controller name.
using $this->request->action Get current action name.
Get resource_id from resources table for current controller and action.
Check record in permission table for resource_id and roll_id.
If record exist then return true.
Else at the end it is returning false by default.
Your code is missing this in the AppController.php
class AppController extends Controller {
public function isAuthorized($user) {
return true;
}
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => ['fields' => ['username' => 'email']]
],
'authorize' => ['Controller'],
]);
//some other code here
}
I want to add a new form to the edit customer page, so far so good, using rewrites to customer_edit_tabs i was able to add a tab and my admin form to the page. Code looks like this.
protected function _beforeToHtml()
{
$this->addTab('extraoptions', array(
'label' => Mage::helper('customer')->__('Extra options'),
'class' => 'ajax',
'url' => $this->getUrl('module/adminhtml_tabs/info', array('_current' => true)),
));
This adds my tab corrently. From there the link on the tabs controller:
public function infoAction()
{
$this->_init();
$this->getResponse()->setBody(
$this->getLayout()->createBlock('module/adminhtml_tabs_edit')->toHtml()
);;
}
This links to my form container on Block/Adminhtml/Tabs/Edit.php
class Namespace_Module_Block_Adminhtml_Tabs_Edit extends Mage_Adminhtml_Block_Widget_Form_Container{public function __construct()
{
parent::__construct();
$this->_objectId = 'id';
$this->_mode = 'edit';
$this->_blockGroup = 'module';
$this->_controller = 'adminhtml_tabs';
$this->_updateButton('save', 'label', Mage::helper('module')->__('Save'));
}
public function getHeaderText()
{
return Mage::helper('module')->__('Extra Options');
}
}
My Block/Adminhtml/Tabs/Edit/Form.php
class Namespace_Module_Block_Adminhtml_Tabs_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
public function __construct()
{
parent::__construct();
}
protected function _prepareForm()
{
$form = new Varien_Data_Form(array(
'id' => 'info_form',
'action' => $this->getUrl('module/adminhtml_tabs/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post',
'enctype' => 'multipart/form-data'
)
);
$fieldset = $form->addFieldset('extra_options', array('legend' => Mage::helper('module')->__('Extra Options Fieldset')));
$fieldset2->addField('extra', 'text', array(
'name' => 'zip',
'title' => Mage::helper('module')->__('extra'),
'label' => Mage::helper('module')->__('extra data'),
'maxlength' => '250',
'required' => false,
));
$form->setUseContainer(true);
}
protected function _prepareLayout()
{
return parent::_prepareLayout();
}
Everything is fine, I have a new button below the default save customer buttons, but this save button does not update the action, so if i click it, it goes to the default customer/edit/save action, it does not tell me the method does not exist which it should. My guess is that there is something wrong with the container but i have tried three tutorials with little differences to no avail, hope someone can help and even maybe someone will find my code helpful.
In this line of code:
'action' => $this->getUrl('module/adminhtml_tabs/save')
You are telling Magento to look for a module named module, a controller aliased adminhtml_tabs, and a saveAction() method within that file.
You need to figure out where you want to send the user when a save needs to be performed, and then place it there (e.g. the route to your controller->saveAction() method).
I decided to create a new button to save with a custom action. On the container:
$this->_addButton('save', array(
'label' => Mage::helper('adminhtml')->__('Save Extras'),
'onclick' => 'document.myform.submit();',
'class' => 'save',
),-1,5);
This did the trick.