I'm using LDAP in my User data fixtures and I don't want to hardcode the LDAP login options. Initially, I tried this:
$options = array(
'host' => '%ldap_host%',
'port' => '%ldap_port%',
'useSsl' => true,
'username' => '%ldap_username%',
'password' => '%ldap_password%',
'baseDn' => '%ldap_baseDn_users%'
);
But that didn't work. I did some research and realized I needed to include the container in my fixtures. However, it's at this point I'm unsure what my next step is.
As I understand it I need to use the container and it's get method to get the service containing the parameters, but I don't know what that is:
$this->container->get('parameters');
Doesn't work, so I'm wondering what I should use.
My full datafixture is as follows:
class LoadFOSUsers extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
/**
* #var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $manager)
{
$this->container->get('parameters');
// Not sure how to access param values.
$options = array(
'host' => '%ldap_host%',
'port' => '%ldap_port%',
'useSsl' => true,
'username' => '%ldap_username%',
'password' => '%ldap_password%',
'baseDn' => '%ldap_baseDn_users%'
);
$ldap = new Ldap($options);
$ldap->bind();
$baseDn = '%ldap_baseDn_users%';
$filter = '(&(&(ObjectClass=user))(samaccountname=*))';
$attributes=['samaccountname', 'dn', 'mail','memberof'];
$result = $ldap->searchEntries($filter, $baseDn, Ldap::SEARCH_SCOPE_SUB, $attributes);
foreach ($result as $item) {
echo $item["dn"] . ': ' . $item['samaccountname'][0] . PHP_EOL;
}
}
public function getOrder()
{
// the order in which fixtures will be loaded
// the lower the number, the sooner that this fixture is loaded
return 8;
}
}
You just have to fetch them from container via getParameter('name') or get them all in a bag via getParameterBag().
So:
$options = array(
'host' => $this->container->getParameter('ldap_host'),
'port' => $this->container->getParameter('ldap_port'),
'useSsl' => true,
'username' => $this->container->getParameter('ldap_username'),
'password' => $this->container->getParameter('ldap_password'),
'baseDn' => $this->container->getParameter('ldap_baseDn_users')
);
etc.
Related
I have too many function for database inside one model file
See my example :
<?php
namespace App\Models;
use CodeIgniter\Model;
use Medoo\Medoo;
class DBMedoo extends Model {
public $database;
public $maxfolder;
protected $session;
function __construct()
{
include APPPATH . 'ThirdParty/vendor/autoload.php';
$this->session = \Config\Services::session();
$this->session->start();
$this->database = new Medoo([
// [required]
'type' => 'mysql',
'host' => 'localhost',
'database' => 'db_testing',
'username' => 'root',
'password' => '',
// [optional]
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'port' => 3306,
// [optional] Table prefix, all table names will be prefixed as PREFIX_table.
'prefix' => '',
// [optional] Enable logging, it is disabled by default for better performance.
'logging' => true,
// [optional]
// Error mode
// Error handling strategies when error is occurred.
// PDO::ERRMODE_SILENT (default) | PDO::ERRMODE_WARNING | PDO::ERRMODE_EXCEPTION
// Read more from https://www.php.net/manual/en/pdo.error-handling.php.
'error' => \PDO::ERRMODE_SILENT,
// [optional]
// The driver_option for connection.
// Read more from http://www.php.net/manual/en/pdo.setattribute.php.
'option' => [
\PDO::ATTR_CASE => \PDO::CASE_NATURAL
],
// [optional] Medoo will execute those commands after connected to the database.
'command' => [
'SET SQL_MODE=ANSI_QUOTES'
]
]);
}
public function FDatabase() {
return $this->database;
}
public function UpdatePriceAlertPush($idx) {
$this->FDatabase()->update('tb_apppricealert', [
'triggered' => 1,
'ispush' => 1,
'ipaddress' => $_SERVER['REMOTE_ADDR'],
'datetime' => date('Y-m-d H:i:s')
], [
'idx' => $idx
]);
}
include 'Ticker.php'; // Here error
include 'CheckUpdateVersion.php'; // Here error
// and 50 more.....
}
?>
How to separate each public function into every part of file and include in the main model ?
In my example above both :
include 'Ticker.php'; // Here error
include 'CheckUpdateVersion.php'; // Here error
Got error.
This is "Ticker.php"
<?php
// ================================== TICKER
function InsertTicker($array) {
$this->FDatabase()->action(function($database) use (&$array) {
$this->FDatabase()->insert('tb_ticker', [
'ticker' => $array['ticker'],
'company' => $array['company'],
'ipaddress' => $_SERVER['REMOTE_ADDR'],
'datetime' => date('Y-m-d H:i:s')
]);
// If you found something wrong, just return false value to rollback the whole transaction.
if ($this->FDatabase()->error) {
return false;
}
});
}
function SelectAllTicker() {
$Data = $this->FDatabase()->select('tb_ticker', '*');
return $Data;
}
function GetTicker($ticker) {
$Data = $this->FDatabase()->get('tb_ticker', '*', [
'ticker' => $ticker
]);
return $Data;
}
?>
and this is "CheckUpdateVersion.php"
<?php
// ================================== CHECK UPDATE VERSION
function GetUpdateVersion() {
$Data = $this->FDatabase()->get('tb_version', '*', [
'ORDER' => [
'idx' => 'DESC'
]
]);
return $Data;
}
?>
I want to separate every category function to each file. So in my model it is easy to read and find the function. Also the model will look more tidy.
Is there anyway to achieve it ? I don't want to put all public function into one file. It is too long to read and when try to use the function I need to search the name.
If I separate it into some of file base on category. Then it is easy to find and structure data may look tidy.
Remember this is codeigniter 4
Trying to use doctrine with slim 4 and php-di I don't get it running with autowire.
Following my setup:
index.php
$definitions = [
'settings' => [
'doctrine' => [
'dev_mode' => true,
'cache_dir' => __DIR__.'/../var/cache/doctrine',
'metadata_dirs' => [__DIR__.'/../src/Domain/'],
'connection' => [
'driver' => 'pdo_mysql',
'host' => 'webdb',
'port' => 3306,
'dbname' => 'db',
'user' => 'user',
'password' => 'pass',
]
]
],
EntityManagerInterface::class => function (ContainerInterface $c): EntityManager {
$doctrineSettings = $c->get('settings')['doctrine'];
$config = Setup::createAnnotationMetadataConfiguration(
$doctrineSettings['metadata_dirs'],
$doctrineSettings['dev_mode']
);
$config->setMetadataDriverImpl(
new AnnotationDriver(
new AnnotationReader,
$doctrineSettings['metadata_dirs']
)
);
$config->setMetadataCacheImpl(
new FilesystemCache($doctrineSettings['cache_dir'])
);
return EntityManager::create($doctrineSettings['connection'], $config);
},
UserRepositoryInterface::class => get(UserRepository::class)
then my repository:
class UserRepository extends \Doctrine\ORM\EntityRepository implements UserRepositoryInterface {
public function get($id){
$user = $this->_em->find($id);
...
}
}
Currently I get the follwoing error message:
"Doctrine\ORM\Mapping\ClassMetadata" cannot be resolved: Parameter $entityName of __construct() has no
value defined or guessable
Full definition:
Object (
class = Doctrine\ORM\Mapping\ClassMetadata
lazy = false
...
can somebody tell me how to solve that issue respectively is there any other maybe cleaner/easier way to integrate doctrine using php-di?
Update
Referring to the hint that ClassMetadata can't be autowired I changed the structure as follows:
index.php
$definitions = [
EntityManager::class => DI\factory([EntityManager::class, 'create'])
->parameter('connection', DI\get('db.params'))
->parameter('config', DI\get('doctrine.config')),
'db.params' => [
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => '',
'dbname' => 'foo',
],
'doctrine.config' => Setup::createAnnotationMetadataConfiguration(array(__DIR__."/src/core/models/User"), true),
...
userservice/core/models/User.php:
namespace userservice\core\models;
use userservice\core\exceptions\ValidationException;
use \DateTime;
use ORM\Entity;
/**
* #Entity(repositoryClass="userservice\infrastructure\repositories\UserRepository")
*/
class User extends Model{
/**
* #Column(type="string", length="50")
* #var string
*/
private $name;
...
And the userservice/infrastructure/UserRepository.php:
namespace userservice\infrastructure\repositories;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\ORMInvalidArgumentException;
use userservice\core\models\User;
use userservice\core\repositories\UserRepositoryInterface;
use userservice\infrastructure\repositories\Repository;
class UserRepository extends Repository implements UserRepositoryInterface {
private $_repository;
/**
*
* #param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager) {
parent::__construct($entityManager);
$this->_repository = $entityManager->getRepository('User'); // OR $this->entityManager->find('User', 1);
}
Now I'm getting the following error in UserRepository construct (getRepository):
Uncaught Doctrine\Persistence\Mapping\MappingException: Class 'User' does not exist in C:\projects\microservices\user-service\vendor\doctrine\persistence\lib\Doctrine\Persistence\Mapping\MappingException.php
How can I get doctrine find the entities?
Having an issue using $this->container inside of my controllers.
When I try to access the logger/monolog in the code below, it fails miserably:
$this->container->get('logger')->addInfo('Request: users->get-one');
Here's the code in src/dependancies.php:
<?php
$container = $app->getContainer();
// monolog
$container['logger'] = function ($c) {
$logs = $c->get('settings')['logger'];
$logger = new Monolog\Logger($logs['name']);
$logger->pushProcessor(new Monolog\Processor\UidProcessor());
$logger->pushHandler(new Monolog\Handler\StreamHandler($logs['path'], $logs['level']));
return $logger;
};
// database
$container['db'] = function ($c) {
$database = $c->get('settings')['database'];
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection([
'driver' => 'mysql',
'host' => $database['hostname'],
'database' => $database['database'],
'username' => $database['username'],
'password' => $database['password'],
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
return $capsule;
};
// register users controller
require __DIR__ . '/../src/controllers/users.php';
$container['UsersController'] = function($c) {
return new UsersController($c);
};
Below is the code that's in src/controllers/users.php:
<?php
use Psr\Container\ContainerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
class UsersController {
protected $container;
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
public function get(Request $request, Response $response, $args) {
$this->container->get('logger')->addInfo('Request: users->get-one');
/**
* TODO: Replace $args['id'] with the id from the current token payload
*/
$data = Users::find($args['id']);
return $response->withJSON($data)->withStatus(200);
}
public function create(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->create');
$user = $request->getParsedBody();
$data = Users::create([
'first_name' => $user['first_name'],
'last_name' => $user['last_name'],
'email' => $user['email'],
'password' => password_hash($user['password'], PASSWORD_BCRYPT),
'telephone' => $user['telephone'],
'timezone' => $user['timezone'],
'verification' => '011010'
]);
return $response->withJSON($data)->withStatus(200);
}
public function update(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->update');
$user = $request->getParsedBody();
$data = Users::where('id', $args['id'])->update([
'first_name' => $user['first_name'],
'last_name' => $user['last_name'],
'email' => $user['email'],
'password' => password_hash($user['password'], PASSWORD_BCRYPT),
'telephone' => $user['telephone'],
'timezone' => $user['timezone']
]);
return $response->withJSON($data)->withStatus(200);
}
public function delete(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: users->delete');
$data = Users::destroy($args['id']);
return $response->withJSON($data)->withStatus(200);
}
/*
* ==============================
* Manager Functions Routines
* ==============================
*/
public function getAll(Request $request, Response $response, $args) {
$this->logger->addInfo('Request: admin->users->getAll');
$data = Users::all();
return $response->withJSON($data)->withStatus(200);
}
}
I have tried following different tutorials as well as the documentation on the Slim website however, nothing has seemed to fix the issue. I am sure it's something easily fixed that I am just missing.
PHP Slim 3 Framework - Use MonoLog in Custom Class - Using $this when not in object context - The accepted answer here just seems silly to do when I want to be able to access the entire app container and NOT just the logger.
Any help is appreciated.
Thank you!
Well, I figured it out. Apparently using two semicolons when invoking the controller routine is not the proper way of doing things. Oops!
/*
* users::read::one
* method:get
*/
$app->get('/users', '\UsersController::get');
When the code above is adjust to only use one semicolon, it works:
/*
* users::read::one
* method:get
*/
$app->get('/users', '\UsersController:get');
I'd like to keep users away from editing configuration files, so I've made web interface in admin panel for setting up Mail server, username, password, port, encryption..
I was working well in Laravel 4.2, but now when the app has been rewritten into Laravel 5, an error occurs:
Class 'Settings' not found in <b>F:\htdocs\app\config\mail.php</b> on line <b>18</b><br />
For this purpose I've created a service provider, made a facade, put them in config/app.php, Settings::get('var')/Settings::set('var') work perfectly, but not for mail settings.
config/mail.php:
<?php return array(
'driver' => Settings::get('mail_driver'),
'host' => Settings::get('mail_host'),
'port' => Settings::get('mail_port'),
'from' => array('address' => Settings::get('mail_from_address'), 'name' => Settings::get('mail_from_name')),
'encryption' => Settings::get('mail_encryption'),
'username' => Settings::get('mail_username'),
'password' => Settings::get('mail_password'),
'sendmail' => Settings::get('mail_sendmail'),
'pretend' => false,
);
config/app.php:
'providers' => [
...
'App\Providers\SettingsServiceProvider',
...
'aliases' => [
...
'Settings' => 'App\Custom\Facades\Settings',
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Custom\Settings;
class SettingsServiceProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton('settings', function()
{
return new Settings;
});
}
}
<?php namespace App\Custom;
use App\Setting;
class Settings {
public function get($var) {
try{
$setting = Setting::first();
} catch(exception $e)
{
return false;
}
return $setting->$var;
}
public function set($var, $val) {
try{
$setting = Setting::first();
$setting->$var = $val;
$setting->save();
} catch(exception $e)
{
return false;
}
return true;
}
}
<?php
namespace App\Custom\Facades;
use Illuminate\Support\Facades\Facade;
class Settings extends Facade {
protected static function getFacadeAccessor() { return 'settings'; }
}
Any ideas how to implement Laravel mail settings using database?
To archive this I created CustomMailServiceProvider by extending Illuminate\Mail\MailServiceProvider so as to overwrite this method:
protected function registerSwiftTransport(){
$this->app['swift.transport'] = $this->app->share(function($app)
{
return new TransportManager($app);
});
}
Here is the complete solution
I created CustomMailServiceProvider.php in app\Providers
namespace App\Providers;
use Illuminate\Mail\MailServiceProvider;
use App\Customs\CustomTransportManager;
class CustomMailServiceProvider extends MailServiceProvider{
protected function registerSwiftTransport(){
$this->app['swift.transport'] = $this->app->share(function($app)
{
return new CustomTransportManager($app);
});
}
}
I created CustomTransportManager.php in app/customs directory -
NB: app/customs directory doesn't exist in default laravel 5 directory structure, I created it
namespace App\Customs;
use Illuminate\Mail\TransportManager;
use App\Models\Setting; //my models are located in app\models
class CustomTransportManager extends TransportManager {
/**
* Create a new manager instance.
*
* #param \Illuminate\Foundation\Application $app
* #return void
*/
public function __construct($app)
{
$this->app = $app;
if( $settings = Setting::all() ){
$this->app['config']['mail'] = [
'driver' => $settings->mail_driver,
'host' => $settings->mail_host,
'port' => $settings->mail_port,
'from' => [
'address' => $settings->mail_from_address,
'name' => $settings->mail_from_name
],
'encryption' => $settings->mail_encryption,
'username' => $settings->mail_username,
'password' => $settings->mail_password,
'sendmail' => $settings->mail_sendmail,
'pretend' => $settings->mail_pretend
];
}
}
}
And finally, I replaced 'Illuminate\Mail\MailServiceProvider', in config/app.php with 'App\Providers\CustomMailServiceProvider',
I have added
$this->app['config']['services'] = [
'mailgun' => [
'domain' => $settings->mailgun_domain,
'secret' => $settings->mailgun_secret,
]
];
to CustomTransportManager __construct() to include mailgun API credentials that I'm using as mailing service
I configured as mentioned, however got the following error. While I tried your code found that from Laravel 5.4 share method is deprecated and instead informed to use singleton.
Call to undefined method Illuminate\Foundation\Application::share()
here is the below method using singleton instead using share method:
protected function registerSwiftTransport(){
$this->app->singleton('swift.transport', function ($app){
return new CustomTransportManager($app);
});
}
#DigitLimit , method share() has been dropped since Laravel 5.4. I had to work-around this problem using other methods, and I am not sure they are perfect. Here is my registerSwiftTransport() method in CustomMailServiceProvider class.
Firstly, we need to determine if code is not executed while calling app through command line: "if(strpos(php_sapi_name(), 'cli') === false)". If we don't check that and don't prevent setting new params in this case, Artisan will throw us errors in command line. Secondly, we need to get settings from database somehow. I did it using my method getSettingValue(), where first argument is setting key, and second argument is default value if setting is not found. As you see, I assigned settings to $this->app['config']['mail'].
After that, I used singleton() method:
protected function registerSwiftTransport(){
if (strpos(php_sapi_name(), 'cli') === false) {
$this->app['config']['mail'] = [
'driver' => Setting::getSettingValue('mail_driver', '****'),
'host' => Setting::getSettingValue('mail_host', '****'),
'port' => Setting::getSettingValue('mail_port', 25),
'from' => [
'address' => Setting::getSettingValue('mail_from_address', '****'),
'name' => Setting::getSettingValue('mail_from_name', '****'),
],
'encryption' => Setting::getSettingValue('mail_encryption', '***'),
'username' => Setting::getSettingValue('mail_username', '****'),
'password' => Setting::getSettingValue('mail_password', '****'),
];
}
$this->app->singleton('swift.transport', function ($app) {
return new Illuminate\Mail\TransportManager($app);
});
}
Following is my cake console code to generate database schema. I have to manage multiple database schema migration. When I am calling generateDb function it creates a master schema after that i am switching database connection to client database, but client schema is not generating. its again generating master schema.
class HelloShell extends AppShell {
public $uses = array('ClientDbdetail');
public function generateDb() {
$runCommand = shell_exec(APP.'Console/cake schema generate -f master');
if ($runCommand) {
$sessionArray = $this->ClientDbdetail->find('first', array('recursive' => -1));
$this->__switchDb($sessionArray['ClientDbdetail']);
shell_exec(APP.'Console/cake schema generate -f client');
$this->out('Schema generated');
} else {
$this->out('Schema not generated');
}
}
private function __switchDb(array $userDetail) {
$username = 'default';
$settings = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => 3306,
'login' => $userDetail['user_dbuser'],
'password' => $userDetail['user_dbpwd'],
'database' => $userDetail['user_dbname'],
'prefix' => ''
);
ConnectionManager::drop($username);
ConnectionManager::create($username, $settings);
ConnectionManager::getDataSource($username);
}
}
From CakePHP book there is an example.
public $connection = 'default';
public function before($event = array()) {
$db = ConnectionManager::getDataSource($this->connection);
$db->cacheSources = false;
return true;
}
and after :
public function before($event = array()) {
$articles = ClassRegistry::init('Articles', array(
'ds' => $this->connection
));
// Do things with articles.
}
see this : http://book.cakephp.org/2.0/en/console-and-shells/schema-management-and-migrations.html