Given a web application based PHP or ruby in its backend, and programmed on JavaScript in the frontend, sometimes we need to define values in both sides to process data that municates between the frontend and backend through APIs.
In JavaScript would be something like this:
var options = {
OPT_A : 1,
OPT_B : 2,
OPT_C : 3
};
switch(data.type)
{
case options.OPT_A:
/* */
break;
case options.OPT_B:
/* */
break;
case options.OPT_C:
/* */
break;
}
And in php something like this:
const OPT_A = 1;
const OPT_B = 2;
const OPT_C = 3;
The problem is that you have to define them twice; once in each language. This could lead to errors/inconsistencies.
The only way I've thought is defining the JavaScript part from the server, but I don't like the idea of JS code being written by PHP/Ruby code.
Is there any way to this without code duplication?
Given a web application based PHP or ruby in its backend, and programmed on JavaScript in the frontend, sometimes we need to define values in both sides to process data that municates between the frontend and backend through APIs.
In JavaScript would be something like this:
var options = {
OPT_A : 1,
OPT_B : 2,
OPT_C : 3
};
switch(data.type)
{
case options.OPT_A:
/* */
break;
case options.OPT_B:
/* */
break;
case options.OPT_C:
/* */
break;
}
And in php something like this:
const OPT_A = 1;
const OPT_B = 2;
const OPT_C = 3;
The problem is that you have to define them twice; once in each language. This could lead to errors/inconsistencies.
The only way I've thought is defining the JavaScript part from the server, but I don't like the idea of JS code being written by PHP/Ruby code.
Is there any way to this without code duplication?
Share Improve this question edited Mar 4, 2022 at 16:07 TylerH 21.1k79 gold badges79 silver badges114 bronze badges asked Jul 9, 2014 at 7:29 danikazedanikaze 1,6542 gold badges18 silver badges37 bronze badges 4- 2 How about munication through JSON? – elclanrs Commented Jul 9, 2014 at 7:31
- 2 Generating JS on the server is accepted practive, though elclanrs suggestion to use JSON sound like a solid solution. – michaelward82 Commented Jul 9, 2014 at 7:32
- @elclanrs do you mean getting the data structure from PHP using AJAX or when loading the page? It's another option but also dislike the idea of making a different petition everytime. A good way would be generating all the enum data in JSON as you say and making it available for JS. I think is the way I like the most. – danikaze Commented Jul 9, 2014 at 7:35
- So, with this 3 ments I guess the best way is having a server-generated file with all the "public" (usable by the frontend) data structure/enum definitions from the server. I guess I'll think about a class to generate this static file from multiple backend files, since all the definitions can be in different places.. – danikaze Commented Jul 9, 2014 at 7:45
3 Answers
Reset to default 1Here is a solution for how to create a PHP enum and send it to the front-end as an object.
Here in PHP I create an enum class called Food:
abstract class Food
{
const BANANA = 0;
const ORANGE = 1;
const WATERMELON = 2;
const BANANA_STRING = 'banana';
const ORANGE_STRING = 'orange';
const WATERMELON_STRING = 'watermelon';
const MAP = [
self::BANANA => self::BANANA_STRING,
self::ORANGE => self::ORANGE_STRING,
self::WATERMELON => self::WATERMELON_STRING
];
const REVERSEMAP = [
self::BANANA_STRING => self::BANANA,
self::ORANGE_STRING => self::ORANGE,
self::WATERMELON_STRING => self::WATERMELON
];
static function toString($enum){
return self::MAP[$enum];
}
static function toEnum($string){
return self::REVERSEMAP[$string];
}
}
I am using the Laravel framework in these next steps but it should be mostly the same depending on your project. The important part here is I use ::MAP which I created in my enum:
use PathToMyLibrary\MyLibrary\Enums\Food;
class FoodController extends Controller {
public function foodView() {
$title = "hello";
$food_enum = Food::MAP;
// attach these variables to the food view
return view('food', pact('title', 'food_enum'));
}
}
Now inside of my food.blade.php file (the PHP-html view template file used in Laravel), I can convert this $food_enum PHP object into a JavaScript object.
@section('title')
{{title}}
@endsection
@section('page_content')
<div class="page-heading">
<h1>{{title}}</h1>
</div>
<div id="food-app">...your content...</div>
@endsection
@section('includes')
<script>
// convert this $food_enum from a PHP object into a JavaScript object
var food_enum = <?php echo json_encode($food_enum); ?>;
</script>
@endsection
At this point you will have an object in JavaScript that matches the same enum object you had in PHP.
No more needing to maintain a redundant enum in PHP and JavaScript!
You're going to want to read up on webservices. A webservice is essentially a function. You pass it some parameters, and it gives you back some information. Usually used to allow programs to access external data. You can see them in action with virtually any API. See stackexchange's api for an example.
Minimal example:
#sinatra routing
get '/webservice/test' do
content_type :json
data = {options: {
opt_a: 1,
opt_b: 2,
opt_c: 3
}}
JSON.pretty_generate(data)
end
So, when you access your-site./webservice/test
, you'll get:
{
"options": {
"opt_a": 1,
"opt_b": 2,
"opt_c": 3
}
}
Using this data in javascript bees trivial:
var call = new XMLHttpRequest();
call.onreadystatechange = function() {
if(call.readyState == XMLHttpRequest.DONE) {
if(call.status == 200) {
obj = JSON.parse(call.responseText);
console.log(obj);
} else if(xmlhttp.status == 400) {
console.log("error 400");
} else {
alert("some other thing happened");
}
}
}
call.open("GET", "/webservice/test", true);
call.send();
Now you have your data on the client side!
Specifically, obj
will be Object {options: Object}
, so you'd access your 3 options with obj.options.opt_a
to get 1
.
There are some good plain English explanation of a webservice over here.
If you're not familiar with http response codes, you can look at a full list here. That's the call.status
section of the javascript code.
If you're so inclined, you can do the same ajax call in jQuery with $.getJSON("/webservice/test", function() ...)
. You can read more about it here
In my projects I make an endpoint on my API that return the enum in json. Them I store it with redux to not recall it on each time I visit the page. If you don't use a JS framework, you can still make an url that is triggered by an ajax request and feed your javascript. You can too make a json file that is stored in a public directory and import it in javascript and file get contents in your backend language