laravel-commode / common
Common helpers/utils/services for laravel-commode
Requires
- php: >=5.4.0
- illuminate/routing: 4.2.*
- illuminate/support: 4.2.*
Requires (Dev)
- mockery/mockery: dev-master
- satooshi/php-coveralls: dev-master
This package is not auto-updated.
Last update: 2024-11-23 16:40:03 UTC
README
#Commode: Common
laravel-commode/common is common utils/services package for all commode packages. Some of them are supposed to use only inside laravel-commode and some of them might be useful for development.
####Contents
You can install laravel-commode/common using composer:
"require": {
"laravel-commode/common": "dev-master"
}
To enable package you need to register LaravelCommode\Common\CommodeCommonServiceProvider
service provider.
Actually, there are two ways of registering CommodeCommonServiceProvider
- first one is common for all
service providers - you can simply add it into laravel application config providers list:
<?php
// ./yourLaravelApplication/app/config/app.php
return [
// ... config code
'providers' => [
// ... providers
'LaravelCommode\Common\CommodeCommonServiceProvider'
]
];
Or you could start using GhostService service providers and just implement one, because every GhostService
service provider checks if CommodeCommonServiceProvider
was registered, if it was not GhostService
registers it automatically. For example it could be your central application service provider, that would load
dependent service providers:
<?php namespace MyApp\ServiceProviders;
use LaravelCommode\Common\GhostService;
class ApplicationServiceProvider extends GhostService
{
// your ghost service code
public function uses()
{
return [
'MyApp\ServiceProviders\DomainLogicServiceProvider', // your domain logic service provider,
'MyApp\ServiceProviders\DALServiceProvider', // your data access layer service provider,
// ... e.t.c.
];
}
}
And later in your config you could simply add only ApplicationServiceProvider
without any mention of
CommodeCommonServiceProvider
, DomainLogicServiceProvider
and others...:
<?php
// ./yourLaravelApplication/app/config/app.php
return [
// ... config code
'providers' => [
// ... providers,
/**
/* will load all dependent services returned from uses()
/* method and CommodeCommonServiceProvider as well
**/
'MyApp\ServiceProviders\ApplicationServiceProvider'
]
];
GhostService is a descendant of an Illuminate\Support\ServiceProvider
with some useful features.
To create a ghost service you simply need to extend LaravelCommode\Common\GhostService
class
and implement 2 basic protected methods: registering()
and launching()
.
<?php namespace MyApp\ServiceProviders;
use LaravelCommode\Common\GhostService;
class YourServiceProvider extends GhostService
{
/**
* Will be triggered when the app is booting
**/
protected function launching() { }
/**
* Triggered when service is being registered
**/
protected function registering() { }
}
One of the most useful features of GhostService is that it load dependent service providers. It might be
useful when your main app config file is a large headache of when you are developing custom package and you
don't want to abuse next developer/user with implementation of dependent service providers. For service
automatic loading you can override method public function uses()
that must return array of service
providers' names. If dependent service has been loaded it will ignored in loading chain.
<?php namespace MyApp\ServiceProviders;
use LaravelCommode\Common\GhostService;
class YourServiceProvider extends GhostService
{
public function uses()
{
return [
'MyApp\ServiceProviders\DALServiceProvider',
'Illuminate\Hashing\HashServiceProvider',
'Vendor\Package\UsefulServiceProvider'
];
}
/**
* Will be triggered when the app is booting
**/
protected function launching() { }
/**
* Triggered when service is being registered
**/
protected function registering() { }
}
For those laravel users, who brought a lot of critics into 'Facades in Laravel' topic GhostService providers
resolving method protected function with($resolvable, callable $do)
. Method expects $resolvable
argument
to be string
or array
of strings, that would contain bindings that are already registered in IoC
container or can be resolved in runtime and $do
argument to be callable
:
<?php namespace MyApp\ServiceProviders;
use LaravelCommode\Common\GhostService;
class YourServiceProvider extends GhostService
{
/**
* @var Illuminate\View\Factory|null
*/
protected $viewFactory = null;
public function uses()
{
return [
'MyApp\ServiceProviders\DALServiceProvider',
'Illuminate\Hashing\HashServiceProvider',
'Vendor\Package\UsefulServiceProvider'
];
}
/**
* Will be triggered when the app is booting
**/
protected function launching() { }
private function doSomethingWithHash(\Illuminate\Hashing\BcryptHasher $hash)
{
//do something with $hash
}
private function doSomethingWithUseful(\Vendor\UsefulPackage\IUsefulBoundInterface $useful)
{
//do something with $useful
}
/**
* Triggered when service is being registered
**/
protected function registering()
{
$usings = ['hash', \Vendor\UsefulPackage\IUsefulBoundInterface::class, 'view'];
$this->with($usings, function ($hash, $useful, $view)
{
$this->doSomethingWithHash($hash);
$this->doSomethingWithUseful($useful);
$this->viewFactory = $view;
});
}
}
If your service provider needs to register a facade or list of facades, you can simply do it by overriding
protected $aliases = [];
and assigning it an array where keys are facade names and values are bound
facades' class names:
protected $aliases = [
'MyFacade' => \MyVendor\MyPackage\Facades\MyFacade::class
];
Resolver
Resolver is a small, but useful class for building something flexible or for something that requires resolving.
It is available through CommodeResolver
facade, or - if you are a facade hater you can find it registered in
IoC container through alias "commode.common.resolver" or can initialize new instance as
new \LaravelCommode\Common\Resolver\Resolver($laravelApplication)
.
For example, let's say that you have some structure for your security module like ISecurityUser and it's bound to your configured eloquent auth model.
<?php namespace App\System\Security\Abstractions;
interface ISecurityUser
{
public function hasPermission($permission);
public function hasPermissions(array $permissions);
}
<?php namespace App\DAL\Concrete\Eloquent\Models;
use Illuminate\Database\Eloquent\Model;
class Account extends Model implements ISecurityUser
{
/* your eloquent model code */
}
<?php namespace App\ServiceProviders;
use LaravelCommode\Common\GhostService\GhostService;
use MyApp\System\Security\Abstractions\ISecurityUser;
class ACLServiceProvider extends GhostService
{
public function launching() {}
public function registering()
{
$this->app->bind(ISecurityUser::class, function ($app)
{
return app('auth')->user(); // note that returned value might be null
});
}
}
Resolver
can resolve closures and class methods or turn them into resolvable closures. Here's an example
of using it.
###Resolver and closures:
<?php
use App\System\Security\Abstractions\ISecurityUser;
$closureThatNeedsToBeResolved = function ($knownParameter1, $knownParameterN, ISecurityUser $needsToBeResolved = null)
{
return func_get_args();
};
$resolver = new \LaravelCommode\Common\Resolver\Resolver(); // or app('commode.resolver');
$knownParameter1 = 'Known';
$knownParameter2 = 'Parameter';
/**
* Resolving closure and running it
**/
$result = $resolver->closure($closureThatNeedsToBeResolved, [$knownParameter1, $knownParameter2]);
$resultClosure = $resolver->makeClosure($closureThatNeedsToBeResolved);
var_dump(
$result, $resultClosure($knownParameter1, $knownParameter2),
$result === $resultClosure($knownParameter1, $knownParameter2)
);
// outputs
// array (size=3)
// 0 => string 'Known' (length=5)
// 1 => string 'Parameter' (length=9)
// 2 => object(MyApp\DAL\Concrete\Eloquent\Models\Account)
// array (size=3)
// 0 => string 'Known' (length=5)
// 1 => string 'Parameter' (length=9)
// 2 => object(MyApp\DAL\Concrete\Eloquent\Models\Account)
// boolean true
###Resolver and class methods:
<?php
use App\System\Security\Abstractions\ISecurityUser;
class SomeClass
{
public function methodThatNeedsToBeResolved($knownParameter1, $knownParameterN, ISecurityUser $needsToBeResolved = null)
{
return func_get_args();
}
}
$resolver = new \LaravelCommode\Common\Resolver\Resolver(); // or app('commode.resolver');
$someClass = new SomeClass();
$knownParameter1 = 'Known';
$knownParameter2 = 'Parameter';
$result = $resolver->method($someClass, 'methodThatNeedsToBeResolved', [$knownParameter1, $knownParameter2]);
// or ->method(SomeClass::class, ..., ...) for calling static method or resolving class through
// app IOC
$resultClosure = $resolver->methodToClosure($someClass, 'methodThatNeedsToBeResolved');
// or ->method(SomeClass::class, ..., ...) for calling static method or resolving class through
// app IOC
var_dump(
$result, $resultClosure($knownParameter1, $knownParameter2),
$result === $resultClosure($knownParameter1, $knownParameter2)
);
// outputs
// array (size=3)
// 0 => string 'Known' (length=5)
// 1 => string 'Parameter' (length=9)
// 2 => object(MyApp\DAL\Concrete\Eloquent\Models\Account)
// array (size=3)
// 0 => string 'Known' (length=5)
// 1 => string 'Parameter' (length=9)
// 2 => object(MyApp\DAL\Concrete\Eloquent\Models\Account)
// boolean true
Controller
laravel-commode/common provides simple controller that doesn't change default controller that much, but it provides functionality that often being questioned on StackOverflow and resources like that on Laravel 4.0-4.2.
LaravelCommode\Common\Controllers\CommodeController
provides resolvable method calls, can separate ajax
calls into different methods or disallow ajax calls at all.
Methods resolver is enabled by default, but you can disable it by overriding protected $resolveMethods
and setting it to protected $resolveMethods = false;
. This functionality is extremely useful with
laravel-commode/viewmodel package installed. Example:
<?php namespace MyApp\Domain\Areas\Administrator\Controllers;
use LaravelCommode\Common\Controllers\CommodeController;
use LaravelCommode\ViewModel\Interfaces\IRequestBag;
class AccountController extends CommodeController
{
/* some controller code */
protected function returnBack()
{
return \Redirect::to(\URL::current())->withInput();
}
public function getSearch(IRequestBag $searchParams)
{
$collection = $this->accountService->search($searchParams->toArray());
return \View::make('Administrator::account.search', compact('collection'));
}
public function postEdit($id, AccountViewModel $viewModel)
{
if (!$viewModel->isValid())
{
return $this->returnBack()->withErrors($viewModel->getValidator());
}
if (!$this->accountStrategy->updateFromViewModel($viewMode))
{
return $this->returnBack()->with('error.strategy', $this->accountStrategy->getState());
}
return \Redirect::action(__CLASS__.'@getIndex');
}
}
Ajax separation calls are disabled by default, but you can enable it by overriding
protected $separateRequests
and setting it to protected $separateRequests = true;
. To define an ajax
method simply adding 'ajax' prefix to your method name. Example:
<?php namespace MyApp\Domain\Areas\Site\Controllers;
use LaravelCommode\ViewModel\Interfaces\IRequestBag;
class PostsController extends CommodeController
{
protected $separateRequests = true;
/* some controller code */
/**
* Returns JSONable results when ajax is triggered
**/
public function ajaxgetLatest($lastId = null)
{
return $this->postService->getLatest($lastId);
}
/**
* Returns same collection as ::ajaxgetLatest() method,
* but wraps it with view
**/
public function getLatest()
{
return \View::make('Site::posts.list', [
'posts' => $this->ajaxgetLatest()
]);
}
}
You can disallow ajax calls by overriding protected $allowAjax
and setting it to
protected $allowAjax = false;
- would return 404 http status code.