In my laravel app, I want to schedule some tasks using the scheduler. In order not to duplicate code, I want to re-use functionality already in some of my Modules. I specifically made one CronModule, that uses some of the other modules for it's job.
In my app/Console/Kernel.php I have this for the schedule function:
protected function schedule(Schedule $schedule)
{
$cronmodule = $this->app->make('App\Dashboard\Modules\CronModule');
$schedule->call(function () {
echo "======yes";
})->everyMinute();
}
The problem that I run into, is that some of my other modules make use of the Illuminate\Support\Facades\Auth Facade, which is aliased in config\app.php to "Auth". I don't actually need the Auth facade to work for any of the functions called by my CronModule. Of course that wouldn't make sense in the scope of CronJobs. But I think the modules for some reason can't find that Facade already when importing it, and so running php artisan schedule:run errors out with
[ErrorException]
Use of undefined constant Auth - assumed 'Auth' (this will throw an Error in a future version of PHP)
Related
I'm developing some packages for Laravel (for internal use).
It is logical for a package, to have its own seeders.
For example, let's suppose we are creating a package called Company\Geo that has the data of countries and continents and flags, etc.
It's a good UX that this package should have 100% self-contained seeder classes to populate the database tables with the data.
However, I'm stuck at running seeders from packages. This is my package directory strcuture:
- host => (a laravel app to test the package)
- WebSite
- packages
- Company
- FirstPackage
- database
- migrations
- seeders
- FirstSeeder.php
- src
- Models
- Http
- Controllers
And here is my FirstSeeder.php code:
<?php
namespace Company\FirstPackage\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\App;
class FirstSeeder extends Seeder
{
public function run()
{
// code to seed
}
}
And here is my composer.json of the Company\FirstPackage package:
"autoload": {
"classmap": [
"/database/migrations"
],
"psr-4": {
"Company\\FirstPackage\\": "src/",
"Company\\FirstPackage\\Database\\": "database/"
}
},
Yet when I run php artisan db:seed --class=FirstSeeder I get this error:
Target class [Database\Seeders\FirstSeeder] does not exist.
How can I call seeders of my package, without publishing them to the host package?
I have just read the source code. I believe you got to do this:
// Pls use double backward slashes.
php artisan db:seed --class=php artisan db:seed --class=Company\\Package\\Database\\Seeder\\FirstSeeder
You might want to take a look at the Illuminate\Database\Console\Seeds\SeedCommand::getSeeder() method.
You can use the same logic that is used in ServiceProvider. This way you can simply run: php artisan db:seed and it should run any seeders you have in your packages.
protected function loadSeeders($seed_list){
$this->callAfterResolving(DatabaseSeeder::class, function ($seeder) use ($seed_list) {
foreach ((array) $seed_list as $path) {
$seeder->call($seed_list);
// here goes the code that will print out in console that the migration was succesful
}
});
}
then you can create a list using a function that gets every class name you are using in your package. And put it inside, like this
$seed_list[] = 'Vendor/Name/Directory/ClassName'
// inside your service provider
boot()
{
$this->loadSeeders($seed_list)
}
this is just a copy past please see
https://laracasts.com/discuss/channels/laravel/best-way-to-load-seeds-and-routes-from-a-package
First of all, sorry for my english, im not a native talker. I'm learning Laravel, and I got stuck in a little problem. I cant execute a very simple cron job in a Hosting with Cpanel. I have this code in Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
\Log::info('This is a log');
})->everyMinute();
}
I had enabled the Cron job in Cpanel, every one minute (* * * * *), and evidently something is executing, because every minute i have this error registered in the log (obviusly not my text):
[2020-04-19 18:47:26] local.ERROR: Declaration of Carbon\Translator::setLocale($locale) must be compatible
with Symfony\Contracts\Translation\LocaleAwareInterface::setLocale(string $locale)
{"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0):
Declaration of Carbon\\Translator::setLocale($locale) must be compatible with
Symfony\\Contracts\\Translation\\LocaleAwareInterface::setLocale(string $locale)
at /home/grupodem/bad-conf/vendor/nesbot/carbon/src/Carbon/Translator.php:18)
[stacktrace]
#0 {main}
"}
The goal of this simple exercise that I wanted to do, was just try Cron Jobs in Cpanel. In fact, the code it's very simple, but it doesn't work anyway.
The PHP version of the server is 7.3.16 and the project is Laravel 7.
Thank you very much in advance! Best regards!
Lucas
It's not an issue with the cronjob. It's an issue with laravel.
Method 1:
Add "symfony/translation": "4.3.8" in your composer.json & run composer update
Method 2:
Run composer require symfony/translation:4.3
Then run composer update
This should fix the issue you are facing
I want to do performant testing, so I thought about using PHPUnit_Framework_TestCase instead of TestCase in my test files. I'm sacrificing http requests testing, but I want at least to use some of the components of Laravel (like its providers and such).
Here's what it looks like :
<?php
class ChatTest extends PHPUnit_Framework_TestCase
{
/** #test */
public function chat_can_be_accepted()
{
$this->chat->setStatus(Chat::CHAT_STATUS_WAIT_MASTER);
$this->chat->accept();
$this->assertEquals(Chat::CHAT_STATUS_WAIT_CONFIRM, $this->chat->getStatus());
}
}
I have an error saying Call to a member function connection() on null. setStatus actually uses Laravel internals in this example (something as simple as a relationship that needs the app).
I already tried switching every providers, but it seems code is not even going through providers. Also tried changing PHP versions, or extensions.
I'm answering my own question for future reminders, and also because I never found this answer anywhere else.
At this point I was using PHPStorm and it doesn't auto load the phpunit.xml file when launching tests by default.
That line in the file launches Laravel (works with Lumen too) along with the tests : bootstrap="bootstrap/app.php".
This is needed to use Laravel internals even without using their test frameworks.
To use this in PHPStorm :
To use this in CLI :
phpunit --configuration phpunit.xml
For implement of a Nested Set for my news category I want to use Baum package.
After installing this Package via Composer and add BaumServiceProvider to config/app.php providers, I try to install a new Model named Category via Below command:
php artisan baum:install MODEL
But I faced to the following error :
[InvalidArgumentException]
There are no commands defined in the "baum" namespace.
Of course I ran php artisan command and But there were no command named Baum on generated commands list.
What should I do?
First you have to add the code below in config/app.php:
Baum\Providers\BaumServiceProvider::class
If the problem still persists configuration files may be cached. Just call:
php artisan config:clear
Make sure that you added
Baum\Providers\BaumServiceProvider::class
To the providers array in the app.php file located in config/app.php
Whenever I know that I have added something into Laravel's core files, and it's not working from the command line, I typically just run
php artisan optimize
to regenerate all of the classes, and it will typically work. Running this command is something that I find myself doing fairly often.
In AppServiceProvider.php (app\Providers) you can modify register function: public function register()
{
$this->app->register(\Baum\Providers\BaumServiceProvider::class);
}
Not sure why 5.2 have error, just tweak a bit myself.
Try add this on APP/Console/kernel.php
protected $commands = [
//Commands\Inspire::class,
// Register Baum nestedset command
Commands\BaumCommand::class,
Commands\InstallCommand::class
];
and create two files and copy BaumCommand.php and InstallCommand in /vendor/baum/baum/src/Baum/console.
then change a namespace at the top.
namespace Baum\Commands;
to
namespace App\Console\Commands;
Introduction
I've never worked with a framework before (Zend, CakePHP, etc) and finally decided to sit down and learn one. I'm starting with Laravel because the code looks pretty and unlike some other frameworks I tried to install, the "Hello, World!" example worked on the first try.
The Goal
For the time being, I want my app to do something very simple:
User submits a request in the form of: GET /dist/lat,lng
The app uses the remote IP address and MaxMind to determine $latitude1 and $longitude1
This request path is parsed for $latitude2 and $longitude2
Using these two positions, we calculate the distance between them. To do this I'm using Rafael Fragoso's WorldDistance PHP class
Since I plan to re-use this function in later projects, it didn't seem right to throw all of the code into the /app directory. The two reusable parts of the application were:
A service provider that connects to MaxMind and returns a latitude and longitude
A service provider that takes two points on a globe and returns the distance
If I build facades correctly then instead of my routes.php file being a mess of closures within closures, I can simply write:
Route::get('dist/{input}', function($input){
$input = explode( "," , $input );
return Distance::getDistance( GeoIP::getLocation(), $input );
});
What I've tried
Initial Attempt
For the first service provider, I found Daniel Stainback's Laravel 5 GeoIP service provider. It didn't install as easily as it should have (I had to manually copy geoip.php to the /config directory, update /config/app.php by hand, and run composer update and php artisan optimize) however it worked: A request to GET /test returned all of my information.
For the second service provider, I started by trying to mimic the directory structure and file naming convention of the GeoIP service provider. I figured that if I had the same naming convention, the autoloader would be able to locate my class. So I created /vendor/stevendesu/worlddistance/src/Stevendesu/WorldDistance\WorldDistanceServiceProvider.php:
<?php namespace Stevendesu\WorldDistance;
use Illuminate\Support\ServiceProvider;
class WorldDistanceServiceProvider extends ServiceProvider {
protected $defer = false;
public function register()
{
// Register providers.
$this->app['distance'] = $this->app->share(function($app)
{
return new WorldDistance();
});
}
public function provides()
{
return ['distance'];
}
}
I then added this to my /config/app.php:
'Stevendesu\WorldDistance\WorldDistanceServiceProvider',
This fails with a fatal error:
FatalErrorException in ProviderRepository.php line 150:
Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
Using WorkBench
Since this utterly failed I figured that there must be some other file dependency: maybe without composer.json or without a README it gives up. I don't know. So I started to look into package creation. Several Google searches for "create package laravel 5" proved fruitless. Either:
They were using Laravel 4.2, in which case the advice was "run php artisan workbench vendor/package --resources"
Or
They were using Laravel 5, in which case the docs were completely useless
The official Laravel 5 docs give you plenty of sample code, saying things like:
All you need to do is tell Laravel where the views for a given namespace are located. For example, if your package is named "courier", you might add the following to your service provider's boot method:
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}
This makes the assumption that you have a service provider to put a boot method in
Nothing in the docs says how to create a service provider in such a way that it will actually be loaded by Laravel.
I also found several different resources all of which assume you have a repository and you just want to include it in your app, or assume you have "workbench". Nothing about creating a new package entirely from scratch.
PHP Artisan did not even have a "workbench" command, and there was no "workbench.php" file in /config, so anything I found related to workbench was worthless. I started doing some research on Workbench and found several different questions on StackOverflow.
After a long time and some experimentation, I managed to get laravel/workbench into my composer.json, composer update, composer install, manually build a workbench.php config file, and finally use the PHP Artisan Workbench command to make a new package:
php artisan workbench Stevendesu/WorldDistance --resources
This created a directory: /workbench/stevendesu/world-distance with a number of sub-directories and only one file: /workbench/stevendesu/world-distance/src/Stevendesu/WorldDistance/WorldDistanceServiceProvider.php
This service provider class looked essentially identical to the file I created before, except that it was in the /workbench directory instead of the /vendor directory. I tried reloading the page and I still got the fatal error:
FatalErrorException in ProviderRepository.php line 150:
Class 'Stevendesu\WorldDistance\WorldDistanceServiceProvider' not found
I also tried php artisan vendor:publish. I don't really know what this command does and the description wasn't helpful, so maybe it would help? It didn't.
Question
How do I create a new service provider as a package so that in future projects I can simply include this package and have all the same functionality? Or rather, what did I do wrong so that the package I created isn't working?
After two days of playing with this I managed to find the solution. I had assumed that the directory structure mapped directly to the autoloader's path that it checked (e.g. attempting to access a class Stevendesu\WorldDistance\WorldDistanceServiceProvider would look in vendor/stevendesu/world-distance/WorldDistanceServiceProvider)... This isn't the case.
Reading through the composer source code to see how it actually loads the files, it builds a "classmap" - essentially a gigantic array mapping classes to their respective files. This file is built when you run composer update or composer install - and it will only be built correctly if composer knows the details of your package. That is - if your package is included in your project's composer.json file
I created a local git repository outside of my app then added my package to my app's composer.json file then ran composer update -- suddenly everything worked perfectly.
As for the:
It didn't install as easily as it should have
the secret sauce here was first add the service provider to /config/app.php then, second run php artisan vendor:publish