PHP File Upload with Custom upload actions

PHP File Upload with Custom upload actions

delcristdelcrist Posts: 6Questions: 2Answers: 0

PHP File Upload with Custom upload actions

I've read through the documentation and several discussions here, and haven't been able to find a solution for the following issue/question.

Resources:
1. PHP File Upload
2. db->update
3. document upload path
4. DataTables: Class Database > update()

I have two tables linked by a third:

manufacturer                     file
+----+-----------+---------+     +----+----------+----------+----------+----------+
| id | make      | founded |     | id | filesize | filename | web_path | sys_path |
+----+-----------+---------+     +----+----------+----------+----------+----------+
| 1  | Ford      | 1903    |     | 1  | 1234567  | 1.pdf    |          |          |
| 2  | Chevrolet | 1911    |     | 2  | 1234567  | 2.pdf    |          |          |
| 3  | Honda     | 1946    |     | 3  | 1234567  | 3.pdf    |          |          |
|    |           |         |     | 4  | 1234567  | 4.pdf    |          |          |
|    |           |         |     | 5  | 1234567  | 5.pdf    |          |          |
+----+-----------+---------+     +----+----------+----------+----------+----------+


manufacturer_files
+----+-----------------+----------+
| id | manufacturer_id | file_id  |
+----+-----------------+----------+
| 1  | 1               | 1        |
| 2  | 2               | 2        |
| 3  | 1               | 3        |
| 4  | 2               | 4        |
+----+-----------------+----------+

I also submit additional information in the POST request:

if ( $_SERVER["REQUEST_METHOD"] == "POST" ) {
  
  $customString = $_POST["customString"]
  $make = $_POST["make"];
  $founded = $_POST["founded"];

  // Web path to file
  $webPath = '/cars/' . $customString . '/' . $make . '/' . $founded;

  // System path
  $sysPath = $_SERVER['DOCUMENT_ROOT'] . $webPath;

}

Building Editor...

Editor::inst( $db , 'manufacturer' )
->fields(
    Field::inst( 'make' ),
    Field::inst( 'founded' )
  )
->join(
    Mjoin::inst( 'file' )
      ->link( 'manufacturer' . '.id' , 'manufacturer_files' . '.manufacturer_id' )
      ->link( 'file' . '.id' , 'manufacturer_files' . '.file_id' )
      ->fields(
        Field::inst( 'id' )
        ->upload(
          Upload::inst(  function ( $file, $id ) {

            $fileName = $file['name'];

            // What I'd like to do here is construct the system path
            // where the file will be uploaded, based on the
            // additional information provided in the POST response.
            move_uploaded_file( $fileName , $sysPath );

            return $id;
          } )
            ->db( $files, 'id', array(
                'filename'    => Upload::DB_FILE_NAME,
                'filesize'    => Upload::DB_FILE_SIZE
                // Based on information from above linked discussions
                // I understand I cannot do something like
                // 'web_path'    => Upload::DB_FILE_SIZE
                // And that I should do something like:
                // $db->update( 'file', [ "web_path" => $webPath . $fileName ], [ "id" => $id ] );
              ) )
        ) // End upload
      ) // End fields
) // End join
->process( $_POST )
->json();

  1. How do I pass information obtained/constructed from POST into the closure function? Line 20:
    move_uploaded_file( $fileName , $sysPath );
    
  2. Also, would I be able to reuse information previously provided to the first table? Line 3:
    Field::inst( 'make' ),
    
  3. In the discussion linked above (item 3), Allan suggests including db->update() in the closure function. I'm not sure how to link that in as well:
    $db->update( 'image', [ "web_path" => ... ], [ "id" => $id ] );
    

Any help would be greatly appreciated.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,791Questions: 1Answers: 10,513 Site admin
    Answer ✓
    1. Ah yes - PHP's somewhat crazy variable scoping. You have to use the use() statement. For example:
    function ( $file, $id ) use ( $sysPath ) {
    

    Bonkers if you have been used to working with Javascript, C# or most any other language, but you need to tell PHP what variables you want in the closure.

    1. I'm not quite sure I understand what information you would reuse from that line?

    2. The line of code you have there looks good! The first parameter passed to the method is the table to update, the second is a list of parameters (key/value) to set and the last one is the where condition (i.e. in this case, update the row with id=$id.

    Allan

  • delcristdelcrist Posts: 6Questions: 2Answers: 0

    Hello,

    Thank you for your help. It works great. For anyone else that stumbles upon this discussion, the updated file:

    if ( $_SERVER["REQUEST_METHOD"] == "POST" ) {
      
      $customString = $_POST["customString"]
      $make = $_POST["make"];
      $founded = $_POST["founded"];
    
      // Web path to file
      $webPath = '/cars/' . $customString . '/' . $make . '/' . $founded;
    
      // System path
      $sysPath = $_SERVER['DOCUMENT_ROOT'] . $webPath;
    
      // Create an array to hold variables to be used in the closure function.
      $varArray = [
        "customString"  => $customString,
        "make"          => $make,
        "founded"       => $founded,
        "webPath"       => $webPath,
        "sysPath"       => $sysPath
      ];
    
    }
    
    // DataTables PHP library
      include( "DataTables.php" );
    
    // Alias Editor classes so they are easy to use
      use
      DataTables\Editor,
      DataTables\Editor\Field,
      DataTables\Editor\Format,
      DataTables\Editor\Mjoin,
      DataTables\Editor\Upload,
      DataTables\Editor\Validate;
    
    Editor::inst( $db , 'manufacturer' )
    ->fields(
        Field::inst( 'make' ),
        Field::inst( 'founded' )
      )
    ->join(
        Mjoin::inst( 'file' )
          ->link( 'manufacturer' . '.id' , 'manufacturer_files' . '.manufacturer_id' )
          ->link( 'file' . '.id' , 'manufacturer_files' . '.file_id' )
          ->fields(
            Field::inst( 'id' )
            ->upload(
              Upload::inst(  function ( $file, $id ) use ( $varArray, $db ) {
    
                move_uploaded_file( $file['tmp_name'] , $varArray["sysPath"] . $file['name'] );
    
                $db->update(
                  'file', // Database table to update
                  [
                    "web_path" => $varArray["webPath"] . $file['name'],
                    "system_path" => $varArray["sysPath"]  . $file['name']
                  ],
                  [ "id" => $id ]
                );
    
                return $id;
              } )
                ->db( $files, 'id', array(
                    'filename'    => Upload::DB_FILE_NAME,
                    'filesize'    => Upload::DB_FILE_SIZE
                  ) )
            ) // End upload
          ) // End fields
    ) // End join
    ->process( $_POST )
    ->json();
    
    

    Remember to include $db in the scope of the closure function. Line 48:

    Upload::inst(  function ( $file, $id ) use ( $varArray, $db ) {
    
This discussion has been closed.