Bridge between JS and PHP complex data - php

I am required to build a complex control panel.
It has to be user configured and after he has made an arbitrary number of changes, he submits them and is presented with the newly configured report.
Now there are a lot of possible configuration options and the JS must be able to draw the control elements/init them with values and PHP must do the business logic - all based on given configuration object - and both must be able to change the values of options before passing the object to the other side.
Now the obvious solution is to have predefined configuration objects on both sides:
PHP:
class config {
public $anArray = array();
}
JS:
{
anArray : []
}
And the sides can communicate fluently via json_encode and $.parseJSON.
However, the structure of both entities must match and I've no idea how to ensure that. Has anyone any ideas on how to communicate complex data structures among those two technologies?
EDIT: to clarify, by structure I mean the properties of the two objects: the object itself is a simple configuration wrapper so it has no private properties, no methods etc, only public fields that are scalar or simple indexed arrays.
So I want a solution to develop it in a DRY way: if I want to add a field called for example "paginationEnabled" it should appear in both - the JS and PHP object:
PHP:
class config {
public $anArray = array();
public $paginationEnabled = true;
}
JS:
{
anArray : [],
paginationEnabled : true
}
I could implement them separately on both sides, but it would not be DRY (which is terrible in this scenario) and I can sense there must be a solution for that, I just can't think of one.

The simplest solution is to included the entire JSON-encoded object structure on every request to the server, and in every page returned by the server. This will be necessary anyway since neither PHP nor JavaScript persists between page loads (unless you're using AJAX, which would only make the JavaScript persist anyway).
Of course that only works if the data is already in a form that can be JSON-encoded. (Arrays and simple objects can be encoded to any depth, but not objects of nontrivial classes, file handles or functions.) If it isn't, then you'll need to convert it to one, then convert back on the other end - for example, if the class of an object is important, then you first need to ensure that a corresponding class exists on the other side, then you can indicate the desired classname with {class: $class, value: $value} - and add code on the other end to find that construction and rebuild an object of the desired class. If you need to copy functions across, then that might be manageable if you store all of your functions as JavaScript, and include a JavaScript interpreter library in PHP. That's probably more trouble than it's worth, however.
If the JSON object is much too large to send on every request, then you're left with storing it in the database (in a form suitable for databases) and using AJAX to update the database when something changes on the JavaScript side, or to retrieve any part of the object that the client code doesn't already have.

Related

What is faster: an index-array or getters and variables? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I am trying to figure out what should be considered better for performance:
I have a bunch of objects that contain a lot of page-data.
A few examples of the data that an object can have:
filepath of PHP-file for includes
CSS filepath
JavaScript filepath
Meta data of the page
The object is specific for each type of content. I have an interface that defines the render-function. Each object implements this function differently.
Example:
class PhpFragment extends FragmentBase {
public function render() {
//... render output for this type of data
}
}
I am currently using a parent-object that contains variables that can contain multiple object of the type mentioned above. The object looks something like this:
class pageData {
protected $CSS;
protected $PHP;
protected $JS;
protected $Meta;
protected etc...
public function getCSS() {
return $this->CSS;
}
public function getPHP() {
return $this->PHP;
}
public function getJS() {
return $this->JS;
}
}
Whenever I load in a page, I walk through a template and render the data of each object that matches the tag in the template.
For example: If a template has a line where CSS is needed, I call the getCSS function of the pageData which returns an array of objects. Foreach of these objects I call the render function and add the data in the page.
What do I want?
I want to get rid of these fixed variables in the pageData object to be able to use my design as dynamically as possible. I want the pageData object to disappear and just have an array of different fragment-objects.
To achieve this, I need to replace the get-functions in the pageData with something clever?
My top priority is performance, so I thought I'd look through all the objects once to get all the different types, and put all the types as key in the array, the value of the array will then be a subarray that contains the correct key to the objects that match the type.
What I was wondering, before I start changing the design entirely, is this faster?
I don't know if this is the right place to ask this question (it's more a code-review question IMO). Anyway, here's a couple of thoughts I'd consider if I were you:
What are objects
Objects are units of functionality, or entities that represent a specific set of values. DTO's (like your pageData class) serves one purpouse: to group, and represent a set of values that belong together. The fact that a class has a type (type-hints) and an interface makes a code-base testable, easier to understand, maintain, debug, and document.
At first glance, a simple DTO isn't too different from a simple array, and yes, objects have a marginal performance cost.
The question you need to ask is whether or not you want to shave of those 1 or 2 ms per request at the cost of: increased development time, less testable, more error prone, and harder to maintain code. I'd argue that for this reason alone, DTO's make more sense than arrays
pre-declared properties are fast
If you want an object that is as dynamic as possible, then PHP offers you to possibility to add properties to instances on the fly:
Class Foo{}
$x = new Foo;
$x->bar = 'new property';
echo $x->bar;//echoes new property
So in essence, objects are just as flexible as arrays. However, properties that weren't declared beforehand are (again marginally) slower than predeclared properties.
When a class definition declares 3 properties, these properties are stored in a hash table. When accessing a member of an instance, this hashtable will be checked first. Internally, these hashtable lookups are O(1), If no properties were declared, any "dynamic" property is stored in a second hash table. Lookups on this fallback HT are O(n). Not terrible, but worse than they need be.
In addition to dynamic properties being less performant, they're also always public, so you have no control over their values (they can be reassigned elsewhere), and they are, of course, susceptible to human error (typo's):
$x = new Foo;
$x->foo = 'Set the value of foo';
echo $x->fo;//typo...
Getters and setters are good
The methods you have now don't do anything, true enough, but consider this:
class User
{
protected $email;
public function setEmail($email)
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email');
}
$this->email = $email;
return $this;
}
}
A setter like this not only allows me to control/check when and where a property is set, but also to validate the data that someone is trying to assign to it. You can validate the data. You can ensure that, no matter what, if you receive an instance of User, the email will either be null, or a valid email address.
There are many more reasons why objects make more sense than arrays, but these alone, to me at least, outweigh the benefits of 2ms/req performance gain.
If performance is such an issue, why not write in a faster language?
If all you're after is performance, you might want to look into languages that outperform PHP to begin with. Don't get me wrong: I honestly like PHP, but it's just a fact that, for example, Go can do the same thing, only faster.
Pass by value, copy-on-write, and (almost) pass by reference
Arrays are, essentially, scalar values. Pass an array to a function, and any changes made to that array inside the function doesn't change the array you passed to that method. Objects are (sort-of) passed by reference. That's to say: objects are passed by identifier.
Say you have an instance of Foo. The Zend engine will assign a unique ID to that instance (eg 123). When you call a function and pass that instance, internally, you'll pass the identifier of that object to the method not the object itself.
This has several implications: When changing the state of the instance, PHP doesn't have to make a copy of the object: it just uses the ID to get the zval (internal representation of a PHP variable), and operates on the same piece of memory. The net result: you're passing a simple value (an int), and whatever happens to the object, wherever it happens, the state is shared throughout.
Arrays are different: Passing an array is (sort-of) passing a copy of that value. In reality, PHP is clever enough to pass a reference to the existing array, but once you start reassigning values, PHP does have to create a copy. This is the copy-on-write mechanism. Put simply, the idea is: do not create needless copies of values, unless you have to:
function foo(array $data)
{
$x = $data[0];//read, no copy of argument is required
$data[1] = $x * $data[3];//now, we're altering the argument, a copy is created
}
$data = [1, 2, 3, 4];
foo($data);//passes reference
Depending on how you use the arrays or objects you pass to functions, one might perform better than the other. On the whole: passing an array that you'll only use to read values will most likely outperform passing an object. However, if you start operating on the array/object, an object might turn out to outperform arrays...
TL;DR
Yes, arrays are generally faster than objects. But they're less safe, pretty much impossible to test, harder to maintain an non-communicative (public function doStuff(array $data) doesn't tell me as much as public function doStuff(User $data)).
Owing to the copy-on-write and the way instances are passed to functions, it's impossible to say which will be faster with absolute certainty. It really boils down to what you do: is the array fairly small, and are you only reading its values, then it's probably going to be faster than objects.
The moment you start operating on the data, it's entirely possible objects might prove to be faster.
I can't just leave it there without at least mentioning that old mantra:
Premature optimization is the root of all evil
Switching from objects to arrays for performance sake does smell of micro-optimization. If you have in fact reached the point that there's nothing else to optimize but these kinds of trivial things, then the project is either a small one; or you're the first person to actually work on a big project and actually finish it. In all other cases, you shouldn't really be wasting time on this kind of optimization.
Things that are far more important to profile, and then optimize are:
Caching (opcache, memcache, ...)
Disk IO (including files, autoloader mechanisms)
Resource management: open file pointers, DB connections (when to connect, when to close connections)
If you're using a traditional SQL DB: queries... The vast majority of PHP applications can benefit a lot by having a DBA look at the queries and actually optimize those
Server setup
...
Only if you've gone through this list, and more, could you perhaps consider thinking about some micro optimization. That is of course, if by then you haven't encountered any bugs...

Php global variable across the whole project

I'm relatively new to PHP, and I'm looking for a way to define certain objects as globally accessible from throughout the project, from multiple PHP scripts.
In Java, if I've to access some objects globally, I define some public class named Globals , and define the objects that I need to access as static in the Globals class. I then access those objects wherever I need with: Globals.variable_name .
So basically, I need to initialize these global objects only once and then use them whenever I need them..
One use case:
I've a class named Logger that has methods to log certain events in a log file. I need to have 1 Logger instance/object that can be used by all the PHP scripts in the project, whenever they've to log something. I'd rather not have each PHP script using it's own instance of Logger.
The naive Java-like approach I tried, that did not work:
I created a public class named Globals in a separate PHP file (named Globals.php) with one static object of type Logger, named $logHandle. I included this PHP file in all other PHP files where I need this Logger object. I then tried to access this object , using Globals->logHandle from one of the other PHP scripts. This attempt failed miserably.
Is there some similar approach?
Thanks.
PHP is not Java.
In web applications, the PHP environment is initialized for each request - and each request is handled in a different process with it's own memory space. It is possible to share access to data (including serialized objects, but not resources such as database connections and file handles) across different instances. You probably know this already but have not yet realised how it influences the way you write code.
I'd rather not have each PHP script using it's own instance of Logger
Why not?
One very good reason is that allowing multiple processes to write to the same open file handle requires locking to prevent the file getting all mesed up. BUT THIS IS PHP - STOP REINVENTING THINGS FROM SCRATCH. Writing to stderr will append the details to the webserver error log or use the OS syslog facilities - that's what they are there for.
It is impossible to have the same object available to all instances of PHP - you can unserialize an object in all instances - but then it's not the same object. You can run a daemon with a single object which might be accessible to all other PHP instances via a socket connection - but it's not running in the same address space.
If you validly have a class that you want to be universally available via an object with a fixed name, then simply create an instance of the object in each script or via an include file. The approach you tried is the way to go about this (but don't name your objects with reserved words). We don't know why it failed because you didn't provide any error messages or code.
I assume you're asking about common case (now only web-oriented application). And for that - no, you can not define some thing like you've described, in native way. This is the thing that is called superglobals in PHP.
But on the other hand - you need to do that for some reason, not "just because you want it". And, if so - then use configuration file. Create some application configuration file, read it once at start of application (bootstrap) and you'll get all needed values. I'm not saying anything about file structure - it can be xml/ini/yaml/whatever/you/like. But the idea is - to split this logic from application structure itself and use separate file for storing desired values.
Another option is to use some separate PHP file(s) and include it at bootstrap. Define all needed variables/constants in that file(s) and you'll get similar behavior. Note, that in terms of namespaces it's less "global" and you'll need to resolve all that cases manually.
For web-applications, however, one of possible solutions may be using sessions. $_SESSION is a superglobal array and it will behave like you want (i.e. will be accessible from everywhere). But that is not applicable always - and not always you'll want to deal with sessions to store session-independent data.
you can do like this
you said that you have included in all other classes change methods in your global class to static
<?php
class Logger {
public static function log($msg) {
// ...
}
}
you can use it like
Logger::log($msg);
http://www.php.net/manual/en/reserved.variables.globals.php
i think that is what you're after.
To access a static attribute in PHP you need to call it with the Class::$attribute notation, and the static methods need to be called with the Class::method() notation.
The -> notation is used when calling attributes of a class instance.

Passing an Object between PHP pages, IDE and passing object to other classes problems

I've inherited some PHP code that I need to make significant changes on. I know with PHP it is possible to serialize an Object, and pass the serialized text between pages as FormData. In the code I've inherited, they have done just that, But this is creating some maintainability problems. I'm wondering if taking this approach is even a good idea.
For example ...
When the user opens PageA.php the following is created:
$expensiveObj = new ExpensiveClass($id);
The $expensiveObj is then serialized and the resulting text is stored in a div with the following:
<div id="expensiveObj"><?php echo strtr(base64_encode(serialize($expensiveObj)), '+/=', '-_,');?></div>
When PageA.php loads, an ajax call is made to PageB.php. The content of the div is passed along as a post variable to PageB.php. Within PageB.php the following code unserializes the object:
$expensiveObj = unserialize(base64_decode(strtr($_POST['expensiveObj'], '-_,', '+/=')));
The fields and methods of the $expensiveObj are now accessible to PHP. The problems I'm encountering are
Because the $expensiveObj is not identified in PageB.php as an instance of the Class ExpensiveClass then the IDE doesn't know that the fields and functions of ExpensiveClass are available. I can't do autocomplete, nor lookup within the IDE what functions are available. Plus the IDE can't catch potential issues. The other developer worked exclusively in VI, so he never cared.
PageB.php needs to be re-factored. There is view, business, and controller logic all happening within this page, I would prefer to create a couple of classes, but I'm encountering a problem where I don't know how to pass the $expensiveObj to a class.
My questions are, is there a way to pass an Object to a class? And is there a way inform the IDE that the passed in post variable is indeed an instance of ExpensiveClass?
Lastly, is it even a good idea to be passing around objects this way, or should I be looking at a larger re-factor?
Storing objects directly in HTML is never a good idea, because it can be easily changed by client. In PHP is more common to create new object on every request according to given parameters. I see you are initializing your object using $id, so you can just pass this id between requests. Storing data to session also isn't best practice, session should be used for session-specific data, e.g. logged-in user etc.
If the creation of the object is very expensive, you can use cache, e.g. memcache, some external library or just to write your own, for example storing data in JSON on file system or in database.

API Design: Multiple $_REQUEST's vs single $_REQUEST encoded in json

I'm building an API, and I'm at a crossroads as how to implement it. I plan on using json, since they can represent objects/arrays so easily in php and javascript.
I have two ways to implement it pretty much:
1) Include the method call into the json
$input = $_REQUEST['i'];
$i_obj = json_decode($input);
api_handle($i_obj);
2) Push the method call (and perhaps other variables, such as the session) in parallel, and just pull the data via $_REQUEST.
$method = $_REQUEST['m'];
$argv = json_decode($_REQUEST['argv']);
api_handle($method,$argv);
I can see that in the second case, there may be less for the json_decode to debug, but from a user friendly point of view, an ajax/js coder could just build the object and send it json_encoded via input "i".
My question in the end is, are either of these good ways to implement this, or is there perhaps an even better way? Please keep in mind, this is a simple example, and does not represent the rest of the project's scope for this API.
In this particular case it's better idea to couple all method call data into one object rather then getting it from $_REQUEST key by key since $_REQUEST contains other unrelated data as well at the same level.
Method name and its arguments are tied together and must be transferred as single packet. Maybe some day you'll deside to add ability to call i.e. class static methods. It will be much harder to add one more key to $_REQUEST and its processing then add one more field to object since object is much more encapsulated thing and that will narrow area affected by changes in your code.
And of course you can name object fields by a whim withot thinking if this key is already taken in $_REQUEST by another script.

How can i handle a form submit using REAL OOP in PHP

Im used to java and creating UML.. and i was wondering how can PHP be OOP, the objects live only until you make a request.. then they destroy, so if im using a database is useless to create a class and add the members (variables) to the class, they will be useless.. i cant pass the main system object from one page to another, or similar so how can PHP be compare to jave? you never do OOP .. i mean REAL OOP.. not creating classes , in fact your index will be a procedural file with some object instance and then ? how about if i make a html form and i want to submit the data.. i have to call a file which is not a class is a php procedural file were i grab the submited data with POST, from that file you will instance a class and do some logic there.. but for me thats not pure OOP.. can somebody point me to the right way of OOP using a form submit example ?
Thanks!
You're labouring under a misapprehension that object oriented programming by definition includes a persistent environment with objects that exist independantly of page requests. I'm afraid it doesn't.
PHP does do "real" object-oriented programming. But PHP's execution environment is like executing a CGI program: upon a page request, the program starts and it ends when the page is finished. Within that paradigm, objects can exist only as long as the page is producing content. Therefore, the first thing the page must do is to load the framework to define and instantiate the required objects, such as a database handler and object mappers that must load and save their data within a page request cycle. Some frameworks will also create objects with the page-request data that your code and objects can then access, sometimes from within objects.
But PHP does not provide this natively because it does not enforce a framework. It is by nature procedural so a framework must be added so as to define and create the desired objects if you don't want to work that way.
There is an advantage to doing things this way. It means a page's code need only concern itself with a single page request. Almost all issues to do with data-sharing and multiply-threaded execution is pushed out to things that can handle it invisibly, like the database and the web server.
Check out any of the latest php framework and how they handle forms. (like ZF or Yii).
b.t.w the "problem" you refer too is client-server architecture and not a minus of PHP.
Each request is a new process with a new MAIN or new Class with static main function which are practically the same.
"so if im using a database is useless
to create a class and add the members
(variables) to the class, they will be
useless"
It sounds like you want an object-relational mapper. There are several popular ones for PHP, as discussed at this previous question.

Categories