Finding the project root from within a composer package - php

I'm trying to provide potential locations of a config file within my package: .config.yml
At present, I've loaded an array within one of my classes with some typical locations:
protected $configDirectories = [
'./',
'./config',
'./app/config',
'./config',
'./vendor/name/packagename/config'
];
Problem is; my package is loaded into ./vendor/name/packagename and of course, ./ doesn't know how to get to the project root.
The aim is to allow users of this package to just drop .config.yml into any of the pre-specified directories and it should be picked up. How can I achieve this?

I had a similar situation. In my case, the front-end controller was in ./. So, I required the user of my package to do something like ...
\Wonderful\Package\Init::setRootDirectory(__DIR__);
(But I eventually decided that instead of having magic search order happening under the covers to locate the config file, I ended up having the one (or more) config files specified explicitly (can be anywhere with any name) ...
\Wonderful\Package\Init::loadConfigFile(__DIR__.'/config.yml');
\Wonderful\Package\Init::loadConfigFile(__DIR__.'/config.DEV-overrides.yml');

If you want to give the user the ability to configure your bundle, you MUST do it via semantic configuration and not via a specified and own config file. Do it the Symfony way.

Related

How to use one module in two different application/project in yii2

I have module created in the basic project of yii2 and now i want to access or use that module another project/application of mine....
How can I achieve this.
please help me out here.
To use module in different apps there are 3 things you need.
The module must not be dependent on classes from core project. For any class that needs to be implemented by core project the module should define interface and depend on that interface instead of class itself.
The module should use different namespace than app and autoloader must know how to load classes from that namespace. (more about that later)
You have to add module in your config in same way you've added it in first project.
The points 1 and 3 are pretty much self-explaining. If are not sure how to add module in config see the yii2 guide.
Now back to the second point. While naive way of copying module over to second project would work it will turn maintaining the module into nightmare because each change would have to be done in each copy of module. So it's better to keep the code of module in one place and make it available for each project. There are multiple ways of doing that.
If you want to, you can turn your module into extension and make it publicly available through packagist as it was suggested by M. Eriksson in comments. After that you would simply add your extension through composer as any other dependency.
Composer also allows you to define and use private repositories if you don't want to publish your module at packagist. See composer documentation for more details.
The most trivial way is to simply put the code into separate folder outside of project. If you do that, you have to make sure that autoloaders in your projects are capable of finding the files locations to load classes. There are two options how to do that. In any case you will want to avoid conflicts with namespaces used by your project, that's why you need to use different namespace.
Let's assume that you've put your module files into folder /path/to/modules/myModule and all classes in your module belongs to namespace modules\myModule. You have to make sure that your webserver can access that folder and that it can run php scripts there.
First option is to use Yii's autoloader. That autoloader uses aliases to look for classes. If you add #modules alias and point it to /path/to/modules folder, the Yii autoloader will try to look for any class from modules\* namespace in /path/to/modules folder. You can add the alias in your config file (web.php, console.php or any other config file you use):
return [
// ...
'aliases' => [
'#modules' => '/path/to/modules',
// ... other aliases ...
],
];
The second option is to use project's composer.json file to set autoloader generated by composer to load your classes.
{
"autoload": {
"psr-4": {
"modules\\": "/path/to/modules"
}
}
}
You can find more info about this in composer's documentation.
Don't forget to run composer dump-autoload after you change autoload settings in your composer.json file to update the generated autoloader.

Laravel: Update .env file by publishing a third-party package

I have a library which I want to wrap into Laravel package.
My library uses two configs: the public config.php for some nonsensitive settings and .env private config for sensitive credentials.
I'd like to vendor:publish my configs for end user. And it seems fine for public config.php but how to publish my .env in Laravel-friendly way? I failed to find any way to do it by vendor:publish.
The application's .env file is primarily there for keeping sensitive information out of configuration files and other resources that often get committed to source control. It's not intended to be published in any way.
What you can do is create a separate configuration file with some sensible defaults preset, while at the same time allowing the user to override them. For example:
// my-config.php
return [
'user_model => env('MY_USER_MODEL', App\User::class),
...
];
If needed, they can implement their own User model or omit setting it within their own env file and defaulting to the implementation you've specified.
You'll see this approach quite often in packages providing roles, permissions, tenancy, etc.

Laravel: Join two application by one config

My project is two Laravel applications in one folder. Why two separate applications instead of one? I have good reasons. Anyway, for example, every time I want to change the app name in the config (config/app.php) I go and edit the .env file in both directories (of the two applications) and then execute artisan config:cache to update the cached config.
It's not much of a task or anything, but it's a bad design I believe. So, I am looking for a way to take the values shared between these two application out to a separate file. And have these application load this file and override/apply the values inside it to the app configuration.
So, now I have a config.php in the root directory (which holds the other two apps in /app1 and /app2). And inside each app's AppServiceProvider I call the config.php and loop through the values and set each using Config::set(..., ...).
This worked for me well, but of course changing the values loaded in the \Config package doesn't change the values that were fetched from it earlier to this point. For example app()->environment() returns the value set in the config/app.php, not the new value introduced in the global config.php. That's because the App library asked for the env property before I could override it!
So, what I want your help with is: you either tell me about a more smart/standard way to achieve 1 config for 2 apps setup. Or tell me where to put the code that overrides the app config with the new values from my global config.php (currently I put the code in register() in App\Providers\AppServiceProvider)
You can share env settings by removing one of .env files and make a symlink to the other file instead of a common file. In this case if you change a file, both applications get changed values.

Allow users of an opensourced project to add their own files to their copy

So I'm creating a semi-popular open source project and am looking for ways for its users to customize their copy.
Basically I've zero experience using Composer and next to none with git submodules. I have this file structure pushed to git:
/ROOT
----/subdirectory/
---------/another.file.php
----/main.class.php
----/config.default.php
It would be ideal for users to be able to copy config.default.php to the same directory, rename it to config.php (and by doing that override the default configuration values) - and I'd like them to be able to add their own files to the /subdirectory/ too, allowing them to extend the tool to their unique requirements.
My question is, don't those files get trimmed when pull (in the case of git submodule) or Composer update is performed? If so, how do I achieve the requirements with as little fuss for the end user as possible:
A single, optional, freely editable configuration file
Two directories that can contain files that users create
Above alterations stay within the users own version control system and are not removed when a new version is fetched.
Thank you for your patience in advance.
What most application frameworks/CMSs are doing these days is to split this process in two packages:
one library package (e.g. symfony/symfony, laravel/framework) that contains the bulk of the code, and that will be installed in vendor/
one "bootstrap" package (e.g. symfony/framework-standard-edition, laravel/laravel) that contains an application shell that your users can start from. That would contain default config and a composer.json that includes the library package + whatever else is needed in the "require" section. This bootstrap package is typically not updated via composer since it becomes the application/site of your users. Therefore it should contain as little code as possible, and be essentially only configuration.
You currently load your user config when your class loads:
if ( is_readable( KINT_DIR . 'config.php' ) ) {
require KINT_DIR . 'config.php';
}
If you added a public setConfig() property, then the config could be located anywhere, and your default would still work (code off the top of my wee head):
Public static function setConfig($config) {
if ( is_readable( $config ) ) {
require $config;
}
}

Symfony 1.4 - Doctrine - Custom Plugin - How do I get plugin model files to reside in plugin directory?

I am creating a custom plugin, and am trying to keep all related model files contained within the plugin directory structure. However, when I build the model, some files get dropped into lib/model/doctrine/... and others in plugins/userPlugin/lib/model/... . According to Doctrine docs I can add a "package" option to the schema.yml file, and generated model files will be created in the location as defined by my dot-notation entry, for example:
# plugins/userPlugin/config/doctrine/schema.yml
connection: store-rw-user
options:
# Fully expect resulting model files to be dropped in this directory (vs the main model dir)
package: userPlugin.lib.model.doctrine
....
As mentioned, this config setup still results in model files being dropped into the main lib/model/doctrine directory. I even tried this, to no avail:
# plugins/userPlugin/config/doctrine/schema.yml
connection: store-rw-user
options:
package: userPlugin
package_custom_path: /tmp/userPlugin
....
Just wanted to see if the files were dropped in the /tmp directory, but they were not.
Before I start tearing apart the source code, I figured I would ask first, to see if there is something I am missing.
It's perfectly normal to get model files in your project directory after building. The purpose of this is to let you customize the plugin model on per-project basis, because the classes inside these files inherit from the classes defined in the plugin's files. I use plugins too, and most of the time, all the code I write resides in the plugin's model files.

Categories