Cakephp 3.0 download file - cakephp-3.0

I asked a question before about file uploading. I managed to get it working and my next step is getting the file to be downloaded by a customer the files may be different formats from videos to PDFs.
I did read about media views, but they where cakephp 2.0. I have found that 2.0 seems to cause problems for me at least.
I can upload my files for uploading if it helps.
Nased on the link Alex posted, how would I call this function in my view this is the function based from the cakephp book link
public function downloadFile($id)
{
$file = $this->Attachments->getFile($id);
// a view.
$this->response->file(
$file['files/content'],
['download' => true]
);
return $this->response;
}

To get a link to that function (using the cakephp default routing) you would do this in your view:
echo $this->Html->link('Download File', ['controller' => 'Attachments', 'action' => 'download_file', $id]);

public function download(){
$file_path = WWW_ROOT.'uploads'.DS.'file_name.doc';
$this->response->file($file_path, array(
'download' => true,
'name' => 'file_name.ppt',
));
return $this->response;
}

Related

Can I display pictures outside backend web folder in yii2?

I have a little problem. I can’t view images outside the backend web folder.
Aliases in common\config\main:
'aliases' => [
'#upload' => dirname(dirname(__DIR__)).'/upload',
],
View Dataprovider:
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Yii::getAlias('#upload') . $data->codice_prodotto . '/' . $data->immagine, ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
Can I resolve? Thanks.
If your file is not accessible for http server, so you can't directly download it.
You can:
Move uploads directory to directory accessible for the http-server
Create action that will read the file from private directory and stream it to the browser (you can use yii\web\Response::sendFile() function for that)
Streaming file to the browser
Please read this official docs article to understand this deeply: https://www.yiiframework.com/doc/api/2.0/yii-web-response#sendFile()-detail
Action code example for your case: *
public function actionFile($filename)
{
$storagePath = Yii::getAlias('#upload');
// check filename for allowed chars (do not allow ../ to avoid security issue: downloading arbitrary files)
if (!preg_match('/^[a-z0-9]+\.[a-z0-9]+$/i', $filename) || !is_file("$storagePath/$filename")) {
throw new \yii\web\NotFoundHttpException('The file does not exists.');
}
return Yii::$app->response->sendFile("$storagePath/$filename", $filename);
}
And view Dataprovider configuration: *
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Url::to(['/path/to-streaming-action/file', 'filename' => $data->codice_prodotto . '/' . $data->immagine]), ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
* Notice that this code is not ready to copy-paste, please read it carefully and try to understand the principle before implement it in your code.

Laravel: Store error messages in database

Any one know how to send error messages to database in laravel which generate from app/exceptions/handler.php ?
I need to send what error massages generated in report() method to database.
If you are interested doing this manually, you can do something as following.
Step 1 -
Create a model to store errors that has a DB structure as following.
class Error extends Model
{
protected $fillable = ['user_id' , 'code' , 'file' , 'line' , 'message' , 'trace' ];
}
Step 2
Locate the App/Exceptions/Handler.php file, include Auth, and the Error model you created. and replace the report function with the following code.
public function report(Exception $exception) {
// Checks if a user has logged in to the system, so the error will be recorded with the user id
$userId = 0;
if (Auth::user()) {
$userId = Auth::user()->id;
}
$data = array(
'user_id' => $userId,
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
);
Error::create($data);
parent::report($exception);
}
(I am demonstrating this using laravel 5.6)
Because Laravel uses Monolog for handling logging it seems that writing Monolog Handler would be the cleanest way.
I was able to find something that exists already, please have a look at monolog-mysql package. I did not use it, so I don't know whether it works and if it works well, but it's definitely good starting point.

How to use telegram api package in CakePHP 3?

I tried to use PHP telegram bot in my CakePHP 3 website, but encountered many problems.
done
I ran "composer require longman/telegram-bot" and copied package to "plugins" folder.
and then "bin/cake plugin load longman/telegram-bot".
questions
1. Where I must put the package and why? vendor or plugins
2. How to call package methods in URL?
I added "index" method to "telegram-bot/src/Telegram.php" and tried this snippet code in my "Template/Users/index.ctp".
echo $this->Html->link('telegram', ['plugin' => 'longman/telegram-bot', 'controller' => 'telegram', 'action' => 'index']);
that results
Error: A route matching "array ( 'plugin' => 'longman/telegram-bot', 'controller' => 'telegram', 'action' => 'index', '_ext' => NULL, )" could not be found.
3. What I must add to "routes.php"?
4. How can I use "telegram-bot/src/Telegram.php" methods in my controllers and models.
5. Is there anything else that must be observed?
Thanks.

Leaflet extension and Geosearch Directory not found

Im relatively new to the Yii framework. I'm trying to get leaflet extension to work on my project. I installed it via composer and everything seems to be installed properly but when I try to insert it into an activeForm it throws me this error:
The file or directory to be published does not exist: /vendor/bower/leaflet/dist
Im trying to build a Geosearch field with a map.
The extensions I have installed are:
"2amigos/yii2-leaflet-extension": "~1.0",
"2amigos/yii2-leaflet-geocoder-plugin": "~1.0",
"2amigos/yii2-leaflet-geosearch-plugin": "~1.0"
This is my code on the ActiveForm (its just the same as the provided on GitHub):
use dosamigos\leaflet\layers\TileLayer;
use dosamigos\leaflet\LeafLet;
use dosamigos\leaflet\types\LatLng;
use dosamigos\leaflet\plugins\geosearch\GeoSearch;
use dosamigos\leaflet\widgets\Map;
<?php
$center = new LatLng(['lat' => 39.67442740076734, 'lng' => 2.9347229003906246]);
$geoSearchPlugin = new GeoSearch([
'service' => GeoSearch::SERVICE_OPENSTREETMAP
]);
$tileLayer = new TileLayer([
'urlTemplate' => 'link not allowed because its one of my first posts...',
'clientOptions' => [
'attribution' => 'Tiles Courtesy of MapQuest ' . ', ' . 'Map data © OpenStreetMap contributors, ' . 'CC-BY-SA', 'subdomains' => '1234'
]
]);
$leafLet = new LeafLet([
'name' => 'geoMap',
'tileLayer' => $tileLayer,
'center' => $center,
'zoom' => 10,
'clientEvents' => [ // setting up one of the geo search events for fun
'geosearch_showlocation' => 'function(e){ console.log(e.target); }'
]
]);
// add the plugin
$leafLet->installPlugin($geoSearchPlugin);
// run the widget (you can also use Map::widget([...]))
echo $leafLet->widget();
?>
Is there something I'm missing or doing wrong?
Thanks in advanced
Your problem is that the original Leaflet js and css files are no longer available through Bower, and 2amigos have not changed their composer file to reflect the changes. Yii is attempting to publish a css file from the requested location, and the file doesn't yet exist, hence the error message. You'll either need to go to the original Leaflet repository and copy the relevant files into the required directories, or update the composer file to point to the original files on GitHub. Sorry, I don't know enough about composer to be able to help with this bit!

Cakephp 3 & Ajax, send $.get additional data

I try to send custom data using $.get from jquery but cakephp 3 does not recognize the variables.
Here is my function in controller:
public function view($cat,$id,$page){
$comments = $this->Comments->find('all')->where(['category =' => $cat, 'AND' => ['category_id =' => $id]])->order(['comments.created' => 'DESC'])
->contain([
'Reports' => function($q){return $q->where(['user_id =' => $this->Auth->user('id')]);},
'Chars' => function($q){ return $q->select(['id','name','class','race','level','guild_id', 'user_id'])
->contain(['Guilds' => function($q){ return $q->select(['id','name']);
}]);
}])->limit(3)->page($page);
if($cat == 'Videos'){
$subject = $this->Comments->Videos->get($id);
}
$category = $cat;
$this->set(compact('subject','comments','category'));
}
}
And here's the .js
$('.more').click(function(){
$.get($(this).attr('href'),{cat:'Videos',id:'44',page:'2',function(data){
$('.coms').empty().append(data);
});
return false;
});
And the link:
<?= $this->Html->link('More', ['controller' => 'Comments','action' => 'view'], ['class' => 'btn btn-primary more']) ?>
The fix values in the .js is for the test, it works if I send the data in the link with $.get(href) but I want to know how to pass custom data in the $.get request.
Thank you for your help
CakePHP doesn't magically map query string parameters to method arguments, that's not even supported by routes.
You can access query string paramters via the request object
$this->request->query('cat');
See also http://book.cakephp.org/3.0/en/controllers/request-response.html#query-string-parameters
The solution
Hi, I did a little api to get the data I need from a json array.
So I created an ApiController to do all the ajax requests I need. Here is test example:
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;
class ApiController extends AppController
{
public function test($id)
{
$UsersTable = TableRegistry::get('Users');
$users = $UsersTable->find()->where(['id <' => $id]);
$this->set(compact('users'));
}
}
?>
I want to get the list of all my users from an ajax call (that's the worst idea ever but it's just for the test ;))
Now I need to enable json for this view. For this, I need to go in config/routes.php to add this:
Router::scope('/api', function($routes){
$routes->extensions(['json']);
$routes->connect('/test/*', ['controller' => 'Api', 'action' => 'test', '_ext' => 'json']);
});
Now when I go on http://localhost/mywebsite/api/test/100, I have a json array of all the users with an id < 100, ready to get pulled by an ajax script.
'_ext' => 'json'
means you don't have to go on api/test.json to display the json array
Now on a random view in a random controller, I put a button to try all this and I call my javascript file to do my ajax request.
<button class="test">Test button</button>
<?= $this->Html->script('test', ['block' => true]) ?>
Now in my test.js:
$(document).ready(function(){
var value = 100;
$('.test').click(function(){
$.get('/api/test/' + value, function(data){
console.log(data);
});
});
});
I click the button and the log shows an array with all the users I wanted in my console when I push F12 (on chrome).
Hope this will help someone