Hi I have a project that uses composer to handle mongo libraries, if I debug with a "test cli application" as console application it works fine, as soon as I try to run it as "run on server" it "looses" autoload.php. The server is a native eclipse's php server
my project directory tree is:
D:\EclipseWorkspace-GIT\mongowithcomposer
├───src
│ ├───MongoHandler
│ ├───WebContent
│ │ ├───js
│ │ ├───resources
│ │ │ └───images
│ │ ├───DEFINITIONS.PHP
│ │ ├───HOME.PHP
│ │ └───style
│ └───XML-Handler
├ COMPOSER.JSON
├ COMPOSER.LOCK
└───vendor
├───composer
├─── AUTOLOAD.PHP
└───mongodb
└───mongodb
├───.github
│ └───ISSUE_TEMPLATE
├───.phpcs
├───.travis
├───docs
│ ├───.static
│ ├───includes
│ ├───reference
.......
this is the error I got:
Warning: require_once(D:\Eclipse-Workspace-GIT\.metadata\.plugins\org.eclipse.wst.server.core\tmp6\htdocs\mongowithcomposer\autoload.php): failed to open stream: No such file or directory in D:\Eclipse-Workspace-GIT\.metadata\.plugins\org.eclipse.wst.server.core\tmp6\htdocs\mongowithcomposer\definitions.php on line 10
NOTE: In the tree output the files are higlighted by being UPPERCASE
EDIT:
this is the server automatic path mapping:
<Server>
<Port name="HTTP/1.1" protocol="HTTP">8181</Port>
<PathMapping local="/mongowithcomposer/vendor/composer" module="mongowithcomposer" remote="D:\Eclipse-Workspace-GIT\.metadata\.plugins\org.eclipse.wst.server.core\tmp6\htdocs\mongowithcomposer"/>
<PathMapping local="/mongowithcomposer/src" module="mongowithcomposer" remote="D:\Eclipse-Workspace-GIT\.metadata\.plugins\org.eclipse.wst.server.core\tmp6\htdocs\mongowithcomposer"/>
<PathMapping local="/mongowithcomposer/vendor/mongodb/mongodb/src" module="mongowithcomposer" remote="D:\Eclipse-Workspace-GIT\.metadata\.plugins\org.eclipse.wst.server.core\tmp6\htdocs\mongowithcomposer"/>
</Server>
This is PDT bug. In current implementation rather than just run php -S it copy .buildpath dirs into separate dir, and then run server.
I have a plan to fix this for in Eclipse 2020-09 and already prepared issue for this: https://github.com/eclipse/pdt/issues/68
I would like to create a Symfony project. I have the same issue as many people concerning php version: Symfony uses the wrong one.
λ php -version
PHP 7.4.1 (cli) (built: Dec 17 2019 19:24:02) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
λ symfony -V
Symfony CLI version v4.12.4 (Tue Jan 14 13:09:08 UTC 2020)
λ symfony check:requirements
Symfony Requirements Checker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> PHP is using the following php.ini file:
C:\xampp\php\php.ini
> Checking Symfony requirements:
..............WWW......W..
[OK]
Your system is ready to run Symfony projects
I have Xampp installed but I use Laragon with 7.4.1 on Windows 10 and wish to use that one, but Symfony tells me this:
λ symfony local:php:list
┌─────────┬─────────────────────────────────────────────┬─────────┬─────────┬─────────────┬─────────┬─────────┐
│ Version │ Directory │ PHP CLI │ PHP FPM │ PHP CGI │ Server │ System? │
├─────────┼─────────────────────────────────────────────┼─────────┼─────────┼─────────────┼─────────┼─────────┤
│ 7.3.10 │ C:\xampp\php │ php.exe │ │ php-cgi.exe │ PHP CGI │ * │
│ 7.4.1 │ C:\laragon\bin\php\php-7.4.1-Win32-vc15-x64 │ php.exe │ │ php-cgi.exe │ PHP CGI │ │
└─────────┴─────────────────────────────────────────────┴─────────┴─────────┴─────────────┴─────────┴─────────┘
The current PHP version is selected from default version in $PATH
Even though there is no trace of Xampp or php 7.3.1 in my $PATH.
λ echo %path:;=&echo.%
C:\Program Files\cmder_mini\bin
C:\Program Files\cmder_mini\vendor\bin
C:\Program Files\cmder_mini\vendor\conemu-maximus5\ConEmu\Scripts
C:\Program Files\cmder_mini\vendor\conemu-maximus5
C:\Program Files\cmder_mini\vendor\conemu-maximus5\ConEmu
C:\Program Files (x86)\Common Files\Oracle\Java\javapath
C:\Windows\system32
C:\Windows
C:\Windows\System32\Wbem
C:\Windows\System32\WindowsPowerShell\v1.0\
C:\Windows\System32\OpenSSH\
C:\Program Files\nodejs\
C:\Program Files\Git\cmd
C:\ProgramData\ComposerSetup\bin
C:\laragon\bin\php\php-7.4.1-Win32-vc15-x64\php.exe
C:\Program Files\Symfony
C:\laragon\bin
C:\laragon\bin\apache\httpd-2.4.35-win64-VC15\bin
C:\laragon\bin\composer
C:\laragon\bin\laragon\utils
C:\laragon\bin\mysql\mysql-5.7.24-winx64\bin
C:\laragon\bin\nginx\nginx-1.16.0
C:\laragon\bin\ngrok
C:\laragon\bin\notepad++
C:\laragon\bin\php\php-7.4.1-Win32-vc15-x64
C:\laragon\bin\putty
C:\laragon\bin\redis\redis-x64-3.2.100
C:\laragon\bin\telnet
C:\laragon\usr\bin
C:\Program Files\Sublime Text 3\
C:\Users\User\AppData\Local\Yarn\config\global\node_modules\.bin
C:\Users\User\AppData\Roaming\Composer\vendor\bin
C:\Users\User\AppData\Roaming\npm
C:\Ruby26-x64\bin
C:\Users\User\AppData\Local\Microsoft\WindowsApps
C:\Program Files\JetBrains\PhpStorm 2019.2.3\bin
C:\Program Files\JetBrains\DataGrip 2019.2.5\bin
C:\Program Files\Git\cmd
C:\Program Files\Git\mingw64\bin
C:\Program Files\Git\usr\bin
C:\Program Files\cmder_mini
(I checked user & system $PATH)
I tried to force Symfony into using 7.4.1 by running in a project directory:
λ echo "7.4.1" > .phpversion
When I run
λ symfony local:php:refresh
λ symfony local:php:list
I get:
λ WARNING the current dir requires PHP "7.4.1" (.php-version from current dir: C:\laragon\www\CMS_test\.php-version), but this version is not available
I also tried renaming the Xampp directory name, and as a matter of fact, that "works".
C:\
λ symfony check:requirements
php does not seem to be available under C:\xampp\php
C:\
λ symfony local:php:list
┌─────────┬─────────────────────────────────────────────┬─────────┬─────────┬─────────────┬─────────┬─────────┐
│ Version │ Directory │ PHP CLI │ PHP FPM │ PHP CGI │ Server │ System? │
├─────────┼─────────────────────────────────────────────┼─────────┼─────────┼─────────────┼─────────┼─────────┤
│ 7.4.1 │ C:\laragon\bin\php\php-7.4.1-Win32-vc15-x64 │ php.exe │ │ php-cgi.exe │ PHP CGI │ * │
└─────────┴─────────────────────────────────────────────┴─────────┴─────────┴─────────────┴─────────┴─────────┘
The current PHP version is selected from default version in $PATH
But that solution isn't really satisfying to me.
I've search StackOverflow for several hours, tried to re-install Symfony, restart the computer, ask friends etc no one seem to have another solution.
So, why does Symfony search for php in a Xampp directory ? Is it possible to choose another default one like Laragon's ? Any idea ?
I just had this problem on my Windows environment. For some reason, symfony is not reading .php-version correctly when I create it using echo "7.2" > .php-version.
The problem was gone once I deleted and created a new text file from my IDE. Probably creating it using vscode code .php-version or using the File Explorer would work too (I didn't try it, yet).
Edit: I just tried creating the file with VS Code and Notepad - Both worked. But I still don't know why it doesn't work when creating with echo...
Edit2: I think I got it. Looks like PowerShell's echo "" > file will create the file with UTF-16 encoding. After converting the file to UTF-8 it worked as expected.
Just delete your .php-version file and create in manually from your ide! With the from encoding (using echo from terminal) the error message was
the current dir requires PHP ��7.4.10
you can see the encoding is wrong by the question marks.
Creating the file from the ide fixed my problem!
I have three old applications (running on Symfony 2) where each one has been developed in separated git repositories and configured in their respective vhosts:
company.com Company website.
admin.company.com Website administration.
api.company.com API company service.
Even though, they share the same database. So we're decided (the Company) unify all of them in one application with Symfony 4 structure & approach, mainly to remove a big quantity of duplicated data and to improve its maintenance.
Right now, I'm integrating all in one application/repository as was planned, but I'm starting to deal with some performance & structure issues:
As I've just one entry point index.php I did two routes prefixes to be able to access for company.com/admin/ and company.com/api/ sub app, so all routes are loaded each time :(
All bundles and configuration is loaded and processed needlessly for each request. For example: when I access the API path the SonataAdminBundle is loaded too :(
The cache clear command takes a long time to complete.
The tests are breaking down and now takes a long time to complete too.
I'd like to keep the early vhost and load just the needed bundles and configuration per domains:
company.com Loads bundles, routes and configuration for a company website only (SwiftmailerBundle, ...)
admin.company.com Loads bundles, routes and configuration only for website administration (SecurityBundle, SonataAdminBundle, ...)
api.company.com Loads just the bundles, routes and configuration to provide a fast API company service (SecurityBundle, FOSRestBundle, NelmioApiDocBundle, ...)
This is what I'm doing so far:
// public/index.php
// ...
$request = Request::createFromGlobals();
$kernel = new Kernel(getenv('APP_ENV'), getenv('APP_DEBUG'));
// new method implemented in my src/kernel.php
$kernel->setHost($request->server->get('HTTP_HOST'));
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
I've check the current host prefix in Kernel::registerBundles() method and I loaded the needed bundles only, but still I've problems with bin/console file (it doesn't work as HTTP_HOST variable is not defined for CLI) I'd like to clear the cache for each "sub-app" and so on.
I have been doing some research on this topic but so far I couldn't find anything helpful for my scenario (Symfony 4).
Is possible to have many applications under one project repository running independently (like individual apps) but sharing some configuration? What is the best approach to achieve it?
Thanks in advance.
Likely the multiple kernels approach could be a good option to solve this kind of project, but thinking now in Symfony 4 approach with environment variables, structure and kernel implementation, it could be improved.
Name-based Virtual Kernel
The term "Virtual Kernel" refers to the practice of running more than one application (such as api.example.com and admin.example.com) on a single project repository. Virtual kernels are "name-based", meaning that you have multiple kernel names running on each application. The fact that they are running on the same physical project repository is not apparent to the end user.
In short, each kernel name corresponds to one application.
Application-based Configuration
First, you'll need replicate the structure of one application for config, src, var directories and leave the root structure for shared bundles and configuration. It should look like this:
├── config/
│ ├── admin/
│ │ ├── packages/
│ │ ├── bundles.php
│ │ ├── routes.yaml
│ │ ├── security.yaml
│ │ └── services.yaml
│ ├── api/
│ ├── site/
│ ├── packages/
│ ├── bundles.php
├── src/
│ ├── Admin/
│ ├── Api/
│ ├── Site/
│ └── VirtualKernel.php
├── var/
│ ├── cache/
│ │ ├── admin/
│ │ │ └── dev/
│ │ │ └── prod/
│ │ ├── api/
│ │ └── site/
│ └── log/
Next, making use of the Kernel::$name property you can stand out the application to run with dedicated project files (var/cache/<name>/<env>/*):
<name><Env>DebugProjectContainer*
<name><Env>DebugProjectContainerUrlGenerator*
<name><Env>DebugProjectContainerUrlMatcher*
This will be the key of the performance as each application has by definition its own DI container, routes and configuration files. Here is a complete sample of the VirtualKernel class that supports the previous structure:
src/VirtualKernel.php
// WITHOUT NAMESPACE!
use Symfony\Component\HttpKernel\Kernel;
class VirtualKernel extends Kernel
{
use MicroKernelTrait;
private const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function __construct($environment, $debug, $name)
{
$this->name = $name;
parent::__construct($environment, $debug);
}
public function getCacheDir(): string
{
return $this->getProjectDir().'/var/cache/'.$this->name.'/'.$this->environment;
}
public function getLogDir(): string
{
return $this->getProjectDir().'/var/log/'.$this->name;
}
public function serialize()
{
return serialize(array($this->environment, $this->debug, $this->name));
}
public function unserialize($data)
{
[$environment, $debug, $name] = unserialize($data, array('allowed_classes' => false));
$this->__construct($environment, $debug, $name);
}
public function registerBundles(): iterable
{
$commonBundles = require $this->getProjectDir().'/config/bundles.php';
$kernelBundles = require $this->getProjectDir().'/config/'.$this->name.'/bundles.php';
foreach (array_merge($commonBundles, $kernelBundles) as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
}
}
}
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
$container->setParameter('container.dumper.inline_class_loader', true);
$this->doConfigureContainer($container, $loader);
$this->doConfigureContainer($container, $loader, $this->name);
}
protected function configureRoutes(RouteCollectionBuilder $routes): void
{
$this->doConfigureRoutes($routes);
$this->doConfigureRoutes($routes, $this->name);
}
private function doConfigureContainer(ContainerBuilder $container, LoaderInterface $loader, string $name = null): void
{
$confDir = $this->getProjectDir().'/config/'.$name;
if (is_dir($confDir.'/packages/')) {
$loader->load($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
}
if (is_dir($confDir.'/packages/'.$this->environment)) {
$loader->load($confDir.'/packages/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
}
$loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob');
if (is_dir($confDir.'/'.$this->environment)) {
$loader->load($confDir.'/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
}
}
private function doConfigureRoutes(RouteCollectionBuilder $routes, string $name = null): void
{
$confDir = $this->getProjectDir().'/config/'.$name;
if (is_dir($confDir.'/routes/')) {
$routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
}
if (is_dir($confDir.'/routes/'.$this->environment)) {
$routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
}
$routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
}
}
Now your \VirtualKernel class requires an extra argument (name) that defines the application to load. In order for the autoloader to find your new \VirtualKernel class, make sure add it to composer.json autoload section:
"autoload": {
"classmap": [
"src/VirtualKernel.php"
],
"psr-4": {
"Admin\\": "src/Admin/",
"Api\\": "src/Api/",
"Site\\": "src/Site/"
}
},
Then, run composer dump-autoload to dump the new autoload config.
Keeping one entry point for all applications
├── public/
│ └── index.php
Following the same filosofy of Symfony 4, whereas environment variables decides which development environment and debug mode should be used to run your application, you could add a new APP_NAME environment variable to set the application to execute:
public/index.php
// ...
$kernel = new \VirtualKernel(getenv('APP_ENV'), getenv('APP_DEBUG'), getenv('APP_NAME'));
// ...
For now, you can play with it by using PHP's built-in Web server, prefixing the new application environment variable:
$ APP_NAME=site php -S 127.0.0.1:8000 -t public
$ APP_NAME=admin php -S 127.0.0.1:8001 -t public
$ APP_NAME=api php -S 127.0.0.1:8002 -t public
Executing commands per application
├── bin/
│ └── console.php
Add a new console option --kernel to be able to run commands from different applications:
bin/console
// ...
$name = $input->getParameterOption(['--kernel', '-k'], getenv('APP_NAME') ?: 'site');
//...
$kernel = new \VirtualKernel($env, $debug, $name);
$application = new Application($kernel);
$application
->getDefinition()
->addOption(new InputOption('--kernel', '-k', InputOption::VALUE_REQUIRED, 'The kernel name', $kernel->getName()))
;
$application->run($input);
Later, use this option to run any command different to default one (site).
$ bin/console about -k=api
Or if you prefer, use environment variables:
$ export APP_NAME=api
$ bin/console about # api application
$ bin/console debug:router # api application
$
$ APP_NAME=admin bin/console debug:router # admin application
Also you can configure the default APP_NAME environment variable in the .env file.
Running tests per application
├── tests/
│ ├── Admin/
│ │ └── AdminWebTestCase.php
│ ├── Api/
│ ├── Site/
The tests directory is pretty similar to the src directory, just update the composer.json to map each directory tests/<Name>/ with its PSR-4 namespace:
"autoload-dev": {
"psr-4": {
"Admin\\Tests\\": "tests/Admin/",
"Api\\Tests\\": "tests/Api/",
"Site\\Tests\\": "tests/Site/"
}
},
Again, run composer dump-autoload to re-generate the autoload config.
Here, you might need create a <Name>WebTestCase class per application in order to execute all tests together:
test/Admin/AdminWebTestCase
namespace Admin\Tests;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
abstract class AdminWebTestCase extends WebTestCase
{
protected static function createKernel(array $options = array())
{
return new \VirtualKernel(
isset($options['environment']) ? $options['environment'] : 'test',
isset($options['debug']) ? $options['debug'] : true,
'admin'
);
}
}
Later, extends from AdminWebTestCase to test admin.company.com application (Do the same for another ones).
Production and vhosts
Set the environment variable APP_NAME for each vhost config in your production server and development machine:
<VirtualHost company.com:80>
SetEnv APP_NAME site
# ...
</VirtualHost>
<VirtualHost admin.company.com:80>
SetEnv APP_NAME admin
# ...
</VirtualHost>
<VirtualHost api.company.com:80>
SetEnv APP_NAME api
# ...
</VirtualHost>
Adding more applications to the project
With three simple steps you should be able to add new vKernel/applications to the current project:
Add to config, src and tests directories a new folder with the <name> of the application and its content.
Add to config/<name>/ dir at least the bundles.php file.
Add to composer.json autoload/autoload-dev sections the new PSR-4 namespaces for src/<Name>/ and tests/<Name> directories and update the autoload config file.
Check the new application running bin/console about -k=<name>.
Final directory structure:
├── bin/
│ └── console.php
├── config/
│ ├── admin/
│ │ ├── packages/
│ │ ├── bundles.php
│ │ ├── routes.yaml
│ │ ├── security.yaml
│ │ └── services.yaml
│ ├── api/
│ ├── site/
│ ├── packages/
│ ├── bundles.php
├── public/
│ └── index.php
├── src/
│ ├── Admin/
│ ├── Api/
│ ├── Site/
│ └── VirtualKernel.php
├── tests/
│ ├── Admin/
│ │ └── AdminWebTestCase.php
│ ├── Api/
│ ├── Site/
├── var/
│ ├── cache/
│ │ ├── admin/
│ │ │ └── dev/
│ │ │ └── prod/
│ │ ├── api/
│ │ └── site/
│ └── log/
├── .env
├── composer.json
Unlike multiple kernel files approach, this version reduces a lot of code duplication and files; just one kernel, index.php and console for all applications, thanks to environment variables and virtual kernel class.
Example based-on Symfony 4 skeleton: https://github.com/yceruto/symfony-skeleton-vkernel
Inspired in https://symfony.com/doc/current/configuration/multiple_kernels.html
You can create new environments like: admin, website, api. Then by provide environment variable SYMFONY_ENV by apache/nginx you will be able to run dedicated application and still use sub domains company.com, admin.company.com, api.company.com. Also you will be able to easily load only required routing.
Depends from how many application you want to create based on this approach you can add conditions to load specified bundles by project in AppKernel class or create separate classes for each project.
You should also read this article https://jolicode.com/blog/multiple-applications-with-symfony2
Also when you want to run Behat testing, you should run it with this command:
for windows:
set APP_NAME=web&& vendor\bin\behat
for linux:
export APP_NAME='web' && vendor\bin\behat
where "web" is your kernel name you want to run.
The KernelInterface::getName() method and the kernel.name parameter have been deprecated. There's no alternative to them because this is a concept that no longer makes sense in Symfony applications.
If you need a distinctive ID for the kernel of the application, you can use the KernelInterface::getContainerClass() method and the kernel.container_class parameter.
Similarly, the getRootDir() method and the kernel.root_dir parameter have been deprecated too. The alternative is to use the getProjectdir() and kernel.project_dir method introduced in Symfony 3.3
See https://symfony.com/blog/new-in-symfony-4-2-important-deprecations#deprecated-the-kernel-name-and-the-root-dir
I am trying to implement PSR-4 autoloading in my project. It is an existing application I have inherited that doesn't currently use OOP (it's all scripted), but I am hoping to refactor over time to use OOP, and PSR-4 is crucial for me as it will end up being a large project.
At this present time we do not rely on any external libraries (old application entirely written in-house), so composer is ONLY being used for autoloading at this moment in time, but will use third-party packages eventually such as phpunit.
My app structure on my server looks like this:
/var/www/appurl/
│ composer.json
│
├───htdocs
│ ├───AppName
│ │ ├───admin
│ │ │ authenticated.php
│ │ │ init.php
│ │ │ login.php
│ │ │
│ │ └───php
│ │ └───search.php
│ └───Framework
│ ├───Helpers
│ │ └───OSHelpers.php
└───vendor
│ autoload.php
│
└───composer
autoload_classmap.php
autoload_namespaces.php
autoload_psr4.php
autoload_real.php
ClassLoader.php
composer.json:
{
"autoload": {
"psr-4": {
"Framework\\": "htdocs/Framework"
}
}
}
login.php calls authenticated.php when a user successfully logs in, and authenticated calls my init.php script which contains:
<?php
require_once('../../../vendor/autoload.php');
?>
it is search.php that has the error. The user is redirected to search.php when they are authenticated.
search.php has the lines:
use Framework\Helpers\OSHelpers;
$current_os = OSHelpers::GetConciseOSFromUserAgent($user_agent);
OSHelpers.php is namedspaced as: namespace Framework\Helpers;
the static call to OSHelpers works fine if require_once is used, but the 2nd line where I define $current_os is where it appears to be failing.
The error I receive is:
Fatal error: Class 'Framework\Helpers\OSHelpers' not found in /var/www/appurl/htdocs/AppName/php/search.php on line 829
I'm at a bit of a loss about why it does this? When I follow the example in this video (https://www.youtube.com/watch?v=VGSerlMoIrY) my example app works fine, but trying to replicate this in a slightly more complicated structure is giving me problems.
I have done composer dump-autoload -o, and looking within the vendor directory shows that my classes are defined correctly. From vendor/composer/autoload_classmap.php:
'Framework\\Helpers\\OSHelpers' => $baseDir . '/htdocs/Framework/Helpers/OSHelpers.php',
I'm trying to integrate the Doctrine ORM in my Framework. This is the basic structure of my framework.
├───app
│ ├───cache
│ ├───config
│ ├───controllers
│ ├───database
│ │ ├───mapping
│ │ ├───entities
│ │ └───repositories
│ ├───models
│ └───views
├───bin
├───framework
│ ├───cache
│ └───library
├───vendor
So i need to set the default path in Doctrine so that mapping, entity and repository files were generated on those directories:
├───database
│ ├───mapping
│ ├───entities
│ └───repositories
I've been reading the official documentation of Doctrine ORM, but I have not accomplished anything. I would appreciate if someone can help me a little. Sorry if i have orthographic failures.
Regards.
Try this.May it help u.
Let your framework be XYZ:
Make following changes in your index file.
require_once 'XYZ/Loader/Autoloader.php';
$loader = XYZ_Loader_Autoloader::getInstance()
->registerNamespace('Doctrine')
->pushAutoloader(array('Doctrine', 'autoload'));
use Doctrine\ORM\EntityManager, Doctrine\ORM\Configuration;
$manager = Doctrine_Manager::getInstance();