I'm using this class to use wordpress like hooks and filters in my user management system, I use a autoload class to load all my classes, however it won't recognise this class unless its static, how can i make this class static ?
<?php
class Hooks
{
/**
* $filters holds list of hooks
* #access public
* #since 0.1
* #var array
*/
protected static $filters = [];
/**
* $merged_filters
* #var array
*/
protected static $merged_filters = [];
/**
* $actions
* #var array
*/
protected static $actions = [];
/**
* $current_filter holds the name of the current filter
* #access public
* #since 0.1
* #var array
*/
protected static $current_filter = [];
// Disable object instantiation
private function __construct() {}
/**
* gets instance of this class
* #access public
* #since 0.1
public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new Hooks();
}
return self::$_instance;
}
*/
/**
* FILTERS
*/
/**
* add_filter Hooks a function or method to a specific filter action.
* #access public
* #since 0.1
* #param string $tag The name of the filter to hook the $function_to_add to.
* #param callback $function_to_add The name of the function to be called when the filter is applied.
* #param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
* #param int $accepted_args optional. The number of arguments the function accept (default 1).
* #return boolean true
*/
public static function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
$idx = self::_filter_build_unique_id($tag, $function_to_add, $priority);
self::$filters[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
unset( self::$merged_filters[ $tag ] );
return true;
}
/**
* remove_filter Removes a function from a specified filter hook.
* #access public
* #since 0.1
* #param string $tag The filter hook to which the function to be removed is hooked.
* #param callback $function_to_remove The name of the function which should be removed.
* #param int $priority optional. The priority of the function (default: 10).
* #param int $accepted_args optional. The number of arguments the function accepts (default: 1).
* #return boolean Whether the function existed before it was removed.
*/
public static function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
$function_to_remove = self::_filter_build_unique_id($tag, $function_to_remove, $priority);
$r = isset(self::filters[$tag][$priority][$function_to_remove]);
if ( true === $r) {
unset(self::$filters[$tag][$priority][$function_to_remove]);
if ( empty(self::$filters[$tag][$priority]) )
unset(self::$filters[$tag][$priority]);
unset(self::$merged_filters[$tag]);
}
return $r;
}
/**
* remove_all_filters Remove all of the hooks from a filter.
* #access public
* #since 0.1
* #param string $tag The filter to remove hooks from.
* #param int $priority The priority number to remove.
* #return bool True when finished.
*/
public static function remove_all_filters($tag, $priority = false) {
if( isset(self::$filters[$tag]) ) {
if( false !== $priority && isset(self::$filters[$tag][$priority]) )
unset(self::$filters[$tag][$priority]);
else
unset(self::$filters[$tag]);
}
if( isset(self::$merged_filters[$tag]) )
unset(self::$merged_filters[$tag]);
return true;
}
/**
* has_filter Check if any filter has been registered for a hook.
* #access public
* #since 0.1
* #param string $tag The name of the filter hook.
* #param callback $function_to_check optional.
* #return mixed If $function_to_check is omitted, returns boolean for whether the hook has anything registered.
* When checking a specific function, the priority of that hook is returned, or false if the function is not attached.
* When using the $function_to_check argument, this function may return a non-boolean value that evaluates to false
* (e.g.) 0, so use the === operator for testing the return value.
*/
public static function has_filter($tag, $function_to_check = false) {
$has = !empty(self::$filters[$tag]);
if ( false === $function_to_check || false == $has )
return $has;
if ( !$idx = self::_filter_build_unique_id($tag, $function_to_check, false) )
return false;
foreach ( (array) array_keys(self::$filters[$tag]) as $priority ) {
if ( isset(self::$filters[$tag][$priority][$idx]) )
return $priority;
}
return false;
}
/**
* apply_filters Call the functions added to a filter hook.
* #access public
* #since 0.1
* #param string $tag The name of the filter hook.
* #param mixed $value The value on which the filters hooked to <tt>$tag</tt> are applied on.
* #param mixed $var,... Additional variables passed to the functions hooked to <tt>$tag</tt>.
* #return mixed The filtered value after all hooked functions are applied to it.
*/
public static function apply_filters($tag, $value) {
$args = array();
// Do 'all' actions first
if ( isset(self::$filters['all']) ) {
self::$current_filter[] = $tag;
$args = func_get_args();
self::_call_all_hook($args);
}
if ( !isset(self::$filters[$tag]) ) {
if ( isset(self::$filters['all']) )
array_pop(self::$current_filter);
return $value;
}
if ( !isset(self::$filters['all']) )
self::$current_filter[] = $tag;
// Sort
if ( !isset( self::$merged_filters[ $tag ] ) ) {
ksort(self::$filters[$tag]);
self::$merged_filters[ $tag ] = true;
}
reset( self::$filters[ $tag ] );
if ( empty($args) )
$args = func_get_args();
do {
foreach( (array) current(self::$filters[$tag]) as $the_ )
if ( !is_null($the_['function']) ){
$args[1] = $value;
$value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
}
} while ( next(self::$filters[$tag]) !== false );
array_pop( self::$current_filter );
return $value;
}
/**
* apply_filters_ref_array Execute functions hooked on a specific filter hook, specifying arguments in an array.
* #access public
* #since 0.1
* #param string $tag The name of the filter hook.
* #param array $args The arguments supplied to the functions hooked to <tt>$tag</tt>
* #return mixed The filtered value after all hooked functions are applied to it.
*/
public static function apply_filters_ref_array($tag, $args) {
// Do 'all' actions first
if ( isset(self::$filters['all']) ) {
self::$current_filter[] = $tag;
$all_args = func_get_args();
self::_call_all_hook($all_args);
}
if ( !isset(self::$filters[$tag]) ) {
if ( isset(self::$filters['all']) )
array_pop(self::$current_filter);
return $args[0];
}
if ( !isset(self::$filters['all']) )
self::$current_filter[] = $tag;
// Sort
if ( !isset( self::$merged_filters[ $tag ] ) ) {
ksort(self::$filters[$tag]);
self::$merged_filters[ $tag ] = true;
}
reset( self::$filters[ $tag ] );
do {
foreach( (array) current(self::$filters[$tag]) as $the_ )
if ( !is_null($the_['function']) )
$args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
} while ( next(self::$filters[$tag]) !== false );
array_pop( self::$current_filter );
return $args[0];
}
/**
* ACTIONS
*/
/**
* add_action Hooks a function on to a specific action.
* #access public
* #since 0.1
* #param string $tag The name of the action to which the $function_to_add is hooked.
* #param callback $function_to_add The name of the function you wish to be called.
* #param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
* #param int $accepted_args optional. The number of arguments the function accept (default 1).
*/
public static function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
return self::add_filter($tag, $function_to_add, $priority, $accepted_args);
}
/**
* has_action Check if any action has been registered for a hook.
* #access public
* #since 0.1
* #param string $tag The name of the action hook.
* #param callback $function_to_check optional.
* #return mixed If $function_to_check is omitted, returns boolean for whether the hook has anything registered.
* When checking a specific function, the priority of that hook is returned, or false if the function is not attached.
* When using the $function_to_check argument, this function may return a non-boolean value that evaluates to false
* (e.g.) 0, so use the === operator for testing the return value.
*/
public static function has_action($tag, $function_to_check = false) {
return self::has_filter($tag, $function_to_check);
}
/**
* remove_action Removes a function from a specified action hook.
* #access public
* #since 0.1
* #param string $tag The action hook to which the function to be removed is hooked.
* #param callback $function_to_remove The name of the function which should be removed.
* #param int $priority optional The priority of the function (default: 10).
* #return boolean Whether the function is removed.
*/
public static function remove_action( $tag, $function_to_remove, $priority = 10 ) {
return self::remove_filter( $tag, $function_to_remove, $priority );
}
/**
* remove_all_actions Remove all of the hooks from an action.
* #access public
* #since 0.1
* #param string $tag The action to remove hooks from.
* #param int $priority The priority number to remove them from.
* #return bool True when finished.
*/
public static function remove_all_actions($tag, $priority = false) {
return self::remove_all_filters($tag, $priority);
}
/**
* do_action Execute functions hooked on a specific action hook.
* #access public
* #since 0.1
* #param string $tag The name of the action to be executed.
* #param mixed $arg,... Optional additional arguments which are passed on to the functions hooked to the action.
* #return null Will return null if $tag does not exist in $filter array
*/
public static function do_action($tag, $arg = '') {
if ( ! isset(self::$actions) )
self::$actions = array();
if ( ! isset(self::$actions[$tag]) )
self::$actions[$tag] = 1;
else
++self::$actions[$tag];
// Do 'all' actions first
if ( isset(self::$filters['all']) ) {
self::$current_filter[] = $tag;
$all_args = func_get_args();
self::_call_all_hook($all_args);
}
if ( !isset(self::$filters[$tag]) ) {
if ( isset(self::$filters['all']) )
array_pop(self::$current_filter);
return;
}
if ( !isset(self::$filters['all']) )
self::$current_filter[] = $tag;
$args = array();
if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
$args[] =& $arg[0];
else
$args[] = $arg;
for ( $a = 2; $a < func_num_args(); $a++ )
$args[] = func_get_arg($a);
// Sort
if ( !isset( self::$merged_filters[ $tag ] ) ) {
ksort(self::$filters[$tag]);
self::$merged_filters[ $tag ] = true;
}
reset( self::$filters[ $tag ] );
do {
foreach ( (array) current(self::$filters[$tag]) as $the_ )
if ( !is_null($the_['function']) )
call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
} while ( next(self::$filters[$tag]) !== false );
array_pop(self::$current_filter);
}
/**
* do_action_ref_array Execute functions hooked on a specific action hook, specifying arguments in an array.
* #access public
* #since 0.1
* #param string $tag The name of the action to be executed.
* #param array $args The arguments supplied to the functions hooked to <tt>$tag</tt>
* #return null Will return null if $tag does not exist in $filter array
*/
public static function do_action_ref_array($tag, $args) {
if ( ! isset(self::$actions) )
self::$actions = [];
if ( ! isset(self::$actions[$tag]) )
self::$actions[$tag] = 1;
else
++self::$actions[$tag];
// Do 'all' actions first
if ( isset(self::$filters['all']) ) {
self::$current_filter[] = $tag;
$all_args = func_get_args();
self::_call_all_hook($all_args);
}
if ( !isset(self::$filters[$tag]) ) {
if ( isset(self::$filters['all']) )
array_pop(self::$current_filter);
return;
}
if ( !isset(self::$filters['all']) )
self::$current_filter[] = $tag;
// Sort
if ( !isset( $merged_filters[ $tag ] ) ) {
ksort(self::$filters[$tag]);
$merged_filters[ $tag ] = true;
}
reset( self::$filters[ $tag ] );
do {
foreach( (array) current(self::$filters[$tag]) as $the_ )
if ( !is_null($the_['function']) )
call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
} while ( next(self::$filters[$tag]) !== false );
array_pop(self::$current_filter);
}
/**
* did_action Retrieve the number of times an action is fired.
* #access public
* #since 0.1
* #param string $tag The name of the action hook.
* #return int The number of times action hook <tt>$tag</tt> is fired
*/
public static function did_action($tag) {
if ( ! isset( self::$actions ) || ! isset( self::$actions[$tag] ) )
return 0;
return self::$actions[$tag];
}
/**
* HELPERS
*/
/**
* current_filter Retrieve the name of the current filter or action.
* #access public
* #since 0.1
* #return string Hook name of the current filter or action.
*/
public static function current_filter() {
return end( self::$current_filter );
}
/**
* Retrieve the name of the current action.
*
* #since 0.1.2
*
* #uses current_filter()
*
* #return string Hook name of the current action.
*/
public static function current_action() {
return self::current_filter();
}
/**
* Retrieve the name of a filter currently being processed.
*
* The function current_filter() only returns the most recent filter or action
* being executed. did_action() returns true once the action is initially
* processed. This function allows detection for any filter currently being
* executed (despite not being the most recent filter to fire, in the case of
* hooks called from hook callbacks) to be verified.
*
* #since 0.1.2
*
* #see current_filter()
* #see did_action()
* #global array $wp_current_filter Current filter.
*
* #param null|string $filter Optional. Filter to check. Defaults to null, which
* checks if any filter is currently being run.
* #return bool Whether the filter is currently in the stack
*/
public static function doing_filter( $filter = null ) {
if ( null === $filter ) {
return ! empty( self::$current_filter );
}
return in_array( $filter, self::$current_filter );
}
/**
* Retrieve the name of an action currently being processed.
*
* #since 0.1.2
*
* #uses doing_filter()
*
* #param string|null $action Optional. Action to check. Defaults to null, which checks
* if any action is currently being run.
* #return bool Whether the action is currently in the stack.
*/
public static function doing_action( $action = null ) {
return self::doing_filter( $action );
}
/**
* _filter_build_unique_id Build Unique ID for storage and retrieval.
* #param string $tag Used in counting how many hooks were applied
* #param callback $function Used for creating unique id
* #param int|bool $priority Used in counting how many hooks were applied. If === false and $function is an object reference, we return the unique id only if it already has one, false otherwise.
* #return string|bool Unique ID for usage as array key or false if $priority === false and $function is an object reference, and it does not already have a unique id.
*/
private static function _filter_build_unique_id($tag, $function, $priority) {
static $filter_id_count = 0;
if ( is_string($function) )
return $function;
if ( is_object($function) ) {
// Closures are currently implemented as objects
$function = array( $function, '' );
} else {
$function = (array) $function;
}
if (is_object($function[0]) ) {
// Object Class Calling
if ( function_exists('spl_object_hash') ) {
return spl_object_hash($function[0]) . $function[1];
} else {
$obj_idx = get_class($function[0]).$function[1];
if ( !isset($function[0]->filter_id) ) {
if ( false === $priority )
return false;
$obj_idx .= isset(self::$filters[$tag][$priority]) ? count((array)self::$filters[$tag][$priority]) : $filter_id_count;
$function[0]->filter_id = $filter_id_count;
++$filter_id_count;
} else {
$obj_idx .= $function[0]->filter_id;
}
return $obj_idx;
}
} else if ( is_string($function[0]) ) {
// Static Calling
return $function[0].$function[1];
}
}
/**
* __call_all_hook
* #access public
* #since 0.1
* #param (array) $args [description]
*/
public static function __call_all_hook($args) {
reset( self::$filters['all'] );
do {
foreach( (array) current(self::$filters['all']) as $the_ )
if ( !is_null($the_['function']) )
call_user_func_array($the_['function'], $args);
} while ( next(self::$filters['all']) !== false );
}
}//end class
/**
* Hooks Shortcuts not in class
*/
function add_action($hook, $function) {
return Hooks::add_action($hook, $function);
}
function has_action($hook, $function) {
return Hooks::has_action($hook, $function);
}
function do_action($hook, $args = '') {
return Hooks::do_action($hook, $args);
}
function remove_action($hook, $function, $priority = '') {
return Hooks::remove_action($hook, $function, $priority);
}
function remove_all_actions($hook, $priority = '') {
return Hooks::remove_all_actions($hook, $priority);
}
?>
EDIT: Heres my autoloader class:
<?php
class Autoloader {
/**
* File extension as a string. Defaults to ".php".
*/
protected static $fileExt = '.php';
/**
* The top level directory where recursion will begin. Defaults to the current
* directory.
*/
protected static $pathTop = __DIR__;
/**
* A placeholder to hold the file iterator so that directory traversal is only
* performed once.
*/
protected static $fileIterator = null;
/**
* Autoload function for registration with spl_autoload_register
*
* Looks recursively through project directory and loads class files based on
* filename match.
*
* #param string $className
*/
public static function loader($className) {
$directory = new RecursiveDirectoryIterator(static::$pathTop, RecursiveDirectoryIterator::SKIP_DOTS);
if (is_null(static::$fileIterator)) {
static::$fileIterator = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::LEAVES_ONLY);
}
$filename = $className . static::$fileExt;
foreach (static::$fileIterator as $file) {
if (strtolower($file->getFilename()) === strtolower($filename)) {
if ($file->isReadable()) {
include_once $file->getPathname();
}
break;
}
}
}
/**
* Sets the $fileExt property
*
* #param string $fileExt The file extension used for class files. Default is "php".
*/
public static function setFileExt($fileExt) {
static::$fileExt = $fileExt;
}
/**
* Sets the $path property
*
* #param string $path The path representing the top level where recursion should
* begin. Defaults to the current directory.
*/
public static function setPath($path) {
static::$pathTop = $path;
}
}
Autoloader::setFileExt('.php');
spl_autoload_register('Autoloader::loader');
?>
You cannot declare a class as static, but you can do the following:
restricting object instantiation:
private function __construct() {} // Constructor disabled
private function __clone() {} // Cloning disabled
private function __wakeup() {} // Serialization disabled
declare all properties static
declare all methods static
and you have a basically static-like class.
For example:
<?php
class Hooks
{
protected static $filters = [];
protected static $merged_filters = [];
protected static $actions = [];
protected static $current_filter = [];
// You don't need an instance unless you want to implement a simpleton pattern.
// protected static $_instance;
// Disable object instantiation
private function __construct() {}
private function __clone() {}
private function __serialize() {}
// You don't need this either:
// public static function getInstance() { ... }
public static function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1)
{
$idx = self::filter_build_unique_id($tag, $function_to_add, $priority);
self::$filters[$tag][$priority][$idx] = ['function' => $function_to_add, 'accepted_args' => $accepted_args];
unset( self::$merged_filters[ $tag ] );
return true;
}
//
// ...and so on...
//
to answer my issue of autoloader not loading my class, i moved the require to my autoloader to before session_start(); in my system and bam ! autoloaded nicely :)
Related
I'm saving laravel app settings in database, but i can't use this trick in config\app.php. When i use in models or controllers withsetting('app.name') or \setting('app.url') working. But when i use this in config\app.php i'm getting this error;
Fatal error: Uncaught RuntimeException: A facade root has not been set. in /home/vagrant/SeraEnerji/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 234
( ! ) RuntimeException: A facade root has not been set. in /home/vagrant/SeraEnerji/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 234
Call Stack
# Time Memory Function Location
1 0.0001 401512 {main}( ) .../index.php:0
2 0.0252 821816 App\Http\Kernel->handle( ) .../index.php:55
3 0.0459 1270304 App\Http\Kernel->renderException( ) .../Kernel.php:120
4 0.0459 1270304 App\Exceptions\Handler->render( ) .../Kernel.php:326
5 0.0459 1270304 App\Exceptions\Handler->render( ) .../Handler.php:49
6 0.0463 1272856 App\Exceptions\Handler->prepareResponse( ) .../Handler.php:190
7 0.0467 1279088 App\Exceptions\Handler->renderHttpException( ) .../Handler.php:293
8 0.0467 1279088 App\Exceptions\Handler->registerErrorViewPaths( ) .../Handler.php:378
9 0.0514 1359464 Illuminate\Support\Facades\Facade::replaceNamespace( ) .../Handler.php:401
10 0.0514 1359840 Illuminate\Support\Facades\Facade::__callStatic( ) .../Handler.php:401
How can i get values from database for config\app.php?
İnfo: I'm followed this guide, https://www.qcode.in/save-laravel-app-settings-in-database/
My table:
id | name | val
----------------------------------------
1 | app_name | Site Name
2 | app_description | Site Description
3 | app_url | example.com
app\utils\helpers.php
<?php
if (! function_exists('setting')) {
function setting($key, $default = null)
{
if (is_null($key)) {
return new \App\Models\Setting\Setting();
}
if (is_array($key)) {
return \App\Models\Setting::set($key[0], $key[1]);
}
$value = \App\Models\Setting::get($key);
return is_null($value) ? value($default) : $value;
}
}
app\models\setting.php
<?php
namespace App\Models;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class Setting extends Model
{
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* Add a settings value
*
* #param $key
* #param $val
* #param string $type
* #return bool
*/
public static function add($key, $val, $type = 'string')
{
if ( self::has($key) ) {
return self::set($key, $val, $type);
}
return self::create(['name' => $key, 'val' => $val, 'type' => $type]) ? $val : false;
}
/**
* Get a settings value
*
* #param $key
* #param null $default
* #return bool|int|mixed
*/
public static function get($key, $default = null)
{
if ( self::has($key) ) {
$setting = self::getAllSettings()->where('name', $key)->first();
return self::castValue($setting->val, $setting->type);
}
return self::getDefaultValue($key, $default);
}
/**
* Set a value for setting
*
* #param $key
* #param $val
* #param string $type
* #return bool
*/
public static function set($key, $val, $type = 'string')
{
if ( $setting = self::getAllSettings()->where('name', $key)->first() ) {
return $setting->update([
'name' => $key,
'val' => $val,
'type' => $type]) ? $val : false;
}
return self::add($key, $val, $type);
}
/**
* Remove a setting
*
* #param $key
* #return bool
*/
public static function remove($key)
{
if( self::has($key) ) {
return self::whereName($key)->delete();
}
return false;
}
/**
* Check if setting exists
*
* #param $key
* #return bool
*/
public static function has($key)
{
return (boolean) self::getAllSettings()->whereStrict('name', $key)->count();
}
/**
* Get the validation rules for setting fields
*
* #return array
*/
public static function getValidationRules()
{
return self::getDefinedSettingFields()->pluck('rules', 'name')
->reject(function ($val) {
return is_null($val);
})->toArray();
}
/**
* Get the data type of a setting
*
* #param $field
* #return mixed
*/
public static function getDataType($field)
{
$type = self::getDefinedSettingFields()
->pluck('data', 'name')
->get($field);
return is_null($type) ? 'string' : $type;
}
/**
* Get default value for a setting
*
* #param $field
* #return mixed
*/
public static function getDefaultValueForField($field)
{
return self::getDefinedSettingFields()
->pluck('value', 'name')
->get($field);
}
/**
* Get default value from config if no value passed
*
* #param $key
* #param $default
* #return mixed
*/
private static function getDefaultValue($key, $default)
{
return is_null($default) ? self::getDefaultValueForField($key) : $default;
}
/**
* Get all the settings fields from config
*
* #return Collection
*/
private static function getDefinedSettingFields()
{
return collect(config('setting_fields'))->pluck('inputs')->flatten(1);
}
/**
* caste value into respective type
*
* #param $val
* #param $castTo
* #return bool|int
*/
private static function castValue($val, $castTo)
{
switch ($castTo) {
case 'int':
case 'integer':
return intval($val);
break;
case 'bool':
case 'boolean':
return boolval($val);
break;
default:
return $val;
}
}
/**
* Get all the settings
*
* #return mixed
*/
public static function getAllSettings()
{
return Cache::rememberForever('settings.all', function() {
return self::all();
});
}
/**
* Flush the cache
*/
public static function flushCache()
{
Cache::forget('settings.all');
}
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::updated(function () {
self::flushCache();
});
static::created(function() {
self::flushCache();
});
}
}
Okay i found to solution. If there are people who have the same problem with me, the solution I found is as follows.
App\Providers\AppServiceProvider.php
<?php
namespace App\Providers;
use App\Models\Setting;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$settings = Setting::all()->pluck('val', 'name');
config()->set('settings', $settings);
Config::set([
'app.name' => \config('settings.app_name'),
'app.url' => \config('settings.app_url'),
]);
}
}
If I do this I get many properties shown, including display_name, but the first and last names are NOT shown
$user = get_userdata( 4 );
print_r( $user );
However they clearly exist because if I immediately afterwards do this, I am shown the proper last name. The Wordpress docs also mention last_name as being a property.
echo $user->last_name;
So why doesn't print_r show all of the properties? This casts a lot of doubt on being able to use print_r to discover information.
last_name is not a real property of WP_User, but it's made available via magic methods for backwards compatibility.
It's listed as a public property in the docs, but this is a little misleading. More accurately, you can access it as a public property. But when you look at the code, it's being retrieved and set using magic methods.
Proof from the Code
Here's an excerpt of the most relevant code, showing how Wordpress actually keeps a list of several of these backward-compatibility properties, including last_name, in a private, static property called back_compat_keys. When the user requests one of these properties, the magic method __get is called. The magic method uses get_user_meta() to actually retrieve the data for that property. In other words, the data isn't actually stored in the WP_User object; Wordpress just lets you pretend that it is, and it only fetches it when explicitly requested. Here's the code:
<?php
class WP_User {
// ...
/**
* #static
* #since 3.3.0
* #access private
* #var array
*/
private static $back_compat_keys;
public function __construct( $id = 0, $name = '', $blog_id = '' ) {
if ( ! isset( self::$back_compat_keys ) ) {
$prefix = $GLOBALS['wpdb']->prefix;
self::$back_compat_keys = array(
'user_firstname' => 'first_name',
'user_lastname' => 'last_name',
'user_description' => 'description',
'user_level' => $prefix . 'user_level',
$prefix . 'usersettings' => $prefix . 'user-settings',
$prefix . 'usersettingstime' => $prefix . 'user-settings-time',
);
}
// ...
}
// ...
/**
* Magic method for accessing custom fields.
*
* #since 3.3.0
* #access public
*
* #param string $key User meta key to retrieve.
* #return mixed Value of the given user meta key (if set). If `$key` is 'id', the user ID.
*/
public function __get( $key ) {
// ...
if ( isset( $this->data->$key ) ) {
$value = $this->data->$key;
} else {
if ( isset( self::$back_compat_keys[ $key ] ) )
$key = self::$back_compat_keys[ $key ];
$value = get_user_meta( $this->ID, $key, true );
}
// ...
return $value;
}
/**
* Magic method for setting custom user fields.
*
* This method does not update custom fields in the database. It only stores
* the value on the WP_User instance.
*
* #since 3.3.0
* #access public
*
* #param string $key User meta key.
* #param mixed $value User meta value.
*/
public function __set( $key, $value ) {
if ( 'id' == $key ) {
_deprecated_argument( 'WP_User->id', '2.1.0',
sprintf(
/* translators: %s: WP_User->ID */
__( 'Use %s instead.' ),
'<code>WP_User->ID</code>'
)
);
$this->ID = $value;
return;
}
$this->data->$key = $value;
}
/**
* Magic method for unsetting a certain custom field.
*
* #since 4.4.0
* #access public
*
* #param string $key User meta key to unset.
*/
public function __unset( $key ) {
// ...
if ( isset( $this->data->$key ) ) {
unset( $this->data->$key );
}
if ( isset( self::$back_compat_keys[ $key ] ) ) {
unset( self::$back_compat_keys[ $key ] );
}
}
// ...
}
I'm creating an object registry to easily retrieve objects and handle global objects ( objects of which i need just one instance like wrappers around wp_functions or factories )
Basically i have various scenarioes to handle.
1) the object i need to create is a simple class.
2) the object i need to create is a simple class but there is no need for different instances.
3) the object i need to create is created by a factory.
4) the object i need to created needs some parameters.
This is the code i have
<?php
/**
* #author nicola
*
*/
class Ai1ec_Object_Registry implements Ai1ec_Registry_Interface {
CONST PREFIX = 'Ai1ec_';
static private $_objects = array();
static private $_classes = array();
/**
* (non-PHPdoc)
*
* #see Ai1ec_Registry_Interface::get()
*
*/
public function get( $key ) {
$classname = $this->get_classname();
if( ! isset ( self::$_classes[$classname] ) ) {
throw new Ai1ec_Registry_Exception(
'The class "' . $classname . '" was not registered'
);
}
$options = self::$_classes[$classname];
// if it's a global object and it's already set, return it
if ( isset( $options['global'] ) &&
isset( self::$_objects[$classname] ) ) {
return self::$_objects[$classname];
}
$params = array();
if( func_num_args() > 1 ) {
$params = func_get_arg( 1 );
}
// check if the object needs a factory
if ( isset( $options['factory'] ) ) {
return $this->dispatch(
$options['factory'][0],
$options['factory'][1],
$params
);
} else {
if ( empty( $params ) ) {
return new $classname();
} else {
$class = new ReflectionClass( $classname );
return $class->newInstanceArgs( $params );
}
}
}
/**
* (non-PHPdoc)
*
* #see Ai1ec_Registry_Interface::set()
*
*/
public function set( $key, $val ) {
if ( ! is_object( $val ) ) {
throw new Ai1ec_Registry_Exception( 'Only Objects can be stored in the registry' );
}
$classname = $this->get_classname();
if ( isset( self::$_objects[$classname] ) ) {
throw new Ai1ec_Registry_Exception( 'Only one object for each key is allowed' );
}
self::$_objects[$classname] = $val;
}
/**
* Register a class into the registry
*
* #param string $class_name The name of the class to registr
* #param array $options An array of options about the class.
*/
public function register( $class_name, array $options ) {
if( isset( self::$_classes[$class_name] ) ) {
throw new Ai1ec_Registry_Exception( 'A class can\'t be registered twice' );
}
self::$_classes[$class_name] = $options;
}
/**
* A call_user_func_array alternative.
*
* #param string $class
* #param string $method
* #param array $params
*
* #return mixed
*/
public function dispatch( $class, $method, $params = array() ) {
// get an instance of the class
$class = $this->get( $class );
switch ( count( $params) ) {
case 0:
return $class->{$method}();
case 1:
return $class->{$method}( $params[0] );
case 2:
return $class->{$method}( $params[0], $params[1] );
case 3:
return $class->{$method}( $params[0], $params[1], $params[2] );
case 4:
return $class->{$method}(
$params[0],
$params[1],
$params[2],
$params[3]
);
case 5:
return $class->{$method}(
$params[0],
$params[1],
$params[2],
$params[3],
$params[4]
);
default:
return call_user_func_array( array( $class, $method ), $params );
}
}
/**
* Return the class name from the key.
*
* #param string $key
*
* #return string
*/
private function get_classname( $key ) {
return self::PREFIX . $key;
}
}
it should handle all the cases, but is this the best way to do this? Doesn't this introduce too much overhead?
I have an issue in accessing the array in php.
$path = "['a']['b']['c']";
$value = $array.$path;
In the above piece of code I have an multidimensional array named $array.
$path is a dynamic value which I would get from database.
Now I want to retrieve the value from $array using $path but I am not able to.
$value = $array.$path
returns me
Array['a']['b']['c']
rather than the value.
I hope I have explained my question properly.
You have two options. First (evil) if to use eval() function - i.e. interpret your string as code.
Second is to parse your path. That will be:
//$path = "['a']['b']['c']";
preg_match_all("/\['(.*?)'\]/", $path, $rgMatches);
$rgResult = $array;
foreach($rgMatches[1] as $sPath)
{
$rgResult=$rgResult[$sPath];
}
The Kohana framework "Arr" class (API) has a method (Arr::path) that does something similar to what you are requesting. It simply takes an array and a path (with a . as delimiter) and returns the value if found. You could modify this method to suit your needs.
public static function path($array, $path, $default = NULL, $delimiter = NULL)
{
if ( ! Arr::is_array($array))
{
// This is not an array!
return $default;
}
if (is_array($path))
{
// The path has already been separated into keys
$keys = $path;
}
else
{
if (array_key_exists($path, $array))
{
// No need to do extra processing
return $array[$path];
}
if ($delimiter === NULL)
{
// Use the default delimiter
$delimiter = Arr::$delimiter;
}
// Remove starting delimiters and spaces
$path = ltrim($path, "{$delimiter} ");
// Remove ending delimiters, spaces, and wildcards
$path = rtrim($path, "{$delimiter} *");
// Split the keys by delimiter
$keys = explode($delimiter, $path);
}
do
{
$key = array_shift($keys);
if (ctype_digit($key))
{
// Make the key an integer
$key = (int) $key;
}
if (isset($array[$key]))
{
if ($keys)
{
if (Arr::is_array($array[$key]))
{
// Dig down into the next part of the path
$array = $array[$key];
}
else
{
// Unable to dig deeper
break;
}
}
else
{
// Found the path requested
return $array[$key];
}
}
elseif ($key === '*')
{
// Handle wildcards
$values = array();
foreach ($array as $arr)
{
if ($value = Arr::path($arr, implode('.', $keys)))
{
$values[] = $value;
}
}
if ($values)
{
// Found the values requested
return $values;
}
else
{
// Unable to dig deeper
break;
}
}
else
{
// Unable to dig deeper
break;
}
}
while ($keys);
// Unable to find the value requested
return $default;
}
I was hoping to find an elegant solution to nested array access without throwing undefined index errors, and this post hits high on google. I'm late to the party, but I wanted to weigh in for future visitors.
A simple isset($array['a']['b']['c'] can safely check nested values, but you need to know the elements to access ahead of time. I like the dot notation for accessing multidimensional arrays, so I wrote a class of my own. It does require PHP 5.6.
This class parses a string path written in dot-notation and safely accesses the nested values of the array or array-like object (implements ArrayAccess). It will return the value or NULL if not set.
use ArrayAccess;
class SafeArrayGetter implements \JsonSerializable {
/**
* #var array
*/
private $data;
/**
* SafeArrayGetter constructor.
*
* #param array $data
*/
public function __construct( array $data )
{
$this->data = $data;
}
/**
* #param array $target
* #param array ...$indices
*
* #return array|mixed|null
*/
protected function safeGet( array $target, ...$indices )
{
$movingTarget = $target;
foreach ( $indices as $index )
{
$isArray = is_array( $movingTarget ) || $movingTarget instanceof ArrayAccess;
if ( ! $isArray || ! isset( $movingTarget[ $index ] ) ) return NULL;
$movingTarget = $movingTarget[ $index ];
}
return $movingTarget;
}
/**
* #param array ...$keys
*
* #return array|mixed|null
*/
public function getKeys( ...$keys )
{
return static::safeGet( $this->data, ...$keys );
}
/**
* <p>Access nested array index values by providing a dot notation access string.</p>
* <p>Example: $safeArrayGetter->get('customer.paymentInfo.ccToken') ==
* $array['customer']['paymentInfo']['ccToken']</p>
*
* #param $accessString
*
* #return array|mixed|null
*/
public function get( $accessString )
{
$keys = $this->parseDotNotation( $accessString );
return $this->getKeys( ...$keys );
}
/**
* #param $string
*
* #return array
*/
protected function parseDotNotation( $string )
{
return explode( '.', strval( $string ) );
}
/**
* #return array
*/
public function toArray()
{
return $this->data;
}
/**
* #param int $options
* #param int $depth
*
* #return string
*/
public function toJson( $options = 0, $depth = 512 )
{
return json_encode( $this, $options, $depth );
}
/**
* #param array $data
*
* #return static
*/
public static function newFromArray( array $data )
{
return new static( $data );
}
/**
* #param \stdClass $data
*
* #return static
*/
public static function newFromObject( \stdClass $data )
{
return new static( json_decode( json_encode( $data ), TRUE ) );
}
/**
* Specify data which should be serialized to JSON
* #link http://php.net/manual/en/jsonserializable.jsonserialize.php
* #return array data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* #since 5.4.0
*/
function jsonSerialize()
{
return $this->toArray();
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WAMP Stack PHP “Fatal error: Class ‘SoapClient’ not found”
I downloaded a library from this site library and when I tried to use it's examples it says : "Fatal error: Class 'SoapClient' not found in C:\wamp\www\Amazon-ECS\Exeu-Amazon-ECS-PHP-Library-9030053\lib\AmazonECS.class.php on line 231" How should I able to fix this?
<?php
/**
* Amazon ECS Class
* http://www.amazon.com
* =====================
*
* This class fetchs productinformation via the Product Advertising API by Amazon (formerly ECS).
* It supports three basic operations: ItemSearch, ItemLookup and BrowseNodeLookup.
* These operations could be expanded with extra prarmeters to specialize the query.
*
* Requirement is the PHP extension SOAP.
*
* #package AmazonECS
* #license http://www.gnu.org/licenses/gpl.txt GPL
* #version 1.3.4-DEV
* #author Exeu <exeu65#googlemail.com>
* #contributor Julien Chaumond <chaumond#gmail.com>
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library/wiki Wiki
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library Source
*/
class AmazonECS
{
const RETURN_TYPE_ARRAY = 1;
const RETURN_TYPE_OBJECT = 2;
/**
* Baseconfigurationstorage
*
* #var array
*/
private $requestConfig = array(
'requestDelay' => false
);
/**
* Responseconfigurationstorage
*
* #var array
*/
private $responseConfig = array(
'returnType' => self::RETURN_TYPE_OBJECT,
'responseGroup' => 'Small',
'optionalParameters' => array()
);
/**
* All possible locations
*
* #var array
*/
private $possibleLocations = array('de', 'com', 'co.uk', 'ca', 'fr', 'co.jp', 'it', 'cn', 'es');
/**
* The WSDL File
*
* #var string
*/
protected $webserviceWsdl = 'http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl';
/**
* The SOAP Endpoint
*
* #var string
*/
protected $webserviceEndpoint = 'https://webservices.amazon.%%COUNTRY%%/onca/soap?Service=AWSECommerceService';
/**
* #param string $accessKey
* #param string $secretKey
* #param string $country
* #param string $associateTag
*/
public function __construct($accessKey, $secretKey, $country, $associateTag)
{
if (empty($accessKey) || empty($secretKey))
{
throw new Exception('No Access Key or Secret Key has been set');
}
$this->requestConfig['accessKey'] = $accessKey;
$this->requestConfig['secretKey'] = $secretKey;
$this->associateTag($associateTag);
$this->country($country);
}
/**
* execute search
*
* #param string $pattern
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function search($pattern, $nodeId = null)
{
if (false === isset($this->requestConfig['category']))
{
throw new Exception('No Category given: Please set it up before');
}
$browseNode = array();
if (null !== $nodeId && true === $this->validateNodeId($nodeId))
{
$browseNode = array('BrowseNode' => $nodeId);
}
$params = $this->buildRequestParams('ItemSearch', array_merge(
array(
'Keywords' => $pattern,
'SearchIndex' => $this->requestConfig['category']
),
$browseNode
));
return $this->returnData(
$this->performSoapRequest("ItemSearch", $params)
);
}
/**
* execute ItemLookup request
*
* #param string $asin
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function lookup($asin)
{
$params = $this->buildRequestParams('ItemLookup', array(
'ItemId' => $asin,
));
return $this->returnData(
$this->performSoapRequest("ItemLookup", $params)
);
}
/**
* Implementation of BrowseNodeLookup
* This allows to fetch information about nodes (children anchestors, etc.)
*
* #param integer $nodeId
*/
public function browseNodeLookup($nodeId)
{
$this->validateNodeId($nodeId);
$params = $this->buildRequestParams('BrowseNodeLookup', array(
'BrowseNodeId' => $nodeId
));
return $this->returnData(
$this->performSoapRequest("BrowseNodeLookup", $params)
);
}
/**
* Implementation of SimilarityLookup
* This allows to fetch information about product related to the parameter product
*
* #param string $asin
*/
public function similarityLookup($asin)
{
$params = $this->buildRequestParams('SimilarityLookup', array(
'ItemId' => $asin
));
return $this->returnData(
$this->performSoapRequest("SimilarityLookup", $params)
);
}
/**
* Builds the request parameters
*
* #param string $function
* #param array $params
*
* #return array
*/
protected function buildRequestParams($function, array $params)
{
$associateTag = array();
if(false === empty($this->requestConfig['associateTag']))
{
$associateTag = array('AssociateTag' => $this->requestConfig['associateTag']);
}
return array_merge(
$associateTag,
array(
'AWSAccessKeyId' => $this->requestConfig['accessKey'],
'Request' => array_merge(
array('Operation' => $function),
$params,
$this->responseConfig['optionalParameters'],
array('ResponseGroup' => $this->prepareResponseGroup())
)));
}
/**
* Prepares the responsegroups and returns them as array
*
* #return array|prepared responsegroups
*/
protected function prepareResponseGroup()
{
if (false === strstr($this->responseConfig['responseGroup'], ','))
return $this->responseConfig['responseGroup'];
return explode(',', $this->responseConfig['responseGroup']);
}
/**
* #param string $function Name of the function which should be called
* #param array $params Requestparameters 'ParameterName' => 'ParameterValue'
*
* #return array The response as an array with stdClass objects
*/
protected function performSoapRequest($function, $params)
{
if (true === $this->requestConfig['requestDelay']) {
sleep(1);
}
$soapClient = new SoapClient(
$this->webserviceWsdl,
array('exceptions' => 1)
);
$soapClient->__setLocation(str_replace(
'%%COUNTRY%%',
$this->responseConfig['country'],
$this->webserviceEndpoint
));
$soapClient->__setSoapHeaders($this->buildSoapHeader($function));
return $soapClient->__soapCall($function, array($params));
}
/**
* Provides some necessary soap headers
*
* #param string $function
*
* #return array Each element is a concrete SoapHeader object
*/
protected function buildSoapHeader($function)
{
$timeStamp = $this->getTimestamp();
$signature = $this->buildSignature($function . $timeStamp);
return array(
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'AWSAccessKeyId',
$this->requestConfig['accessKey']
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Timestamp',
$timeStamp
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Signature',
$signature
)
);
}
/**
* provides current gm date
*
* primary needed for the signature
*
* #return string
*/
final protected function getTimestamp()
{
return gmdate("Y-m-d\TH:i:s\Z");
}
/**
* provides the signature
*
* #return string
*/
final protected function buildSignature($request)
{
return base64_encode(hash_hmac("sha256", $request, $this->requestConfig['secretKey'], true));
}
/**
* Basic validation of the nodeId
*
* #param integer $nodeId
*
* #return boolean
*/
final protected function validateNodeId($nodeId)
{
if (false === is_numeric($nodeId) || $nodeId <= 0)
{
throw new InvalidArgumentException(sprintf('Node has to be a positive Integer.'));
}
return true;
}
/**
* Returns the response either as Array or Array/Object
*
* #param object $object
*
* #return mixed
*/
protected function returnData($object)
{
switch ($this->responseConfig['returnType'])
{
case self::RETURN_TYPE_OBJECT:
return $object;
break;
case self::RETURN_TYPE_ARRAY:
return $this->objectToArray($object);
break;
default:
throw new InvalidArgumentException(sprintf(
"Unknwon return type %s", $this->responseConfig['returnType']
));
break;
}
}
/**
* Transforms the responseobject to an array
*
* #param object $object
*
* #return array An arrayrepresentation of the given object
*/
protected function objectToArray($object)
{
$out = array();
foreach ($object as $key => $value)
{
switch (true)
{
case is_object($value):
$out[$key] = $this->objectToArray($value);
break;
case is_array($value):
$out[$key] = $this->objectToArray($value);
break;
default:
$out[$key] = $value;
break;
}
}
return $out;
}
/**
* set or get optional parameters
*
* if the argument params is null it will reutrn the current parameters,
* otherwise it will set the params and return itself.
*
* #param array $params the optional parameters
*
* #return array|AmazonECS depends on params argument
*/
public function optionalParameters($params = null)
{
if (null === $params)
{
return $this->responseConfig['optionalParameters'];
}
if (false === is_array($params))
{
throw new InvalidArgumentException(sprintf(
"%s is no valid parameter: Use an array with Key => Value Pairs", $params
));
}
$this->responseConfig['optionalParameters'] = $params;
return $this;
}
/**
* Set or get the country
*
* if the country argument is null it will return the current
* country, otherwise it will set the country and return itself.
*
* #param string|null $country
*
* #return string|AmazonECS depends on country argument
*/
public function country($country = null)
{
if (null === $country)
{
return $this->responseConfig['country'];
}
if (false === in_array(strtolower($country), $this->possibleLocations))
{
throw new InvalidArgumentException(sprintf(
"Invalid Country-Code: %s! Possible Country-Codes: %s",
$country,
implode(', ', $this->possibleLocations)
));
}
$this->responseConfig['country'] = strtolower($country);
return $this;
}
/**
* Setting/Getting the amazon category
*
* #param string $category
*
* #return string|AmazonECS depends on category argument
*/
public function category($category = null)
{
if (null === $category)
{
return isset($this->requestConfig['category']) ? $this->requestConfig['category'] : null;
}
$this->requestConfig['category'] = $category;
return $this;
}
/**
* Setting/Getting the responsegroup
*
* #param string $responseGroup Comma separated groups
*
* #return string|AmazonECS depends on responseGroup argument
*/
public function responseGroup($responseGroup = null)
{
if (null === $responseGroup)
{
return $this->responseConfig['responseGroup'];
}
$this->responseConfig['responseGroup'] = $responseGroup;
return $this;
}
/**
* Setting/Getting the returntype
* It can be an object or an array
*
* #param integer $type Use the constants RETURN_TYPE_ARRAY or RETURN_TYPE_OBJECT
*
* #return integer|AmazonECS depends on type argument
*/
public function returnType($type = null)
{
if (null === $type)
{
return $this->responseConfig['returnType'];
}
$this->responseConfig['returnType'] = $type;
return $this;
}
/**
* Setter/Getter of the AssociateTag.
* This could be used for late bindings of this attribute
*
* #param string $associateTag
*
* #return string|AmazonECS depends on associateTag argument
*/
public function associateTag($associateTag = null)
{
if (null === $associateTag)
{
return $this->requestConfig['associateTag'];
}
$this->requestConfig['associateTag'] = $associateTag;
return $this;
}
/**
* #deprecated use returnType() instead
*/
public function setReturnType($type)
{
return $this->returnType($type);
}
/**
* Setting the resultpage to a specified value.
* Allows to browse resultsets which have more than one page.
*
* #param integer $page
*
* #return AmazonECS
*/
public function page($page)
{
if (false === is_numeric($page) || $page <= 0)
{
throw new InvalidArgumentException(sprintf(
'%s is an invalid page value. It has to be numeric and positive',
$page
));
}
$this->responseConfig['optionalParameters'] = array_merge(
$this->responseConfig['optionalParameters'],
array("ItemPage" => $page)
);
return $this;
}
/**
* Enables or disables the request delay.
* If it is enabled (true) every request is delayed one second to get rid of the api request limit.
*
* Reasons for this you can read on this site:
* https://affiliate-program.amazon.com/gp/advertising/api/detail/faq.html
*
* By default the requestdelay is disabled
*
* #param boolean $enable true = enabled, false = disabled
*
* #return boolean|AmazonECS depends on enable argument
*/
public function requestDelay($enable = null)
{
if (false === is_null($enable) && true === is_bool($enable))
{
$this->requestConfig['requestDelay'] = $enable;
return $this;
}
return $this->requestConfig['requestDelay'];
}
}
The error appears to be caused by the version of PHP that you have does not have the SOAP extension enabled.
To resolve this simply start wamp, click on the wamp system tray icon. Within this screen select PHP then PHP extensions. This will display a list of extensions. Ensure that php_soap is ticked.
If you intend to access soap servers that use HTTPs then you will also ensure php_openssl is ticked.