Laravel 4.2, Artisan::call() ignoring --env option - laravel-4

I'm building an application that needs to create a new database, perform migrations and seed db data via a web page.
I'm trying to achieve this with the following code in Laravel 4.2. Note, this is within a controller I've setup.
Artisan::call("migrate", array(
"--env" => "production"
));
No matter what environment I pass with the "--env" option, the environment that the migration is run on is the current environment that the site is currently running on. Ie. If I'm running on my local environment, and I run the above, it will execute the migration on the local environment which isn't what I'm looking to do.
If I run the equivalent command php artisan --env=production migrate from the command line, I get the results I'm looking to achieve. For the time being, I'm getting past this via passthru() but I'd like to take advantage of this Artisan facade if I can.
Does anyone know what's going on with this?

This isn't a pleasant way to do it, but it works.
Assuming your Artisan environment is based on $_SERVER['HTTP_HOST'] and you know the HTTP_HOST that will load your environment then you can set it manually before calling start.php
I used this to define the Artisan environment based on the base_url I was using in a Behat profile. That way I could configure fixture my database before running tests.
/**
* #BeforeSuite
*/
public static function runFixtures(SuiteEvent $suiteEvent) {
// Get the environment domain
$parameters = $suiteEvent->getContextParameters();
$baseUrl = $parameters['base_url'];
$urlParts = parse_url($baseUrl);
$_SERVER['HTTP_HOST'] = $urlParts['host'];
// Now call start.php
require_once 'bootstrap/start.php';
// Call Artisan
$stream = fopen('php://output', 'w');
Artisan::call(
'migrate:refresh',
[
'--seed' => true,
],
new StreamOutput($stream)
);
}

--env is the option to specify application's environment when the application is starting. In other words, if you specify --env option, Laravel will use your specified environment instead runs a detecting method in environment detecting method.
So, If you run artisan via CLI with --env option, In start file, artisan can detect --env option from $_SERVER variable, specify the application environment and run your command.
In contrast, when you call Artisan::call(), Laravel will resolve the console application class (Illuminate\Console\Application) and run your command. Because your application was started, then Application just runs your command without detecting environment. More over, latest version of migration command class use application environment to get a database connection
Therefore, when your call Artisan::call() the --env option is completely omitted.
Just my opinion. If you really want to avoid using passthru() function, you can rename the production database connection name in app/config/database.php to unique name e.g. production and set your default database connection to your new name. When you want to migrate production database, just call Artisan::call('migrate', array('--database' => 'production', '--force' => true)) instead of changing the environment.

Related

Using different URLs for local and CI testing

I want to use Cypress to test locally and on CI at the same time. On CI, I would like to test a production version of my application, which has a different baseUrl than the local version, obviously. I am using the https://github.com/bjowes/cypress-ntlm-auth package to ause windows authentication for the CI, and to do so I have to call cy.ntlm line in my tests. I want to make an IF function that calls the cy.ntlm line ONLY if the baseUrl matches the production one. If the baseUrl is localhost then I would like the cy.ntlm line to be ignored. So my bottom line questions are, how do I let cypress know that I want to use 2 different URLs and how do I pack that into an IF statement? Thank you
You can check the baseUrl to conditionally call cy.ntlm,
const baseUrl = Cypress.config('baseUrl')! // use non-null assertion operator
const isLocal = baseUrl.includes('localhost')
if (!isLocal) {
cy.ntlm(...)
}
When using Typescript with Cypress you will get complaints because Typescript has no idea if you have set the baseUrl configuration or not.
You can overcome that by adding ! after getting the baseUrl value.
Ref Typescript - Non-null assertion operator
I separated the steps to make it clearer.
Assuming your cypress config file has the baseUrl. You can then update the baseUrl using the CLI during run time. For this create two different scripts with the staging and production URL's in your package.json like this:
"scripts": {
"test:local": "cypress run --config baseUrl=https://example.com/staging",
"test:ci": "cypress run --config baseUrl=https://example.com/production"
}
Then to run the scripts in CI use npm run test:ci and for local use npm run test:local.

How to start a cron job using schedule:run manually in Laravel 5 (October CMS actually)

I know how to run cron jobs on Linux server,
I know how to use $schedule->command('foo')->daily();
I have read this document many times https://laravel.com/docs/5.0/artisan
But my question is where shall I write this line exactly
$schedule->command('foo')->daily();?
and what is $schedule variable actually? I mean is this any predefined variable in parent classes to which we can directly call if not which class we shall include in our file and how to instantiate this $schedule object.
My main concern is what is the elegant way to schedule jobs, what is the point of writing this in code where i am writing my logic because this line should run once in lifetime if I am not wrong because this will then push the job in Jobs table and then
* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1 should take care of it for rest of the lifetime
then where exactly I shall write such code which will run only once while we deploying the application on the server before starting the main cron schedule:run.
Please, someone guide me why there is no written document for how to run a scheduled task manually without writing it in a code which will be called many time during execution of a real world web application.
First, unless you're actually using Laravel 5.0, specifically, you'll want to make sure you're looking at the right version documentation (and if you are using 5.0, specifically, I highly recommend upgrading, as it's long out of support). The current version (as of this writing) is 5.5, and October CMS has been updated accordingly.
As to your question, if I'm understanding you right, you don't want a scheduled, repeating job, but simply an Artisan command. To write an Artisan command, you create a class in the Console/Commands folder (this can be generated with the make:command Artisan command) and register it in Console/Kernel.php. You can then access it by running php artisan your:command (where your:command is the name you've chosen for your command).
If you want to schedule a repeating job, you put that $schedule line into Console/Kernel.php. The $schedule variable is imported through Laravel's dependency resolver.
If you have a deployment script that you use, and you want to call that single command programmatically, you can do so with Artisan::call(), within your deploy script (be sure to import the Artisan facade):
Artisan::call('your:command');
Three Steps to take:
1) Set up cron task
http://octobercms.com/docs/setup/installation#crontab-setup
Cron will call the command scheduler every minute. Then October evaluates any scheduled tasks and runs the tasks that are due.
2) Make your console command
http://octobercms.com/docs/console/development
This command can be executed manually on the command line. And can be executed on scheduled time as explained next.
3) Register a schedule for the newly made console command in the Plugin registration class
http://octobercms.com/docs/plugin/scheduling#defining-schedules
class MyPlugin extends PluginBase
{
[...]
public function registerSchedule($schedule)
{
$schedule->command('cache:clear')->daily();
}
}
Hope this helps!
Upgrade to Laravel 8 (that is how I tested it)
run php artisan schedule:list - see what you have
run php artisan schedule:test - you will be given options
Which command would you like to run?:
[0] App\...
[1] App\...
then you type a number and see it is working

Laravel Environment Configuration with Heroku

I am writing my code on Nitrous.IO using Laravel I configured my start.php to the following
$env = $app->detectEnvironment(array(
'local' => array('harrenhal-php-95199'),
'staging' => array('*.herokuapp.com'),
));
I tried this format I also tried the hostname itself both seems not to working. is there a specific practice to do so?
Once I run hostname on the shell in heroku I get this result "9e7831e0-284c-48b8-88a4-3afbbbac0b35" which changes over time.
the problem php don't detect herokuapp.com so the staging environment doesn't work
From the Laravel docs
If you need more flexible environment detection, you may pass a
Closure to the detectEnvironment method, allowing you to implement
environment detection however you wish
$env = $app->detectEnvironment(function()
{
return $_SERVER['MY_LARAVEL_ENV'];
});

How to dynamically set phantomJS command line options on Heroku

I have a phantomjs app running on heroku. I need to be able to set several commands which are normally accessed by the command line (https://github.com/ariya/phantomjs/wiki/API-Reference), preferably at runtime, but if necessary once a day.
I want to set the heroku procfile to:
phantomjs --config=/path/to/config.json somescript.js
where the config.json looks like
{
/* Same as: --ignore-ssl-errors=true */
"ignoreSslErrors": true,
/* Same as: --max-disk-cache-size=1000 */
"maxDiskCacheSize": 1000,
/* Same as: --output-encoding=utf8 */
"outputEncoding": "utf8"
/* etc. */
}
My thought is I would like to upload a json object to the heroku ephemeral filesystem before running my phantomjs app. I'm hoping when it runs it will use the updated config file. Does this seem reasonable? Has anyone tried something like this?
I would set a variable through
heroku config:set NAME=VALUE
which is read at runtime, so you could change it whenever you need to.
You could also update config variables via their API: https://devcenter.heroku.com/articles/platform-api-reference#config-var, if you have the need to change them more often.

How to disable Kint in local environment under Laravel 4

I'm using Kint via Composer in Laravel 4 by loading kint first in composer.json so that dd() is defined by kint, not laravel (suggested here).
I want to leave debug calls in my app, and disable Kint if not in the local environment. I'm successfully using config overrides for Anvard using the following structure:
/app/config/local/packages/provider/package_name/overridefile.php
Unfortunately, this is not working for Kint with the following structure:
/app/config/packages/raveren/kint/local/config.php or
/app/config/packages/raveren/kint/local/config.default.php
The Kint documentation states:
You can optionally copy the included config.default.php and rename to config.php to override default values…
…which works for me (/vendor/raveren/kint/config.php)
How do I achieve this:
without editing a file in the /vendor/ directory that will get overwritten by composer
so that kint is only enabled in the local envirnoment
I've also tried adding the following to a helpers.php file which is called before composer in /bootstrap/autoload.php as suggested here:
<?php
isset( $GLOBALS['_kint_settings'] ) or $GLOBALS['_kint_settings'] = array();
$_kintSettings = &$GLOBALS['_kint_settings'];
/** #var bool if set to false, kint will become silent, same as Kint::enabled(false) or Kint::$enabled = false */
$_kintSettings['enabled'] = false;
unset( $_kintSettings );
(but no dice :)
Any suggestions? TIA!
I'm not familiar with kint but checked the documentation and found that, to disable kint output, you may use (in runtime)
// to disable all output
Kint::enabled(false);
In Laravel you can check the environment using
$env = App::environment();
if($env == 'your_predefined_environment') {
Kint::enabled(false);
}
To configure your environment, you may check the documentation.
Update : I've setup my local environment as givel below (in bootstrap/start.php)
$env = $app->detectEnvironment(array(
'local' => array('*.dev'),
));
And in my local machine, I've setup a virtual mashine which has laravel4.dev as it's base url, so if I visit the app using laravel4.dev or laravel4.dev/logon then I can check the environment in my BaseController.php and it detects the local environment because of .dev
public function __construct()
{
if(App::environment() == 'local') {
// do something
}
}
In your case, I don't know where is the first debug/trace you used to print the output, so you should keep the environment checking and disabling the Kint code before you use any debug/trace but you may try this (if it works for you) but you can check the environment in your filter/routes files too.
Hmm.. I'm not sure if this is the ideal way to do it, but this works, and seems Laravel'ish:
// top of app/start/global.php
Kint::enabled(false);
and
// app/start/local.php
Kint::enabled(true);
(assuming you've got a local environment defined: see #TheAlpha's answer for more info)
http://laravel.com/docs/lifecycle#start-files

Resources