Laravel base_path() gives error - Call to undefined method baseDir() - php

I have a tester class and I'm trying to use the global helper method base_path(), but I get the error below:
Error: Call to undefined method Illuminate\Container\Container::basePath()
/myproject/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:182
/myproject/tests/Feature/DataCsvSeedTest.php:31
/myproject/vendor/phpunit/phpunit/src/TextUI/Command.php:195
/myproject/vendor/phpunit/phpunit/src/TextUI/Command.php:148
Looks like helper.php in Laravel calls basePath(), and can't find it. Am I missing a namespace or some other setting for the global helper functions? Using Laravel 5.5.
<?php
namespace Tests\Feature;
use Tests\TestCase;
class DataCsvSeedTest extends TestCase
{
public function setUp()
{
$baseDir = base_path();
print "basedir = ". $baseDir;
}
}

Ah... This is a testClass,
class DataCsvSeedTest extends TestCase
{
public function setUp()
{
parent::setUp();
$baseDir = base_path();
print "basedir = ". $baseDir;
}
}
when you are overriding setUp() method don't forget to call the parent::Setup(), which will bootstrap the application.

Related

Method in trait not able to be called from controller

I'm trying to use a trait to handle image upload on my Laravel application, but none of the functions in my Trait can be called from the controller.
It throws a BadMethodCallException and says that the function couldn't be found.
I've tried using really simple functions to test if it is a problem with the trait or whether the function itself has an issue, but even a simple return function that only contains
return "sampletext";
has the same issue.
The path of the trait is under App/Traits/UploadTrait
and I've already checked the spelling on the use statement in my controller, which says use App\Traits\UploadTrait;
namespace App\Traits;
trait UploadTrait
{
public function test(){
return "testtext";
}
}
And the controller has
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use App\User;
use App\Profile;
use App\Traits\UploadTrait;
use Image;
class UserProfileController extends Controller
{
...
protection function updateProfile($args, Request $request){
...
return $this->test();
...
Of course I expect the function in my trait to be called, but this does not happen.
You need to use the trait inside your controller and move the $this->test() inside a class function:
<?php
use App\Traits\UploadTrait;
class UserProfileController extends Controller
{
use UploadTrait; // <-- Added this here
public function index()
{
return $this->test(); // <-- Moved this into a function
}
}
You have to put the use keyword to use that trait and its methods in the class
trait UploadTrait
{
public function test(){
return "testtext";
}
}
class Controller{
}
class UserProfileController extends Controller
{
use UploadTrait;
}
$ob = new UserProfileController();
echo $ob->test();
You can make a function to and call the trait function.
More Details
Use trait inside the class like:
use my/path/abcTrait;
Class My class{
use abcTrait;
}
Now, you can call trait functions with $this->functionName () in functions.

Use a Facade outside Laravel 5 (in CodeIgniter)

I am trying to get a Laravel package (maatwebsite/excel) to work on CodeIgniter.
The error I get is: Message: A facade root has not been set.
Is there a way to get Laravel facades to work under CodeIgniter?
I read this article: https://www.sitepoint.com/how-laravel-facades-work-and-how-to-use-them-elsewhere/ which suggests to me that I need to call
Illuminate\Support\Facade::setFacadeApplication($app);
But what should $app be?
My code so far is this:
// Report.php
class Rapportage extends MY_Controller {
public function __construct()
{
parent::__construct();
// This doesn't work, what should I put here?
Illumiante\Support\Facade::setFacadeApplication($app);
}
public function generate_rapport()
{
// This is where the error occurs
return Excel::download(new PersonExport, 'rapport.xlsx');
}
}
// Reports/Persons.php
namespace Exports;
use Person;
use Maatwebsite\Excel\Concerns\FromCollection;
class PersonExport implements FromCollection
{
public function collection()
{
return Person::all();
}
}

Config class not found when unit testing laravel package

I'm working on a Laravel (5.4) package, and I'm trying to do unit testing. I have this class :
<?php
namespace Sample;
class Foo
{
public function getConfig()
{
$config = \Config::get('test');
return $config;
}
}
I have this test :
<?php
use PHPUnit\Framework\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
When I execute phpunit I have this error :
Error: Class 'Config' not found
How can I unit test this class ?
Thank you.
Instead of extends PHPUnit\Framework\TestCase, you should extends Tests\TestCase:
<?php
namespace Tests\Unit;
// use PHPUnit\Framework\TestCase;
use Tests\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
Moreover, Config or other Laravel facades may not work in #dataProvider method, please see Laravel framework classes not available in PHPUnit data provider for more info.
It is good practice to mock the dependencies in your code. In this case you are depending on an outside class (Config). Usually I test it like this:
// make sure the mock config facade receives the request and returns something
Config::shouldReceive('get')->with('test')->once()->andReturn('bla');
// check if the value is returned by your getConfig().
$this->assertEquals('bla', $config);
Obviously, you need to import the Config facade in your test.
BUT: I would inject the Config class in the constructor in my real code, instead of using the facade. But that's me... :-)
Something like this
class Foo
{
/** container for injection */
private $config;
public function __construct(Config config) {
$this->config = $config;
}
public function getConfig()
{
$config = $this->config->get('test');
return $config;
}
}
And then test it by injecting a mock Config into the constructor.
Try by including like this
use Illuminate\Support\Facades\Config;

Issue with Facade and injected dependency in Laravel 4

I am having an issue getting a Facade to work properly with a dependency injected into the underlying class.
I have a class called 'Listing'. It has one dependency called 'AdvertRepository' which is an interface and a class called EloquentAdvert which implements the interface. The code for these three classes is here:
// PlaneSaleing\Providers\Listing.php
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
class Listing {
protected $advert;
public function __construct (AdvertRepository $advert_repository) {
$this->advert = $advert_repository;
}
public function test() {
$this->advert->test();
}
public function test2() {
echo "this has worked";
}
}
// PlaneSaleing\Repositories\Advert\AdvertRepository.php
<?php namespace PlaneSaleing\Repositories\Advert;
interface AdvertRepository {
public function test();
}
// PlaneSaleing\Repositories\Advert\EloquentAdvert.php;
<?php namespace PlaneSaleing\Repositories\Advert;
class EloquentAdvert implements AdvertRepository {
public function test() {
echo 'this has worked';
}
}
I have then created a service provider called ListingServiceProvider.php, which has the following code:
// PlaneSaleing/Providers/ListingServiceProvider.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
}
}
I also added this to the ServiceProviders array in app.php
Now, if I inject Listing as a dependency into a controller and call the test method (as shown below) Laravel correctly detects the dependency, instantiates EloquentAdvert via its binding and displays 'this has worked'.
// Controllers/TestController.php
use PlaneSaleing\Providers\Listing;
class TestController extends BaseController {
protected $listing;
public function __construct(Listing $listing) {
$this->listing = $listing;
}
public function test1() {
$this->listing->test();
}
}
Now, I then created a facade for Listing. I added a new facade as follows and added an alias in app.php:
// PlaneSaleing\Providers\ListingFacade.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\Facades\Facade;
class ListingFacade extends Facade {
protected static function getFacadeAccessor() {
return 'Listing';
}
}
I also added the following new lines to ListingServiceProvider.php:
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
use PlaneSaleing\Repositories\Advert\EloquentAdvert;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
// New lines...
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
}
}
NOW...if I call Listing::test(), I get the following error: Cannot instantiate interface PlaneSaleing\Repositories\Advert\AdvertRepository.
If I call Listing::test2() , I get 'this has worked' so it seems the Facade is working correctly.
It seems that when accessing Listing via its Facade the binding between AdvertRepository and EloquentAdvert doesnt work. I have looked at my code in the ServiceProvider thinking it was the issue, but I cant figure it out.
Both the Facade and binding work when tested individually but not when both are used at the same time.
Any ideas???
OK, So I have figured it out...For those who run into a similar problem...
The offending statement was in ListingServiceProvider.php which read:
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
The error is the new AdvertRepository statement. The reason being is that, we are telling php to directly instantiate the interface 'AdvertRepository'. Instead, we need to tell Laravel to instantiate the appropriate implementation of the 'AdvertRepository' interface. To do that, we use App::make('AdvertRepository'). That way, Laravel uses the binding previously declared to instantiate the correct implementation.
If your constructor is not being inject with a class, you must tell Laravel what class will be used when it needs to instantiate a particular interface:
Put this in your filters or bindings file:
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', function()
{
return new PlaneSaleing\Repositories\Advert\EloquentAdvert;
});

Target Class is not instantiable

I'm building a small REST API with Laravel 4. I'm using an HMVC scheme in the application. The issue is, when I try to call a controller for the API, PHP says that the class is not instantiable.
Target [App\Modules\ChunkletAPI\v1\ServerController] is not instantiable.
Here's the class itself, in v1/controllers:
<?php namespace App\Modules\ChunkletAPI\v1;
class ServerController extends ChunkletAPI {}
Which inherits from
<?php namespace App\Modules\ChunkletAPI\v1;
use Controller;
abstract class ChunkletAPI extends Controller {
protected $name;
protected function __construct() {
$this->name = '\Model\ ' . str_replace('Controller', '', get_class($this));
}
public function index() {
$n = $this->name;
return $n::all();
}
}
The routing is done by:
<?php namespace App\Modules\ChunkletAPI;
use \Illuminate\Support\Facades\Route;
Route::group(array('prefix' => 'api/v1'), function()
{
Route::resource('server', 'App\Modules\ChunkletAPI\v1\ServerController');
});
I cannot figure out what is occurring - I've tried playing around, making the parent class non-abstract, etc - and Google is no help. Any ideas?
Found out why. ChunkletAPI->__construct() had to be set as public, not protected. Otherwise, it looked to Laravel like a static class.

Categories