I made new plugin with informations find at this post: https://luketowers.ca/blog/how-to-use-laravel-packages-in-october-cms-plugins/
I update composer.php and in vendor folder i got created files I see plugin phpclasses/evalmath in backend.
When on page i try do math operation:
function onStart() {
// instantiate a new EvalMath
$m = new EvalMath;
$m->suppress_errors = true;
// set the value of x
$m->evaluate('x = 3');
var_dump($m->evaluate('y = (x > 5)'));
}
I got error that Class 'EvalMath' not found Class is defined in file /plugins/phpclasses/evalmath/vendor/phpclasses/evalmath/evalmath.class.php What i am doing wrong?
in file /plugins/phpclasses/evalmath/composer.json
{
"require": {
"phpclasses/evalmath": ">=1.0.0"
},
"repositories": [
{
"type": "composer",
"url": "https:\/\/www.phpclasses.org\/"
},
{
"packagist": false
}
]
}
in file /plugins/phpclasses/evalmath/Plugin.php
<?php namespace phpclasses\evalmath;
use App;
use Config;
use System\Classes\PluginBase;
use Illuminate\Foundation\AliasLoader;
/**
*
* Class Plugin */
class Plugin extends PluginBase
{
/**
*
* Returns information about this plugin.
* #return array
*/
public function pluginDetails()
{
return ['name' => 'phpclasses/evalmath',
'description' => 'OctoberCMS plugin for demonstrating the use of Laravel Packages within October plugins',
'author' => 'hhh',
'icon' => 'icon-leaf'
];
}
/**
*
* Runs right before the request route */
public function boot()
{
// Setup required packages $this->bootPackages(); }
/**
*
* Boots (configures and registers) any packages found within this plugin's packages.load configuration value
* #see https://luketowers.ca/blog/how-to-use-laravel-packages-in-october-plugins
* #author Luke Towers octobercms#luketowers.ca
*/
public
function bootPackages()
{ // Get the namespace of the current plugin to use in accessing the Config of the plugin $pluginNamespace = str_replace('\', '.', strtolower(NAMESPACE));
// Instantiate the AliasLoader for any aliases that will be loaded
$aliasLoader = AliasLoader::getInstance();
// Get the packages to boot
$packages = Config::get($pluginNamespace . '::packages');
// Boot each package
foreach ($packages as $name => $options) {
// Setup the configuration for the package, pulling from this plugin's config
if (!empty($options['config']) && !empty($options['config_namespace'])) {
Config::set($options['config_namespace'], $options['config']);
}
// Register any Service Providers for the package
if (!empty($options['providers'])) {
foreach ($options['providers'] as $provider) {
App::register($provider);
}
}
// Register any Aliases for the package
if (!empty($options['aliases'])) {
foreach ($options['aliases'] as $alias => $path) {
$aliasLoader->alias($alias, $path);
}
}
}
}
}
}
in file /plugins/phpclasses/evalmath/classes/config.php
<?php
return [
// This contains the Laravel Packages that you want this plugin to utilize listed under their package identifiers
'packages' => [
'phpclasses/evalmath' => [
],
],
];
the most of the code in file /plugins/phpclasses/evalmath/Plugin.php(bootPackages()) is not nessesary if you dont have configs or additional providers or aliases
if its a laravel package you can use \App::register('\Your\LaravelPackage\ServiceProvider'); in the boot function
to register the package with the laravel Provider
and ad an alias for your package
$alias = \Illuminate\Foundation\AliasLoader::getInstance()->alias('YourAlias', '\Your\LaravelPackage\Facade');
if its not a laravel package try use the full namespace i think its \EvalMath if you use this package https://www.phpclasses.org/browse/file/11680.html
Related
I need to create a service (for jwt logic) that will be standalone, but I see that it is not so easy to refer to the service I have to use 'new' and unfortunately then I create a new instance... :/ but I want to work globally (using public methods) on one and store the token value.
application/service/Jwt.php
<?php
class Application_Service_Jwt
{
private $token;
public function getToken()
{
return $this->token;
}
public function setToken($token)
{
$this->token = $token;
}
}
application/configs/services.global.php
<?php
return [
"services" => array(
'Jwt' => new Application_Service_Jwt()
)
];
application/Bootstrap.php
protected function _initServiceManager()
{
$conf = glob(__DIR__ . "/configs/services.global.php", GLOB_BRACE);
$serviceManagerConfigurator = new \Laminas\ServiceManager\Config($conf["services"]);
$serviceManager = new \Laminas\ServiceManager\ServiceManager();
$serviceManagerConfigurator->configureServiceManager($serviceManager);
// Register it into zend registry is not mandatory
\Zend_Registry::set("serviceManager", $serviceManager);
return $serviceManager;
}
This is how to implement Laminas Service Manager in ZF1 application. This also work with ZF2 and ZF3 Service manager since they are the same.
In your composer add this dependency
"laminas/laminas-servicemanager": "^3.4"
In your Bootstrap.php add this _init function
protected function _initServiceManager()
{
$files = glob(__DIR__ . "/configs/{config,services}.{global,".APPLICATION_ENV."}.php", GLOB_BRACE);
$conf = [];
foreach ($files as $file) {
$conf = array_replace_recursive($conf, include($file));
}
$serviceManagerConfigurator = new \Laminas\ServiceManager\Config($conf["services"]);
$serviceManager = new \Laminas\ServiceManager\ServiceManager();
$serviceManagerConfigurator->configureServiceManager($serviceManager);
// Register it into zend registry is not mandatory
\Zend_Registry::set("serviceManager", $serviceManager);
return $serviceManager;
}
Now, under application/configs you should create the services.global.php file, where you can add your services definition (read the doc for all the possibilities it offers, ZF2 version is ok )
return [
"services" => [,
"factories" => [
"hello" => function() {
return "OK";
}
]
]
In the same folder, add config.{ENVIRONMENT}.php files, where you can define properties depending on your ENVIRONMENT ( they are also loaded depending on its value )
return [
"myApiConfig" => [
"endpoint" => "...",
"username" => "...",
"password" => "...",
],
From your controller you can access your service manager instances using both getResource or Zend registry, you can add this in your overridden init
$this->serviceManager = $this->getFrontController()->getParam('bootstrap')->getResource('serviceManager');
And get any defined service
$this->serviceManager->get('hello');
You can also separate your service classes that use proper php namespaces adding the autoload key in your composer ( change the namespace name and directory as you wish )
"autoload": {
"psr-4": {
"MyNewLibs\\": "library/"
}
},
I have a view composer file called statistics.blade.php which is accessed on every page in the application(also included on the dashboard). On the dashboard page the same set of data is displayed in the form tiles.
class StatisticsComposer
{
public function compose(View $view)
{
# models
$ModelA = new ModelA();
$ModelB = new ModelB();
$ModelC = new ModelC();
...
# binding data
$view->with('arrayStatistics', [
'ModelA' => $ModelA->_someMethod(),
'ModelB' => $ModelB->_someMethod(),
'ModelC' => $ModelC->_someMethod(),
...
]);
}
}
I need to access this arrayStatistics array on the dashboard index file. Is it possible..?
After you created your StatisticsComposer then you need to boot it in service provider.
Create a service provider called ComposerServiceProvider such as ;
class ComposerServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer(['statistics'], StatisticsComposer::class); // assuming it is in `resources` folder
// other view composer bindings...
}
}
and at it to app.php's providers array such as;
'providers' => [
// ... other providers
App\Providers\ComposerServiceProvider::class,
],
Then $arrayStatistics will be accessible on your statistics.blade.
Edit:
I think it is better to not use arrayStatistics but ModelA, ModelB directly for direct usage/access.
Good morning.
i have a problem using the new Symfony architecture.
i created a modern controller where routing is working perfect.
now i want to search products with ProductRepository.
MyModule/src/Repository/ProductRepository
namespace PrestaShop\Module\MyModule\Repository;
use Doctrine\DBAL\Connection;
class ProductRepository
{
/**
* #var Connection the Database connection.
*/
private $connection;
/**
* #var string the Database prefix.
*/
private $databasePrefix;
/**
* #param int $langId the lang id
* #return array the list of products
*/
public function findAllbyLangId(int $langId)
{
$prefix = $this->databasePrefix;
$productTable = "${prefix}product";
$productLangTable = "${prefix}product_lang";
$query = "SELECT p.* FROM ${productTable} p LEFT JOIN ${productLangTable} pl ON (p.`id_product` = pl.`id_product`) WHERE pl.`id_lang` = :langId";
$statement = $this->connection->prepare($query);
$statement->bindValue('langId', $langId);
$statement->execute();
return $statement->fetchAll();
}
}
MyModule/config/services.yml
services:
product_repository:
class: PrestaShop\Module\MyModule\Repository\ProductRepository
arguments: ['#doctrine.dbal.default_connection', '%database_prefix%']
MyController
$products = $this->get('product_repository')->findAllByLangId(1);
dump($products);
Now i get the following error:
"Attempted to load class "ProductRepository" from namespace "PrestaShop\Module\MyModule\Repository".
Did you forget a "use" statement for another namespace?"
What im missing there?
Thx for your time and help.
update - Stacktrace:
**ClassNotFoundException**
Symfony\Component\Debug\Exception\ClassNotFoundException:
Attempted to load class "ProductRepository" from namespace
"PrestaShop\Module\EasyUpload\Repository".
Did you forget a "use" statement for another namespace?
at var\cache\dev\ContainerZiol6qc\getProductRepositoryService.php:8
at require()
(var\cache\dev\ContainerZiol6qc\appDevDebugProjectContainer.php:1713)
at ContainerZiol6qc\appDevDebugProjectContainer->load('getProductRepositoryService.php')(vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Container.php:304)
at Symfony\Component\DependencyInjection\Container->get('product_repository')
(vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait.php:67)
at Symfony\Bundle\FrameworkBundle\Controller\Controller->get('product_repository')
(modules\easyupload\src\Controller\DemoController.php:111)
at EasyUpload\Controller\DemoController->search()
(modules\easyupload\src\Controller\DemoController.php:76)
at EasyUpload\Controller\DemoController->indexAction(object(Request), null)(vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php:151)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php:68)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, false)
(vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php:200)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request), 1, false)
(admin108ptrz6g\index.php:86)`
It's look like you didn't create composer.json file with predefined namespaces.
Here example:
{
"name": "YourName/YourModuleName",
"description": "Awesome description",
"autoload": {
"psr-4": {
"YourName\\YourModuleName\\": "/",
"YourName\\YourModuleName\\Repository": "src/Repository/",
}
},
"config": {
"prepend-autoloader": false
},
"type": "prestashop-module"
}
OR if you want with Prestashop right way
{
"name": "YourName/YourModuleName",
"description": "Awesome description",
"autoload": {
"psr-4": {
"Prestashop\\Module\\YourModuleName": "src/",
"Prestashop\\Module\\YourModuleName\\Repository": "src/Repository/",
}
},
"config": {
"prepend-autoloader": false
},
"type": "prestashop-module"
}
Then run composer install and add to your YourModuleName.php file require_once.
$autoloadPath = __DIR__ . '/vendor/autoload.php';
if (file_exists($autoloadPath)) {
require_once $autoloadPath;
}
I was also searching for hours and find out I needed this exact structure to register the mycompany.mymodule.myservice. This has to be exactly like this in Prestashop 1.7.6:
// mycompany\mymodule\config
config
admin
services.yml
front
services.yml
common.yml
Also make sure your namespace is setup correctly.
I want to be able to add a unique id (Uid) to my logging.
In Example 1: Which is depended on config/logging.php and ProcessorTap files below is not working as expected. The logging is configured to use stdout which refers to the ProcessorTap class that is suppose to add a Uid, when the log statement is created (in accordance with UidProcessor)
Example 2: Which uses purely Mono classes works as expected.
Why isnt Example 1 adding the Uid to the logs, when laravel ("laravel/framework": "5.7.*") should be using Monolog classes as well ?
Example 1: When this api is invoked, the output for Log::info('test') does not include UiD
Route::get('/test', function () {
Log::info('test'); //output = [2020-03-24 04:51:16] local.INFO: test
});
config/logging.php:
'default' => env('LOG_CHANNEL', 'stdout'), //.env LOG_CHANNEL=stdout
'stdout' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'with' => [
'stream' => 'php://stdout',
],
'tap' => [
ProcessorTap::class,
],
]
ProcessorTap:
use Monolog\Processor\UidProcessor;
class ProcessorTap
{
/**
* Customize the given logger instance.
*
* #param \Illuminate\Log\Logger $logger
* #return void
*/
public function __invoke($logger)
{
$logger->pushProcessor(new UidProcessor());
}
}
Example 2: Working correctly the Uid (a484a6729e14996c0af1)
is added to the log for $logger->info('test')
use Monolog\Logger;
use Monolog\Processor\UidProcessor;
Route::get('/test', function () {
$logger = new Logger('main');
$logger->pushProcessor(new UidProcessor(20));
$logger->info('test'); // output = [2020-03-24 04:57:26] main.INFO: test [] {"uid":"a484a6729e14996c0af1"}
});
This might be a laravel (5.7)/mono version specific issue, but I was able to resolve the via iterating via the handlers and calling pushProcessor
use Monolog\Processor\UidProcessor;
class ProcessorTap
{
/**
* Customize the given logger instance.
*
* #param \Illuminate\Log\Logger $logger
* #return void
*/
public function __invoke($logger)
{
collect($logger->getHandlers())->each(function ($handler) {
$handler->pushProcessor(new UidProcessor());
});
}
}
I am trying to include a custom defined validation file that is local to my system and wish to use it with 'package' files from an application I downloaded online. The purpose is so that I can have my own custom validators since I made modifications to this application.
I keep getting the error -> 'Class 'Models\Validators\Photo' not found'
Controller:
use JeroenG\LaravelPhotoGallery\Controllers\AlbumsController; /* From Package */
use JeroenG\LaravelPhotoGallery\Controllers\PhotosController; /* From Package */
use JeroenG\LaravelPhotoGallery\Models\Album; /* From Package */
use JeroenG\LaravelPhotoGallery\Models\Photo; /* From Package */
use Models\Validators as Validators; /* Custom local file */
class EditPhotosController extends PhotosController {
public function __construct()
{
parent::__construct();
}
public function update($albumId, $photoId)
{
$input = \Input::except('_method');
$validation = new Validators\Photo($input); // Here's where error occurs
/* Validation check and update code etc. */
}
}
}
Photo.php -> File path: Models\Validators\Photo.php
namespace Models\Validators;
class Photo extends Validator {
public static $rules = array(
'album_id' => 'required',
'photo_name' => 'required',
'photo_description' => 'max:255',
);
}
Is this just a simple namespacing issue?
The most likely problem is that composer doesn't add file Models/Validators/Photo.php to the autoload index. Make sure you have provided correct path for your files in composer.json.
Try running
composer dump-autoload
to regenerate the autoload files.