I have used a component for uploading image,there is no problem in controller after add component.Here the code
class OesUsersController extends AppController {
var $helpers = array('Html', 'Form');
var $components = array('upload');
public function index() {
}
public function upload()
{
if (empty($this->data))
{
$this->render();
}
else
{
$this->cleanUpFields();
// set the upload destination folder
$destination = realpath('../../app/webroot/img/uploads/') . '/';
// grab the file
$file = $this->data['Image']['filedata'];
// upload the image using the upload component
$result = $this->Upload->upload($file, $destination, null, array('type' => 'resizecrop', 'size' => array('400', '300'), 'output' => 'jpg'));
if (!$result){
$this->data['Image']['filedata'] = $this->Upload->result;
} else {
// display error
$errors = $this->Upload->errors;
// piece together errors
if(is_array($errors)){ $errors = implode("<br />",$errors); }
$this->Session->setFlash($errors);
$this->redirect('/images/upload');
exit();
}
if ($this->Image->save($this->data)) {
$this->Session->setFlash('Image has been added.');
$this->redirect('/images/index');
} else {
$this->Session->setFlash('Please correct errors below.');
unlink($destination.$this->Upload->result);
}
}
}
The problem is image doesn't come from add.ctp
here the add.ctp code
<label for="Image">Image:</label>
<input type="file" name="data[Image][filedata]" id="ImageFiledata" />
add function code
public function add() {
$clint_ip=$this->request->clientIp();
if ($this->request->is('post')) {
$this->OesUser->create();
pr($this->request->data);
$this->request->data['OesUser']['user_otpkey']=String::uuid();
$this->request->data['OesUser']['user_regdate']=date("Y-m-d H:i:s");
$this->request->data['OesUser']['user_ip']=$clint_ip;
$this->barcode($this->request->data['OesUser']['user_otpkey']);
if ($this->OesUser->save($this->request->data)) {
$this->Session->setFlash(__('The oes user has been saved'), 'flash_success');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The oes user could not be saved. Please, try again.'), 'flash_fail');
}
}
$this->set('ip',$clint_ip);
}
here, database field name: image
controller name :OesUsers
Model name :OesUser
for full work I have taken help from this link
http://labs.iamkoa.net/2007/10/23/image-upload-component-cakephp/
How is your entire form looks like in add.ctp?
It sounds to me that you did not add
enctype="multipart/form-data"
to the form. That will cause the form not to post the file.
And also, it is recommended to use Form helper to create form.
When using Form helper, specify the form type to file
$this->Form->create('model',array('type'=>'file'));
Related
I'm working on CakePHP 3.4
I have a contact_messages table to save message via form on website.
I want to send user an email whenever a new message is saved.
For that, I have created mailer class like
<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
use Cake\Event\Event;
use Cake\Datasource\EntityInterface;
class ContactMessageMailer extends Mailer
{
public function newMessage($message)
{
$this
->setProfile('no-reply')
->setTemplate('new_message')
->setLayout('message')
->setEmailFormat('html')
->setTo($user->email) // user email
->setSubject('Verify Account')
->setViewVars(['name' => $user->first_name, 'email' => $user->email, 'message' => $message->body]);
}
public function implementedEvents()
{
return [
'Model.afterSave' => 'alertMessage'
];
}
public function alertMessage(Event $event, EntityInterface $entity, \ArrayObject $options)
{
if ($entity->isNew()) {
$this->send('newMessage', [$entity]);
}
}
}
and registering event in ContactMessagesTable.php
$mailer = new UserMailer(); //use App\Mailer\UserMailer;
$this->eventManager()->on($mailer);
ContactMessages belongsTo Users and Users is having email of user whom to send the email.
How can I get users information in Mailer?
Will probably do this;
In the User table;
public function processUser($user)
{
if($this->save($user)){
$event = new Event('Model.afterSave', $this, [$entity = $user])
$this->eventManager()->dispatch($event);
return true;
}else{
return false;
}
}
In ContactMessage Table ;
public function initialize()
{
parent::intialize();
$mailer = new UserMailer(); //use App\Mailer\UserMailer;
$this->Users->eventManager()->on($mailer); //ContactMessage has to be related to User table
}
Hope I was able to communicate.
I'm a newbie at cakephp. I got a form with 5 inputs. My form should be able to save either one user input or all 5 inputs. I'm able to save when user fills all 5 inputs, however, when user fills only 1 or 2 and saves it. Blank spaces with date created (current date) gets saved in the database. How can i make it to save only the user inputs from the form without any empty fields in the database. My Add function below.
public function add() {
if ($this->request->is('post')) {
$this->Item->create();
for ($i=0;$i<5;$i++){
if(empty($this->request->data['Item'][$i]['name'])){
}else{
$name = $this->request->data['Item'][$i]['name'];
$explode_name = explode(":",$name);
$this->request->data['Item'][$i]['name'] = $explode_name[0];
$this->request->data['Item'][$i]['hrid'] = $explode_name[1];
}
}
if ($this->Item->saveAll($this->request->data['Item'])) {
$this->Session->setFlash(__('The Item has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The item could not be saved. Please, try again.'));
}
}
$itemTypes = $this->Item->ItemType->find('list',array('order' =>array('ItemType.name' => 'asc')));
$this->set(compact('itemTypes'));
}
There is a small thing that you are missing, and it is that whether there is name empty or not but it has a value set for that particular index. You should unset that in case the value is empty as below
public function add() {
if ($this->request->is('post')) {
$this->Item->create();
for ($i=0;$i<5;$i++){
if(empty($this->request->data['Item'][$i]['name'])){
// here we are removing the empty name index so that it does not saves the result
unset($this->request->data['Item'][$i]);
}else{
$name = $this->request->data['Item'][$i]['name'];
$explode_name = explode(":",$name);
$this->request->data['Item'][$i]['name'] = $explode_name[0];
$this->request->data['Item'][$i]['hrid'] = $explode_name[1];
}
}
// also here we should check here that atleast there is one entry
if(!empty($this->request->data['Item'])){
if ($this->Item->saveAll($this->request->data['Item'])) {
$this->Session->setFlash(__('The Item has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The item could not be saved. Please, try again.'));
}
} else {
$this->Session->setFlash(__('There is no such item. Please fill value for at least one item.'));
}
}
$itemTypes = $this->Item->ItemType->find('list',array('order' =>array('ItemType.name' => 'asc')));
$this->set(compact('itemTypes'));
}
Please try the above code.
In CakePHP 2.x you can do it as like below-
public function add(){
if ($this->request->is('post')) {
$this->Item->create();
$items = $this->request->data['Item']; /*Get all items Array*/
$items = array_filter(array_map('array_filter', $items)); /*Remove all empty array, only keep Array with user inputs*/
if ($this->Item->saveAll($items)) {
/*Success*/
} else {
/*Error*/
}
}
}
In CakePHP 3.x you can do it as like below-
public function add() {
if ($this->request->is('post')) {
$items = $this->request->data['Item']; /*Get all items Array*/
$items = array_filter(array_map('array_filter', $items)); /*Remove all empty array, only keep Array with user inputs*/
$entities = $this->Item->newEntities($items); /*Prepare all Data*/
if($this->Item->saveMany($entities)){ /*Save all data*/
/*Success*/
}else{
/*Error*/
}
}
}
Record can not be saved in my login function. I don't know why.
Does anyone know what the problem is?
Other functions in the controller (add, edit, delete) work without problems.
...
class UsersController extends AppController
{
...
/**
* Login method
*/
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$user = $this->Users->newEntity($user,['validate' => false]);
$user->isNew(false);
//Last login date
$user->test = 'abcdef';
$user->modified = new Time();
$this->Users->save($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Error'));
}
}
...
}
Why you use newEntity ?
Try to remove it and do something liek this :
$this->Auth->setUser($user);
$user->isNew(false);
$user->validate=false;
//Last login date
$user->test = 'abcdef';
$user->modified = new Time();
$this->Users->save($user);
If it doesn't work try to show entity errors to know why :
Before : $this->Users->save($user);
Do that :
debug($user->errors());
die();
It works on this way:
public function login()
{
if ($this->request->is('post')) {
$authUser = $this->Auth->identify();
if ($authUser) {
$this->Auth->setUser($authUser);
$User = $this->Users->get($authUser['id']);
//Last login date
$User->modified = new Time();
$this->Users->save($User);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Error'));
}
}
I have somehow implemented UPLOADIFIVE in my CakePHP application. Everything seems to work great including uploading multiple files and inserting the correct information in the Database.
Based on the following code, I would like to UPLOAD AND SAVE EVERY FILE WITH A RANDOM NAME TAKING INTO ACCOUNT THE CURRENT DATE OR SOMETHING SIMILAR.
How could I accomplish this?
In my Photos Controller I have the following function:
// This function is called at every file upload. It uploads the file onto the server
// and save the corresponding image name, etc, to the database table `photos`.
function upload() {
$uploadDir = '/img/uploads/photos/';
if (!empty($_FILES)) {
debug($_FILES);
$tempFile = $_FILES['Filedata']['tmp_name'][0];
$uploadDir = $_SERVER['DOCUMENT_ROOT'] . $uploadDir;
$targetFile = $uploadDir . $_FILES['Filedata']['name'][0];
// Validate the file type
$fileTypes = array('jpg', 'jpeg', 'gif', 'png'); // Allowed file extensions
$fileParts = pathinfo($_FILES['Filedata']['name'][0]);
// Validate the filetype
if (in_array($fileParts['extension'], $fileTypes)) {
// Save the file
move_uploaded_file($tempFile,$targetFile);
$_POST['image'] = $_FILES['Filedata']['name'][0];
$this->Photo->create();
if ($this->Photo->save($_POST)) {
$this->Session->setFlash($targetFile, 'default', array('class' => 'alert_success'));
$this->redirect(array('action' => 'index'));
}
} else {
// The file type wasn't allowed
//echo 'Invalid file type.';
$this->Session->setFlash(__('The photo could not be saved. Please, try again.', true));
}
}
}
In my View file - admin_add.ctp I have added the following function
$('#file_upload').uploadifive({
'auto' : false,
'uploadScript' : '/photos/upload',
'buttonText' : 'BROWSE FILES',
'method' : 'post',
'onAddQueueItem' : function(file) {
this.data('uploadifive').settings.formData = { 'photocategory_id' : $('#PhotoPhotocategoryId').val() };
}
});
<input type="file" name="file_upload" id="file_upload" />
function upload() {
$uploadDir = '/img/uploads/photos/';
if (!empty($_FILES)) {
debug($_FILES);
// $tempFile = $_FILES['Filedata']['tmp_name'][0];
$uploadDir = $_SERVER['DOCUMENT_ROOT'] . $uploadDir;
$targetFile = $uploadDir . $_FILES['Filedata']['name'][0];
// Validate the file type
$fileTypes = array('jpg', 'jpeg', 'gif', 'png'); // Allowed file extensions
$fileParts = pathinfo($_FILES['Filedata']['name'][0]);
// Validate the filetype
if (in_array($fileParts['extension'], $fileTypes)) {
// Save the file
$tempFile = time()."_".basename($_FILES['Filedata']['name'][0]);
$_POST['image'] = $tempFile;
move_uploaded_file($tempFile,$targetFile);
$this->Photo->create();
if ($this->Photo->save($_POST)) {
$this->Session->setFlash($targetFile, 'default', array('class' => 'alert_success'));
$this->redirect(array('action' => 'index'));
}
} else {
// The file type wasn't allowed
//echo 'Invalid file type.';
$this->Session->setFlash(__('The photo could not be saved. Please, try again.', true));
}
}
}
Chetanspeed thanks so much for quickly helping out with this. Based on his solution I was able to make it work. Below is the code that worked for me which is slightly different than Chetanspeed
function upload() {
$uploadDir = '/img/uploads/photos/';
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'][0]; // Temp file should not be changed since it contains the physical location of the file /tmp/file.jpg
$uploadDir = $_SERVER['DOCUMENT_ROOT'] . $uploadDir;
$randomString = time(); // Save this random string to a variable
$targetFile = $uploadDir . $randomString."_".basename($_FILES['Filedata']['name'][0]); //randomString is added to target...
// Validate the file type
$fileTypes = array('jpg', 'jpeg', 'gif', 'png'); // Allowed file extensions
$fileParts = pathinfo($_FILES['Filedata']['name'][0]);
// Validate the filetype
if (in_array($fileParts['extension'], $fileTypes)) {
//image name posted to database containing the randomString generated from time...thanks Chetanspeed
$_POST['image'] = $randomString."_".basename($_FILES['Filedata']['name'][0]);
move_uploaded_file($tempFile,$targetFile);
$this->Photo->create();
if ($this->Photo->save($_POST)) {
$this->Session->setFlash($targetFile, 'default', array('class' => 'alert_success'));
$this->redirect(array('action' => 'index'));
}
} else {
// The file type wasn't allowed
//echo 'Invalid file type.';
$this->Session->setFlash(__('The photo could not be saved. Please, try again.', true));
}
}
}
When isAuthorized = false the user is redirected to '/' is there a way to change this. I want to redirect to the user dashboard (/users/dashboard) with a flash message saying 'Access prohibited' or something like that.
Cheers!
public function isAuthorized($user) {
if (isset($user['role']) && $user['role'] === 'admin') {
return true; //Admin can access every action
}
return false; // The rest don't
}
If your isAuthorised variable is being evaluated in your controller.
You can call the redirect function.
$this->redirect(array('controller' => 'users', 'action' => 'dashboard'));
If you are actually inside the users controller allready, just call
$this->redirect(array('action' => 'dashboard'));
If not, where are you checking the isAuthorised value?
This is not an ideal solution. However it seems that there is no way to do this with the current built in AuthComponent
Edit: Added code as an example.
public function isAuthorized($user) {
if (parent::isAuthorized($user)) {
return true;
}
// Authorised actions
if (in_array($this->action, array('dashboard'))) {
return true;
}
// Will break out on this call
$this->redirect(array('controller' => 'users', 'action' => 'dashboard'));
return false;
}
I think the best way is to use exception and extends like that :
AppController.php
public function isAuthorized($user) {
throw new ForbiddenException(__('You are not authorized to access.'));
}
AnotherController.php
public function isAuthorized($user) {
if (isset($user['role']) && $user['role'] === 'admin') {
return true;
}
return parent::isAuthorized($user);
}
With this code you are able to manage the roles and the error.
If they are being logged out you can send them where you want with:
$this->Auth->logoutRedirect
I would personally use:
$this->Auth->authError = "You are not authorized to access.";
In order to redirect them to root with a flash message notifying them of the error.
Is a wrong behavior of AuthComponent.
In a nutshell: if the url is visited by a link, the framework is able to reconstruct the path and then redirect to the referring page. Otherwise (by direct entry into a url bar) it fails and it redirects to the home page.
The "bug" is documented and it will be corrected in a future release.
See: http://cakephp.lighthouseapp.com/projects/42648/tickets/591-inconsistent-redirect-behaviour-by-auth-acl
I do a little better than #deep55.
isAuthorized() method can throw an exception no problem, but i think that the inheritance of the Controllers would permit us to improve authorization algorithm using first AppController.isAuthorized(), not last.
So, here is my solution, assuming that I use a user model called Utilisateur, and a role model called Role.
AppController :
/**
* Parent method
*/
public function isAuthorized($user){
App::uses('Utilisateur','Model');
$User = new Utilisateur();
$isAdmin = $User->hasRole(10,$user['id']);
if ($isAdmin) {
return true;
}
}
/**
* Reject unauthorized actions
*/
public function rejectRequest(){
$errorMessage = __("Sorry, you can't do this.");
if ($this->isRest()) {
throw new ForbiddenException($errorMessage);
} else {
$this->Auth->authError = $errorMessage;
$this->Auth->flash['params']['class'] = 'alert-danger';
}
return false ;
}
Utilisateur model :
/**
* hasRole method return true if the user belongs to the correct role group
*/
public function hasRole($role_id, $user_id){
if (!isset($user_id)) {
if (!empty($this->id)) {
$user_id = $this->id ;
} else throw new Exception("Error, parameter $user_id is missing", 1);
}
$user = $this->find('first',array(
'conditions' => array('Utilisateur.id' => $user_id),
'fields' => array('id'),
'contain' => array('Role.id')
));
$roles = $user['Role'];
foreach ($roles as $r) {
if ($role_id == $r['id']) {
return true;
}
}
}
And last, in a specific controller :
/**
* Child method
*/
public function isAuthorized($user){
if (parent::isAuthorized($user)) {
return true;
}
if ( false ) {
return true ;
}
if ( false ) {
return true ;
}
return $this->rejectRequest() ;
}
For Cake version 2, as written in documentation for AuthComponent:
AuthComponent::$unauthorizedRedirect
Controls handling of unauthorized access. By default unauthorized user is redirected to the referrer URL or AuthComponent::$loginRedirect or ‘/’. If set to false a ForbiddenException exception is thrown instead of redirecting.
you can configure AuthComponent to redirect you to custom page in one place using unauthorizedRedirect property.
Just set it in the place where you configure Auth as a component
'Auth' => array(
... other settings...,
'unauthorizedRedirect' => '/users/dashboard'
)
After being redirected, you can print error message defined by authError property
echo $this->Session->flash();
echo $this->Session->flash('auth');
but it will be the same message for any authentication or authorization error.