laravel: config file name convention? - php

foo_constants.php or fooConstants.php?
It seems laravel would do some name conversion when you use Config::get('...'), which one do you use?

foo.php
Why specify constants at all? Convention I've generally seen is single word filenames. I think in general most 'config' type settings will be constant in an environment even if it is variable between environments.
Take a look at the aws/aws-sdk-php-laravel composer package as an example. That file is named config.php in the package, but gets published to aws.php.
rydurham/Sentinel is another popular package. It also only has a single-word filename.
Update
In the situation you describe in your comment, I would do something like this:
<?php // File: foo.php
return [
'sheep' => [
'clothing' => 'wool',
'chews_on' => 'cud',
],
'wolf' => [
'clothing' => 'fur',
'chews_on' => 'sheep',
],
];
And you can access both of those via Config::get('foo.sheep') and Config::get('foo.wolf'), respectively. When they're defined on the server, they're still 'on the server' so to speak. If you wish to release the values stored in foo.sheep to the public you can, and you can do so without also exposing foo.wolf.

Related

Phan/phan configuration for Symfony5 project

I'm new at static analysis and I'm trying to use phan/phan on my current project.
My phan/config.php is as follow.
<?php
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command-line arguments will be applied
* after this file is read.
*/
return [
// Supported values: `'5.6'`, `'7.0'`, `'7.1'`, `'7.2'`, `'7.3'`,
// `'7.4'`, `null`.
// If this is set to `null`,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan.
//
// Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
// TODO: Set this.
'target_php_version' => null,
// A list of directories that should be parsed for class and
// method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors.
//
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
'src',
'vendor/symfony/console',
],
// A regex used to match every file name that you want to
// exclude from parsing. Actual value will exclude every
// "test", "tests", "Test" and "Tests" folders found in
// "vendor/" directory.
'exclude_file_regex' => '#^vendor/.*/(tests?|Tests?)/#',
// A directory list that defines files that will be excluded
// from static analysis, but whose class and method
// information should be included.
//
// Generally, you'll want to include the directories for
// third-party code (such as "vendor/") in this list.
//
// n.b.: If you'd like to parse but not analyze 3rd
// party code, directories containing that code
// should be added to both the `directory_list`
// and `exclude_analysis_directory_list` arrays.
'exclude_analysis_directory_list' => [
'vendor/'
],
];
?>
My problem is that I have a lot of "false positive" errors like this :
src\Controller\UserController.php:6 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace Route (\Symfony\Component\Routing\Annotation\Route)
src\Controller\UserController.php:7 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace UserPasswordEncoderInterface (\Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface)
src\Controller\UserController.php:8 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace ContainerBagInterface (\Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface)
src\Controller\UserController.php:9 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace Security (\Sensio\Bundle\FrameworkExtraBundle\Configuration\Security)
It seems that phan can't detect Symfony vendors and I'm wondering how to correct it ?
I'm using php 7.4 with a Symfony 5 project
Looks like it's known issue:
https://github.com/phan/phan/issues/1757
In this Github issue, they advise using Phan Extension: https://github.com/Drenso/PhanExtensions#annotationsymfonyannotationplugin
Or try using PHPStan or Psalm.
I found it, the problem was on the following lines :
'directory_list' => [
'src',
'vendor/symfony/console',
],
This was taken directly from Phan example configuration, but since only the folder 'vendor/symfony/console' is included in directory_list, Phan has no way to know other Symfony components.
I've replaced this with :
'directory_list' => [
'src',
'vendor',
],
By including the entire vendor directory, it is parsed and Phan know every vendor object used in src.
As mentionned by Leprechaun, I've encoutered another problem with annotation not being correctly parsed by phan, and had to include the following plugin
'plugins' => [
'vendor/drenso/phan-extensions/Plugin/Annotation/SymfonyAnnotationPlugin.php'
],
Now it works.

Laravel filesystem sftp cached adapter

I am struggling with this issue for some time.
I am using the sftp adapter to connect to another server where i read/write files a lot.
For thumbnail creation i use background jobs with laravel horizon to retrieve pdf contents from the remote sftp server and then generate a jpg and place in local filesystem.
For first setup i need to make around 150k of thumbnails.
When i use a lot of processes in horizon the remote server can't handle this number of connections.
I must limit to max 2 processes at the moment (10 secs~ * 150k~) not optimal.
I want to cache the connection because i know it is possible and probably solves my problem, but can't get it to work:(
The only reference/tutorial/example/docs i could find is
https://medium.com/#poweredlocal/caching-s3-metadata-requests-in-laravel-bb2b651f18f3
https://flysystem.thephpleague.com/docs/advanced/caching/
When i use the code from the example like this:
Storage::extend('sftp-cached', function ($app, $config) {
$adapter = $app['filesystem']->createSftpAdapter($config);
$store = new Memory();
return new Filesystem(new CachedAdapter($adapter->getDriver()->getAdapter(), $store));
});
I get the error: Driver [] is not supported.
Is there anyone here who can help me a bit further on this?
It appears necessary to adjust your configuration:
In your config/filesystems.php file, add a 'caching' key to your storage:
'default' => [
'driver' => 'sftp-cached',
// ...
'cache' => [
'store' => 'apc',
'expire' => 600,
'prefix' => 'laravel',
],
],
This example is based on official documentation (https://laravel.com/docs/5.6/filesystem#caching), but it is not described well how the 'store' key is used here (where memcached is the example), and you would need to change the implementation of your driver to new Memcached($memcached); (with an instance to inject) instead.
In your case, since the sftp-cached driver implements $store = new Memory();, the cache config must reflect this with 'store' => 'apc' (which is RAM based cache). Available 'store' drivers are found in config/cache.php.
(If you use APC and get an error message Call to undefined function Illuminate\Cache\apc_fetch(), this PHP extension must be installed, see e.g. http://php.net/manual/en/apcu.installation.php)
Finally, I believe the 'prefix' key in config/filesystems.php must be set to the same as the cache key prefix in config/cache.php (which is 'prefix' => 'cache' by default).

How to include a separate file inside bootstrap.php that is meant for application wide constants and other application-wide Configure::write values?

I am using CakePHP3.
I prefer to put my application-wide PHP constants and Configure::write values inside a separate php file, usually called constants.php
And then at the end of the bootstrap.php, I will include this constants.php file.
I have no problems with the PHP constants. However, I have issues using Configure::write inside this separate file.
Is there a way to use Configure::write in a separate php file? I have tried using
use Cake\Core\Configure;
inside constants.php but I still get errors.
EDIT
Example of constants.php
<?php
/**
* provide all the kinds of site ID
*/
Configure::write('ADMINISTRATOR_SIDEBAR', array(
'quotations' => [
'link' => '/quotations',
],
'projects' => [
'sub_menu' => [
[
'title' => 'Project 1',
'icon' => '',
'link' => '/job_projects/view/5',
]
],
'link' => '/job_projects'
]
));
When I write that and then
require __DIR__ . '/constants.php';
in the last line of bootstrap.php
I get
Error: Class 'Configure' not found
File ...constants.php
Line: 8
When I then added use Cake\Core\Configure; at the top of constants.php, the error is removed.
Does this mean my issue is solved?
Do you have that many constants? Use class constants instead:
class UserType {
const ADMIN = 'admin';
const USER = 'user';
}
IMO it is better to keep them organized in classes than having tons of global constants. I dislike constants most of the time because you can't really never ever change them at run time. So this leaves just two use cases for them:
Things that should never ever change at runtime (which is rare)
Using them for "identifiers" instead of strings
Explaining 2. a little more: $userRole === 'admin' can fail because of a typo, you won't get an error and might end up with a pretty shitty to debug situation while doing $userRole === UserRole::ADMIN will throw an error if it is not present.
You're not showing any code, so no idea what you're doing wrong with Configure. Why are you not simply using Configure::load() and the `$config = []' array in the file you're going to load with that method?

Laravel environment variables: Undefined Index for array

I have the following setup with Laravel 4.2:
bootstrap/start.php (hostname correct, environment is local)
$env = $app->detectEnvironment(array(
'production' => array('produrl'),
'local' => array('MBP-Ivo.local', 'iMac-Ivo.local'),
));
.env.local.php (in project root, .env.php is exactly the same except mysql info)
<?php
return [
// Code variables
'mysqlUsername' => 'user',
'mysqlPassword' => 'password',
'mysqlDatabase' => 'database',
'paymentIdeal' => false,
'shipmentCountries' => [
'Nederland' => 'Nederland',
'Belgie' => 'Belgie'
]
];
config/app.php (I don't overwrite with app/config/local/app.php)
<?php
return array(
'paymentIdeal' => $_ENV['paymentIdeal'],
'shipmentCountries' => $_ENV['shipmentCountries']
);
There are some more variables, but the problem is with shipmentCountries.
Undefined index: shipmentCountries
All variables declared are working (eg paymentIdeal), but shipmentCountries gives an error. I think because it's an array? The name is exactly the same everywhere, including capital letters.
Does anyone know why I can't get this working?
BTW: I'm choosing this option to prevent users having to change their application configs. I want to use only one *.env file to configure all important stuff. And yes, I know these values could be saved to the database, but that's for later :)
/edit:
When I dump the $_ENV, I get the following:
Array
(
[mysqlUsername] => ***
[mysqlPassword] => ***
[mysqlDatabase] => ***
[paymentIdeal] =>
[shipmentCountries.Nederland] => Nederland
[shipmentCountries.Belgie] => Belgie
);
Somehow it "flattens" the array shipmentCountries. Anyone knows how and why?
You're right, the file get's converted in a flat array using the dot notation (with array_dot)
I believe the reason behind this, is that environment variables are just not supposed to be arrays as they are normally passed in when using a CLI.
So, what can you do about it?
Convert the array from dot to non-dot
In your app/start/global.php use this code to convert the array back to it's original format:
$array = array();
foreach ($_ENV as $key => $value) {
array_set($array, $key, $value);
}
$_ENV = $array;
Use another file and load it yourself
Also inside app/start/global.php (this would be .my.env.local.php)
$config = require base_path().'/.my.env.'.app()->env.'.php';
$_ENV = array_merge($_ENV, $config);
Sidenotes
I'd think again if you really don't want to use config files. It is possible to have your own config file and maybe you can even place it in the root of the project.
Also I'd change the array to a numeric one:
'shipmentCountries' => [
'Nederland',
'Belgie'
]
With the tip of lukasgeiter, I went searching again, and found this:
https://github.com/laravel/framework/issues/5291 and https://github.com/laravel/framework/pull/4623
It looks like Laravel doesn't support this option.
What I do now is save it as a JSON string, and decode it when neccesary.
Another way is to json_encode your associative array in the env.local.php, then in your config
json_decode($_ENV['shipmentCountries'],true);
Don't forget the boolean argument there to make it convert into arrays.

Add LDAP entry to Active Directory via ext/ldap

Using ext/ldap I'm trying to add entries to an Active Directory. As long as I only use one single structural objectClass everything works as expected, but as soon as I try to add an entry with a second auxiliary objectClass, the server reports an error:
Server is unwilling to perform; 00002040: SvcErr: DSID-030F0AA0,
problem 5003 (WILL_NOT_PERFORM), data
0
The following code works:
ldap_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
'ou' => 'Test',
'objectClass' => 'organizationalUnit',
'l' => 'location'
));
This doesn't:
ldap_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
'ou' => 'Test',
'associatedDomain' => 'domain',
'objectClass' => array('organizationalUnit', 'domainRelatedObject'),
'l' => 'location'
));
The same happens if I try to add an auxiliary objectClass to an existing entry:
ldap_mod_add($ldap, 'OU=Test,OU=Test,DC=domain,DC=example,DC=local', array(
'associatedDomain' => 'domain',
'objectClass' => 'domainRelatedObject'
));
The corresponding error message is essentially the same
Server is unwilling to perform;
00002040: SvcErr: DSID-030508F8,
problem 5003 (WILL_NOT_PERFORM), data
0
As all other updating and adding operations work, I think the problem must be related to the objectClass attribute.
As I've not enough experience with Active Directories (I'm used to OpenLDAP):
Are there any known issues with objectClasses in Active Directory? Am I missing something here? Are there any restrictions that disallow adding e.g. domainRelatedObject to an organizationalUnit? What the heck 's going on here ;-)?
Just in case you're wondering: the domainRelatedObject is present in the Active Directory schema.
I just found that, in order to add dynamic (per-instance) aux classes, the forest functional level of the domain must be 2003.
You may not have permission to set the objectClass attribute. See whether you can attach the auxiliary class after creation, through ADSI Edit. If you can't, fix the permissions first (check the Properties tab in the Advanced view of Security settings)
I could attach this specific class right now, onto a organizationalUnit object, as a domain admin; so in principle, this is possible.

Categories