Codeigniter passing objects within views - php

I am loading a view from a Controller file and that View loads another view which a final one as below,
First view Call :
Controller: device.php
public function device_name(){
$data = new stdClass;
$data->device_name = "Apple";
$this->load->view('apple_device',$data);
}
Second view call :
View: In apple_device.php
$device_name->count = 123;
$this->load->view('device_counts',$device_name);
I am using object here instead of an array as a passing variable between views. But if i use array, it works fine.
And the above code throwing error as like below,
Message: Attempt to assign property of non-object
Any help would be appreciated.

Yes, you may still pass through objects, but not at the 'first level', you'll need to wrap the object you want to pass through inside an array.
public function device_name(){
$mobiles = new stdClass;
$mobiles->device_name = "Apple";
$data = array( "mobiles" => $mobiles );
$this->load->view('apple_device',$data);
}
This is because when CodeIgniter will initialize the view, it will check the contents of the second view() parameter. If it's an object - it'll cast it to an array via get_object_vars() (See github link)
protected function _ci_object_to_array($object)
{
return is_object($object) ? get_object_vars($object) : $object;
}
Which will in turn, turn your initial $data into:
$data = new stdClass;
$data->device_name = "Apple";
$example = get_object_vars( $data );
print_r( $example );
Array ( [device_name] => Apple )
Thus to avoid this, nest your object inside an array() which will avoid being converted.

Related

Call to undefined method stdClass::count() in laravel

I trying to paginate my JSON response but got error like this
Call to undefined method stdClass::count()
My JSON response from the Laravel API by using guzzle ......
here is my controller code
public function index()
{
$response = $this->client->get('getUserIndex')->getBody();
$content = json_decode($response->getContents());
$total = $content->count();
$paginationRecord = CollectionPaginate::paginate($content, $total, '15');
return view('configuration.comuserprofiles.ComUserProfilesList', ['paginationRecord' => $paginationRecord->data]);
}
$content = json_decode($response->getContents());
$total = $content->count();
I am not entirely sure why you think the result of json_decode would have a count method? The JSON decoding always results in a generic object (stdClass) since there's no way for the PHP interpreter to know it represents an available class.
The ->count method is available on Countable implementations (such as ArrayCollection). If you expect a Countable class, then you can either have a factory to build your object from JSON or try to cast the stdClass to ArrayCollection.
Otherwise, if your JSON data is a valid array, you can try to use
$decoded = json_decode($data, true)
meaning it will decode it to an array rather than an object, which enables you to do
count($decoded)
$content is an object, not a collection or array you can use php method count with array get $total
Please Change to
public function index()
{
$response = $this->client->get('getUserIndex')->getBody();
$content = json_decode($response->getContents(),true );
$total = count($content);
$paginationRecord = CollectionPaginate::paginate($content, $total, '15');
return view('configuration.comuserprofiles.ComUserProfilesList', ['paginationRecord' => $paginationRecord->data]);
}

Print array from class php

I'm trying to print data from an array. The array is from a class. I'm getting
array(0) { }
instead of:
Array ( [0] => header_index.php [1] => footer.php )
The code is:
<?php
class TemplateModel {
public function getTemplate($template = "index"){
switch($template){
case "index":
$templateconfig = array("header_index.php","footer.php");
break;
}
return $templateconfig;
}
}
$temodel = new TemplateModel();
var_dump(get_object_vars($temodel));
$temodel -> getTemplate();
?>
What i'm doing wrong? Thanks in Advance
var_dump(get_object_vars($temodel));
will output class member $temodel. There are no class member variables, so output is empty. If you want to output your array, you have to for example do this:
print_r($temodel -> getTemplate());
My immediate thoughts are it looks like you are setting the variables in the function 'getTemplate' and that is not being called until after the var_dump.
ADD:
And I just noticed you are not capturing the return of the function. You are var_dumping the object created from the class.
FIX:
<?php
class TemplateModel {
public function getTemplate($template = "index"){
switch($template){
case "index":
$templateconfig = array("header_index.php","footer.php");
break;
}
return $templateconfig;
}
}
$temodel = new TemplateModel();
$returned_var = $temodel -> getTemplate();
var_dump($returned_var);
?>
If you want to set the array as a variable of the object, that is a different problem.
It looks like you're not initializing the $templateconfig variable until getTemplate() is called. And you don't call it until after var_dump().
So basically, you're dumping an object that has no initalized member properties which is why you see an empty array.
Your object itself has no variables (properties) to be returned with a call to get_object_vars(). The $templateconfig variable only exists within the scope of the getTemplate() function and is not a property of the object.
If your intent is to make it a property of the object, you should do something like this:
class TemplateModel {
private $template_config = array(
'index' => array("header_index.php","footer.php"),
// add other configs here
);
public function getTemplate($template = "index"){
if(empty($template)) {
throw new Exception('No value specified for $template');
} else if (!isset($this->template_config[$template])) {
throw new Exception('Invalid value specified for $template');
}
return $this->template_config[$template];
}
}
$temodel = new TemplateModel();
var_dump($temodel->getTemplate());
Note here if you call get_object_vars() you still would get an empty array as I have made the $template_config variable private, forcing the caller to use the getTemplate() method to access the template data.

PHP : object method+proprety call from var

I want to call an object method+property with the content stored in a var ...
for example :
// setup the object
$xpath = new DOMXpath();
// setup the 'method'+'property' to call
$var1 = "query('something')->item(O)->nodeValue";
$return = $xpath->$var1();
Obviously, I make a mistake ... assuming that direct call is working, i.e.:
$return2 = $xpath->query('something')->item(0)->value;
echo "Return2 : ".$return2; //print okeedokee ...
How to pass args to query()? And how to add extra args to it?
I think you have to call
$return=$xpath->$var1;
Note : call_user_func is the function you need
Example :
alpha.php
class Alpha
{
public function getAlpha($arr_input)
{
echo "<pre>";
print_r($arr_input);
}
}
index.php
include_once 'alpha.php';
$post = array('one','two','three');
$obj_alpha = new Alpha();
call_user_func( array( $obj_alpha , 'getAlpha' ), $post ) ;
//here I call `getAlpha` function from object of class alpha (`$obj_alpha`)
with argument `$post`
//will print $post array
You can do this using eval():
$return = eval('return $xpath->' . $var1 .';');
However, using eval() with user-input is pretty much always a bad idea. So be careful there.

Dynamically call Class with variable number of parameters in the constructor

I know that it is possible to call a function with a variable number of parameters with call_user_func_array() found here -> http://php.net/manual/en/function.call-user-func-array.php . What I want to do is nearly identical, but instead of a function, I want to call a PHP class with a variable number of parameters in it's constructor.
It would work something like the below, but I won't know the number of parameters, so I won't know how to instantiate the class.
<?php
//The class name will be pulled dynamically from another source
$myClass = '\Some\Dynamically\Generated\Class';
//The parameters will also be pulled from another source, for simplicity I
//have used two parameters. There could be 0, 1, 2, N, ... parameters
$myParameters = array ('dynamicparam1', 'dynamicparam2');
//The instantiated class needs to be called with 0, 1, 2, N, ... parameters
//not just two parameters.
$myClassInstance = new $myClass($myParameters[0], $myParameters[1]);
You can do the following using ReflectionClass
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = array ('dynamicparam1', 'dynamicparam2');
$reflection = new \ReflectionClass($myClass);
$myClassInstance = $reflection->newInstanceArgs($myParameters);
PHP manual: http://www.php.net/manual/en/reflectionclass.newinstanceargs.php
Edit:
In php 5.6 you can achieve this with Argument unpacking.
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = ['dynamicparam1', 'dynamicparam2'];
$myClassInstance = new $myClass(...$myParameters);
I implement this approach a lot when function args are > 2, rather then end up with an Christmas list of arguments which must be in a specific order, I simply pass in an associative array. By passing in an associative array, I can check for necessary and optional args and handle missing values as needed. Something like:
class MyClass
{
protected $requiredArg1;
protected $optionalArg1;
public function __construct(array $options = array())
{
// Check for a necessary arg
if (!isset($options['requiredArg1'])) {
throw new Exception('Missing requiredArg1');
}
// Now I can just localize
$requiredArg1 = $options['requiredArg1'];
$optionalArg1 = (isset($options['optionalArg1'])) ? $options['optionalArg1'] : null;
// Now that you have localized args, do what you want
$this->requiredArg1 = $requiredArg1;
$this->optionalArg1 = $optionalArg1;
}
}
// Example call
$class = 'MyClass';
$array = array('requiredArg1' => 'Foo!', 'optionalArg1' => 'Bar!');
$instance = new $class($array);
var_dump($instance->getRequiredArg1());
var_dump($instance->getOptionalArg1());
I highly recommend using an associative array, however it is possible to use a 0-index array. You will have to be extremely careful when constructing the array and account for indices that have meaning, otherwise you will pass in an array with offset args and wreck havoc with your function.
You can do that using func_get_args().
class my_class {
function __construct( $first = NULL ) {
$params = func_get_args();
if( is_array( $first ) )
$params = $first;
// the $params array will contain the
// arguments passed to the child function
foreach( $params as $p )
echo "Param: $p\n";
}
}
function my_function() {
$instance = new my_class( func_get_args() );
}
echo "you can still create my_class instances like normal:";
$instance = new my_class( "one", "two", "three" );
echo "\n\n\n";
echo "but also through my_function:";
my_function( "one", "two", "three" );
Basically, you simply pass the result of func_get_args to the constructor of your class, and let it decide whether it is being called with an array of arguments from that function, or whether it is being called normally.
This code outputs
you can still create my_class instances like normal:
Param: one
Param: two
Param: three
but also through my_function:
Param: one
Param: two
Param: three
Hope that helps.
I've found here
Is there a call_user_func() equivalent to create a new class instance?
the example:
function createInstance($className, array $arguments = array())
{
if(class_exists($className)) {
return call_user_func_array(array(
new ReflectionClass($className), 'newInstance'),
$arguments);
}
return false;
}
But can somebody tell me if there is an example for classes with protected constructors?

Accessing object properties of type array dynamically

I am building a Language class for internationalization, and I would like to access the properties dynamically (giving the string name), but I don't know how to do it when dealing with arrays (this is just an example):
class Language {
public static $languages_cache = array();
public $index_header_title;
public $index = array(
"header" => array(
"title" => NULL
)
);
}
Now I add languages like this:
Language::$languages_cache["en"] = new Language();
Language::$languages_cache["en"]->index_header_title = "Welcome!"; //setting variable
Language::$languages_cache["en"]->index["header"]["title"] = "Welcome!"; //setting array
Function for accessing members dynamically:
function _($member, $lang)
{
if (!property_exists('Language', $member))
return "";
return Language::$languages_cache[$lang]->$member;
}
So, outputting members:
echo _('index_header_title', "en"); //works
echo _('index["header"]["title"]', "en"); //does not work
I would need a way for accessing arrays dynamically.. for public and private via __set() function.
Thank you!
You could try using a separator flag so that you can parse the array path. The only problem is you are mixing you properties and arrays so that might complicate things.
You would call your function like this:
echo _('index.header.title', "en");
And your function would parse the path and return the correct value. Take a look at the array helper in Kohana 3.0. It has the exact function that you want. http://kohanaframework.org/guide/api/Arr#path

Categories