Save data to the database using Form in Cakephp

Asked

Viewed 1,055 times

0

I’m trying to make a tool for the administrator, the site I’m building, that will allow you to upload images to a folder on the server, so that they appear posthumously in the gallery. The image upload is working correctly, however its name is not entered in the database. This should be inserted in the "gallery_images" table, in the "path" field. How to solve this problem?

I’m using Cakephp 2.4.4

Controller

    <?php
class AdminsController extends AppController{

    public $components = array('RequestHandler');
    public function admin_index(){
        if(!$this->Session->check('Admin')){
        $this->Session->setFlash('Está a aceder a uma zona restrita. Por favor faça Login.');
        $this->redirect(array(
                                'controller' => 'admins',
                                'action' => 'login'));
        }
        $this->layout='admin_index';
    }
    public function add_foto() {            
        if(!$this->Session->check('Admin')){
        $this->Session->setFlash('Está a aceder a uma zona restrita. Por favor faça Login.');
        $this->redirect(array(
                                'controller' => 'admins',
                                'action' => 'login'));
        }
        $this->layout='admin_index';
        $file=$this->request->data['gallery_images']['path'];
        if($this->request->is('post') || $this->request->is('put')){
                $this->Admin->create();
            $this->Admin->save($file);
            move_uploaded_file($this->data['gallery_images']['path']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/html/PushUp_app/app/webroot/img/gallery/' . $this->data['gallery_images']['path']['name']);
                     if($this->Admin->save($this->request->data)){
                     $this->Session->setFlash(__('Ficheiro carregado com sucesso!'));
            }
        }
        //$this->Admin->id = $id;
        //$this->Post->save($data=array($this->data['Admins']['path']), $params=array('fieldList'=>'path'));
        //$this->Post->saveField('path', $this->data['Admins']['path']);
            /*if ($this->ModelName->save($this->request->data)) {
                $this->Session->setFlash('Data Saved!');
            }*/
        //if($this->request->is('post')){
        //  $this->Admin->save($this->request->data);
            //}
        //}
    }
}
    ?>

View

    <h2>Adicionar Fotografia</h2>
    <?php
echo "<br>";
echo $this->Form->create('Admin',array('type'=>'file'));
echo $this->Form->file('gallery_images.path');
echo "<br>";
//echo $this->Form->submit();
echo $this->Form->end('Guardar');

    ?>

Table gallery_images

Table admins

Código Certo

Controller

    <?php
    class GalleryController extends AppController {

    public function admin_upload_image(){
        $this->layout = 'admin_index';
        if($this->request->is('post') || $this->request->is('put')) {
          /*  $file = $this->request->data['gallery_images']['path']['name'];*/
        $file = array(
                'GalleryImage' => array(
                'path' => $this->request->data['gallery_images']['path']['name']
                                        )
                );
            move_uploaded_file($this->data['gallery_images']['path']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/html/PushUp_app/app/webroot/img/gallery/' . $this->data['gallery_images']['path']['name']);

            $this->loadModel('GalleryImage');
            $this->GalleryImage->create();

            if($this->GalleryImage->save($file)){
                $this->Session->setFlash(__('Ficheiro carregado com sucesso!'));
            }
            else{
                $this->Session->setFlash(__('Erro ao carregar o ficheiro!'));
            }
        }
    }
}
?>

View

    <h2>Adicionar Fotografia</h2>
    <?php
echo "<br>";
echo $this->Form->create('GalleryImage',array('type'=>'file'));
echo $this->Form->file('gallery_images.path');
echo "<br>";
//echo $this->Form->submit();
echo $this->Form->end('Guardar');

    ?>

Model

    <?php
App::uses('AppModel', 'Model');
class GalleryImage extends AppModel{
    public $displayField ='path';
    public $useTable = 'gallery_images';
}
    ?>
  • 1

    What the Admin->save() function is doing?

  • @Lucio Should write in the database.

  • You can show the table structure admin?

  • @Paulorodrigues already added to the post, in the background.

1 answer

2


Let’s go in pieces.

1 - Who is your Model?

  • Admin?
  • gallery_images?

If it is gallery_images is completely incorrect by Cakephp standards.

The right thing would be Galleryimage.


2 - You are trying to save the image in which MODEL?

In the Admin model?

If it is in the Admin, you must fix your array $file, to meet your need:

$file = array(
  'Admin' => array(
    'path' => $this->request->data['gallery_images']['path']['name']
  )
);

Remembering that you should validate yourself in your model Admin has the property:

public $table = 'gallery_images';

In the Galleryimage model?

If it is Galleryimage, should also corrode it:

$file = array(
  'GalleryImage' => array(
    'path' => $this->request->data['gallery_images']['path']['name']
  )
);

Remembering that I’m a model Galleryimage should follow the model below:

<?php
App::uses('AppModel', 'Model');
/**
 * GalleryImage Model
 *
 */
class GalleryImage extends AppModel {

  public $displayField = 'name';
  public $useTable = 'gallery_images';

}

3 - why to change the $file?

From what I understand, in your code you’re doing the following:

$file = $this->request->data['gallery_images']['path']['name'];

With this you created a variable with 1 value x and is saving her.

The problem is you’re not telling Cakephp, what field is this, much less to which Model belongs. Then the right thing would be:

$file = array(
  'NomeDoModel' => array(
    'nome_do_campo' => 'valor_do_campo'
  )
);

With this you’ve assembled/created the array correctly and Cakephp can now understand that you want to save fields A, B and C in the X model.


4 - Why are you running 2 birds? [Doubt]

In your code you run $this->Admin->save($file); and then $this->Admin->save($this->request->data);.

I really don’t understand the need for this. But what you’re doing is:

  • Insert
  • Update of the already inserted record

5 - Image upload

I recommend using the library Wide Image to upload, upload and resize your images.

It’s incredibly easy to implode in Cakephp, whether or not it’s integrated with commiserate.

6 - Code corrected**

Your code should look something like this, depending on whether you’re using the model Admin or Galleryimage, whether the last lines (save) are correct or not:

public function add_foto() {            
  if(!$this->Session->check('Admin')) {

    $this->Session->setFlash('Está a aceder a uma zona restrita. Por favor faça Login.');
    $this->redirect(array(
      'controller' => 'admins',
      'action' => 'login'));
  }

  $this->layout = 'admin_index';

  $file = array(
    'GalleryImage' => array(
      'path' => $this->request->data['gallery_images']['path']['name']
    )
  );

  if($this->request->is('post') || $this->request->is('put')) {

    $this->loadModel('GalleryImage');
    $this->GalleryImage->save($file);

    move_uploaded_file($this->data['gallery_images']['path']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/html/PushUp_app/app/webroot/img/gallery/' . $this->data['gallery_images']['path']['name']);

    // Não sei o que você está tentando fazer aqui, por isso comentei o código
    // if($this->Admin->save($this->request->data)) {
      $this->Session->setFlash(__('Ficheiro carregado com sucesso!'));
    //}

  }
}



Administrative Routes

Based on the assumption that there is a clear difficulty regarding the understanding of administrative area (Administrative Routes), I will try to explain the correct way in the simplest and most practical way possible how it really works.

Setting up the main route /admin

Let’s say you wanted the route /admin is only visible to users present in the group (profile) Administrator, and with it, display login when accessing any sub-route.

To make this work as well as possible, we will use prefixes.

What you must do then is... in your app/Config/routes.php, add the following code:

Router::connect('/admin', array('controller' => 'pages', 'action' => 'dashboard', 'admin' => true));

So I’m saying: when accessing the url http://www.example.com/admin, Cakephp should call the action dashboard controller’s pages, but this route has the admin prefix before the name, which would be in case this:

class PagesController extends AppController {
  public function admin_dashboard() {
    // código aqui
  }
}

Configuring other administrative routes

Besides, let’s say this one user in the Administrator group, can also upload images (Galleryimage). So let’s create the action:

class GalleryImagesController extends AppController {
  public function admin_upload_image() {
    // código aqui
  }
}

class GalleryImage extends AppModel {
  public $table = 'gallery_images';
  public $displayField = 'name';
  // código aqui
}

With that we have the route:

http://www.example.com/admin/gallery_images/upload_image

If you wanted to customize this route, just do the following on your Routes:

Router::connect('/admin/galeria-de-imagens/enviar', array('controller' => 'gallery_images', 'action' => 'upload_image', 'admin' => true));

With that we now have the route:

http://www.example.com/admin/galeria-de-imagens/enviar

To create more administrative routes on different controllers, just follow the example above.

Limiting access only to logged in users

But doing just that I’m making sure of something? NAY!.

Now we have to tell app/Config/AppController.php, administrative routes require login. For this we will use 2 methods:

-beforeFilter() of Cakephp himself -isPrefix() only to help get the current URL prefix

public function beforeFilter() {
  if($this->isPrefix('admin')) {

    // Seta o layout admin para as rotas administrativas
    $this->layout = 'admin';

  } else {

    // Utilizando o método abaixo, permite o acesso as URLs 
    // sem o login (Auth do CakePHP)
    $this->Auth->allow();

  }
}

public function isPrefix($prefix) {
  return isset($this->request->params['prefix']) 
    && $this->request->params['prefix'] == $prefix;
}

Briefly explaining the above code: beforeFilter (which is called before call action) checks which URL prefix is called using the method isPrefix. After detecting the URL, it checks whether the prefix is admin, if it is, arrow the layout admin, if access to all urls through the method $this->Auth->allow();.

Clearly, for this to work you must have yours Auth configured in the AppController, as in the example below:

public $components = array(
  'Auth' => array(
    'authenticate' => array(
      'Form' => array(
        'fields' => array('username' => 'password')
      )
    ),
    'loginAction' => array('controller' => 'users', 'action' => 'login', 'admin' => false),
    'logoutAction' => array('controller' => 'users', 'action' => 'logout', 'admin' => false),
    'loginRedirect' => '/admin',
    'logoutRedirect' => array('controller' => 'users', 'action' => 'login', 'admin' => false),
    'authError' => 'Acesso não permitido.'
  ),
  'Session',
  'RequestHandler',
  'Paginator'
);

With everything configured as shown above, your Urls using the prefix admin are secure, IE, need user login.

Limiting only users of the Administrator group

The simplest way to do this to meet your need is as follows.

Change the method beforeFilter() for him to check the group_id of the logged in User (if it is logged in of course), and if it is the id desired, you allow access to URL.

public function beforeFilter() {
  if($this->isPrefix('admin')) {

    // Com a instrução abaixo, eu verifico se o usuário está logado
    if ($this->Auth->loggedIn()) {

      // Se estiver, verifico se está setado o group_id dele
      if ($this->Session->check('Auth.User.group_id')) {

        // Se ele tem um group_id, verifico se é igual ao desejado
        // Por exemplo: id do Administrador = 1
        if ($this->Session->read('Auth.User.group_id') == 1) {

          // Permite que ele acesse a URL

        } else {

          // Não permite o acesso a URL e redireciona o usuário
          // para uma página específica, neste caso a raiz do site
          $this->Session->setFlash(__('Você não tem permissão para acessar essa URL'));
          $this->Redirect('/');

        }
      }
    }

    // Seta o layout admin para as rotas administrativas
    $this->layout = 'admin';

  } else {

    // Utilizando o método abaixo, permite o acesso as URLs 
    // sem o login (Auth do CakePHP)
    $this->Auth->allow();

  }
}

I believe that’s it.

It’s long, but I think you can now follow the right path using Cakephp


I hope it helped.

Any questions, please insert a comment below.

  • The model to be used is Admin. Regarding the 3rd point, I was trying to pass the post value to that variable. I thought that by saving the variable, Cake would make the association itself. I must say that I am still learning how to use Cake. I remembered seeing something on the Cake website with a format similar to the one you made, which is actually there, I thought cake treated information that way, not that I had to. In relation to 4 point, this content in if would be something like: if($this->Admin->save($file)=true), mixed from other solutions

  • 1

    @Sunt Right, but since you already executed save the first time, it is easier to validate through a variable based on the first time. As for variables, Cakephp needs to know at least the FIELD NAME, in case you just spoke $file = 'valor', with this you are not saying ANYTHING to Cakephp. Anyway, what I posted helped you with, or do you have any specific questions? Don’t hesitate to ask.

  • On the model just have this line public $table = 'gallery_images'; within the class?

  • @Sunt if you are going to use the ADMIN model to save the GALLERY IMAGE, yes. Otherwise you should do the loadModel() of GalleryImage and save using it: $this->GalleryImage->save($file);.

  • @Sunt only one question so that I can edit my answer to help you better. Which model are you using to save Gallery Image? Admin? Or you have the Gallery Image model?

  • So, I’m using Model Galleryimage with Galleryimagescontroller and Model Admin with Adminscontrolelr. Now I am in doubt if I am confusing things, because the Galleryimage model is only serving to pass the images for an action of Galleryimagescontroller. Should I take care of the upload too? The way I am doing this is so that the Admin model handles all actions performed by the Adminscontroller, or by the site administrator via the admin panel tools.

  • 1

    @Sunt I think you are confusing one thing: using the Admincontroller to represent the administrative area. There is no need to do this. I’ll rewrite my question. Wait a few minutes.

  • @Sunt took longer than expected to reply, but I ask you to read my answer again from start to finish, to clearly understand how routes work in Cakephp, etc.

  • From now on, thank you very much for the dedication and work you’re doing to help me, and for the fantastic explanations. The code you should put in the Function admin_dashboard in the Pagescontroller refers to what exactly? Also by doing Insert in the database, Cake is sending Array as content for path field, SQL Query: INSERT INTO 'pushup_app'.'gallery_images' ('path', 'modified', 'created') VALUES (Array, '2014-03-20 15:26:50', '2014-03-20 15:26:50').

  • 1

    @Sunt my mistake: change your code to the following: $file = $this->request->data['gallery_images']['path']['name']; because, the way you/I had put it, he was taking the array $_FILES and setting in variable. Now in this case, you’re taking the name image, however, in this exact way may occur a situation of another image with the same name overwrite its. So I recommend you create a hash, or some combination of values, for example: sha1(date + time (including ms) + image name). So you get a unique name for the image.

  • @Sunt don’t forget to mark the answer at the end if it has helped you.

  • Now it is no longer an error but the name does not pass to the database, only the dates. pr() that I made to $file gives the image name correctly. Some problem with the model?

Show 8 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.