display username in layout.phtml in zend framework 2.5.1 - php

I am new in zend and using zend framework 2.5.1.
Using "authservice" i have done login authentication in my project. I am able to fetch login detail by using $this->getAuthService()->getIdentity(); in my controller. But i want to use it in each and every view page (layout).
So that i could manage session but i am unable to do this.
Moreover i want to display logged in username in layout.phtml(or header.phtml).
I want to show logged in user name like "Welcome ABC".
So please help me to solve this problem.

See the Identity view helper for in your view files like: layout.phtml or page specific ones.
Just like the document states:
if ($user = $this->identity()) {
echo $this->translate('Welcome') . ' ' . $this->escapeHtml($user->getUsername());
} else {
echo $this->translate('Welcome guest');
}

I use a custom view helper to achieve this, passing the Auth service via factory.
My view helper
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\Authentication\AuthenticationService;
class WelcomeUser extends AbstractHelper
{
private $welcomeUser;
/**
*
* #param AuthenticationService $auth
*/
public function __construct(AuthenticationService $auth)
{
$this->welcomeUser = 'Guest';
if ($auth->hasIdentity()) {
$user = $auth->getIdentity();
$this->welcomeUser = $user->getFirstLastName();
}
}
/**
*
* #return string
*/
public function __invoke()
{
return $this->welcomeUser;
}
}
And it's factory
namespace Application\View\Helper\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\View\Helper\WelcomeUser;
use Zend\Authentication\AuthenticationService;
class WelcomeUserFactory implements FactoryInterface
{
/**
*
* #param ServiceLocatorInterface $serviceLocator
* #return WelcomeUser
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new WelcomeUser($serviceLocator->getServiceLocator()->get(AuthenticationService::class));
}
}
Don't forget to register you view helper in module.config.php
'view_helpers' => array(
'factories' => array(
'welcomeUser' => 'Application\View\Helper\Service\WelcomeUserFactory',
),
),
Finally in your layout.phtml use <?php echo $this->welcomeUser(); ?>
I hope this point you in the right direction.

Related

Laravel Trait with constructor works in controller but not in model

I have a StripeClient service provider which needs a key to instantiate:-
namespace App\Providers;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
use Stripe\StripeClient;
class StripeServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(StripeClient::class, function ($app) {
return new StripeClient(config('services.stripe.secret'));
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [StripeClient::class];
}
Then a trait with a bunch of api call functions like this:-
trait StripeClientTrait
{
protected $stripe;
function __construct(StripeClient $stripeClient)
{
$this->stripe = $stripeClient;
}
/**
* #param User $user
*
* #return \Stripe\Customer
* #throws \Stripe\Exception\ApiErrorException
*/
function createCustomer(User $user)
{
return $this->stripe->customers->create([ 'name' => $user->fullname,
'email' => $user->email
]);
}
...
The trait works in a controller perfectly as expected:-
class SubscriptionContoller extends Controller
{
use StripeClientTrait;
public function checkout()
{
try {
$customer = $this->createCustomer(Auth::user());
if($checkoutSession = $this->createCheckoutSession($customer)) {
return redirect($checkoutSession->url);
}
} catch (ApiErrorException $ex){
Log::error($ex->getMessage());
return back()->with(['error'=>$ex->getMessage()]);
}
return back();
}
...
But I now need to use the trait in a model to provide access to some api functions.
class Company extends Tenant
{
use HasFactory, StripeClientTrait;
but adding the trait causes:-
Too few arguments to function App\Models\Company::__construct(), 0 passed in /home/vagrant/code/profiler/vendor/spatie/laravel-multitenancy/src/Models/Concerns/UsesTenantModel.php on line 13 and exactly 1 expected
Can anyone tell me how to implement the trait without using the constructor? I just need some static function helpers to lookup stuff on the API.
Thanks for any guidance :-)
having persevered I've found this way to use the service container in a model:-
public function getPrices()
{
$stripe = app(StripeClient::class);
return $stripe->prices->all(['active'=>true]);
}
But would still like to understand how to use the trait in the model, if anyone could explain I'd be grateful

Some Route Resource Not Working in Codeigniter 4

I cannot find the problem using
$routes->resource
Please help me figure out what is the problem.
This is how I put my routes resource in config routes :
$routes->resource('ApiManageBanner', ['controller' =>'App\Controllers\ApiData\ApiManageBanner']); // get, put, create, delete
Recently I just move all my project to the newest codeigniter 4 version 4.2.6 from the previous version 4.1.2
This is my controllers :
<?php
namespace App\Controllers\ApiData;
use App\Controllers\BaseController;
use CodeIgniter\RESTful\ResourceController;
use Codeigniter\API\ResponseTrait;
class ApiManageBanner extends ResourceController
{
use ResponseTrait;
function __construct()
{
}
// equal to get
public function index() {
echo "Test";
}
// equal to post
public function create() {
}
// equal to get
public function show($id = null) {
}
// equal to put
public function update($id = null) {
}
// equal to delete
public function delete($id = null) {
}
}
I just try a simple to echo "Test".
But I got this error :
I search everywhere but cannot find the problem related to the error.
If I change the routes name to 'ApiManageBanners' using 's' :
$routes->resource('ApiManageBanners', ['controller' =>'App\Controllers\ApiData\ApiManageBanner']); // get, put, create, delete
It is working.
But I cannot change my routes name because my application is reading
'ApiManageBanner' not 'ApiManageBanners'
I am very curious what cause the problem. It is not working for almost all my resources api controller routes.
I found the problem. According to the error it is related to session. When I check all my file. I found that I always init the :
$this->Session = \Config\Services::session();
In all my controller and model __construct();
function __construct()
{
$this->Session = \Config\Services::session();
}
So I remove it and init globaly in BaseController.php
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* #var CLIRequest|IncomingRequest
*/
protected $request;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [''];
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
// Preload any models, libraries, etc, here.
// E.g.: $this->session = \Config\Services::session();
$this->session = \Config\Services::session();
$this->language = \Config\Services::language();
$this->language->setLocale($this->session->lang);
}
}
Then the error is gone.

Laravel 5.6 Inject variable with Service Provider in a group of routes

I have a part of site that starts with specific prefix /manage.
Can I somehow like with AppServiceProvider view-composers inject a variable in all routes from that prefix?
I tried to do it by passing this variable to layout of all that routes. But then I met a problem. I use this variable in blade view of specific page, and it returns me variable not defined.
Then, I inspect laravel debugger and saw the order of loading of blade files. And it was :
1. Current page view
2. Layout view
3. Sidebars and other stuff
So, the fact that current page is loaded before layout, cause error of undefined variable.
So, how can I solve that ? Thanks.
Code from my Service provider :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\CT;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->composer(['website.implicare.ct.show', 'website.implicare.ct.petition.index', 'layouts.ct'], function($view) {
$ct = request()->ct;
$permissions = [];
foreach($ct->userPermissions(auth()->id()) as $userPermission) {
if($userPermission->pivot->ct_id == $ct->id) {
array_push($permissions, $userPermission->name);
}
}
$view->with('permissions', $permissions);
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
create ComposerServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public $theme = 'mytheme';
public function boot()
{
view()->composer($this->theme.'.includes.navbar', 'App\Http\ViewComposers\MenuComposer');
view()->composer($this->theme.'.includes.header', 'App\Http\ViewComposers\MenuComposer');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}

get controller name & action in view file in zend framework 2

I want to get controller and action name in respective view file
as when I GOTO login page
Controller=> authenticate
And action=> Login
come in action
I want to get those name directly in view with out passing it from each and every controller, because on every view file I want controller and action name.
To do this the proper ZF2 way you should write a custom view helper.
You can call this view helper for example RouteMatchHelper.
Then in the view you can simply do $this->routeMatchHelper();
<?php
namespace Application\View\Helper;
use Zend\Mvc\Router\RouteMatch;
use Zend\View\Helper\AbstractHelper;
class RouteMatchHelper extends AbstractHelper
{
/**
* #var RouteMatch
*/
protected $routeMatch;
/**
* Constructor with dependency
*
* #param RouteMatch $routeMatch
*/
public function __construct(RouteMatch $routeMatch)
{
$this->routeMatch = $routeMatch;
}
public function __invoke()
{
$controller = $this->routeMatch->getParam('controller');
$action = $this->routeMatch->getParam('action');
return sprintf(
"the action is %s and the controller name is %s",
$action,
$controller
);
}
}
You need RouteMatch in your view helper so you have to setup a factory. You will have to register the factory under the view_helpers key in your module.config.php file:
'view_helpers' => array(
'factories' => array(
'routeMatchHelper' => `Application\View\Helper\RouteMatchHelperFactory`
)
)
And then the factory itself:
<?php
namespace Application\View\Helper;
use Zend\Mvc\Router\RouteMatch;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class RouteMatchHelperFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return RouteMatchHelper
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
/** #var RouteMatch $routeMatch */
$routeMatch = $serviceManager->get('Application')->getMvcEvent()->getRouteMatch();
return new RouteMatchHelper($routeMatch);
}
}
This code is not tested, but you get the point.
You can read more on writeing custom helperss in the official ZF2 documentation.

ZF2 Dependency Injection onto Controller objects without the Service Locator

I have been doing a read up on ZF2 Service Locator component and could say I understand how its being used. I have, however, a question which I think its silly but it wouldn't hurt to ask.
I want to have a namespace inside my Module called Component where I can put generic code in like say FunctionsComponent.php, MailerComponent.php or ExcelComponent.php. This would allow me to do some stuff inside my controllers.
What I would like to tryout is to have an ability to have controllers define the components they are interested to use (see below):
class SalesController extends AbstractController
{
protected $components = ['Excel'];
//In some action
public function exportAction()
{
$data = ['data to be exported'];
/**
$data : data to be exported
boolean : Whether to force download or save the file in a dedicated location
*/
$this->Excel->export($data, true);
}
}
The idea is to create a ComponentCollection that perhaps implements the FactoryInterface or ServiceLocatorInterface and then let it check each controller when the MvcEvent has been triggered inside my Module class and have the ComponentCollection inject all the controller component and make them accessible without using the service locator as shown below:
$excel = $sm->get('Application\Component\Excel');
I am well aware that this may seem like a daunting ask but I feel like the best way to learn a framework among other things is to play around with it and try to do the unimaginable.
You should create a BaseController somewhere and then extend all your Controllers from BaseController. Then you can inject your dependencies in your BaseController and use anywhere in kids. For example, I am doing this in my Controller to set head title:
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class BaseController extends AbstractActionController
{
/**
* Sets the head title for every page
*
* #param string $title
*/
public function setHeadTitle($title)
{
$viewHelperManager = $this->getServiceLocator()->get('ViewHelperManager');
// Getting the headTitle helper from the view helper manager
$headTitleHelper = $viewHelperManager->get('headTitle');
// Setting a separator string for segments
$headTitleHelper->setSeparator(' - ');
// Setting the action, controller, module and site name as title segments
$siteName = 'Ribbon Cutters';
$translator = $this->getServiceLocator()->get('translator');
$title = $translator->translate($title);
$headTitleHelper->append(ucfirst($title));
$headTitleHelper->append($siteName);
}
}
Instead of defining methods, you can define properties.
public $headTitleHelper
and assign it in constructor of BaseController
$this->headTitleHelper = $this->getServiceLocator()->get('ViewHelperManager')->get('headTitle');
Now you can use $this->headTitleHelper in child controllers.
And then
<?php
namespace Application\Controller;
use Zend\View\Model\ViewModel;
use Application\Controller\BaseController;
class IndexController extends BaseController
{
/**
* Property for setting entity manager of doctrine
*/
protected $em;
/**
* landing page
*
* #return ViewModel
*/
public function indexAction()
{
$this->setHeadTitle('Welcome'); // Welcome - Ribbon Cutters
$viewModel = new ViewModel();
return $viewModel;
}
/**
* Sets and gives Doctrine Entity Manager
*
* #return Doctrine Entity Manager
*/
protected function getEntityManager()
{
if (null === $this->em) {
$this->em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
}
return $this->em;
}
}
I think this can help you.

Categories