I need a cron job in one of my older web site (CakePHP 1.3).
I made the following steps:
created shell in /somepath/public_html/app/vendors/shells/valute.php
class ValuteShell extends Shell {
var $uses = array('Valute');
function main() {
$this->Valute->cacheGetKonverterData();
}
}
created BASH script and save this to my vendors folder as cakeshell (/somepath/public_html/app/vendors/cakeshell)
#!/bin/bash
TERM=dumb
export TERM
cmd="cake"
while [ $# -ne 0 ]; do
if [ "$1" = "-cli" ] || [ "$1" = "-console" ]; then
PATH=$PATH:$2
shift
else
cmd="${cmd} $1"
fi
shift
done
$cmd
changed the permissions on the this file to 777.
called cronjob like this:
0 0 * * * /somepath/public_html/app/vendors/cakeshell valute -cli /usr/bin -console /somepath/public_html/cake/console -app /somepath/public_html/app
Unfortunately cronjob does not work. Why?
When I call: http://www.somedomain.net/valutes/save_valute
everything works fine.
<?php
class ValutesController extends AppController {
var $name = 'Valutes';
var $uses = array('Valute');
function save_valutes()
{
$this->layout = null; // turn off the layout
$this->Valute->cacheGetKonverterData();
}
}
?>
cakeshell: cmd should have the PATH of the Cake core's cake file
cmd="/somepath/public_html/lib/Cake/Console/cake"
crontab:
0 0 * * * /somepath/public_html/app/vendors/cakeshell valute -app /somepath/public_html/app >> var/log/crontab
Related
Good evening :-)
I am learning Symfony(3) now, and I would like to use test for my classes. I've read that unittests shouldn't use databases, mocking its objects rather.
But despite this, I would like to create in setUp()/KernelTestCase database (e.q. MySQL) and read its content for file, next doing tests (simple -unittests), and purge at tearDown().
Is it possible do it with dumped MySQL file?
What is best (? lazy) way to do it?
I would rather to read prepared (dumped) SQL-like file then 'update:schema' from ORM-class. Where to put file in Symfony3? How read it and create database content?
Pls. help me.
I am using this for years:
Load tests data with the DoctrineFixtures bundle
Launch tests
Repeat! This is for me the most efficient as you only load your test data once; NOT for every tests. Of course you will have to think harder of your tests scenario.
For example, think about a crud test:
Test1:
Check that list has 1 item (loaded by fixtures)
Test2:
Create an item
Check that list has 2 items
Test3:
Delete an element
Check that the list has 1 item
So the tests must be executed in this order exactly. If you are loading fixtures between each test you don't have to take care of that order but it will make your tests slow.
I feel loading fixtures once is better because it will act as a user would normally do: create, delete, update items... And therefore you can check that there is no side effect between each action.
My load fixtures script:
#!/bin/bash
echo "##########################################################################"
echo "# Refresh data model, reload all reference data, load fixtures, #"
echo "# validate schema for the dev env. #"
echo "##########################################################################"
php bin/console doctrine:database:create --if-not-exists --env=dev
php bin/console doctrine:schema:drop --force --env=dev
php bin/console doctrine:schema:create --env=dev
php bin/console doctrine:schema:validate --env=dev
php bin/console doctrine:fixtures:load -n --env=dev
echo -e " --> DONE\n"
Or if you want to load a database for SQL files, use:
php bin/console doctrine:database:import db.sqb --env=dev
Instead of the load fixtures command.
Then, to launch the tests:
./bin/simple-phpunit --debug --verbose $1
$1 is an argument to specify the test suite to load. (main, front, API, backend...) which you can parameter in your phpunit.xml.dist file. (you can omit it to run all the tests)
My solution is:
This load all SQL files to MySQL TEST DB - defined in 'parameters_test.yml' and processing test and drops all DB tables before next test and again with next tests... It can be probably be done shorter and in more right way with command php bin/console doctrine:database:import ... as #Tokeeen.com said. Thank you for help.
// tests/AppBundle/Repository/BotsDbTest.php
<?php
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Yaml\Parser;
class BotsDbTest extends KernelTestCase
{
private $doctr;
private $db_cred;
private $db;
/**
* {#inheritDoc}
*/
protected function setUp()
{
$kernel = self::bootKernel();
$this->doctr = $kernel->getContainer()
->get('doctrine')
->getManager();
// for tests with loaded content
$this->db = new \AppBundle\Wiks\BotsDb();
// https://symfony.com/doc/current/bundles/extension.html
// get DB credientals from "parameters_test.yml":
$configDirectories = array( 'app/config' );
$locator = new FileLocator( $configDirectories );
$yamlUserFiles = $locator->locate( 'parameters_test.yml', null, false );
// https://davidegan.me/parse-yaml-in-php-using-symfony-yaml/
$yaml = new Parser();
$yaml_array = $yaml->parse( file_get_contents( $yamlUserFiles['0'] ) );
// needen DB is the second in Symfony - as database2 in file "parameters_test.yml":
$prefix_db = 'database2';
// looking for all keys with suffix: eq: 'database2_host'
$needed_sufix = [ 'host', 'port', 'name', 'user', 'password' ];
$this->db_cred = array();
foreach ( $yaml_array[ 'parameters' ] as $key => $value ) {
if ( strpos( $key, $prefix_db ) !== false ) {
foreach ( $needed_sufix as $needed_key ) {
if ( strpos( $key, $needed_key ) !== false ) {
$this->db_cred[ $needed_key ] = $value;
}
}
}
}
if ( count( $this->db_cred ) == count( $needed_sufix ) ) {
// check is all found
/*Array (
[host] => 127.0.0.1
[port] =>
[name] => db_name
[user] => user_name
[password] => ***
) */
$finder = new Finder();
// find and put into mysql all files as prepared content to tests
$finder->files()->name('*.sql');
foreach ( $finder->in( array( 'tests/dbcontent' ) ) as $file ) {
$shell_command = 'mysql --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'];
$shell_command .= ' '.$this->db_cred['name'].'< '.$file->getRealPath();
shell_exec( $shell_command );
}
}
}
/**
* {#inheritDoc}
*/
protected function tearDown()
{
parent::tearDown();
// remoove DB content ( all tabels ):
$shell_command = 'mysqldump --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'].' ';
$shell_command .= '--add-drop-table --no-data '.$this->db_cred['name'].' | ';
$shell_command .= 'grep -e \'^DROP \| FOREIGN_KEY_CHECKS\' | ';
$shell_command .= 'mysql --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'].' '.$this->db_cred['name'];
shell_exec( $shell_command );
$this->doctr->close();
$this->doctr = null; // avoid memory leaks
}
/** tests, tests, tests...
*
*/
public function test_getBots()
{
$res = $this->db->getBots( $this->doctr );
$this->assertEquals(5, count( $res ));
[...]
Helpful links:
How to remove all MySQL tables from the command-line without DROP database permissions?
https://davidegan.me/parse-yaml-in-php-using-symfony-yaml/
https://symfony.com/doc/current/components/finder.html
https://symfony.com/doc/current/bundles/extension.html
Using Cake version 2.4.3 stable
So I am having a time here, I have modified this plug in to save files to the app folder https://github.com/srs81/CakePHP-AjaxMultiUpload/
The uploaded files are being saved to /public_html/app/files
Now the strange thing is, when trying to serve these files to the view, I can read the file name, the file size, but not the file itself, image, pdf, etc.
When I try to access the file via direct url, i get this error :
Error: FilesController could not be found.
How can it be that I can read the file name, the file size, but not the file itself?
There is a need to save the files in the app folder. These files should be protected and therefore only be accessed by users who are logged into the application. I have tried to use cake send file response with no outcome.
Edit : I guess the real question at hand here is how can I read files from APP . DS . 'files' ?
View code :
public function view ($model, $id, $edit=false) {
$results = $this->listing ($model, $id);
$directory = $results['directory'];
$baseUrl = $results['baseUrl'];
$files = $results['files'];
$str = "<dt>" . __("Pictures") . "</dt>\n<dd>";
$count = 0;
$webroot = Router::url("/") . "ajax_multi_upload";
foreach ($files as $file) {
$type = pathinfo($file, PATHINFO_EXTENSION);
$filesize = $this->format_bytes (filesize ($file));
$f = basename($file);
$url = $baseUrl . "/$f";
if ($edit) {
$baseEncFile = base64_encode ($file);
$delUrl = "$webroot/uploads/delete/$baseEncFile/";
$str .= "<a href='$delUrl'><img src='" . Router::url("/") .
"ajax_multi_upload/img/delete.png' alt='Delete' /></a> ";
}
$str .= "<img src='$url' /> ";
$str .= "<a href='$url'>" . $f . "</a> ($filesize)";
$str .= "<br />\n";
}
$str .= "</dd>\n";
return $str;
}
And the upload / save
public function upload($dir=null) {
// max file size in bytes
$size = Configure::read ('AMU.filesizeMB');
if (strlen($size) < 1) $size = 20;
$relPath = Configure::read ('AMU.directory');
if (strlen($relPath) < 1) $relPath = "files";
$sizeLimit = $size * 1024 * 1024;
$this->layout = "ajax";
Configure::write('debug', 0);
$directory = APP . DS . $relPath;
if ($dir === null) {
$this->set("result", "{\"error\":\"Upload controller was passed a null value.\"}");
return;
}
// Replace underscores delimiter with slash
$dir = str_replace ("___", "/", $dir);
$dir = $directory . DS . "$dir/";
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
$uploader = new qqFileUploader($this->allowedExtensions,
$sizeLimit);
$result = $uploader->handleUpload($dir);
$this->set("result", htmlspecialchars(json_encode($result), ENT_NOQUOTES));
}
The only real change from the original plug in is changing WWWROOT to APP to make the switch. Saving works fine and lovely. But its just weird that I can read the file name, file size in the view no problem but cannot view an image, pdf, etc.
The problem:
You cannot display files that are outside the webroot via a direct URL - that's the whole point in putting them above the webroot in the first place - to make them NOT directly accessible.
So building the image src path in the controller first (not good practice anyway) won't change the fact that when that path gets to the browser, and it reads the source of the image as trying to pull an image from above webroot, it won't/can't.
The Solution:
The solution is to use a CakePHP's Sending files (what used to be Media Views). Then, you set your img's "src" to a controller/action. In that action, it basically says "display this action as an image" (or pdf, or whatever else).
Path to use in Controller:
took this from one of my apps which is doing exactly the above, and here's the path I used for a file in 'files' (same level as webroot):
file_exists(APP . 'files' . DS . $your_filename)
Create a symbolic link to your folder inside of the webroot ;-)
Ok, I'm trying to File & Folder classes as specified here:
http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#
My Folder Controller looks like this:
<?php
App::uses('AppController', 'Controller');
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
class FolderController extends AppController {
public $uses = array();
public function display() {
$dir = '/var/www/html/letters/pdfdir/';
$files = $dir->find('.*\.pdf', true);
foreach ($files as $file) {
$file = new File($dir->pwd() . DS . $file);
$contents = $file->read();
echo 'CONTENT: '.$contents;
// $file->write('I am overwriting the contents of this file');
// $file->append('I am adding to the bottom of this file.');
// $file->delete(); // I am deleting this file
$file->close(); // Be sure to close the file when you're done
}
}
}
but I get the following error:
Error: Call to a member function find() on a non-object
File: /var/www/html/letters/app/Controller/FolderController.php
Line: 13
Any help appreciated.
Regards
You have a mistake
$dir = '/var/www/html/letters/pdfdir/';
should be
$dir = new Folder('/var/www/html/letters/pdfdir');
In your original code $dir is just a variable of string type. However, it should be an object of Folder class.
Another note: you have to remove the trailing slash.
$dir is still a string, you need to pass it to a File or Folder object to become usable as an object.
# Cron Job for Cakephp #
I have create 1 file cron_scheduler.php which is copy of wamp/www/projectname/app/webroot/index.php file and it is also in the same folder
i have tried to run throw command prompt but didn't get any result.
how to run cronjob for Cakephp ? i don't have any idea
if anyone knows , please help me.
Thanks in advance.
<?php
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
/**
* These defines should only be edited if you have cake installed in
* a directory layout other than the way it is distributed.
* Each define has a commented line of code that explains what you
would change.
*
*/
if (!defined('ROOT')) {
//define('ROOT', 'FULL PATH TO DIRECTORY WHERE APP DIRECTORY IS
//LOCATED DO NOT ADD A TRAILING DIRECTORY SEPARATOR';
//You should also use the DS define to seperate your directories
define('ROOT', dirname(dirname(__FILE__)));
}
if (!defined('APP_DIR')) {
//define('APP_DIR', 'DIRECTORY NAME OF APPLICATION';
define('APP_DIR', basename(dirname(__FILE__)));
}
/**
* This only needs to be changed if the cake installed libs are located
* outside of the distributed directory structure.
*/
if (!defined('CAKE_CORE_INCLUDE_PATH'))
{
//define ('CAKE_CORE_INCLUDE_PATH', FULL PATH TO DIRECTORY WHERE
//CAKE CORE IS INSTALLED DO NOT ADD A TRAILING DIRECTORY SEPARATOR';
//You should also use the DS define to seperate your directories
define('CAKE_CORE_INCLUDE_PATH', ROOT);
}
///////////////////////////////
//DO NOT EDIT BELOW THIS LINE//
///////////////////////////////
if (!defined('WEBROOT_DIR'))
{
define('WEBROOT_DIR', 'webroot');
}
if (!defined('WWW_ROOT')) {
//define('WWW_ROOT', dirname(__FILE__) . DS);
define('WWW_ROOT', dirname(__FILE__) . DS . 'webroot' . DS);
}
if (!defined('CORE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', CAKE_CORE_INCLUDE_PATH .
PATH_SEPARATOR .
ROOT . DS . APP_DIR . DS . PATH_SEPARATOR . ini_get('include_path'));
define('APP_PATH', null);
define('CORE_PATH', null);
} else {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
}
require CORE_PATH . 'cake' . DS . 'bootstrap.php';
define('CRON_DISPATCHER',true);
if($argc == 2)
{
$Dispatcher= new Dispatcher();
$Dispatcher->dispatch($argv[1]);
}
?>
> i have tried to run throw command promt but didn't get any result
> how to run cronjob for Cakephp ? i don't have any idea
if anyone knows , please help me.
Thanks
Step1: Create a shell file with name ReminderShell.php and Path should be PROJECT_DIR_PATH/PROJECT_NAME/app/Console/Command/ReminderShell.php Copy below script and paste it
class ReminderShell extends Shell {
var $tasks = array('Mail');
function main() {
$this->Mail->enroll_reminder();
}
}
Step2: Create Task file with name MailTask.php and path should be PROJECT_DIR_PATH/PROJECT_NAME/app/Console/Command/Task/MailTask.php
<?php
App::uses('CakeEmail', 'Network/Email');
class MailTask extends Shell {
var $uses = array('Contact');
public function enroll_reminder() {
$Email = new CakeEmail();
$Email->config('default');
$reminder = $this->Contact->find('all');
if (!empty($reminder)) {
foreach ($reminder as $val) {
$id = $val['Contact']['id'];
$name = $val['Contact']['first_name'];
$email = $val['Contact']['email'];
$Email->template('reminder')
->viewVars(array('fname' => $name))
->emailFormat('html')
->subject('xyz.com: Enrollment Reminder')
->to($email)
->from('noreply#xyz.com');
if ($Email->send()) {
$update_val['Contact']['id'] = $id;
$update_val['Contact']['enroll_reminder'] = 'sent';
$update_val['Contact']['enroll_reminder_date'] = date("Y-m-d H:i:s");
$this->Contact->save($update_val['Contact']);
$this->out($email.' Mail Sent');
}
}
}
}
Step3: Create a email template with name reminder.ctp and path should be PROJECT_DIR_PATH/PROJECT_NAME/app/View/Emails/html/reminder.ctp
Step4: Create email.php in config directory
Step5: Run below command in Terminal: Console/cake Reminder
PROJECT_DIR_PATH/PROJECT_NAME/app Console/cake Reminder
For complete files checkout from https://github.com/pankajkumarjha2010/cronjob-in-cakephp2.3.x
For cronjobs in CakePHP, you may have a look at http://book.cakephp.org/2.0/en/console-and-shells/cron-jobs.html. This works fine for me.
But please note, sometimes there are not all the environmental parameters available. I ran into this problem when accessing env('HTTP_HOST') within the cronjob methods. But when considering this, it should be no problem.
I need to retrieve the mysql connection settings and store them as variables. I know that the file configuration.php contains what I need. I just don't know how to call it accurately. Here are the 4 variables (and associate values) that I need:
1) $host = public $host from config file
2) $user = public $user from config file
3) $password = public $password from config file
4) $db_name = public $db from config file
$info =& JFactory::getApplication();
$info->getCfg('host');
$info->getCfg('user');
$info->getCfg('db');
// defined in libraries/joomla/application/application.php (380)
function getCfg( $varname ) {
$config =& JFactory::getConfig();
return $config->getValue('config.' . $varname);
}
looking at the code in joomla application you can also do the following :
$config =& JFactory::getConfig();
and get most if the info you want .