ypnos-web / cakephp-datatables

CakePHP3 Plugin for DataTables plug-in for jQuery
MIT License
27 stars 24 forks source link

Installation in a CakePHP 4 App #79

Closed dividedbynothing closed 4 years ago

dividedbynothing commented 4 years ago

Hi,

I'm working to install cakephp-datatables on a new CakePHP 4 app (CakePHP version 4.0.8).

I've updated my composer.json with:

"require": {
    "ypnos-web/cakephp-datatables": "^3.0"
}

Then I run composer update and I get this result:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for ypnos-web/cakephp-datatables ^3.0 -> satisfiable by ypnos-web/cakephp-datatables[v3.0].
    - ypnos-web/cakephp-datatables v3.0 requires cakephp/cakephp ^3.6 -> satisfiable by cakephp/cakephp[3.6.0, 3.6.0-RC1, 3.6.0-RC2, 3.6.0-beta1, 3.6.0-beta2, 3.6.0-beta3, 3.6.1, 3.6.10, 3.6.11, 3.6.12, 3.6.13, 3.6.14, 3.6.15, 3.6.2, 3.6.3, 3.6.4, 3.6.5, 3.6.6, 3.6.7, 3.6.8, 3.6.9, 3.7.0, 3.7.0-RC1, 3.7.0-RC2, 3.7.0-RC3, 3.7.0-beta1, 3.7.1, 3.7.2, 3.7.3, 3.7.4, 3.7.5, 3.7.6, 3.7.7, 3.7.8, 3.7.9, 3.8.0, 3.8.0-RC1, 3.8.0-RC2, 3.8.0-RC3, 3.8.0-beta1, 3.8.1, 3.8.10, 3.8.11, 3.8.12, 3.8.2, 3.8.3, 3.8.4, 3.8.5, 3.8.6, 3.8.7, 3.8.8, 3.8.9, 3.9.0-RC1, 3.9.0-RC2, 3.x-dev] but these conflict with your requirements or minimum-stability.

I tried adding minimum-stability dev to composer.json, but that opens up a long list of other issues.

Is there an installable package for CakePHP 4? Thanks! D.

ypnos-web commented 4 years ago

Hello,

Thank you for the issue.

The composer.json file of cakephp-datatables needs to be edited to allow version 4 of cakephp (current ^3.6 rejects 4.x). Then it needs to be tested for compatibility. I would expect it to be compatible with 4.x but I am not able to test right now.

Would you like to try it out?

8 Jun. 2020 13:27:11 dividedbynothing notifications@github.com:

Hi,

I'm working to install cakephp-datatables on a new CakePHP 4 app (CakePHP version 4.0.8).

I've updated my composer.json with:

"require": { "ypnos-web/cakephp-datatables": "^3.0" }Then I run composer update and I get this result:

Your requirements could not be resolved to an installable set of packages. Problem 1 - Installation request for ypnos-web/cakephp-datatables ^3.0 -> satisfiable by ypnos-web/cakephp-datatables[v3.0]. - ypnos-web/cakephp-datatables v3.0 requires cakephp/cakephp ^3.6 -> satisfiable by cakephp/cakephp[3.6.0, 3.6.0-RC1, 3.6.0-RC2, 3.6.0-beta1, 3.6.0-beta2, 3.6.0-beta3, 3.6.1, 3.6.10, 3.6.11, 3.6.12, 3.6.13, 3.6.14, 3.6.15, 3.6.2, 3.6.3, 3.6.4, 3.6.5, 3.6.6, 3.6.7, 3.6.8, 3.6.9, 3.7.0, 3.7.0-RC1, 3.7.0-RC2, 3.7.0-RC3, 3.7.0-beta1, 3.7.1, 3.7.2, 3.7.3, 3.7.4, 3.7.5, 3.7.6, 3.7.7, 3.7.8, 3.7.9, 3.8.0, 3.8.0-RC1, 3.8.0-RC2, 3.8.0-RC3, 3.8.0-beta1, 3.8.1, 3.8.10, 3.8.11, 3.8.12, 3.8.2, 3.8.3, 3.8.4, 3.8.5, 3.8.6, 3.8.7, 3.8.8, 3.8.9, 3.9.0-RC1, 3.9.0-RC2, 3.x-dev] but these conflict with your requirements or minimum-stability.I tried adding minimum-stability dev to composer.json, but that opens up a long list of other issues.

Is there an installable package for CakePHP 4? Thanks! D.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub[https://github.com/ypnos-web/cakephp-datatables/issues/79], or unsubscribe[https://github.com/notifications/unsubscribe-auth/ADZ5ZOPYFGRXSXKN3VAAPKDRVTDIZANCNFSM4NYKCQLQ]. [https://github.com/notifications/beacon/ADZ5ZOP6QYVMA6VRS5BPGP3RVTDIZA5CNFSM4NYKCQL2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4JOSDMWQ.gif]

dividedbynothing commented 4 years ago

Sure, I'd be happy to give it a try. I can do the testing and debugging as needed and let you know the results. Thanks!

ypnos-web commented 4 years ago

I created branch 4.x which also includes some fixes. Try it with

"require": {
    "ypnos-web/cakephp-datatables": "4.x-dev"
}
dividedbynothing commented 4 years ago

Thanks! I've tried to install as above, but composer seems to not find the new branch:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package ypnos-web/cakephp-datatables dev-4.x exists as ypnos-web/cakephp-datatables[2.x-dev, dev-devel, dev-master, dev-php5, v1.0, v2.0, v2.1, v3.0] but these are rejected by your constraint.

This is with "minimum-stability": "dev" in my composer.json.

EDIT: I was looking at the 4.x branch, and found the installation at:

    "require": {
        "x-zolezzi/cakephp-datatables": "dev-master"
    },

Looks like this was updated just when you posted, so I'm assuming that's the updated version? Thanks! D.

ypnos-web commented 4 years ago

I took a patch from x-zolezzi but he also did other changes that I wouldn't go with. Either way if you are happy with his version that's fine.

Apart from that I fixed packagist auto-update. The version you would need is 4.x-dev. If you would like to test and report back it would be a great help for others.

dividedbynothing commented 4 years ago

Thanks... I'll go to 4.x-dev version, test and report back. Thanks for your support. More to come from me...

Edit... Yep, 4.x-dev install worked. Will keep you posted.

dividedbynothing commented 4 years ago

OK, I’ve successfully got ypnos-web/cakephp-datatables: 4.x-dev setup and working on a CakePHP 4 app (Cake version 4.0.8), with a few caveats which I’ll mention at the end.

Background I had a very well working ypnos-web/datatables setup on a CakePHP 3.8 app with tables search, Show # Entries, pagination and some individual column search boxes in a footer. In upgrading my app to Cake 4, I decided to make a clean install of CakePHP 4 and rebake everything, then transfer over my custom code. To set up and test Datatables in 4.0, I created a simple model “Cars” with a few fields (model, color, name, description).

Setup and Configuration

  1. Edited my app’s composer.json to require datatables:

    "require": {
    "ypnos-web/cakephp-datatables": "4.x-dev"
    }

    Ran composer update and the installation completed correctly with composer. The package was installed in app/vendor/ypnos-web. I then ran composer dumpautoload. I checked to make sure the vendor/cakephp-plugins.php file had added the package, and yes, it did.

  2. I did NOT need to add $this->addPlugin('DataTables'); in my Application.php bootstrap() method. I think this is because it’s in the vendor folder, so autoloaded like other vendor packages, not as a plugin.

  3. In my app/src/Controller/AppController.php I did these: a) Added $this->loadComponent('DataTables.DataTables'); into the initialize() method. b) At the bottom of the file, I added a new method:

    public function beforeRender(EventInterface $event)
    {
        parent::beforeRender($event);
        $this->viewBuilder()->setHelpers(['Datatables.Datatables']);
    }

    This is because in CakePHP 4 you can no longer load helpers with the public $helpers variable. With the beforeRender method added here, it is important to also put use Cake\Event\EventInterface; up at the top before the class starts.

  4. At this point, I closed my app and bounced my server (maybe not needed) to make sure the package shows up in my vendor includes (in the cakePHP debug toolbar). Yes it does, and It’s also in the list of installed packages.

  5. In app/src/View/AppView.php, I added $this->loadHelper('DataTables.DataTables'); in the initialize() method. My datatables setup doesn’t work without this.

Setting up my Controller and Template In the CarsController index() method:

  1. Got rid of all the baked code from Cake.

  2. I defined my columns here first:

        $columns = [
        [
            'field' => 'Cars.id',
                        'data' => 'id',
            'visible' => false,
            'searchable' => false,
        ],
        [
            'title' => __('Color'),
                        'field' => 'Cars.color',
            'data' => 'color',
                        'searchable' => true,
        ],
        [
            'title' => __('Model'),
                        'field' => 'Cars.model',
            'data' => 'model'
        ],
        [
            'title' => __('Name'),
                        'field' => 'Cars.name',
            'data' => 'name',
            'className' => 'text-primary',
        ],
        [
            'title' => __('Long Desc'),
                        'field' => 'Cars.longdesc',
            'data' => 'longdesc'
        ]
    ];
        $this->set('columns', $columns);

    Note: the id field always has to be there even though you don't display/search it.

  3. Then add the data query:

        $data = $this->DataTables->find('Cars', 'all', [
           'order' => ['name' => 'asc']
            ], $columns);
        $this->set('data', $data);
  4. Now an important part. The trait viewVars is gone from CakePHP4, so instead you need to use viewBuilder. So to prepare the serialized data I use this code:

        $viewvars = $this->viewBuilder()->getVar('_serialize');
        $this->set('_serialize', array_merge($viewvars, ['data']));
  5. Now, in my index.php template: a) In a PHP code block at the top:

    //'jquery-2.2.0.min.js',--- note, I load jquery in my default layout template, so not here.
    'jquery.dataTables.min.js',
    'dataTables.bootstrap.min.js',   
    'DataTables.cakephp.dataTables.js',
    ], ['block' => true] ); 
    $this->Html->css('dataTables.bootstrap.css', ['block' => true]);  

    Important note here: Here… in the browser (Firefox) console I got the error: “Loading failed for the <script> with source “http://localhost/myapp/js/DataTables.cakephp.dataTables.js”.” So, I i. Copied cakephp.dataTables.js from vendor\ypnos-web\cakephp-datatables\webroot\js to myapp\webroot\js\, and I renamed the file to: DataTables.cakephp.dataTables.js ii. Now there are no errors in the browser console.

b) Got rid of the baked code EXCEPT

    <div class="cars index content">
    <?= $this->Html->link(__('New Car'), ['action' => 'add'], ['class' => 'button float-right']) ?>
    <h3><?= __('Cars') ?></h3>
    <div class="table-responsive">

And the last two closing div tags, I left there.

c) Added a <?php code section. First my options:

    $options = [
        'init' => [
            $this->DataTables->callback('dt.init.columnSearch', [3])
    ],
    'ajax' => [
        'url' => $this->Url->build() // current controller, action, params
    ],
    'data' => $data,
    'deferLoading' => $data->count(),
        'columns' => $columns,
    'order' => [3, 'asc'], // order by name
    ];

d) Then, my custom code for the footer which has individual column search inputs:

     $id = 'cars-table';
     $footer = '';
     $input = $this->Html->tag('input', '', [
         'type' => 'text',
         'class' => 'form-control input-sm',
         'style' => ' min-width: 0; width: 100%; display: inline;margin-left:5px',
     ]);
    $i = 0;
     foreach ($options['columns'] as $c) {
         if (!($options['visible'] ?? true))
             continue;
         $control = ($options['searchable'] ?? true) ? $input : '';
         if($i<4){
              $footer .= $this->Html->tag('td', $control);
        } else {     
          $footer .= $this->Html->tag('td', '&nbsp');   
        }
         $i++;
     }
     $footer = $this->Html->tag('tfoot', $this->Html->tag('tr', $footer));

     echo $this->Html->tag('table', $footer, [
         'id' => $id,
         'class' => 'table table-striped dataTable',
         'style' => 'width:100%',
         'style' => 'margin-left:5px',
     ]);

e) Now draw the datatable: echo $this->Html->scriptBlock($this->DataTables->draw("#$id", $options));

And now datatables loads and functions as expected!

Now the Caveats:

  1. In my setup, if I remove the footer column search boxes, then I don’t get any table rendered at all (just a blank, empty div). I haven’t yet figured out why that is, but this is the same in both CakePHP 3.8 and in 4.0. I can figure that out later.
  2. The styling: In 4.0, It isn’t nearly as beautiful as it was in 3.8. Of course this is due to the css files used in CakePHP 4 and the order in which you load them. CakePHP 4 uses milligram CSS as the base, so it’s different from my old 3.8 app, which had some careful implementation of bootstrap styles throughout. Everything is there, it’d just not laid out cleanly, and not looking very pretty. Fixing that up is another can of worms which I can work on next.

Thanks again for this excellent package... It's super useful for me.

Cheers, D.

dividedbynothing commented 4 years ago

Just a quick update on the styling: I updated my apps' bootstrap version to v3.3.6 (including css, js and fonts). Note that in my app/webroot folder I had to create a new folder called fonts. The cake default one there is just called font and holds cake font files.

So after that, the styling and layout is much improved... pagination bar looks good, the sorting icons are right, and the table striping is correct now. I also adjusted the body - font-size and label,legend font size in milligram.css, since I think overall it was too big for my purposes, especially in datatables.

ypnos-web commented 4 years ago

Thank you very much for your detailed feedback! I am sure it will be helpful for others that convert to CakePHP 4. I guess I should link this issue in the README, what do you think?

dividedbynothing commented 4 years ago

Hi Ypnos, yes, sure, feel free to link it to the README, or copy any or all of it that you want to use directly. I hope it's useful to others... this plugin and the info in the open and closed issues is super useful for me, so I'm happy to share my experience!

I should add one more bit on how I did the View and Edit links; it pretty much follows the info in the documentation:

in my templates/cars/index.php, before setting the $options variable, I added two column definitions:

    $columns[5] = [
        'title' => __('View'), // or ''
        'data' => 'id',
        'sortable' => false,
        'searchable' => false,
        'render' => $this->DataTables->callback('myLinkBuilder', ['<i class="glyphicon glyphicon-eye-open"></i>', $this->Url->build(['action' => 'view'])])
    ];
    $columns[6] = [
        'title' => __('Edit'), // or ''
        'data' => 'id',
        'sortable' => false,
        'searchable' => false,
        'render' => $this->DataTables->callback('myLinkBuilder', ['<i class="glyphicon glyphicon-pencil"></i>', $this->Url->build(['action' => 'edit'])])
    ];

You have to manually set the column array index numbers based on how many fields are in the datatable.

Thanks again for the cool package!