I am trying to create a file upload on cakephp, I haven't been able to find any decent tutorials for cakephp 3.0 that go in detail, and I don't understand how to install plugins.
I have this in my add section
echo $this->Form->create('filename', array('action' => 'upload', 'type' => 'file'));
echo $this->Form->file('filename');
I haven't added anything in the controller yet
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Courses']
];
$this->set('contents', $this->paginate($this->Contents));
$this->set('_serialize', ['contents']);
}
/**
* View method
*
* #param string|null $id Content id.
* #return void
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$content = $this->Contents->get($id, [
'contain' => ['Courses']
]);
$this->set('content', $content);
$this->set('_serialize', ['content']);
}
/**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$content = $this->Contents->newEntity();
if ($this->request->is('post')) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Edit method
*
* #param string|null $id Content id.
* #return void Redirects on successful edit, renders view otherwise.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$content = $this->Contents->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Delete method
*
* #param string|null $id Content id.
* #return void Redirects to index.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$content = $this->Contents->get($id);
if ($this->Contents->delete($content)) {
$this->Flash->success('The content has been deleted.');
} else {
$this->Flash->error('The content could not be deleted. Please, try again.');
}
return $this->redirect(['action' => 'index']);
}
but after this no idea what to do.
First of all, you need to decide on WHEN you're going to handle uploads. I've managed to create a dirty (but working) approach using beforeMarshal method and afterSave method (I'll explain why these two at the end).
If you create your file input like:
<?= $this->Form->file('submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
or for hasMany association:
<?= $this->Form->file('images.'.$i.'.submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
and you define the right associations:
$this->hasMany('Images', [
'foreignKey' => 'model_id'
]);
you could process those files before the Entity gets patched and saved:
public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options) {
$images = array();
$dir = md5(time().$data['name']);
for ($i = 0; $i < count($data['images']); $i++) {
$image = $data['images'][$i]['submittedfile'];
if (!empty($image['name'])) {
if(!isset($data['id'])) {
$data['temp_dir'] = $dir;
}
else {
$dir = $data['id'];
}
if ($this->Images->uploadFile(array('img', 'model', $dir), $image) === true) {
$images[] = array('name' => pathinfo($image['name'], PATHINFO_FILENAME), 'ext' => pathinfo($image['name'], PATHINFO_EXTENSION));
}
}
}
$data['images'] = $images;
}
This is of course an example. I've decided to check, if there's an ID property set on the Entity (like for edit), because if it's not (like for create), you have to somehow identify the right path.
Here you've got a file uploading function:
public function uploadDir($path = array()) {
return $this->wwwRoot . implode(DS, $path);
}
public function uploadFile($path = array(), $filetoupload = null) {
if (!$filetoupload) {
return false;
}
$dir = new Folder($this->uploadDir($path), true, 755);
$tmp_file = new File($filetoupload['tmp_name']);
if (!$tmp_file->exists()) {
return false;
}
$file = new File($dir->path . DS . $filetoupload['name']);
if (!$tmp_file->copy($dir->pwd() . DS . $filetoupload['name'])) {
return false;
}
$file->close();
$tmp_file->delete();
return true;
}
If you added your images while there was no subdirectory with main entity ID, you have to rename the directory as soon as you get the ID:
public function afterSave(Event $event, Entity $entity, \ArrayObject $options) {
if(!empty($entity->temp_dir)) {
$this->Images->renameFolder(array('img', 'model', $entity->temp_dir),$entity->id);
}
}
calling:
public function renameFolder($path = array(), $newName) {
$oldPath = $this->wwwRoot . implode(DS, $path);
$nameToChange = array_pop($path);
array_push($path, $newName);
$newPath = $this->wwwRoot . implode(DS, $path);
return rename($oldPath, $newPath);
}
Using beforeMarshal you're able to inject your file data into Entity structure before the whole Entity is ready for saving (with associations).
Using afterSave you're able to identify the main object ID and call the set of objects you've uploaded before.
Remember to set recursive rights for saving files onto the directory, as well as rights for creating and renaming directories.
Related
I want to build forgot password page in cakephp
Here is my code of user controller
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Http\Exception\UnauthorizedException;
use Cake\Mailer\Email;
use Cake\Mailer\Mailer;
use Cake\email\TransportFactory;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Utility\Security;
use Cake\ORM\TableRegistry;
use Cake\Core\InstanceConfigTrait;
/**
Users Controller
#property \App\Model\Table\UsersTable $Users
#method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class UsersController extends AppController {
public function beforeFilter(\Cake\Event\Event $event) {
$this->Auth->allow([‘add’, ‘logout’]);
parent::beforeFilter($event);
}
/**
Index method
#return \Cake\Http\Response|null
*/
public function index() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException(__(‘You are not allowed to access this page’));
}
$users = $this->paginate($this->Users);
$this->set(compact(‘users’));
}
/**
View method
#param string|null $id User id.
#return \Cake\Http\Response|null
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null) {
$user = $this->Users->get($id, [
‘contain’ => [],
]);
$this->set(‘user’, $user);
}
/**
Add method
#return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->newEntity();
if ($this->request->is(‘post’)) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Edit method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->get($id, [
‘contain’ => [],
]);
if ($this->request->is([‘patch’, ‘post’, ‘put’])) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Delete method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects to index.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$this->request->allowMethod([‘post’, ‘delete’]);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success((‘The user has been deleted.’));
} else {
$this->Flash->error(__(‘The user could not be deleted. Please, try again.’));
}
return $this->redirect([‘action’ => ‘index’]);
}
public function forgotpassword()
{
if ($this->request->is(‘post’)) {
$email = $this->request->getData(‘email’);
$token = Security::hash(Security::randomBytes(25));
$userTable = TableRegistry::get(‘Users’);
if ($email == NULL) {
$this->Flash->error((‘Please insert your email address’));
}
if ($user = $userTable->find(‘all’)->where([‘email’=>$email])->first()) {
$user->token = $token;
if ($userTable->save($user)){
$mailer = new Mailer(‘default’);
$mailer->Transport(‘Smtp’);
$mailer->From([‘noreply[at]codethepixel.com’ => ‘myCake4’])
->setTo($email)
->setEmailFormat(‘html’)
->setSubject(‘Forgot Password Request’)
->deliver(‘Hello
Please click link below to reset your password
Reset Password’);
}
$this->Flash->success(‘Reset password link has been sent to your email (’.$email.’), please check your email’);
}
if ($total = $userTable->find(‘all’)->where([‘email’=>$email])->count()==0) {
$this->Flash->error((‘Email is not registered in system’));
}
}
}
public function resetpassword($token)
{
if($this->request->is(‘post’)){
$hasher = new DefaultPasswordHasher();
$newPass = $hasher->hash($this->request->getData(‘password’));
$userTable = TableRegistry::get(‘Users’);
$user = $userTable->find(‘all’)->where([‘token’=>$token])->first();
$user->password = $newPass;
if ($userTable->save($user)) {
$this->Flash->success(‘Password successfully reset. Please login using your new password’);
return $this->redirect([‘action’=>‘login’]);
}
}
}
public function login() {
if ($this->request->is(‘post’)) {
$user = $this->Auth->identify();
if ($user) {
if ($user[‘is_active’] === 1) {
$users = $this->Users->get($user[‘id’]);
$users->ip_address = $this->request->clientIp();
$users->last_login = date(‘Y-m-d h:i:s’);
if ($this->Users->save($users)) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error((‘Unable to login by your credentials.’));
}
} else {
$this->Flash->error((‘This user not activated, please contact our administrator.’));
}
}
$this->Flash->error(__(‘Invalid username or password, try again’));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
}
After opening forgot password page user enter their email following error received.
Cannot instantiate abstract class Cake\Mailer\Mailer
How do I solve this problem when the user entered their email & reset password will be sent to user's email which will be saved in our database.
Help me please #ndm
In your app.php
use Cake\Mailer\Transport\MailTransport;
.
.
.
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The following keys are used in SMTP transports:
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => null,
'password' => null,
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
'your_project' => [
'className' => 'Smtp',
'host' => 'your_host',
'port' => XXX,
'timeout' => 30,
'username' => 'your_email',
'password' => 'your_password',
'client' => null,
'tls' => true,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you#localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
'your_project' => [
'transport' => 'your_project',
'from' => ['your_email#teste.com' => 'My Site'],
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
Create a folder "Mailer" in src/Mailer. Create an UserMailer.php file
<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
class UserMailer extends Mailer
{
public static $name = 'User';
public function reset($user)
{
$this->to($user->email)
->profile('your_project')
->emailFormat('html')
->template('your_project', 'user')
->layout('user')
->viewVars(['name' => $user->name])
->subject(sprintf('Welcome...', $user->name))
->message("texte...");
}
}
In this case, I created a layout for my email. Create an "Email" folder in the layout.
On your controller, do the following:
$this->getMailer('User')->send('reset', [$user]);
Don't forget to import into the controller:
use Cake\Mailer\MailerAwareTrait;
I use it like this.
Go to the godaddy dashboard and find the SMTP information. It's all you need! Replace with your information
I am using cakephp3. I have a simple web application that has users. I have two user types, Admin and Standard. I want to limit Standard user to only view and index data. Whereas Admin type user should be able to add, edit, delete, view and index user data.
Basically, I want to globally restrict standard users, so that they cannot access the add, edit and delete methods of the controller.
So can anyone help me achieve it?
Below is /src/Controller/UsersController.php
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* Users Controller
*
* #property \App\Model\Table\UsersTable $Users
*/
class UsersController extends AppController
{
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Countries', 'Cities', 'UserGroups', 'UserLevels']
];
$this->set('users', $this->paginate($this->Users));
$this->set('_serialize', ['users']);
}
public function dashboard()
{
}
/**
* View method
*
* #param string|null $id User id.
* #return void
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$user = $this->Users->get($id, [
'contain' => ['Countries', 'Cities', 'UserGroups', 'UserLevels', 'Alerts', 'DeviceLogs', 'Devices']
]);
$this->set('user', $user);
$this->set('_serialize', ['user']);
}
/**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$countries = $this->Users->Countries->find('list', ['limit' => 200]);
$cities = $this->Users->Cities->find('list', ['limit' => 200]);
$userGroups = $this->Users->UserGroups->find('list', ['limit' => 200]);
$userLevels = $this->Users->UserLevels->find('list', ['limit' => 200]);
$this->set(compact('user', 'countries', 'cities', 'userGroups', 'userLevels'));
$this->set('_serialize', ['user']);
}
/**
* Edit method
*
* #param string|null $id User id.
* #return void Redirects on successful edit, renders view otherwise.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$countries = $this->Users->Countries->find('list', ['limit' => 200]);
$cities = $this->Users->Cities->find('list', ['limit' => 200]);
$userGroups = $this->Users->UserGroups->find('list', ['limit' => 200]);
$userLevels = $this->Users->UserLevels->find('list', ['limit' => 200]);
$this->set(compact('user', 'countries', 'cities', 'userGroups', 'userLevels'));
$this->set('_serialize', ['user']);
}
/**
* Delete method
*
* #param string|null $id User id.
* #return \Cake\Network\Response|null Redirects to index.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success(__('The user has been deleted.'));
} else {
$this->Flash->error(__('The user could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error('Your username or password is incorrect.');
}
}
public function logout()
{
$this->Flash->success('You are now logged out.');
return $this->redirect($this->Auth->logout());
}
public function resetPassword() {
}
public function changepassword() {
}
}
Below is AppController.php
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
use \Crud\Controller\ControllerTrait;
public $components = [
'RequestHandler',
'Crud.Crud' => [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete'
],
'listeners' => [
'Crud.Api',
'Crud.ApiPagination',
'Crud.ApiQueryLog'
]
]
];
/**
* Initialization hook method.
*
* Use this method to add common initialization code like loading components.
*
* e.g. `$this->loadComponent('Security');`
*
* #return void
*/
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
// default is referer and in case of no referer loginRedirect (after login)
'loginRedirect' => [
'controller' => 'Users',
'action' => 'dashboard'
],
'logoutRedirect' => '/',
'authError' => "Y"
]);
// Allow the display action so our pages controller
// continues to work.
$this->Auth->allow(['resetPassword','add','changePassword','display']);
}
/**
* Before render callback.
*
* #param \Cake\Event\Event $event The beforeRender event.
* #return void
*/
public function beforeRender(Event $event)
{
if (!array_key_exists('_serialize', $this->viewVars) &&
in_array($this->response->type(), ['application/json', 'application/xml'])
) {
$this->set('_serialize', true);
}
}
}
Regards,
The right approach is to use ControllerAuthorize.
As described in the docs, you have to add in AppController the following:
public function isAuthorized($user = null)
{
// Any registered user can access public functions
if (empty($this->request->params['prefix'])) {
return true;
}
// Only admins can access admin functions
if ($this->request->params['prefix'] === 'admin') {
return (bool)($user['role'] === 'admin');
}
// Default deny
return false;
}
You then have to define admin as a valid key for prefix routing, and move your add, edit and delete actions to the new controller in
src/Controller/Admin/UsersController.php
Greetings,
i'm using a multiple file upload input in Yii2.
The multiole file input is saving very well the files selected inside a folder called audio.
The problen is i cannot inside foreach loop save the name and path of each file in the database model Faixas.php inside a field called ficheiro.
Here is my code:
Controller:
public function actionCreate()
{
$model = new Faixas();
if (Yii::$app->request->isPost) {
$model->files = UploadedFile::getInstances($model, 'files');
if ($model->upload()) {
return $this->render('create', ['model' => $model]);
}
}
return $this->render('create', ['model' => $model]);
}
The Model as a function named upload() to save the files in folder, but the part to save inside the model->ficheiro is not working (don't figure it out ?):
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
$model = new Faixas();
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
And finally the view, which renders the input:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'files[]')->fileInput(['multiple' => true, 'accept' => 'audio/*']) ?>
<button>Submit</button>
Any ideas on the way to get it done?
Many thanks...
The entire Faixas.php model class:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "faixas".
*
* #property integer $id
* #property string $nome
* #property string $ficheiro
* #property string $dummy1
* #property string $dummy2
* #property string $dummy3
* #property string $dummy4
* #property string $dummy5
*/
class Faixas extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'faixas';
}
public $files;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'nome' => Yii::t('app', 'Nome'),
'ficheiro' => Yii::t('app', 'Ficheiro'),
'dummy1' => Yii::t('app', 'Dummy1'),
'dummy2' => Yii::t('app', 'Dummy2'),
'dummy3' => Yii::t('app', 'Dummy3'),
'dummy4' => Yii::t('app', 'Dummy4'),
'dummy5' => Yii::t('app', 'Dummy5'),
];
}
// coloca o Audio na GridView
public function getAudio()
{
return \Yii::$app->request->BaseUrl.'/'.$this->ficheiro;
}
}
Seems you create the model in wrog place. You create a $model = new Faixas(); ouuside the loop. try creating inside.
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
SOLVED... removed from the model file the rule:
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
Now the foreach() loop saves every file Path in the database.
Many thanks to all that somehow tried to achieve a solution.
I have Two Table ones and twos I have A Foreign Key in 'two' table two_one_id
I Want to insert data in both table at a time , means insert data within one form, so how to manage controller and model, can I make one model and one controller for this ? then How To Create The Model And Controller For This
Which Type Of Relation Should Have I Prefer For Both Table?
I Have Made Two Different Tabele One.php and Two.php
and I Have Made Two Controller OnesController.php and twosController.php
Can I Use Scaffold In Both Of Them And Using Scaffold Can I Insert Data In Two Table Within A Controller And Model, If It Is Possible Using Scaffolding , Then How Done It, Or In This Code I Have Tried Without Scaffolding , Manual Manage View */
/*One.php File
public $displayField = 'name';
public $hasOne = array(
'Two' => array(
'className' => 'Two',
'foreignKey' => 'two_one_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
//Two.php
<?php
App::uses('AppModel', 'Model');
class Two extends AppModel {
public $displayField = 'sname';
public $belongsTo = array(
'One' => array(
'className' => 'One',
'foreignKey' => 'two_one_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
//OnesController.php
<?php
App::uses('AppController', 'Controller');
/**
* Ones Controller
*
* #property One $One
* #property PaginatorComponent $Paginator
*/
class OnesController extends AppController {
/**
* Helpers
*
* #var array
*/
public $helpers = array('Html','Form');
public $uses = array('One','Two');
public $components = array('Paginator');
public function index() {
$this->One->recursive = 0;
$this->set('ones', $this->Paginator->paginate());
}
public function view($id = null) {
if (!$this->One->exists($id)) {
throw new NotFoundException(__('Invalid one'));
}
$options = array('conditions' => array('One.' . $this->One->primaryKey => $id));
$this->set('one', $this->One->find('first', $options));
}
public function add() {
if ($this->request->is('post')) {
$this->One->create();
if ($this->One->save($this->request->data)) {
$this->Session->setFlash(__('The one has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The one could not be saved. Please, try again.'));
}
}
}
public function edit($id = null) {
if (!$this->One->exists($id)) {
throw new NotFoundException(__('Invalid one'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->One->save($this->request->data)) {
$this->Session->setFlash(__('The one has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The one could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('One.' . $this->One->primaryKey => $id));
$this->request->data = $this->One->find('first', $options);
}
}
public function delete($id = null) {
$this->One->id = $id;
if (!$this->One->exists()) {
throw new NotFoundException(__('Invalid one'));
}
$this->request->onlyAllow('post', 'delete');
if ($this->One->delete()) {
$this->Session->setFlash(__('The one has been deleted.'));
} else {
$this->Session->setFlash(__('The one could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
}}
You may want to look into: $this->One->saveAll($this->request->data)
http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array
You Just Set Following Code to Your Controller
OnesControllers.php
public function add() {
if ($this->request->is('post')) {
$this->One->create();
}
if (!empty($this->request->data)) {
// We can save the User data:
// it should be in $this->request->data['User']
$one = $this->One->save($this->request->data);
// If the user was saved, Now we add this information to the data
// and save the Profile.
if (!empty($one)) {
// The ID of the newly created user has been set
// as $this->User->id.
$this->request->data['Two']['two_one_id'] = $this->One->id;
// Because our User hasOne Profile, we can access
// the Profile model through the User model:
$this->One->Two->save($this->request->data);
}
}
And Set This in Your View
view/one/add.ctp
<div class="ones form">
<?php echo $this->Form->create('One'); ?>
<fieldset>
<legend><?php echo __('Add One'); ?></legend>
<?php
echo $this->Form->input('name',array('rows' => '10'));
echo $this->Form->create('Two');
echo $this->Form->input('sname');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
Right now my image links look like this:
I need them to look like this:
My Images are stored in APP/uploads/userid/images/filename.jpg
This is my view at the moment:
<?php foreach($file as $files){?>
<?php echo $this->Html->link($files['Image']['filename'], array('controller' => 'images', 'action' => 'downloadImages', $files['Image']['filename']), array('class' => 'frame'));}?>
It works and clicking the link shows the relevant image correctly.
Controller snippet for reference:
public function downloadImages($filename) {
$download = !empty($_GET['download']);
$idUser = $this->Auth->user('idUser');
$folder_url = APP.'uploads/'.$idUser.'/'.'images'.'/'.$filename;
$this->response->file($folder_url, array('download' => $download, 'name' => $filename));
return $this->response;
}
What do I need to do to make images display as links instead of the name of the file?
How to generate an image link
In the question there is this line (paraphrased for clarity):
$downloadUrl = array('controller' => 'images', 'action' => 'downloadImages', $files['Image']['filename'], '?' => array('download' => true));
$imageUrl = array('controller' => 'images', 'action' => 'downloadImages', $files['Image']['filename']);
echo $this->Html->link(
$files['Image']['filename'],
$downloadUrl,
array('class' => 'frame')
);
Instead of linking to the filename - link to the image:
echo $this->Html->link(
$this->Html->image($imageUrl),
$downloadUrl,
array('class' => 'frame', 'escape' => false)
);
OR use the image function directly, since the image function supports that:
echo $this->Html->image(
$imageUrl,
array(
'url' => $downloadUrl
)
);
Here is a copy of y GemsImageComponent that I use to push images to the browser from disk. It handles caching, and uses the file timestamp to see if the image should sent again, or if the browser's current cached version is up to date.
Please up-vote if you find this useful.
<?php
/**
* $settings['cache'] string (optional) How long the browser should cache
* images.
* $settings['expires'] string (optional) If all images should expire after a
* given period from the browsers cache.
*/
class GemsImageComponent extends Component
{
/**
*
* #var array The default settings for the component.
*/
protected $defaults = array(
'cache' => '+7 days',
'expires' => false
);
/**
*
* #var Controller The controller using this component.
*/
protected $controller;
/**
*
* #see Component::__construct()
*/
public function __construct(ComponentCollection $collection,
$settings = array())
{
parent::__construct($collection,
Hash::merge($this->defaults, $settings));
}
/**
*
* #see Component::startup()
*/
public function startup(Controller $controller)
{
$this->controller = $controller;
}
/**
* Sends an image from disk to the browser.
*
* #param string $file The full path to the image file.
* #return mixed The value that the View should return.
*/
public function send($file)
{
$response = $this->controller->response;
$settings = $this->settings;
// the file has to exist
if(! file_exists($file))
{
throw new NotFoundException();
}
// set browser cache options
if($settings['cache'] !== false)
{
$response->cache('-1 minute', $settings['cache']);
}
if($settings['expires'] !== false)
{
$response->expires($settings['expires']);
}
// mark this image with a timestamp of when it last changed.
$timestamp = filemtime($file);
$response->modified($timestamp);
// generate a unique ID that browser cache engines can use to track this
// resource.
// TODO: Add GEMS version number to the hash tag.
$unique = sha1(sprintf('%s-%d', $file, $timestamp));
$response->etag($unique);
// check if we can abort sending this resource
if(! $response->checkNotModified($this->controller->request))
{
$response->file($file, array(
'download' => false
));
}
return $response;
}
}
?>