So I do a print for my object: print_r ($objMailer);
And I get the following below:
mymailer Object
(
[_strRecipient:mymailer:private] =>
[_strBcc:mymailer:private] =>
[_strSubject:mymailer:private] =>
[_strEmail:mymailer:private] =>
[_arrData:mymailer:private] => Array
(
[full_name] => brian
[invitee_name] => test
[email] => test#testing.com
[captcha] => kqd2q9
)
[_arrAttachments:mymailer:private] =>
[_blnCaptcha:mymailer:private] => 1
[_arrErrors:mymailer:private] => Array
(
)
)
I need to echo/print out just the 'full_name' field? How can I go about doing this?
You can not trivially. As the print_r output shows that is within a private member.
You can either provide it from within your (?) mymailer object:
return $this->_arrData['full_name'];
or by using Reflection to make it accessible from the outside:
$refObj = new ReflectionObject($objMailer);
$refProp = $refObj->getProperty('_arrData');
$array = $refProp->getValue($objMailer);
echo $array['full_name'];
If you want to echo the value inside a method of mymailer class, you may use:
echo $this->_arrData['full_name'];
Since it's private you'll need to use a getter
The object you are referencing has an _arrData member variable which has private scope resolution, which means you cannot access it from outside the class. Chances are there is a public accessor which will allow you get the information you are after, but no way to tell unless you introspect the object itself.
I would suggest doing something like:
foreach (get_class_methods($mymailer) as $method) { echo 'M: ' . $method . '<br>'; } exit;
Then you can see the methods available to you, chances are there is a getData() method, with which you can do this:
$mailerData = $mymailer->getData();
var_dump($mailerData['full_name']);
There may even be a method to get the full name, something like this:
var_dump($mymailer->getFullname());
Related
Here My class name is User, When I print my class properties I'm getting my objective name properly. After that, I encoded the data with json_encode(). and then I decoding with json_decode(). I'm getting stdClass objective why?
<?php
class User
{
public $name;
public $age;
public $salary;
}
$user = new User();
$user->name = 'Siddhu';
$user->age = 24;
$user->salary = 7000.80;
print_r($user);
//Output: User Object ( [name] => Siddhu [age] => 24 [salary] => 7000.8 )
print_r(json_encode($user));
//Output: {"name":"Siddhu","age":24,"salary":7000.8}
$d = json_encode($user);
$s = json_decode($d);
print_r($s);
//Output: stdClass Object ( [name] => Siddhu [age] => 24 [salary] => 7000.8 )
If you noticed stdClass is coming, How can I change to user
There is no direct way you can get data in class object either you need to used custom method to decode else you can use serialize() && unserialize() function to get data in the class object when you decode;
$serialized_user_object = serialize($user);
$deserialized_user_object = unserialize($serialized_user_object);
In json_decode you can pass true in second argument if you want data as array.
like this.
var_dump(json_decode($json, true));
to know more about json_decode see here.
The reason this happens can be demonstrated quite easily...
class foo{
public $bar = 'bar';
}
$json = json_encode(new foo);
echo $json."\n\n";
print_r(json_decode($json));
Output
{"bar":"bar"}
stdClass Object
(
[bar] => bar
)
Sandbox
As you can see the output {"bar":"bar"} contains no information about what if any class this was, it could have been ['bar'=>'bar'] and the JSON would be the same... Then when decoding it, you don't have json_decode set to return as an array (second argument set to true), which is fine as that's not really what you want, but when it's set that way you get stdClass objects instead of an associative array for items with non-numeric keys. In short there is no way to recover the class "foo" from the json {"bar":"bar"} as that information does't exist (you can make it exist, but that's another tale for another day).
Using serialize we get something very different.
class foo{
public $bar = 'bar';
}
$json = serialize(new foo);
echo $json."\n\n";
print_r(unserialize($json));
Output
O:3:"foo":1:{s:3:"bar";s:3:"bar";}
foo Object
(
[bar] => bar
)
Sandbox
This O:3:foo means an Object with a class name 3 in length named "foo". So it preserves that information for PHP to use when "decoding" the data.
The whole thing reads like this:
Object (3) "foo" with 1 property named (s)tring (3) "bar" with a value of (s)tring (3) "bar", or something like that.
Make sense.
AS a note PHP's serialize is less portable then JSON, as it only works in PHP, It's also much harder to manually edit then JSON, but if you really want to encode a class than that is the easiest way to do it. That said you can also "repopulate" the class from JSON data, but that can also be hard to maintain.
I have a problem with modifying an array.
foreach ($page->getResults() as $lineItem) {
print_r($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations());
}
This code gives a result:
Array
(
[0] => Google\AdsApi\Dfp\v201611\Location Object
(
[id:protected] => 2250
[type:protected] => COUNTRY
[canonicalParentId:protected] =>
[displayName:protected] => France
)
)
I'm trying to add another, [1] , same type of object to this array.
I made a class to create and add an object:
class Location{
public function createProperty($propertyName, $propertyValue){
$this->{$propertyName} = $propertyValue;
}
}
$location = new Location();
$location->createProperty('id', '2792');
$location->createProperty('type', 'COUNTRY');
$location->createProperty('canonicalParentId', '');
$location->createProperty('displayName', 'Turkey');
array_push($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations(), $location);
Then, if I pass this into print_r() function
print_r($lineItem->getTargeting()->getGeoTargeting()->getExcludedLocations());
It shows the same result.
In the end, I need to send this updated whole $lineItem to this function
$lineItems = $lineItemService->updateLineItems(array($lineItem));
But seems like before sending I can't properly add an object to the array.
Thanks in advance.
PHP returns arrays as a value instead of as a reference. This means you must set the modified value back somehow.
Looking at the library apparently in question, there seems to be setExcludedLocations method for that purpose.
So your code should be something like:
$geo_targeting = $lineItem->getTargeting()->getGeoTargeting();
$excluded_locations = $geo_targeting->getExcludedLocations();
array_push($excluded_locations, $location);
$geo_targeting->setExcludedLocations($excluded_locations);
I don't know how to work with such object, i need to get first and second one status value, tryed to convert it to json, but it gives me nothing. I just don't get it how to open array with such "_data:MailWizzApi_Params:private" name.
Source:
// SEARCH BY EMAIL
$response = $endpoint->emailSearch($myConfig["LIST-UNIQUE-ID"], $_GET["email"]);
// DISPLAY RESPONSE
echo '<hr /><pre>';
print_r($response->body);
echo '</pre>';
I receive such answer
MailWizzApi_Params Object
(
[_data:MailWizzApi_Params:private] => Array
(
[status] => success
[data] => Array
(
[subscriber_uid] => an837jdexga45
[status] => unsubscribed
)
)
[_readOnly:MailWizzApi_Params:private] =>
)
In this case, you can't.
Because it's private field.
For public fields with "incorrect" names you can use snippet:
$name = '}|{';
$obj->$name;
So, let see to your property: [_data:MailWizzApi_Params:private].
It is private field of instance of MailWizzApi_Params class with _data name.
Let's google to it's implementation: Found
As you can see it has toArray public method. Just use it.
print_r($response->body->toArray());
It has ArrayAccess implemented also. So, $response->body['status'] or $response->body['data'] will works.
Thank you guys for fast answers, here is my dumb way if reading status value
(thanks, #Jose Manuel Abarca RodrÃguez)
$toJson = json_encode((array)$response->body);
$toJson = str_replace(array("\u0000MailWizzApi_Params\u0000_"), "", $toJson);
So we receive a normal json:
{"data":{"status":"success","data":{"subscriber_uid":"an837jdexga45","status":"unsubscribed"}},"readOnly":false}
And now we need just to decode it
$json = json_decode($toJson, true);
echo $json['data']['status'];
I am new to OOP.
I am currently working on adding data to an object to then submit it to a database. I have created a method called setData to take two arguments, and then add those arguments into the object.
Inside my class, I use this
public function setData($value1, $value2) {
$this->$value1 = $value2;
}
Where on a form submit, that function is used to store data
$sites = new AddWebsites;
$sites->setData('name', $name);
$sites->setData('page_rank', $pr);
$sites->setData('pa', $pa);
$sites->setData('da', $da);
$sites->setData('tf', $tf);
$sites->setData('cf', $cf);
$sites->setData('keywords', $keywords);
$sites->setData('notes', $notes);
This will output the following data
AddWebsites Object
(
[name] => asdf.com
[page_rank] => 5
[pa] => 15
[da] => 25
[tf] => 14
[cf] => 62
[keywords] => Array
(
[0] => kw1
[1] => kw2
[2] => kw3
[3] => kw4
[4] => kw5
)
[notes] => asdf
)
I have been told that this is wrong, and will throw errors.
I was wondering if there is a better way to achieve this, if it is actually wrong, and if there is an easier way to do this.
With error reporting enabled, I have not run across anything that tells me what I am doing is wrong.
Thanks for your time.
It's wrong in pure OOP terms because you're using PHP's (somewhat unusual) ability to add arbitrary attributes to instantiated objects via your setData method.
What you should be doing - to achieve the goals of encapsulation and data validation - is something like this :
class AddWebsites {
private $name;
private $pageRank;
// etc
// Setters
public function setName(value) {
// you can put validation logic in here
this->name = value;
}
public function setPageRank(value) {
// you can put validation logic in here
this->pageRank = value;
}
// etc
// getters
public function getName() {
return this->name;
}
public function getPageRank() {
return this->pageRank;
}
}
This is using "Getters" and "Setters".
You could however have your members as public then you wouldn't need the getters
One of things i can notice is passing field name in function parameter is not an good idea. Reason behind that is if you by mistake pass wrong field name then php will create one more field for that object.
So if you are having multiple objects of same class some will have that field some will not. This leads to inconsistency.
So I feel this is not correct thing to do as you are not suppose to create properties of class pbject dynamically.
Ideal way is to have different getter and setter functions for each field and fields should be private in scope, so that you/developer will not not able to create new fields by mistake.
Here's what I want to do:
$clsName = substr(md5(rand()),0,10); //generate a random name
$cls = new $clsName(); //create a new instance
function __autoload($class_name)
{
//define that instance dynamically
}
Obviously this isn't what I'm actually doing, but basically I have unknown names for a class and based on the name, I want to generate the class with certain properties etc.
I've tried using eval() but it is giving me fits over private and $this-> references...
//edit
Ok, obviously my short and sweet "here's what I want to do" caused massive strife and consternation amongst those who may be able to provide answers. In the hope of getting an actual answer I'll be more detailed.
I have a validation framework using code hints on the site I maintain. Each function has two definitions
function DoSomething($param, $param2){
//code
}
function DoSomething_Validate(vInteger $param, vFloat $param2){
//return what to do if validation fails
}
I'm looking to add a validator for primary keys in my database. I don't want to create a separate class for EVERY table (203). So my plan was to do something like
function DoSomething_Validate(vPrimaryKey_Products $id){ }
Where the __autoload would generate a subclass of vPrimaryKey and set the table parameter to Products.
Happy now?
As of PHP 7.0, with a little creativity and knowledge of some lesser known PHP features, you can absolutely do this without resorting to eval or creating script files dynamically. You just need to use anonymous classes and class_alias(), like such:
spl_autoload_register(function ($unfoundClassName) {
{
$newClass = new class{}; //create an anonymous class
$newClassName = get_class($newClass); //get the name PHP assigns the anonymous class
class_alias($newClassName, $unfoundClassName); //alias the anonymous class with your class name
}
This works because anonymous classes are still assigned a name behind the scenes and put in the global scope, so you're free to grab that class name and alias it. Check out the second comment under the anonymous classes link above for more information.
Having said that, I feel like all the people in this question who are saying "Eval is always a very bad idea. Just don't use it ever!" are just repeating what they've heard from the hive mind and not thinking for themselves. Eval is in the language for a reason, and there are situations where it can be used effectively. If you're on an older version of PHP, eval might be a good solution here.
However, they are correct in that it can open up very large security holes and you have to be careful how you use it and understand how to eliminate the risks. The important thing is, much like SQL injection, you have to sanitize any input you put in the eval statement.
For example, if your autoloader looked like this:
spl_autoload_register(function ($unfoundClassName) {
{
eval("class $unfoundClassName {}");
}
A hacker could do something like this:
$injectionCode = "bogusClass1{} /*insert malicious code to run on the server here */ bogusClass2";
new $injectionCode();
See how this has the potential to be a security hole? Anything the hacker puts between the two bogusClass names will be run on your server by the eval statement.
If you adjust your autoloader to check the class name passed in (i.e. doing a preg_match to make sure there's no spaces or special characters, checking it against a list of acceptable names, etc.), you can eliminate these risks and then eval might be totally fine to use in this situation. If you're on PHP 7 or higher though, I recommend the anonymous class alias method above.
its funny, actually this is one of the few things where eval doesnt seem such a bad idea.
as long as you can ensure that no user input will ever enter the eval.
you still have downsides like when your using a bytecode cache that code wont be cached etc etc. but the security issues of eval are pretty much related to having user inputy in the eval, or to ending up in the wrong scope.
if you know what you are doing, eval will help you with this.
That said, in my opinion you are much better off when you no rely on type-hinting for your validation, but you have one function
DoSomething_Validate($id)
{
// get_class($id) and other validation foo here
}
I know this is an old question and there are answers that WILL work, but I wanted to offer a few snippets that would answer the original question and I think offer a more expanded solution should someone end up here like I did when searching for an answer to this problem.
Create Single Dynamic Class
<?php
// Without properties
$myclassname = "anewclassname";
eval("class {$myclassname} { }";
// With a property
$myclassname = "anewclassname";
$myproperty = "newproperty";
eval("class {$myclassname} { protected \${$myproperty}; }";
?>
As long as you properly escape your text, you could also add a function in there.
But what about if you want to dynamically create classes based on something that could itself be dynamic such as creating a class for each table in your database as the original question mentioned?
Create Multiple Dynamic Classes
<?php
// Assumes $dbh is a pdo connection handle to your MySQL database
$stmt=$dbh->prepare("show tables");
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$handle = null;
$classcode = '';
foreach ($result as $key => $value) {
foreach ($value as $key => $value) {
$classcode = "class {$value} { ";
$stmt2=$dbh->prepare("DESC $value");
$stmt2->execute();
$result2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
foreach ($result2 as $key => $value) {
$classcode .= "public \${$value['Field']}; ";
}
$classcode .= "}";
eval($classcode);
}
}
?>
This will dynamically generate a class for each table in a database. For each class, a property that is named after each column will ALSO get created.
Now it's been pointed out you shouldn't do this. As long as you control what's going on in the eval, the risk of security isn't a problem. BUT -- there's most likely a solution that makes more sense if you think deeply enough about it. I thought I had the perfect use case for dynamically creating new classes. Careful examination of the problem proved otherwise.
One potential solution -- use the stdClass for creating objects that are just data containers and don't need any methods.
Also -- as mentioned, you could use a script to manually generate lots of classes. In the case of classes mirroring your database tables, you could use the same logic I have above and instead of doing an eval, write that info to a file.
I think using eval() it's not a reliable solution, especially if your script or software will be distributed to different clients. Shared hosting providers always disable eval() function.
I'm thinking of a better aproach like this :
<?php
function __autoload( $class ) {
require 'classes/'.$class.'.php';
}
$class = 'App';
$code = "<?php class $class {
public function run() {
echo '$class<br>';
}
".'
public function __call($name,$args) {
$args=implode(",",$args);
echo "$name ($args)<br>";
}
}';
file_put_contents('classes/App.php' ,$code);
$a = new $class();
$a->run();
After finishing executing the code, you can delete the file if you want, I tested it and it works perfectly.
Using eval() is really a bad idea. It opens a large security hole. Just don't use it!
function __autoload($class) {
$code = "class $class {`
public function run() {
echo '$class<br>';
}
".'
public function __call($name,$args) {
$args=implode(",",$args);
echo "$name ($args)<br>";
}
}';
eval($code);
}
$app=new Klasse();
$app->run();
$app->HelloWorld();
This might help to create a class at runtime.
It also creates a methor run and a catchall method for unknown methods
But better create Objects at runtime, not classes.
This is almost certainly a bad idea.
I think your time would be better spent creating a script that would create your class definitions for you, and not trying to do it at runtime.
Something with a command-line signature like:
./generate_classes_from_db <host> <database> [tables] [output dir]
Please read everyone else answers on how this is truly a very very bad idea.
Once you understand that, here is a small demo on how you could, but should not, do this.
<?php
$clname = "TestClass";
eval("class $clname{}; \$cls = new $clname();");
var_dump($cls);
I have created a package that dynamically creates classes/interfaces/traits... and stores them into a file
you can then just include the created file to be able to use your class
package : https://packagist.org/packages/kanel/enuma
We can create class instance dynamically by following way
I also face this issue in Laravel 5.8 version and now it is working fine for me.
Give full path instead of the class Name
class TestController extends Controller
{
protected $className;
public function __construct()
{
$this->className = 'User';
}
public function makeDynamicInstance()
{
$classNameWithPath = 'App\\' . $this->className;
$classInstance = new $classNameWithPath;
$data = $classInstance::select('id','email')->get();
return $data;
}
}
Output
Illuminate\Database\Eloquent\Collection Object
(
[items:protected] => Array
(
[0] => App\User Object
(
[fillable:protected] => Array
(
[0] => name
[1] => email
[2] => password
[3] => user_group_id
[4] => username
[5] => facebook_page_id
[6] => first_name
[7] => last_name
[8] => email_verified
[9] => active
[10] => mobile
[11] => user_type
[12] => alternate_password
[13] => salt
[14] => email_verification_token
[15] => parent_id
)
[hidden:protected] => Array
(
[0] => password
[1] => remember_token
)
[casts:protected] => Array
(
[email_verified_at] => datetime
)
[connection:protected] => mysql
[table:protected] => users
[primaryKey:protected] => id
[keyType:protected] => int
[incrementing] => 1
[with:protected] => Array
(
)
[withCount:protected] => Array
(
)
[perPage:protected] => 15
[exists] => 1
[wasRecentlyCreated] =>
[attributes:protected] => Array
(
[id] => 1
[email] => admin#admin.com
)
[original:protected] => Array
(
[id] => 1
[email] => admin#admin.com
)
[changes:protected] => Array
(
)
[dates:protected] => Array
(
)
[dateFormat:protected] =>
[appends:protected] => Array
(
)
[dispatchesEvents:protected] => Array
(
)
[observables:protected] => Array
(
)
[relations:protected] => Array
(
)
[touches:protected] => Array
(
)
[timestamps] => 1
[visible:protected] => Array
(
)
[guarded:protected] => Array
(
[0] => *
)
[rememberTokenName:protected] => remember_token
)
)