The Mix manifest does not exist when using orchestral/testbench - php

Creating a custom Laravel package using the orchestral/testbench package that helps package developer to help with PHPUnit test. So, my package on a different place and not in a Laravel installation exactly. Everything works great except the mix() function that I'm using on the blade view for resources.
<script src="{{ asset(mix('js/app.js', 'vendor/trade')) }}"></script>
And, I have the following test route set in the web.php:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function() {
return view('trade::_layouts.app');
});
In addition, I have the following feature test in the ExampleTest.php file:
public function testBasicTest()
{
$response = $this->get('/');
$response->assertStatus(200);
}
When I am running phpunit I am seeing the following error:
Expected status code 200 but received 500.
Failed asserting that false is true.
After dumping the $response in the test, I see the The Mix manifest does not exist. error. After digging for an hour I found that mix() helper function is looking for the mix-manifest.json in the orchestral/testbench package located under the vendor instead of the public folder in my package.
I tried to the following in the package ServiceProvider.php but didn't work either:
$this->app->bind('path.public', function() {
return base_path().'/../public';
});
In addition, I see the laravel/horizon package also using the mix() helper function on the layout.blade.php file as I am doing right now and it is also using the orchestral/testbench package for the test. So, how horizon package is doing the test while I can't? What is the to override mix() helper to ensure the public path is on my package public path instead of the orchestral/testbench path?

There are two ways to override the public_path() returned path to ensure the mix() function can find the mix-manifest.json file.
One would be to override the public_path() method completely to the custom package. Laravel usage if (!function_exists()) {} before declaring any function which is good as we can define our own public_path() function in our package. However, we'll need to make sure that our override function loads before the Laravel helper method and that's another topic.
The easiest way would be to change the path.public from Laravel IoC Container from the particular PHPUnit test where we're having the issue.
public function testBasicTest()
{
$this->app->instance('path.public', $packagePublicDir);
$response = $this->get('/');
$response->assertStatus(200);
}

I think you missed to run npm install && npm run dev

Related

PostHog namespace issue

I installed PostHog in my PHP codebase, and trying to use it by following the tutorial in this link (https://posthog.com/docs/integrate/server/php).
I am attempting to call PostHog::init function as a following:
PostHog::init($apikey,
array('host' => $baseUrl,
"debug" => true)
);
But I am getting error in this line PostHog::init, the error says
"Attempted to load class PostHog" from the global namespace. Did you forget a "use" statement?"
In fact, I am already using the "use" as following "use PostHog\PostHog;", but I am still getting this error. I can confrim that the Posthog library is intall becuase I can read the classess in Poshog library from my codebase.
This is more info about my app:
I use Symfony framework 5 and the app is deployed in docker. I use PHP 7.4 and posthog/posthog-php": "2.1.1".
I checked the vendor folder and PostHog is there (see photo attached)
I implemented service call PosthogHandler where I use PostHog functions (like init, capture and etc). I am calling functions' services from controller. But the issue is that the error appear in the PosthogHandler constructor in line PostHog::init, at PostHog initialisation stage. This is my PosthogHandler service class:
<?php
declare(strict_types=1);
namespace App\Posthogs;
use PostHog\PostHog;
use App\User\User;
class PosthogHandler
{
public function __construct($env, string $key, string $baseUrl)
{
PostHog::init($key,
array('host' => $baseUrl,
"debug" => true)
);
}
public function addEvent(string $eventName, User $user){
PostHog::capture(array(
'distinctId' => $user->getId()->id(),
'event' => $eventName
));
}
}
Any help, why I am getting above error?
The error indicates that your class file could not be autoloaded properly. You might want to check first that PostHog is present in vendor/autoload.php by creating a test file to check
<?php
require_once 'vendor/autoload.php';
var_dump(class_exists('Posthog\Posthog'));
If not you should try this command
composer dump-autoload
It works!
I have three vendor folders in (1) Frontend (1) Controller (3) Services.
Before, I only installed the PostHog library in services folder where I use PostHog functions. This didn't seem working despite the posthog lib appeared in vendor folder.
What it makes work and the error disappears when I installed the posthog lib in controller folder. I don't use posthog in controller at all, I am not sure why I need to install the posthog lib in controller folder in order to work. But eventually it works!

Laravel Dusk - Class config does not exist

recently upgraded a 5.3 project to 5.4 and all seemed good.
Today I started to implement Dusk however had hit an issue when running the example test
☁ footy-finance [5.4] ⚡ php artisan dusk
PHPUnit 6.0.0 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 162 ms, Memory: 6.00MB
There was 1 error:
1) Tests\Browser\ExampleTest::testBasicExample
ReflectionException: Class config does not exist
/Users/owen/Sites/footy-finance/vendor/laravel/framework/src/Illuminate/Container/Container.php:681
/Users/owen/Sites/footy-finance/vendor/laravel/framework/src/Illuminate/Container/Container.php:565
/Users/owen/Sites/footy-finance/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:105
/Users/owen/Sites/footy-finance/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:263
/Users/owen/Sites/footy-finance/vendor/laravel/dusk/src/TestCase.php:203
/Users/owen/Sites/footy-finance/vendor/laravel/dusk/src/TestCase.php:40
I've had a look at line 40 of TestCase.php and its
public function baseUrl()
{
return config('app.url');
}
So it does look like something to do with the global config helper anybody have any ideas?
I'm running
PHP 7.0.14
Laravel/Framework 5.4.8
Laravel/Dusk 1.0.5
The full composer.lock can be seen https://gist.github.com/OwenMelbz/c05172b33f6eb4483e37a56469b53722
Fingers crossed you guys have some ideas!
Cheers :)
I had this error in the log
Class config does not exist
the problem with me was that in the .env file I had set a configuration variable in the following way:
APP_NAME=Application Name
note the space. When I changed it to this:
APP_NAME="Application Name"
the problem got fixed
The issue is with .env file
App_Name
in the original file its written this way>>> APP_NAME=Application Name
Make it like this APP_NAME="Application Name"
In my case, this solution works:
1) Remove all contents of the bootstrap/cache folder
2) Run the composer dump command
For anybody else who has had this issue.
I had prefer stable set in the composer file, which installed PHPUnit 6.
This was "made stable today" - thus it installed during a composer update.
Downgrading to PHPUnit 5 fixes the issue - so was bad timing starting it today.
I just ran into the the same issue, in my case the .env was all clean, no unwrapped empty spaces.
This error message can also occur when writting/debugging a test case, using the setup() method in that test, forgetting to call parent::setup() as the first statement in that function.
protected $stuf;
function setup() {
parent::setup();
$this->stuf = 'stuf';
}
I found very useful info here on what else could happen when you're getting this error message.
I've also had this issue. For me it was caused by calling the config() function inside a dataProvider method. DataProviders are called before the createApplication() method initialises the application, and populates the DI container. Hence config() fails because the app('config') call in the helper function can't resolve the config class from the container.
I'm very late for the party here but for anyone experiencing the same issue with Laravel's unit test and none of the above solutions work, you can look into mine and see if this might help.
In my case, I was trying to call a method that will remove all the test keys that persisted in my Redis database when I run the unit test. The method is called in the tearDown method of the class. The error occurs because the parent constructor is called before the actual tearDown code is executed. That's the reason why I'm having the error.
Instead of this one......
/**
* tearDown is executed after test stub
*/
protected function tearDown()
{
parent::tearDown();
$this->deleteTestKeys();
}
Change it to this one...
protected function tearDown()
{
$this->deleteTestKeys();
parent::tearDown();
}
In this case, the class' is not totally destroyed yet and the Laravel's config method will get called accordingly.
I had this in a Lumen application today. After some investigation and playing around, I found that it was because in PHPStorm it was adding the --no-configuration option onto the phpunit command because I hadn't configured my PHPUnit setup for the project in the IDE.
I corrected that by clicking 'Run > Edit Configurations' and then under 'Defaults > PHPUnit' click the little button to the far right of the 'Use alternative configuration file:' option and set the 'Default configuration file:' to the full path to your project's phpunit.xml.
Hope this helps!
I saw this error after following some dodgy installation instructions for a third party module, which said to register a service provider in bootstrap/app.php
$app->singleton(...);
$app->singleton(...);
$app->register(\Third\Party\ServiceProvider::class);
This caused $this->app['config'] to generate the error BindingResolutionException: Target class [config] does not exist.
I fixed it by putting it in config/app.php, where it belongs:
/*
* Package Service Providers...
*/
Third\Party\ServiceProvider::class,

laravel 5.1 access package config values

I'm starting a package on laravel 5.1. Up till now using laravel 4.2
I've been able to publish the package config file using the following in the boot method of the service provider for my package as described in the documents:
public function boot()
{
$this->publishes([
__DIR__ . '/config/config.php' => config_path('/packages/longestdrive/googlecal/googlecal.php'),
]);
Now I'm trying to access the items in this config using:
config('googlecal.client_id');
This however returns null
If I simply do: config() I get a full array of the config arrays and can see my package config file there.
If I then do: config('longestdrive.googlecal.googlecal.client_id') I can access the variable.
In L4.2 I did not need to add effectively the full path to the variable.
Have I missed something to enable me to simply do: config('googlecal.client_id')
Thanks
You have to merge your config file in ServiceProvider
/**
* Register the service provider.
*/
public function register()
{
$this->app->bind('laravel-db-localization', function ($app) {
return new LaravelDbLocalization();
});
// Load the config file
$this->mergeConfigFrom(__DIR__.'/config/laravel-db-localization.php', 'laravel-db-localization');
}
May be you should run "php artisan config:cache", it works for me:)

Creating a new ServiceProvider / Facade as a package in Laravel 5

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

PHPUnit 3.7 can't find Controller Classes in Laravel 4.1

Setup 1: Echoing back from the route works in PHPUnit
routes.php
Route::get('signup', function(){
return "Hello World!";
});
/tests/SignupTest.php
class SignupTest extends TestCase {
public function testIndex(){
$this->call('GET', 'signup');
$this->assertResponseOK();
}
}
Running PHPUnit returns the following:
OK (1 test, 1 assertion)
Setup 2: But PHPUnit can't find the Signup Controller when I route to it
routes.php
Route::get('signup', array('uses' => 'Signup#process'));
/app/controllers/Signup.php
class Signup extends BaseController {
public function process(){
echo "Hello World!";
}
}
/tests/SignupTest.php
class SignupTest extends TestCase {
public function testIndex(){
$this->call('GET', 'signup');
$this->assertResponseOK();
}
}
PHPUnit returns the following:
There was 1 error:
1) SignupTest::testIndex
ReflectionException: Class Signup does not exist
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:476
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:416
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:423
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:77
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:50
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php:900
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/Route.php:118
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php:964
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php:934
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:677
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:652
/Applications/MAMP/htdocs/laravel/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Client.php:82
/Applications/MAMP/htdocs/laravel/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php:319
/Applications/MAMP/htdocs/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:74
/Applications/MAMP/htdocs/laravel/app/tests/SignupTest.php:12
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
Setup information:
Laravel 4.1
PHPUnit 3.7.28
Both installed by Composer
MAMP running PHP 5.4.4 on Mac OS X 10.8
I don't think I've changed anything in the core/config files of Laravel or PHPUnit.
Things I've tried:
I found a few answers about this type of issue (both on SO and other sites), where the answers suggested fixing mistakes in names of class/file/method, e.g.:
Laravel Controller not working
I don't think this is an issue here, because I've checked all the names. Also it returns "Hello World!" as expected for both the above routes when tested in a browser, suggesting that the route is working fine in Laravel. Problem seems to be with PHPUnit.
My Question: Why can't PHPUnit find the Signup Class in app/controllers?
I'd assumed that because there was a phpunit.xml file in the basic Laravel install, that PHPUnit would know about it. That assumption turned out to be incorrect.
The Problem
PHPUnit wasn't loading phpunit.xml, which meant the bootstrap file in bootstrap/autoload.php wasn't being loaded, so PHPUnit had no idea where any of the class files were, including Signup.php.
The Solution
I added the file path to phpunit.xml in the --configuration switch when I ran PHPUnit:
--configuration /Applications/MAMP/htdocs/laravel/phpunit.xml
General Advice
If PHPUnit tells you it can't find a class, check that it's loading phpunit.xml and/or your bootstrap file. Make sure your phpunit.xml file points correctly to your bootstrap file and that your bootstrap file is configured correctly to load the required classes.
Also, as pointed out in my question, problems can also be caused by inconsistencies between class/file/method names.

Categories