dimanche 31 décembre 2017

Comment créer downloader des fichiers de PDF dans CakePHP3

1.  Comment créer uploader dans CakePHP3
2.  Comment créer downloader dans CakePHP3
3.  Comment créer downloader pour des fichiers de PDF dans CakePHP3

D'abord, nous avons besoin de installer libreoffice pour la conversion à PDF et lang-lack de libreoffice:
$ sudo yum install libreoffice libreoffice-langpack-fr

Et éditez la commande de sudo avec visudo et ajoutez "apache ALL=(ALL) NOPASSWD: /usr/bin/libreoffice" dans ce fichier:
$ sudo visudo
(Ajoutez "apache ALL=(ALL) NOPASSWD: /usr/bin/libreoffice" dans ce fichier)

Redémarrer apache:
$ sudo service httpd restart

Ajoutez la fonction suivante dans l'index.ctp:
    function downloadPdf(){
        var files = getSelectedDocuments(true);
        files_not_excel = files.files_notexcel;
        files = files.checkeditems;
        console.log(files);
        if(files.length < 1 || files === undefined){
            alert('Please select at least one Excel document.');
        } else {
            if(files_not_excel.length > 0 && files_not_excel !== undefined){
                var r = confirm("The following files will not be converted to PDF because they are not excel files:\n"
                + files_not_excel.join(', '));
            } else {
                var r = true;
            }
            if(r === true){
                var csrfToken = $('[name=_csrfToken]').val();
                $.ajax({
                    type: "POST",
                    url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "pdfDownload")); ?>',
                    data: {'files' : files},
                    beforeSend: function(xhr){
                        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                    },
                    success: function(data){
                        var url = '/cake/temp/zip/' + data;
                        console.log(url);
                        download(url);
                    }
                });
            }
        }
    }

Et un bouton pour télécharger fichiers de PDF:
<p><a href="#" onclick="downloadPdf()">Download As PDF</a></p>

L'index.ctp dans l'ensemble:
<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Customer[]|\Cake\Collection\CollectionInterface $customers
 */
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
    <ul class="side-nav">
        <li class="heading"><?= __('Actions') ?></li>
        <li><?= $this->Html->link(__('New Customer'), ['action' => 'add']) ?></li>
    </ul>
</nav>
<div class="customers index large-9 medium-8 columns content">
    <h3><?= __('Customers') ?></h3>
    <p><a href="#" onclick="downloadDocuments()">Download As Zip</a></p>
    <p><a href="#" onclick="downloadPdf()">Download As PDF</a></p>
    <table cellpadding="0" cellspacing="0">
        <thead>
            <tr>
                <th scope="col" class="text-center" style="vertical-align: middle;"><?= $this->Form->checkbox('check_all', ['id'=>'check_all']);?></th>
                <th scope="col"><?= $this->Paginator->sort('id') ?></th>
                <th scope="col"><?= $this->Paginator->sort('name') ?></th>
                <th scope="col"><?= $this->Paginator->sort('file_location', 'File') ?></th>
                <th scope="col"><?= $this->Paginator->sort('created') ?></th>
                <th scope="col"><?= $this->Paginator->sort('modified') ?></th>
                <th scope="col" class="actions"><?= __('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($customers as $customer): ?>
            <tr>
                <?php $temp = explode('.', $customer->file_location); $extension = strtolower(end($temp)); ?>
                <?php $file = ['file_location' => $customer->file_location, 'file_name'=>$customer->name, 'extension'=>$extension] ?>
                <td class="text-center"><?= $this->Form->checkbox('checkbox',['name'=>'check_box', 'value'=>h(json_encode($file))]) ?></td>
                <td><?= $this->Number->format($customer->id) ?></td>
                <td><?= h($customer->name) ?></td>
                <td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
                <td><?= h($customer->created) ?></td>
                <td><?= h($customer->modified) ?></td>
                <td class="actions">
                    <?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
                    <?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
                    <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    <div class="paginator">
        <ul class="pagination">
            <?= $this->Paginator->first('<< ' . __('first')) ?>
            <?= $this->Paginator->prev('< ' . __('previous')) ?>
            <?= $this->Paginator->numbers() ?>
            <?= $this->Paginator->next(__('next') . ' >') ?>
            <?= $this->Paginator->last(__('last') . ' >>') ?>
        </ul>
        <p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
    </div>
</div>
<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
<script>
    $(document).ready(function(){
        $('#check_all').on('click', function() {
            $('input:checkbox[name=check_box]').prop('checked', this.checked);
        });
    });
    function getSelectedDocuments(pdfonly){
        if (pdfonly === undefined) {
            pdfonly = false;
        }
        var checkeditems = [];
        var files_notexcel = [];
        $("input[type=checkbox][name=check_box]").each(function(){
            if (this.checked) {
                var value = JSON.parse($(this).val());
                if(pdfonly === true){
                    var extension = value.extension.toLowerCase();
                    if($.inArray(extension, ['xlsx','xlsm','xls']) !== -1){
                        checkeditems.push(value.file_location);
                    } else {
                        var name = value.file_location.split("/");
                        files_notexcel.push(name[name.length - 1]);
                    }
                } else {
                    checkeditems.push(value.file_location);
                }
            }
        });
        var files = {"checkeditems" : checkeditems, "files_notexcel" : files_notexcel};
        return files;
    }
    function download(url){
        var link=document.createElement('a');
        document.body.appendChild(link);
        link.href=url;
        link.download = 'download';
        link.click();
        link.parentNode.removeChild(link);
    }
    function downloadDocuments(){
        var checkeditems = getSelectedDocuments();
        checkeditems = checkeditems.checkeditems;
        if(checkeditems.length < 1 || checkeditems === undefined){
            alert('Please select at least one document.');
        } else {
            var csrfToken = $('[name=_csrfToken]').val();
            $.ajax({
                type: "POST",
                url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "zipDownload")); ?>',
                data: {'files' : checkeditems},
                beforeSend: function(xhr){
                    xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                },
                success: function(data){
                    var url = '/cake/temp/zip/'+data;
                    console.log(url);
                    download(url);
                }
            });
        }
    }
    function downloadPdf(){
        var files = getSelectedDocuments(true);
        files_not_excel = files.files_notexcel;
        files = files.checkeditems;
        console.log(files);
        if(files.length < 1 || files === undefined){
            alert('Please select at least one Excel document.');
        } else {
            if(files_not_excel.length > 0 && files_not_excel !== undefined){
                var r = confirm("The following files will not be converted to PDF because they are not excel files:\n"
                + files_not_excel.join(', '));
            } else {
                var r = true;
            }
            if(r === true){
                var csrfToken = $('[name=_csrfToken]').val();
                $.ajax({
                    type: "POST",
                    url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "pdfDownload")); ?>',
                    data: {'files' : files},
                    beforeSend: function(xhr){
                        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                    },
                    success: function(data){
                        var url = '/cake/temp/zip/' + data;
                        console.log(url);
                        download(url);
                    }
                });
            }
        }
    }
</script>

Changez le controller de customers et ajoutez les fonctions suivantes comme ça:
    function createZip($uploadToDir = null, $copyFromDir = null, $files = null, $containsYearmonth = false){
        if(!file_exists($uploadToDir)){
            if(!mkdir($uploadToDir, 0755, true)){
                throw new BadRequestException('Can not mkdir.');
            }
            chmod($uploadToDir, 0755);
        }
        try {
            $zip = new ZipArchive();
            $zip_file_name = sha1(time() . rand()).".zip";
            $zip_name = $uploadToDir.$zip_file_name; // Zip name
            $zip->open($zip_name,  ZipArchive::CREATE);
            foreach ($files as $file) {
                $path = $copyFromDir.$file;
                if(file_exists($path)){
                    $zip->addFromString(basename($path), file_get_contents($path));
                }
                else{
                    echo "file does not exist";
                }
            }
            $zip->close();
            return $zip_file_name;
        } catch (BadRequestException $e) {
            throw $e;
        }
    }

    public function pdfDownload(){
        if ($this->request->is('ajax')) {
            $files = $this->request->data['files'];
            $layout = 'ajax';
            $this->loadModel('Documents');
            $this->autoRender = false;
            try {
                $filesPdf = [];
                $uploadToDirPdf = WWW_ROOT.'temp/zip/';
                $copyFromDirPdf = WWW_ROOT.'uploads/customers/';
                $uploadToDirZip = WWW_ROOT.'temp/zip/';
                $copyFromDirZip = WWW_ROOT;
                foreach($files as $file){
                    $extension = $this->getExtension($file);
                    if(in_array($extension,array_map('strtolower',['xlsx','xlsm','xls']))){
                        $pathPdf = $this->excelToPdf($uploadToDirPdf, $copyFromDirPdf, $file);
                        array_push($filesPdf, $pathPdf);
                    }
                }
                $pathZip = $this->createZip($uploadToDirZip, $copyFromDirZip, $filesPdf);
            }catch(BadRequestException $b){
                //$this->Flash->error(__($b->getMessage()));
            }
            echo $pathZip;
        }
    }

    private function excelToPdf($uploadToDir = null, $copyFromDir = null, $file = null){
        $filePath = explode("/", $file);
        $today = new Date();
        $yearmonth = $today->i18nFormat('yyyyMM');
        $dir = $uploadToDir.$filePath[0];
        if(!file_exists($dir)){
            if(!mkdir($dir, 0755, true)){
                throw new BadRequestException('Couldn\'t make directory.');
            }
            chmod($dir, 0755);
        }
        $command = 'sudo /usr/bin/libreoffice --headless --invisible --norestore --nologo --nofirststartwizard --convert-to pdf --outdir "'
        .$uploadToDir.$filePath[0].'" "'
        .$copyFromDir.$file.'"';
        $result = shell_exec($command);
        if(is_null($result)){
            throw new BadRequestException('pdf couldn\'t be created.');
        }
        $filenameArray = explode(".", $file);
        $filename = "";
        for($i = 0; $i < count($filenameArray)-1; $i++){
            $filename .= $filenameArray[$i];
        }
        return 'temp/zip/'.$filename.'.pdf';
    }

Maintenant vous pouvez télécharger les fichiers comme PDF dans l'index.ctp.




Comment créer downloader dans CakePHP3

1.  Comment créer uploader dans CakePHP3
2.  Comment créer downloader dans CakePHP3
3.  Comment créer downloader pour des fichiers de PDF dans CakePHP3

Ajoutez les fonctions dans le controller des customers:
(Et vous avez besoin de ajouter les lignes suivantes dans ce fichier:
use Cake\I18n\Date;
use ZipArchive;
use Cake\Network\Exception\BadRequestException;
)
    private function getExtension($filename){
        $temp = explode('.', $filename);
        $extension = strtolower(end($temp));
        return $extension;
    }

    public function zipDownload(){
        if ($this->request->is('ajax')) {
            $layout = 'ajax';
            $this->autoRender = false;
            $dir = WWW_ROOT . 'temp/zip/';
            $copyFromDir = WWW_ROOT.'uploads/customers/';
            $files = $this->request->data['files'];
            try {
                echo $this->createZip($dir, $copyFromDir, $files);
            } catch (BadRequestException $e) {
                throw $e;
            }
        }
    }

    function createZip($uploadToDir = null, $copyFromDir = null, $files = null, $containsYearmonth = false){
        if(!file_exists($uploadToDir)){
            if(!mkdir($uploadToDir, 0755, true)){
                throw new BadRequestException('Can not mkdir.');
            }
            chmod($uploadToDir, 0755);
        }
        try {
            $zip = new ZipArchive();
            $zip_file_name = sha1(time() . rand()).".zip";
            $zip_name = $uploadToDir.$zip_file_name; // Zip name
            $zip->open($zip_name,  ZipArchive::CREATE);
            foreach ($files as $file) {
                $path = $copyFromDir.$file;
                if(file_exists($path)){
                    $zip->addFromString(basename($path), file_get_contents($path));
                }
                else{
                    echo "file does not exist";
                }
            }
            $zip->close();
            return $zip_file_name;
        } catch (BadRequestException $e) {
            throw $e;
        }
    }

Et changez"index.ctp" dans index.ctp de dossier de "Template" comme ça:
<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Customer[]|\Cake\Collection\CollectionInterface $customers
 */
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
    <ul class="side-nav">
        <li class="heading"><?= __('Actions') ?></li>
        <li><?= $this->Html->link(__('New Customer'), ['action' => 'add']) ?></li>
    </ul>
</nav>
<div class="customers index large-9 medium-8 columns content">
    <h3><?= __('Customers') ?></h3>
    <div><a href="#" onclick="downloadDocuments()">Download As Zip</a></div>
    <table cellpadding="0" cellspacing="0">
        <thead>
            <tr>
                <th scope="col" class="text-center" style="vertical-align: middle;"><?= $this->Form->checkbox('check_all', ['id'=>'check_all']);?></th>
                <th scope="col"><?= $this->Paginator->sort('id') ?></th>
                <th scope="col"><?= $this->Paginator->sort('name') ?></th>
                <th scope="col"><?= $this->Paginator->sort('file_location', 'File') ?></th>
                <th scope="col"><?= $this->Paginator->sort('created') ?></th>
                <th scope="col"><?= $this->Paginator->sort('modified') ?></th>
                <th scope="col" class="actions"><?= __('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($customers as $customer): ?>
            <tr>
                <?php $temp = explode('.', $customer->file_location); $extension = strtolower(end($temp)); ?>
                <?php $file = ['file_location' => $customer->file_location, 'file_name'=>$customer->name, 'extension'=>$extension] ?>
                <td class="text-center"><?= $this->Form->checkbox('checkbox',['name'=>'check_box', 'value'=>h(json_encode($file))]) ?></td>
                <td><?= $this->Number->format($customer->id) ?></td>
                <td><?= h($customer->name) ?></td>
                <td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
                <td><?= h($customer->created) ?></td>
                <td><?= h($customer->modified) ?></td>
                <td class="actions">
                    <?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
                    <?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
                    <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    <div class="paginator">
        <ul class="pagination">
            <?= $this->Paginator->first('<< ' . __('first')) ?>
            <?= $this->Paginator->prev('< ' . __('previous')) ?>
            <?= $this->Paginator->numbers() ?>
            <?= $this->Paginator->next(__('next') . ' >') ?>
            <?= $this->Paginator->last(__('last') . ' >>') ?>
        </ul>
        <p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
    </div>
</div>
<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
<script>
    $(document).ready(function(){
        $('#check_all').on('click', function() {
            $('input:checkbox[name=check_box]').prop('checked', this.checked);
        });
    });
    function getSelectedDocuments(pdfonly){
        if (pdfonly === undefined) {
            pdfonly = false;
        }
        var checkeditems = [];
        var files_notexcel = [];
        $("input[type=checkbox][name=check_box]").each(function(){
            if (this.checked) {
                var value = JSON.parse($(this).val());
                if(pdfonly === true){
                    var extension = value.extension.toLowerCase();
                    if($.inArray(extension, ['xlsx','xlsm','xls']) !== -1){
                        checkeditems.push(value.file_location);
                    } else {
                        var name = value.file_location.split("/");
                        files_notexcel.push(name[name.length - 1]);
                    }
                } else {
                    checkeditems.push(value.file_location);
                }
            }
        });
        var files = {"checkeditems" : checkeditems, "files_notexcel" : files_notexcel};
        return files;
    }
    function download(url){
        var link=document.createElement('a');
        document.body.appendChild(link);
        link.href=url;
        link.download = 'download';
        link.click();
        link.parentNode.removeChild(link);
    }
    function downloadDocuments(){
        var checkeditems = getSelectedDocuments();
        checkeditems = checkeditems.checkeditems;
        if(checkeditems.length < 1 || checkeditems === undefined){
            alert('Please select at least one document.');
        } else {
            var csrfToken = $('[name=_csrfToken]').val();
            $.ajax({
                type: "POST",
                url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "zipDownload")); ?>',
                data: {'files' : checkeditems},
                beforeSend: function(xhr){
                    xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                },
                success: function(data){
                    var url = '/cake/temp/zip/'+data;
                    console.log(url);
                    download(url);
                }
            });
        }
    }
</script>

Et vous pouvez télécharger dans index.ctp:


Fonction de créer paramètres de "get" de URL

Une fonction de créer paramètres de "get" de URL.
    function getquery_build(query,name,value){
        query = query + (query.slice(0, 1) == '?' ? '&'+name+'='+value : '?'+name+'='+value);
        return encodeURI(query);
    }

Comment utiliser:
query = "";
query = getquery_build(query, 'index1', 'value1');
query = getquery_build(query, 'index2', 'value2');
query = getquery_build(query, 'index3', 'value3');
query = getquery_build(query, 'index4', 'value4');
console.log(query);

Le résultat:
?index1=value1&index2=value2&index2=value2&index2=value2

Fonction de "For each" en Javascript

La fonction de "For each" en Javascript.

        var some_array = ['aaa', 'bbb', 'ccc'];
        some_array.forEach(function(value, index) {
             console.log("index: " + index);
             console.log("value: " + value);
        });




samedi 30 décembre 2017

Comment créer uploader dans CakePHP3

1.  Comment créer uploader dans CakePHP3
2.  Comment créer downloader dans CakePHP3
3.  Comment créer downloader pour des fichiers de PDF dans CakePHP3

D'abord, nous créons une table avec un fichier de migration:
<?php
use Migrations\AbstractMigration;

class CreateCustomers extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $table = $this->table('customers');
        $table->addColumn('name', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        $table->addColumn('description', 'text', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('file_location', 'string', [
            'default' => null,
            'null' => true,
            'limit' => 255,
        ]);
        $table->addColumn('created', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->addColumn('modified', 'datetime', [
            'default' => null,
            'null' => false,
        ]);
        $table->create();
    }
}

Et faites les commandes de la migration pour la table de "customers":
$ bin/cake migrations migrate
$ bin/cake bake all customers

Maintenant, créez un uploader avec html5 comme ça:
<input type = "file" name="file"/>

Si nous utilisons $this->Form->input() dans "index.ctp" de CakePHP3:
$this->Form->input('file', ['type'=>'file']);

Et vous allez avoir un uploader comme ça:


Dans l'ensemble, la page de template (index.ctp) sera:
Le code:
<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Customer $customer
 */
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
    <ul class="side-nav">
        <li class="heading"><?= __('Actions') ?></li>
        <li><?= $this->Html->link(__('List Customers'), ['action' => 'index']) ?></li>
    </ul>
</nav>
<div class="customers form large-9 medium-8 columns content">
    <?= $this->Form->create($customer, ['enctype' => 'multipart/form-data']) ?>
    <fieldset>
        <legend><?= __('Add Customer') ?></legend>
        <?php
            echo $this->Form->control('name');
            echo $this->Form->control('description');
            echo $this->Form->control('file_location', ['type'=>'file']);
        ?>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>
</div>


Maintenant, nous avons un "controller" de la table de "customers". Ouvrez le controller de customers et éditez le pour ajouter la fonction suivante: (Ajoutez "use Cake\Network\Exception\BadRequestException;" et "use Cake\I18n\Date;" dans le fichier)
    private function upload($file, $directory) {
        $today = new Date();
        $yearmonth = $today->i18nFormat('yyyyMM');
        $directory = $directory . "/" . $yearmonth;
        if (!file_exists($directory)) {
            if (!mkdir($directory, 0755, true)) {
                throw new BadRequestException('Impossible de créer le répertoire.');
            }
            chmod($directory, 0755);
        }
        switch ($file['error']) {
            case 0:
                break;
            case UPLOAD_ERR_OK:
                break;
            case UPLOAD_ERR_NO_FILE:
                throw new BadRequestException('Fichier introuvable.');
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                throw new BadRequestException('Fichier trop grand.');
            default:
                throw new BadRequestException('Erreur inconnu');
        }
        $temp = explode('.', $file["name"]);
        $extension = strtolower(end($temp));
        $randString = sha1(time() . rand());
        $uploadFile = $randString . "." . $extension;
        if (!rename($file["tmp_name"], $directory . "/" . $uploadFile)) {
            throw new BadRequestException('Impossible de déplacer le fichier.');
        }
        return $yearmonth.'/'.$uploadFile;
    }

Et changez la fonction de "add":
    public function add()
    {
        $customer = $this->Customers->newEntity();
        if ($this->request->is('post')) {
            $data = $this->request->getData();
            $data['file_location'] = $this->upload($data['file_location'], WWW_ROOT.'uploads/customers');
            $customer = $this->Customers->patchEntity($customer, $data);
            if ($this->Customers->save($customer)) {
                $this->Flash->success(__('The customer has been saved.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The customer could not be saved. Please, try again.'));
        }
        $this->set(compact('customer'));
        $this->set('_serialize', ['customer']);
    }

Et vous pouvez uploader un fichier depuis la page de "add".

Le fichier est dans le dossier suivant: \cake\webroot\uploads\customers\201712

Nous pouvons utiliser les fichiers comme ça (dans le fichier de "index.ctp"):

<?php foreach ($customers as $customer): ?>
            <tr>
                <td><?= $this->Number->format($customer->id) ?></td>
                <td><?= h($customer->name) ?></td>
                <td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
                <td><?= h($customer->created) ?></td>
                <td><?= h($customer->modified) ?></td>
                <td class="actions">
                    <?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
                    <?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
                    <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
                </td>
            </tr>
            <?php endforeach; ?>

Le code complet de "index.ctp"
<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\Customer[]|\Cake\Collection\CollectionInterface $customers
 */
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
    <ul class="side-nav">
        <li class="heading"><?= __('Actions') ?></li>
        <li><?= $this->Html->link(__('New Customer'), ['action' => 'add']) ?></li>
    </ul>
</nav>
<div class="customers index large-9 medium-8 columns content">
    <h3><?= __('Customers') ?></h3>
    <table cellpadding="0" cellspacing="0">
        <thead>
            <tr>
                <th scope="col"><?= $this->Paginator->sort('id') ?></th>
                <th scope="col"><?= $this->Paginator->sort('name') ?></th>
                <th scope="col"><?= $this->Paginator->sort('file_location', 'File') ?></th>
                <th scope="col"><?= $this->Paginator->sort('created') ?></th>
                <th scope="col"><?= $this->Paginator->sort('modified') ?></th>
                <th scope="col" class="actions"><?= __('Actions') ?></th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($customers as $customer): ?>
            <tr>
                <td><?= $this->Number->format($customer->id) ?></td>
                <td><?= h($customer->name) ?></td>
                <td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
                <td><?= h($customer->created) ?></td>
                <td><?= h($customer->modified) ?></td>
                <td class="actions">
                    <?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
                    <?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
                    <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    <div class="paginator">
        <ul class="pagination">
            <?= $this->Paginator->first('<< ' . __('first')) ?>
            <?= $this->Paginator->prev('< ' . __('previous')) ?>
            <?= $this->Paginator->numbers() ?>
            <?= $this->Paginator->next(__('next') . ' >') ?>
            <?= $this->Paginator->last(__('last') . ' >>') ?>
        </ul>
        <p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
    </div>
</div>




samedi 23 décembre 2017

Keras dans Windows

Installer Python3 (64bit)


D'abord, vous avez besoin d'installer Python3 pour utiliser Keras. Keras peut être utilisé uniquement avec la version 64 bit de Python3. Alors vérifiez que votre PC soit bien 64 bit.

Cliquer sur le lien de Python:
https://www.python.org/

Le site de Python

Sélectionner "Downloads" -> "WIndows"

Choisissez "Windows x86-64 web-based installer" de python 3.6.
(Parce que, tensorflow est compatible uniquement avec la version 3.5 et 3.6.)

Démarrer le programme d'installation. Cochez "Add Python to PATH".
Et suivez les instructions du programme pour installer la version 64 bit de Python3. 

Après l'installation, dans l'invite de commande, faites la commande pour vérifier si l'installation à réussit. 
python -V

Python 3.6.3

Si la version est affichée, l'installation à réussit.

Installer Keras 


Démarrez l'invite de commande en tant qu’administrateur.

Vous avez installé Python3, vous pouvez utiliser pip aussi dans l'invite de commande.
pip -V

pip 9.0.1 from c:\users\jack\appdata\local\programs\python\python36\lib\site-pack
ages (python 3.6)

Maintenant vous avez besoin d'installer Keras avec pip. Faites la commande suivante:
pip install Keras

Installez Tesorflow:
(Si votre PC n'a pas de carte graphique):
pip install --upgrade tensorflow
(Si votre PC a une carte graphique):
pip install --upgrade tensorflow-gpu

Autre paquets aussi:
pip install matplotlib
pip install h5py
pip install pillow

Créez un fichier texte et le nommer "test.py". (Si l'extension n'est pas visible, changez les paramètres pour le faire apparaître)

Copier-coller le suivant dans le fichier texte:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils

# Get the default MNIST data
(X_train, y_train), (X_test, y_test) = mnist.load_data()

X_train = X_train.reshape(60000, 784) / 255
X_test = X_test.reshape(10000, 784) / 255

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)

# Network
model = Sequential([
        Dense(512, input_shape=(784,)),
        Activation('sigmoid'),
        Dense(10),
        Activation('softmax')
    ])

# Compile
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])

# Learning
model.fit(X_train, y_train, batch_size=200, verbose=1, epochs=20, validation_split=0.1)

# Forecast
score = model.evaluate(X_test, y_test, verbose=1)
print('test accuracy : ', score[1])

Et enregistrez le fichier. 

Allez au répertoire dans l'invite de commande. Par exemple:
cd C:\Users\Jack\Documents\workplace

Faites le fichier "test.py" dans l'invite de commande:
python test.py

Si l'apprentissage automatique de MNIST a démarré, l'installation de Keras a réussi.

Maintenant vous pouvez créer et faire des programmes de Keras dans votre PC! :)