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.
Related
I am trying to use this package to push notifications to users via OneSignal. However I needed to make a little change. My API serves two (related) apps and I have two OneSignal configs. I am trying to override its ServiceProvider (using this technique).
The ServiceProvider presents itself as follows
<?php
namespace NotificationChannels\OneSignal;
use Berkayk\OneSignal\OneSignalClient;
use Illuminate\Support\ServiceProvider;
use NotificationChannels\OneSignal\Exceptions\InvalidConfiguration;
class OneSignalServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*/
public function boot()
{
$this->app->when(OneSignalChannel::class)
->needs(OneSignalClient::class)
->give(function () {
$oneSignalConfig = config('services.onesignal');
if (is_null($oneSignalConfig)) {
throw InvalidConfiguration::configurationNotSet();
}
return new OneSignalClient(
$oneSignalConfig['app_id'],
$oneSignalConfig['rest_api_key'],
''
);
});
}
}
The behavior that I want to change is located in the line
$oneSignalConfig = config('services.onesignal');
As it assumes that my config/services.php has the following entry (stated in the doc) :
// config/services.php
...
'onesignal' => [
'app_id' => env('ONESIGNAL_APP_ID'),
'rest_api_key' => env('ONESIGNAL_REST_API_KEY')
],
...
Whereas I want to set my config/services.php as follows
// config/services.php
...
'onesignal' => [
'app1' => [
'app_id' => env('ONESIGNAL_1_APP_ID'),
'rest_api_key' => env('ONESIGNAL_1_REST_API_KEY')
],
'app2' => [
'app_id' => env('ONESIGNAL_2_APP_ID'),
'rest_api_key' => env('ONESIGNAL_2_REST_API_KEY')
],
],
...
And I want somehow to tell my ServiceProvider (through some kind of parameter) to either do
$oneSignalConfig = config('services.onesignal.app1');
OR
$oneSignalConfig = config('services.onesignal.app2');
But I didn't find any way to pass a parameter to the class, the boot function or the give method (and if I understood well I shouldn't even be doing that).
The only way I could think of is to create two classes that extend the OneSignalChannel::class
and duplicate code in the boot function so it becomes as follows :
public function boot()
{
$this->app->when(FirstOneSignalChannel::class)
->needs(OneSignalClient::class)
->give(function () {
$oneSignalConfig = config('services.onesignal.app1');
if (is_null($oneSignalConfig)) {
throw InvalidConfiguration::configurationNotSet();
}
return new OneSignalClient(
$oneSignalConfig['app_id'],
$oneSignalConfig['rest_api_key'],
''
);
});
$this->app->when(SecondOneSignalChannel::class)
->needs(OneSignalClient::class)
->give(function () {
$oneSignalConfig = config('services.onesignal.app2');
if (is_null($oneSignalConfig)) {
throw InvalidConfiguration::configurationNotSet();
}
return new OneSignalClient(
$oneSignalConfig['app_id'],
$oneSignalConfig['rest_api_key'],
''
);
});
}
The difference in the when provoking a difference in the config but it seems a lot of duplication and not extensible (what if I had three apps).
Should I use this method, or is there a way to pass a parameter to this ServiceProvider or is there another solution ?
https://stackoverflow.com/a/34224082/10371024
I could see what you need, but to pass parameter to boot method is not a good idea according to Laravel architecture. You may try to get what you want with using events as Vladislav suggested.
I have recently been learning about the AppServiceProvider. I have registered a service in the AppServiceProvider which creates a singleton - an instantiated GuzzleHttp Client, like so:
$this->app->singleton('GuzzleHttp\Client', function($api) {
return new Client([
'base_uri' => env('ELASTICSEARCH_HOST'),
'auth' => [
env('ELASTICSEARCH_USER'),
env('ELASTICSEARCH_PASS')
],
]);
});
This is connecting to an ElasticSearch API, and that currently works:
$response = app('GuzzleHttp\Client')->request('GET');
I have set up a facade called ElasticSearchFacade, which contains only the getFacadeAccessor():
protected static function getFacadeAccessor()
{
return 'elasticSearch';
}
I have also registered elasticSearch in my AppServiceProvider, like so:
$this->app->bind('elasticSearch', function() {
return new ElasticSearch();
});
This creates a new ElasticSearch instance. However, I would love to pass the GuzzleHttp\Client into the elasticSearch service. So I have tried adding the following to my ElasticSearch.php file:
use GuzzleHttp\Client;
class ElasticSearch
{
protected $client;
public function __contruct(Client $client)
{
$this->client = $client;
}
public function handle()
{
$response = $this->client->request('GET');
die($response->getBody()->getContents());
}
}
I have now changed the registered service to pass through the GuzzleHttp Client like so:
$this->app->bind('elasticSearch', function() {
return new ElasticSearch(app('GuzzleHttp\Client'));
});
However I am getting the error:
PHP Error: Call to a member function request() on null
The constructor method is __construct not __contruct. You have not defined a custom constructor for your ElasticSearch class. So that member variable is null.
Side Note: do not call env outside of the configuration files.
To avoid having to make these env calls outside of configuration files you can just add configuration files as needed or add to current configuration files. Something like Elastic Search credentials can probably get added to the services.php configuration file:
<?php
return [
...
'elasticsearch' => [
'host' => env('ELASTICSEARCH_HOST'),
'user' => env('ELASTICSEARCH_USER'),
'password' => env('ELASTICSEARCH_PASS'),
],
...
];
Now that you have these in the configuration you can use the configuration system to pull these values:
config('services.elasticsearch'); // that whole array of values
config('services.elasticsearch.host'); // just that host value
Config::get('services.elasticsearch');
app('config')->get(...);
There are multiple ways to access the configuration system.
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
Laravel 5.5
I want to change direction of api token that used in TokenGaurd so,
i created a custom guard named CafeTokenGaurd extends TokenGuard, i define __construct function into it like what i want, something like this:
public function __construct(UserProvider $provider, Request $request) {
parent::__construct($provider, $request);
$this->inputKey = 'api_key'; // I want changing this part
$this->storageKey = 'api_key';
}
Now i want to define api_key from relation with users table like this:
device_user table -> token
i want to define specific tokens for each devices user have, and i want to set api key input and storage key to this column in pivot table between users and devices,
how i should this?!
Thanks
Since the version Laravel 5.7.28, You can simply set up in config/auth.php.
'guards' => [
'api' => [
'driver' => 'token',
'input_key' => 'token', // The input name to pass through
'storage_key' => 'token', // The column name to store in database
'provider' => 'users',
],
],
Because you need to change how the user is retrieved out of the database, you actually need to create and use a custom UserProvider, not a custom Guard. You'll only need the custom guard if you feel like renaming the input key or storage key from api_token.
So, you'll need a new custom UserProvider class that knows how to retrieve your user with the given credentials (token), and you'll need to tell Auth to use your new custom UserProvider class.
First, assuming you're still using Eloquent, start by creating a new UserProvider class that extends the base EloquentUserProvider class. In this example, it is created at app/Services/Auth/MyEloquentUserProvider.php. In this class, you will need to override the retrieveByCredentials function with the details on how to retrieve the user with the provided token.
namespace App\Services\Auth;
use Illuminate\Auth\EloquentUserProvider;
class MyEloquentUserProvider extends EloquentUserProvider
{
/**
* Retrieve a user by the given credentials.
*
* #param array $credentials
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials)) {
return;
}
// $credentials will be an array that looks like:
// [
// 'api_token' => 'token-value',
// ]
// $this->createModel() will give you a new instance of the class
// defined as the model in the auth config for your application.
// Your logic to find the user with the given token goes here.
// Return found user or null if not found.
}
}
Once you've created your class, you need to let Auth know about it. You can do this in the boot() method on your AuthServiceProvider service provider. This example will use the name "myeloquent", but you can use whatever you want (except "eloquent" and "database").
public function boot()
{
$this->registerPolicies();
Auth::provider('myeloquent', function($app, array $config) {
return new \App\Services\Auth\MyEloquentUserProvider($app['hash'], $config['model']);
});
}
And finally, you need to tell Auth to use your new myeloquent user provider. This is done in the config/auth.php config file.
'providers' => [
'users' => [
'driver' => 'myeloquent', // this is the provider name defined above
'model' => App\User::class,
],
],
You can read more about adding custom user providers in the documentation here.
i generated one module which is for web services and module name is "service".
i added code in web.php
'modules'=>[
'service' => [
'class' => 'app\modules\service\service',
],
],
but i am not able to access this module in browser with below URL
http://localhost/projectfoldername/service/login/index
service = Module [ dir : protected/modules/service/service.php]
login = Controller [ dir : protected/modules/service/controllers/loginController.php]
index = action
below is loginController.php code
<?php
namespace app\modules\service\controllers;
class loginController extends \yii\web\Controller
{
public function actionIndex()
{
echo "test";
exit();
// return $this->render('index');
}
}
please help me if i am missing anything.
Controllers directory where your loginController is, should be within module's directory.
protected/modules/service/controllers/loginController.php