Class not found when using custom class - laravel-5.3

I am using excel reader from https://github.com/nuovo/spreadsheet-reader and it is in app folder.
Now when I try to access it from HomeController.php using following code.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\spreadsheet_reader\php_excel_reader\excel_reader2;
use App\spreadsheet_reader\SpreadsheetReader;
class HomeController extends Controller
{
public function index()
{
require_once(base_path().'/app/spreadsheet_reader/php_excel_reader/excel_reader2.php');
$Reader = new \App\spreadsheet_reader\SpreadsheetReader(base_path().'/UnRegisterClient.xlsx');
}
}
Then it gives me following error.
Class 'App\spreadsheet_reader\SpreadsheetReader' not found
Any suggesstion how I can solve this? I mean how I can use my custom class?

Put your external files in the folder app/Libraries (first, create the Libraries folder) then just autoload the folder with that file.
For example, add this folder in the array or “classmap” in composer.json :
"autoload": {
"classmap": [
"database",
"app\Libraries"
],
"psr-4": {
"App\\": "app/"
}
},
Then run composer dump-autoload in your command line.

I think the SpreadsheetReader is not defined in the namespace. You should call just new \SpreadsheetReader(...) or add use SpreadsheetReader and then call it new SpreadsheetReader()

Related

symfony 4 : How to get "/public" from RootDir

I have an image under the public folder.
How can I get my image directory in symfony4 ?
In symfony 3, it's equivalent is :
$webPath = $this->get('kernel')->getRootDir() . '/../web/';
It is a bad practice to inject the whole container, just to access parameters, if you are not in a controller. Just auto wire the ParameterBagInterface like this,
protected $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}
and then access your parameter like this (in this case the project directory),
$this->parameterBag->get('kernel.project_dir');
Hope someone will find this helpful.
Cheers.
You can use either
$webPath = $this->get('kernel')->getProjectDir() . '/public/';
Or the parameter %kernel.project_dir%
$container->getParameter('kernel.project_dir') . '/public/';
In Controller (also with inheriting AbstractController):
$projectDir = $this->getParameter('kernel.project_dir');
In config/services.yaml:
parameters:
webDir: '%env(DOCUMENT_ROOT)%'
In your controller:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
...
public function yourFunction(Parameterbag $parameterBag)
{
$webPath = $parameterBag->get('webDir')
}
If you need to access a directory within public, change the last line to the following:
$webPath = $parameterBag->get('webDir') . '/your/path/from/the/public/dir/'
You can inject KernelInterface to the service or whatever and then get the project directory with $kernel->getProjectDir():
<?php
namespace App\Service;
use Symfony\Component\HttpKernel\KernelInterface;
class Foo
{
protected $projectDir;
public function __construct(KernelInterface $kernel)
{
$this->projectDir = $kernel->getProjectDir();
}
public function showProjectDir()
{
echo "This is the project directory: " . $this->projectDir;
}
}
Starting from Symfony 4.3 we can generate absolute (and relative) URLs for a given path by using the two methods getAbsoluteUrl() and getRelativePath() of the new Symfony\Component\HttpFoundation\UrlHelper class.
New in Symfony 4.3: URL Helper
public function someControllerAction(UrlHelper $urlHelper)
{
// ...
return [
'avatar' => $urlHelper->getAbsoluteUrl($user->avatar()->path()),
// ...
];
}
All above answers seems valid, but I think it's simplier if you configure it as parameter in services.yaml
If you need to use it in serveral services, you can bind it like this:
# services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
bind:
$publicDir: "%kernel.project_dir%/public"
# src/Services/MyService.php
class MyService
{
public function __construct(
private string $publicDir,
) {
}
// …
}
This way, this is configured at one place only, and if later you decide to change /public to something else, you will have to change it only in .yaml file.
If you don't need the root directory but a subdirectory, it might be better to define the final target path: This way you will be more flexible if you need later to move only that directory, like $imageDir or $imagePath (depends if you will use the full directory or only the public path).
Note also the default public path is defined in composer.json file, in the extra.public-dir key

repository pattern on asp core

we are trying to develop a asp core application (MVC) using ef code first . however it seems that requires the db context to be in an executable and not class library .
so the data context was added in the web UI project but the issue that how can the db context's dbset be made available in the repository project ..
example code is as under:
public class CompanyRepository : GenericRepository<Company>, /*IGenericRepository<Company>*/ ICompanyRepository
{
public CompanyRepository(DbContext dbContext) : base(dbContext)
{
}
public async Task<IEnumerable<Company>> GetAllAsync()
{
return await base.GetAllAsync<Company>();
}
}
MVC Project StartUp .cs
services.AddDbContext<DBContext>();
services.AddScoped<ICompanyRepository, CompanyRepository>();
DBCOntext.cs in MVC Project
public class DBContext : DbContext
{
private IConfigurationRoot _config;
public DBContext(IConfigurationRoot config, DbContextOptions options):base(options)
{
_config = config;
}
}
currently it seems to raise following error:
An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve
service for type 'Microsoft.EntityFrameworkCore.DbContext' while
attempting to activate
'On.Store.Repository.Companies.CompanyRepository'.
We have two problems here:
1) When you configure services in a Startup class, you are configuring your custom context (for easier reference, let's name it CustomDbContext):
public class CustomDbContext: DbContext
{
... and in the Startup class:
services.AddDbContext<CustomDbContext>();
... so in your repository, you need to inject a context of declared class, instead of base DbContext class:
// THIS WILL NOT WORK
public class CompanyRepository : GenericRepository<Company>, ICompanyRepository
{
public CompanyRepository(DbContext dbContext) : base(dbContext)
{
}
}
// THIS WILL WORK
public class CompanyRepository : GenericRepository<Company>, ICompanyRepository
{
public CompanyRepository(CustomDbContext dbContext) : base(dbContext)
{
}
}
2) Problem number two is revealed directly from the first problem. So you have CustomDbContext declared in a MVC project, so cannot be used in a referenced repository project. So the solution seems to be easy, you need to move the CustomDbContext out of the MVC project (either to repository project or any other/third project which could be referenced by both MVC and repository). In such way you will easy configure your CustomDbContext in a Startup class, as well as use this context in repositories.
3) As it comes to registering context from external library you can do it easily with MigrationsAssembly method, it will look like this:
services.AddDbContext<CustomDbContext>(options => options.UseSqlServer(
_configuration.GetConnectionString("YourConnectionStringName"),
b => b.MigrationsAssembly("YourExternalAssemblyName")));
This is an very simples project that can help you and other developers.
Generic Repository Pattern in ASP.NET Core
This is addressing your orginal issue of being unable to use migration command line tools and allow you to keep proper separation of layers.
This is a know issue (tracked here) and there are two workarounds as of now, directly taken from the EntityFramework Core documentation:
Workaround 1 - Utilize a separate startup project
Convert the class library project into an “app” project. This can either be a .NET Core app or a desktop .NET app.
Example:
{
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
}
}
}
}
}
Be sure to register the EntityFramework Tools as a project dependency and in the tools section of your project.json.
Example:
{
"dependencies": {
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
}
}
Finally, specify a startup project that is a “runnable app.”
Example:
dotnet ef --startup-project ../MyConsoleApplication/ migrations list
Workaround 2 - Modify your class library to be a startup application
Convert the class library project into an “app” project. This can either be a .NET Core app or a desktop .NET app.
To make the project a .NET Core App, add the “netcoreapp1.0” framework to project.json along with the other settings in the sample below:
{
"buildOptions": {
"emitEntryPoint": true
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
}
}
}
}
}
To make a desktop .NET app, ensure you project targets “net451” or newer (example “net461” also works) and ensure the build option "emitEntryPoint" is set to true.
{
"buildOptions": {
"emitEntryPoint": true
},
"frameworks": {
"net451": { }
}
}

Error Trying include PrestaShopWebService in Controller

I am trying include web service library for prestashop in a controller, but when i try include this class, i get the next error:
Attempted to load class "PrestaShopWebService2" from namespace "AppBundle\Services".
Did you forget a "use" statement for another namespace?
Prestashop v1.5.6
PrestaShopWebService2:
namespace AppBundle\Services;
class PrestaShopWebService2
{//code}
DefaultController:
use AppBundle\Services\PrestaShopWebService2;
public function indexAction()
{
//code
$persta2 = new PrestaShopWebService2("MyURL","mykey", false);
//code
}
Where is the problem?

PHPUnit #expectedException does not respect namesapce imports

I found that PHPUnit's annotation #expectedException does not want to read class namespace paths from use statements (I'm using psr-0 for autoloading).
Take this as an example:
<?php
namespace Outrace\Battleship\Tests;
use Outrace\Battleship\Collection\MastCollection;
use Outrace\Battleship\Exception\CollectionOverflowException;
class MastCollectionTest extends \PHPUnit_Framework_TestCase
{
/**
* #expectedException CollectionOverflowException
*/
public function testAcceptOnlyMasts()
{
$notMastObject = new \stdClass();
$mastCollection = new MastCollection();
$mastCollection->attach($notMastObject);
}
}
The test, when run, will result in this error:
ReflectionException: Class CollectionOverflowException does not exist
To remedy the situation, I tried adding autoload-dev to my compose.json and dumping autoload file again:
"autoload-dev": {
"classmap": [
"src/Outrace/Battleship/Exception/"
]
},
or with psr-4:
"autoload-dev": {
"psr-4": {
"Outrace\\Battleship\\Tests\\": "src/Outrace/Battleship/Tests/",
"Outrace\\Battleship\\Exception\\": "src/Outrace/Battleship/Exception/"
}
},
None of the above would solve the problem, the error would persist.
However, the test would work well if the annotation references a fullu qualified name of the exception class:
/**
* #expectedException Outrace\Battleship\Exception\CollectionOverflowException
*/
public function testAcceptOnlyMasts()
Is this a limitation of PHPUnit or am I doing something wrong here?
This is a limitation with how phpunit works.
Internally it uses php's ReflectionClass which expects the FQCN of the exception. It just takes the string you give it in the annotation.
TestCase.php has the following when checking exceptions $reflector = new ReflectionClass($this->expectedException); and the expectedException property is populated either from the annotation or a call to setExpectedException().
You can use simplified names if you use the setExpectedException() method as you could then do something such as
<?php
namespace Outrace\Battleship\Tests;
use Outrace\Battleship\Collection\MastCollection;
use Outrace\Battleship\Exception\CollectionOverflowException;
class MastCollectionTest extends \PHPUnit_Framework_TestCase
{
public function testAcceptOnlyMasts()
{
$this->setExpectedException(CollectionOverflowException::class);
$notMastObject = new \stdClass();
$mastCollection = new MastCollection();
$mastCollection->attach($notMastObject);
}
}

Symfony2 Composer post-install-cmd

I need to install an symfony2 bundle over the composer and do some stuff after the install process. So for the "stuff" after the install i add one line to the "post-install-cmd" in the composer.json
ServiceBundle\\Core\\Platform::registerService
and it calls the function, everything fine
public static function registerService(Event $event) {
//some stuff
exit;
}
The command I use:
php composer.phar update serviceplatform/bundles/poll
Now my question:
Is it possible to get the name "serviceplatform/bundles/poll" or pass any arguments to the statement? I need the path from the bundle after the install.
extra node is what you're looking for - https://getcomposer.org/doc/04-schema.md#extra
In your composer.json:
"extra": {
"your-parameter": "serviceplatform/bundles/poll"
}
Then, in your ServiceBundle\Core\Platform::registerService:
public static function registerService(Event $event)
{
$extras = $event->getComposer()->getPackage()->getExtra();
$yourParameter = $extras['your-parameter'];
//do your stuff
}
It should do the trick.

Resources