In CodeIgniter, when creating and calling a custom library, it is possible to pass variables (parameters) to the library via a second optional variable.
Example taken from the documentation:
$params = array('type' => 'large', 'color' => 'red');
$this->load->library('someclass', $params);
and
class Someclass {
public function __construct($params)
{
// Do something with $params
}
}
In some cases, it may be desirable to reload the library with a different set of parameters. However, this does not seem to be possible. When the [...]->library() method is called again with a new set of parameters, only the original parameters are expressed—not the new ones. The CodeIgniter documentation does not address this issue.
What are my options?
Related
I would like to understand further how I can harness the power of this feature where one could pass a model as an empty object which is already instantiated and ready for use.
The problem I'm facing is re-usability, I do not want to write the function twice.
So let's take for instance the following function:
API
Route::post('/onboarding/email-verification', 'CustomerController#verifyEmail');
Controller
public function verifyEmail(Request $request, Customer $customer) {}
The function above serves a simple purpose, it allows me to use the Request instance I am already receiving from the http request, where I have an instantiated object as $request, where I can make further use of.
Now in the same controller, I am looking to use verifyEmail(), as $this->verifyEmail() but I can't, since the function is expecting 2 params, I tried rebuilding the function like:
$this->verifyEmail(new Request(['email' => $customer->email]), new Customer()) - since the function expects an email. I tried many other iteration but even if they did work, they look horrendous.
So my question is simple, how can you re-use a Laravel function that is built with models/objects in it's params.
Thanks
You can use a third parameter :
public function verifyEmail(Request $request, Customer $customer, ?string Email)
{
if ($email) {
// use var
} else {
// use request
}
}
And you just inject Request to use it, or make $request parameter nullable :
$this->verifyEmail($request, new Customer(), 'youremail#test.com')
If you want to keep your 2 parameters, you can define new $request variable like this :
$request = new \Illuminate\Http\Request();
$request->replace(['email' => 'email#totest.com']);
$this->verifyEmail($request, new Customer());
I am currently working on a project on the Codeigniter MVC framework. I have created an authentication library to suite the project with several functions. I will be checking and validating data in my controller and then passing the data into one of these functions. For example my register function takes about 5 parameters at the moment, but should I pass these in as strings or should I pass them in as an array? Is there a set rule or is this personal preference?
It's personal preference. If you are passing the parameters to a function, it can be easier to pass them in an array if there are quite a few parameters. Also, passing the parameters in an array means you don't have to pass them to a function in a specific order as you must do when passing each parameter to a function individually.
Example...
function myFunc($param1, $param2, $param3, $param4, $param5) { ... }
For the above, you must pass all params in the exact order...
myFunc('Something', '', 'Something Else', '', '');
An easier way is to pass the parameters in an array...
function myFunc($array) { ... }
The $array can contain all or some of the parameters in any order...
$array { 'param1' => 'Something', 'param3' => 'Something Else' ... }
You just have to make sure your function addresses missing parameters gracefully if you are passing them via an array...
if (empty($array['param1'])) return false; // or whatever should happen
Well it's up to you, but with an array you have to check yourself that proper indices were set to proper types. With individual parameters (and possibly type hints) php will do this for you. Also individual parameters work better with IDE.
How can I get various parameters related to the page request in zf2? Like post/get parameters, the route being accessed, headers sent and files uploaded.
The easiest way to do that would be to use the Params plugin, introduced in beta5. It has utility methods to make it easy to access different types of parameters. As always, reading the tests can prove valuable to understand how something is supposed to be used.
Get a single value
To get the value of a named parameter in a controller, you will need to select the appropriate method for the type of parameter you are looking for and pass in the name.
Examples:
$this->params()->fromPost('paramname'); // From POST
$this->params()->fromQuery('paramname'); // From GET
$this->params()->fromRoute('paramname'); // From RouteMatch
$this->params()->fromHeader('paramname'); // From header
$this->params()->fromFiles('paramname'); // From file being uploaded
Default values
All of these methods also support default values that will be returned if no parameter with the given name is found.
Example:
$orderBy = $this->params()->fromQuery('orderby', 'name');
When visiting http://example.com/?orderby=birthdate,
$orderBy will have the value birthdate.
When visiting http://example.com/,
$orderBy will have the default value name.
Get all parameters
To get all parameters of one type, just don't pass in anything and the Params plugin will return an array of values with their names as keys.
Example:
$allGetValues = $this->params()->fromQuery(); // empty method call
When visiting http://example.com/?orderby=birthdate&filter=hasphone $allGetValues will be an array like
array(
'orderby' => 'birthdate',
'filter' => 'hasphone',
);
Not using Params plugin
If you check the source code for the Params plugin, you will see that it's just a thin wrapper around other controllers to allow for more consistent parameter retrieval. If you for some reason want/need to access them directly, you can see in the source code how it's done.
Example:
$this->getRequest()->getRequest('name', 'default');
$this->getEvent()->getRouteMatch()->getParam('name', 'default');
NOTE: You could have used the superglobals $_GET, $_POST etc., but that is discouraged.
The easisest way to get a posted json string, for example, is to read the contents of 'php://input' and then decode it. For example i had a simple Zend route:
'save-json' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/save-json/',
'defaults' => array(
'controller' => 'CDB\Controller\Index',
'action' => 'save-json',
),
),
),
and i wanted to post data to it using Angular's $http.post. The post was fine but the retrive method in Zend
$this->params()->fromPost('paramname');
didn't get anything in this case. So my solution was, after trying all kinds of methods like $_POST and the other methods stated above, to read from 'php://':
$content = file_get_contents('php://input');
print_r(json_decode($content));
I got my json array in the end.
Hope this helps.
require_once 'lib/Zend/Loader/StandardAutoloader.php';
$loader = new Zend\Loader\StandardAutoloader(array('autoregister_zf' => true));
$loader->registerNamespace('Http\PhpEnvironment', 'lib/Zend/Http');
// Register with spl_autoload:
$loader->register();
$a = new Zend\Http\PhpEnvironment\Request();
print_r($a->getQuery()->get()); exit;
All the above methods will work fine if your content-type is "application/-www-form-urlencoded".
But if your content-type is "application/json" then you will have to do the following:
$params = json_decode(file_get_contents('php://input'), true);
print_r($params);
Reason : See #7 in https://www.toptal.com/php/10-most-common-mistakes-php-programmers-make
If You have no access to plugin for instance outside of controller You can get params from servicelocator like this
//from POST
$foo = $this->serviceLocator->get('request')->getPost('foo');
//from GET
$foo = $this->serviceLocator->get('request')->getQuery()->foo;
//from route
$foo = $this->serviceLocator->get('application')->getMvcEvent()->getRouteMatch()->getParam('foo');
I create a URL like this:
$app->createAbsoluteUrl('/', array(
'param1' => 'val1',
'param2' => 'var2',
);
The generated URL is:
http://mysite.com/param1/var1/param2/var2
But I expect a url like this:
http://mysite.com/?param1=var1¶m2=var2
In function manual it says:
$params array additional GET parameters (name=>value). Both the name and value will be URL-encoded.
But it doesn't seem to work like that. How I can generate the expected URL? Thanks.
You need to specify that the urlManager application component should use the "get" format for the URLs it generates; the default is to use the "path" format. The Yii guide explains how to do it inside your application configuration:
array(
......
'components'=>array(
......
'urlManager'=>array(
'urlFormat'=>'get',
),
),
);
Update: So your urlFormat is "path" and that's by design... what about alternatives?
If you don't mind extending CWebApplication and using your own derived class in its place then you have several options such as:
Define your own createUrlEx method based on the original createUrl. It could look like this:
public function createUrlEx($format,$route,$params=array(),$ampersand='&')
{
$oldFormat = $this->getUrlManager()->getUrlFormat();
$this->getUrlManager()->setUrlFormat($format);
$url = $this->getUrlManager()->createUrl($route,$params,$ampersand);
$this->getUrlManager()->setUrlFormat($oldFormat);
return $url;
}
Override registerCoreComponents so that you can have a second url manager:
protected function registerCoreComponents()
{
parent::registerCoreComponents();
$components=array(
'specialUrlManager'=>array(
'class'=>'CUrlManager',
'urlFormat'=>'get',
),
);
$this->setComponents($components);
}
You can now call Yii::app()->specialUrlManager->createUrl(...) anytime.
You can also approach the problem in other ways:
Extend CUrlManager and expose a method that allows you to select the flavor of url to create on the spot.
If you only need "get" urls in one or two places, you can always create a new CUrlManager object, configure it on the spot, call createUrl and then discard it. You could also hide this ugliness behind a free function. Essentially this (admittedly not recommended) approach is a low-tech version of the first workaround given that has the advantage that you don't need to extend CWebApplication.
You should be able to use something like Yii::app()->urlManager->createPathInfo This will generate the query string as ...&var=val&... using a custom & and = if you like. You could use this to create a query string version of a URL on demand with:
$url = $this->createAbsoluteUrl('/').'index.php?'.Yii::app()->urlManager->createPathInfo($arrayOfStuff);
Or you might even be able to do:
Yii::app()->urlManager->urlFormat = 'get';
$this->createAbsoluteUrl('My/Path');
Yii::app()->urlManager->urlFormat = 'path';
Although I haven't and don't want to test the second method.
URL route should be in the format of 'ControllerID/ActionID'. manual
Your manual link is for CController and isn't for CApplication.
I am making a library for CodeIgniter, and I wish to pass multiple parameters of different types (a PDO object, username and password, configurations, etc).
I know I can pass an array of all of these things, but that doesn't seem to be the best way of doing things (as $params can't ever describe what is needed).
How can I pass multiple parameters to a library?
Thanks in advance.
There are several approaches to this particular problem. I'll list (in preferred order) ways I know to solve it:
Associative Array Arguments:
This approach is pretty flexible, as the order of the parameters doesn't matter, and it resolves a pretty big complaint many have with how PHP defines function parameters. You simply pass in the "non-default" parameters you want. This is probably the most "codeigniterish" way to do it, if that's even a thing.
class MyLibrary {
public function __construct($params = array())
{
// Merge default parameter names and values,
// with given $params array
$params = array_merge(array(
'server' => 'myserver',
'database' => 'mydatabase',
'username' => 'myuser',
'password' => 'mypassword'
), $params);
// Create variables from parameter list
extract($params);
var_dump($server);
var_dump($database);
var_dump($username);
var_dump($password);
}
}
// Initialization:
$this->load->library('mylibrary', array(
'server' => 'server-arg1',
'database' => 'database-arg2'
));
Numbered Arguments:
This approach replicates the typical PHP parameter paradigm (defines names, orders, and default values for all expected parameters).
class MyLibrary {
public function __construct($params = array())
{
// Add relevant defaults to missing parameters
$params = array_merge($params, array_slice(array(
'myserver',
'mydatabase',
'myuser',
'mypassword'
), count($params)));
// Create variables from parameter list
extract(array_combine(array(
'server',
'database',
'username',
'password'
), $params));
var_dump($server);
var_dump($database);
var_dump($username);
var_dump($password);
}
}
// Initialization:
$this->load->library('mylibrary', array('server-arg1', 'database-arg2'));
Override the CI Loader class:
This is AT YOUR OWN RISK. Basically, the CI_Loader::_ci_init_class() method needs to be overridden with a MY_Loader class and corresponding method. These are the lines that you "don't like" (lines 1003-1012 in my install):
// Instantiate the class
$CI =& get_instance();
if ($config !== NULL)
{
$CI->$classvar = new $name($config);
}
else
{
$CI->$classvar = new $name;
}
The "safest" replacement that I could guess would be this:
// Instantiate the class
$CI =& get_instance();
if (isset($config[1])
{
// With numeric keys, it makes sense to assume this is
// is an ordered parameter list
$rc = new ReflectionClass($name);
$CI->$classvar = $rc->newInstanceArgs($config);
}
elseif ($config !== NULL)
{
// Otherwise, the default CI approach is probably good
$CI->$classvar = new $name($config);
}
else
{
// With no parameters, it's moot
$CI->$classvar = new $name;
}
I really don't know how many things this will break, but I can almost certainly say there will be something. It's not really worth the risk. I'd STRONGLY recommend the first approach above.
Cheers!
One can sidestep Codeigniters Loader class and instantiate objects directly. APPPATH is a Codeigniter constant.
require_once( APPPATH.'libraries/some_class.php' );
$this->Some_class = new Some_class( param_1, param_2, param_n );
$this->Some_class->do_something();
Usage is the same as if you'd loaded the Library with Codeigniters Loader class.
$this->load->library( 'some_class' )
$this->Some_class->do_something();
I personally don't like passing arrays to my classes becasue then you have to validate the contents. PHP can take care of this for you when the parameters are passed to the __construct() individually.
From my experience with CodeIgniter, unless you modify the loader class to act differently (as you might know, in application/core/ folder is where you have to implement you custom class) there is no way (no one of that I know)
I use many external libraries (mostly api sdks or sparks) and I like to build my own config files where to set values that will be loaded into libraries when called upon them, so when I need to load libraries I just build a simple or multidimensional $params = array() according to my needs and then work with it inside library.
So in short answer, $this->load->library('lib_name', $params) is the only way I am aware of.
By default in CodeIgniter you can't. You can only pass a single param to your library classes. As stated before that param could be an array that contains all the other parameters and you could just use it as $param[0], $param[1]....
But I agree with you, it's kinda strange and ugly to see.
If you have PHP5+ there's the ReflectionClass that could help you with this but you should edit the source code of CodeIgniter and implement this function. The function you are looking for is ReflectionClass::newInstance() that you can find here.
use $this->upload->initialize($configUpload); after $this->load->library('upload', $configUpload);
this is best way:create a big array
$data1=array('item1','item2','item3');
$arr=array('data1'=>$data1,'data2'=>'item4','data3'=>'item5');//create big array of datas
extract($arr);//convert that to variables again after send to library
//use that again
print_r($data);
echo $data2;
echo $data3;