How to properly delete file related to record - php

I need to delete icon file related to current news if news was deleted.
I see 2 approaches.
First:
public function admin_delete ($id = null, $icon = null) {
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
if ($this->News->delete($id)) {
unlink(WWW_ROOT . 'img/icons/news/' . $icon);
$this->Session->setFlash('ok!');
$this->redirect(array('action' => 'index'));
}
}
I need to pass the record ID and filename to this action from view.
For me it seems slightly ugly and also can cause Nginx related issues.
Second one:
public function admin_delete ($id = null) {
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
$icon = $this->News->read('icon', $id);
if ($this->News->delete($id)) {
unlink(WWW_ROOT . 'img/icons/news/' . $icon['icon']);
$this->Session->setFlash('ok!');
$this->redirect(array('action' => 'index'));
}
}
But I'm not sure is it a good approach and should I use read or find('first').
I hope you can give me some advice on how to do it in more correct way.
Thanks in advance!

None of that stuff should be in controller. Fetch the record using find('first') in the model's beforeDelete() and save the filename in a model property. Then in afterDelete() delete file who's filename you cached in beforeDelete().

Related

Add favorite with symfony

I am learning symfony.
I try to save favorite when I click on a link and when I click again on the link, I wish I could remove the favorite in DB.
When clicking, I do have a new row in my database.
If I click again, it add a new one and don't erase the row.
This is what i have done in my controller:
public function addFavorite(EntityManagerInterface $manager, PostRepository $postRepository, Post $post)
{
$favorite = $postRepository->findOneBy(['content' => $post,'author' => $this->getUser()
]);
if (is_null($favorite)) {
$favorite = new Favorite();
$favorite
->setPost($post)
->setUser($this->getUser());
$manager->persist($favorite);
$manager->flush();
return $this->render('favorite/index.html.twig');
} else {
$manager->remove($favorite);
$manager->flush();
return $this->render('favorite/index.html.twig');
}
}
From what i understand, the problem is that $favorite is still NULL and i don't understand why...
If someone could help me, thanks !
I think it's because you don't request the good entity. I don't really know your entities, but I think this could be more logical :
public function addFavorite(EntityManagerInterface $manager, FavoriteRepository $favoriteRepository, Post $post)
{
$favorite = $favoriteRepository->findOneBy([
'post' => $post,
'user' => $this->getUser()
]);
if (!$favorite) {
$favorite = new Favorite();
$favorite
->setPost($post)
->setUser($this->getUser());
$manager->persist($favorite);
} else {
$manager->remove($favorite);
}
$manager->flush();
return $this->render('favorite/index.html.twig');
}

CakePHP saving foreignKeys not working

I have 3 tables: Computers hasMany Brands, Brands belongsTo Computers and Parts. Now i have these fields in my Brands description,computer_id,part_id. I have the code below to save my data. It will save the description and part_id....But my computer_id does not save at all.
Usually my URL written http://192.168.6.253/computers/brands/add/1 where 1 is computer_id.
How will I save it? Im still beginner in this framework
Controller
public function add($id = null) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
//Assign value to link computer_id
$data = $this->Brand->Computer->findById($id);
$this->set('computers', $data);
//assign select values to parts select
$this->set('parts', $this->Brand->Part->find('list',
array('fields' => array('description'))));
if ($this->request->is('post')) {
$this->Brand->create();
if ($this->Brand->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
$this->redirect(array('action' => 'table/'.$id));
} else {
$this->Session->setFlash(__('Unable to add your post.'));
}
}
}
View
<?php
echo $this->Form->create('Brand');
echo $this->Form->input('part_id',array('empty'=>' '));
echo $this->Form->input('description');
echo $this->Form->input('computer_id',array('type'=>hidden));
echo $this->Form->end('Save Post');
?>
If you are not requiring to send the computer id through the form since it's a url param... you can adjust your add function like this
if ($this->request->is('post')) {
$this->request->data['Brand']['computer_id'] = $id; //manually add the id to the request data object
$this->Brand->create();
if ($this->Brand->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
$this->redirect(array('action' => 'table/'.$id));
} else {
$this->Session->setFlash(__('Unable to add your post.'));
}
}
That's a very basic way of doing it without checking for data integrity, anyone could easily change the param to a 2, but it conforms with your current setup.

CakePHP isAuthorized not working properley when passing arguments

I'm using isAuthorized to deny access to methods if the record id doesn't belong to the user. Profiles can have many documents and documents belong to one profile:
Controller/DocumentsController.php
public function add($id = null) {
if ($this->request->is('post')) {
$this->request->data['Document']['profile_id'] = $id;
$this->request->data['Document']['user_id'] = $this->Auth->user('id');
$this->Document->create();
if ($this->Document->save($this->request->data)) {
$this->Session->setFlash(__('The document has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The document could not be saved. Please, try again.'));
}
}
}
public function isAuthorized($user) {
if ($this->action === 'index') {
return true;
}
if (in_array($this->action, array('view', 'add', 'edit', 'delete'))) {
$document_id = $this->request->params['pass'][0];
if ($this->Document->isOwnedBy($document_id, $user['id'])) {
return true;
}
}
return parent::isAuthorized($this->Auth->user());
}
Model/Document.php
public function isOwnedBy($document, $user) {
return $this->field('id', array('id' => $document, 'user_id' => $user)) === $document;
}
I'm passing the profile id as $id to docments/add from one of my profile views via Cake link helper:
View/Profiles/view.ctp
echo $this->Html->link('New Document',
array('controller' => 'documents', 'action' => 'add',$profile['Profile']['id'])
);
What happens when I click on New Document from profiles/view is that it sends the request but doesn't redirect, just refreshes the page, or it redirects back to profiles/view, not sure which. My first guess is since I'm not defining the profile id in the isAuthorized callback within DocumentsController, isOwnedBy is returning false. Any suggestions on how to get the profile id in isAuthorized within DocumentsController?
Thanks in advance!
The solution to this is relativley easy. When using isAuthorized with parameters from another controller, be sure to reference the right model.
if ($this->Document->Profile->isOwnedBy($document_id, $user['id'])) {
return true;
}

Populate Fields From one Controller, in another.. CAKEPHP

I am currently trying to allow the users to archive events that have already been completed.
Then the event will be viewed in the Archive Table.
So basically I have one archive table, and one event table, and when the user wants to archive the event, they should be able to view the event in the archive add form (which needs to be populated by the $id of the event).
But I do not know how to populate the field.. I have tried setting a value.. but the events are not sessions so that didn't work, and I have also tried setting the $id at the start of the form, but that also didn't work.
Here is the code to my archive function in the events controller.
public function archive($id = null) {
if ($this->request->is('post')) {
$event = $this->Event->read($id);
$archive['Archive'] = $event['Event'];
$archive['Archive']['eventID'] = $archive['Archive']['archiveID'];
unset($archive['Archive']['archiveID']);
$this->loadModel('Archive');
$this->Archive->create();
if ($this->Archive->save($archive)) {
$this->Session->setFlash(__('The event has been archived'));
$this->Event->delete($id);
$this->redirect(array('action' => 'eventmanage'));
} else {
$this->Session->setFlash(__('The event could not be archived. Please, contact the administrator.'));
}
}
}
You need to do one of the following:
Set the values for the fields using $this->request->data in the controller.
public function add($id = null) {
if ($this->request->is('post')) {
[..snip..]
}
$this->loadModel('Event');
$event = $this->Event->read($id);
$this->request->data['Archive'] = $event['Event'];
}
OR
Update the form to set the values.
Update the existing code with the same event read:
public function add($id = null) {
if ($this->request->is('post')) {
[..snip..]
}
$this->loadModel('Event');
$this->set('event', $this->Event->read($id));
}
Then in your form in the Archives/add.ctp file, update each input to reflect the value of the $event.
echo $this->Form->input('eventID', array('type' => 'hidden', 'value' => $event['Event']['id']));
OR
Write a function that will move the record.
Put a button on the Event View called 'Archive'. Create a method in the Event Controller that will archive the event.
public function archive($id = null) {
if ($this->request->is('post')) {
$event = $this->Event->read($id);
$archive['Archive'] = $event['Event'];
$archive['Archive']['event_id'] = $archive['Archive']['id'];
unset($archive['Archive']['id']);
$this->loadModel('Archive');
$this->Archive->create();
if ($this->Archive->save($archive)) {
$this->Session->setFlash(__('The event has been archived'));
$this->Event->delete($id);
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The event could not be archived. Please, contact the administrator.'));
}
}
}

Accessing model data inside a controller in CakePHP 2.0

I'm trying to access data in my Model for my controller method.
For starters what is the difference between these two???
$post = $this->Post->find('first',array('conditions'=>array('Post.id'=>$id)));
$this->set(compact('post'));
and
$this->Post->id = $id;
$this->data = $this->Post->read();
as I'm trying to compare the user_id for a post against the logged in user like so:
if($this->Post->user_id != $this->Auth->user('id'))
but it doesn't work as intended (it always returns false)... what is the difference between the two code chunks and why doesn't my line above work properly?
test to see if it helps to compare this code "userid":
function index() {
$user_id = $this->data['Post']['user_id'];
if($user_id != $this->Auth->user('id')){
//go
}
}
This is what I ended up with:
$post = $this->Post->find('first',array('conditions'=>array('Post.id'=>Tiny::reverseTiny($id))));
if ($this->request->is('post') || $this->request->is('put'))
{
$this->Post->id = $post['Post']['id'];
if ($this->Post->save($this->request->data))
{
$this->Session->setFlash('Your post has been updated');
$this->redirect(array('controller' => 'posts', 'action' => 'index'));
}
else
{
$this->Session->setFlash('Server broke!');
}
}
else
{
if($post['Post']['user_id'] != $this->Auth->user('id'))
{
$this->Session->setFlash('Not yours!');
$this->redirect(array('controller' => 'posts', 'action' => 'index'));
}
else
{
$this->request->data = $this->Post->read(null, $post['Post']['id']);
}
}
There are differences between find() and read(), read will grab all related model data and set the active record of the model to the result. Whereas a find will just all related model data in a query and assign the result to the variable.
Use debug($this->data) to reveal the structure of your returned data. You will find it is $this->data['Post']['user_id'] for the User ID.

Categories