I'm a newbie when it comes to PHP. I wrote some JS to make AJAX requests for my project and it worked well, but I don't have any idea how to convert that into PHP.
I've prepared layouts like the following:
mainLayout.php,
userLayout.php,
offerLayout.php,
In those files are some PHP and MySQL parts that build an HTML page.
In Ajax it was easy to navigate between many users using only one page and replacing some divs with data...
But a huge minus was that you couldn't have a single address reference a user profile or the offer (like mywebsite.com/user1).
Now, when I use PHP I want to achieve same layout effect.
How can I avoid creating a thousands of pages (of course even dynamically it seems to be a waste of memory IMO) like user1.php, user2.php, offer1.php, etc.
I don't know how to achieve the effect of being on a site like example.com/user277373.php without creating thousands of files but only one template.
Two solutions I see is either you use GET to parse your data:
http://example.com/?data=1736861
and than access it over the $_GET variable:
$id = $_GET["data"];
($id will be 1736861)
or you use the flight php extension, that will look something like this:
Flight::route('/id/#id', function($id){
echo "ID: $id";
});
and the URL would look like http://example.com/id/1736861. You can also use multiple variables with the flight module.
I hope this helped, Sebastian
Are you familiar with any MVC frameworks? If not, I would highly recommend getting accustomed to the MVC design paradigm. MVC = Model View Controller. From Wikipedia, a short excerpt:
A model stores data that is retrieved according to commands from the controller and displayed in the view.
A view generates new output to the user based on changes in the model.
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its
associated view to change the view's presentation of the model (e.g.,
scrolling through a document).
Two of the key components of MANY frameworks (in pretty much any language), are Routes and Templates. When utilizing a routing system, you're able to specify a template for every page loaded that matches a specific route. For instance, site.com/people/:id where ':id' can be any value in the URL, and be configured to use "person.html" for the HTML output. Note that "person.html" receives variables/data that will dynamically populate content, e.g. <h2>Hello, {{name}}</h2>
So, to clarify, site.com/people/252, site.com/people/12, site.com/people/5, site.com/people/john would all match the site.com/people/:id route path where :id is dynamic, and your system will use ONE TEMPLATE (which you specify) to display all the data. Don't forget, when that route path is met, that's only step 1. You will probably need to take that :id run some database query and pass that data into the template.
A popular micro PHP framework called Slim, might be a good starting point. Here's documentation for its way of handling Routes and Templates:
https://www.slimframework.com/docs/objects/router.html
https://www.slimframework.com/docs/features/templates.html
Slim is commonly used with Twig, a super popular PHP template engine. Here's its website/documentation: http://twig.sensiolabs.org/
And if that wasn't enough, Slim has a super handy First App Walkthrough that will show you routes, database connection, and templates: https://www.slimframework.com/docs/tutorial/first-app.html
Hope this information helps you on your journey – Best of luck!
Related
I've started using contentful, created a few entries and now I want to make a simple dynamic page with subpages.
Basically, a portfolio. What i want to have there - index page with links to inner portfolio pages. I've got a JSON with entries each of them containing title, content, slug, id, etc.
How do i make them have each of their page with url? Template is going to be the same. So for example the user comes to url.com/someurl and he sees the page for some specific item in entries.
My gut is telling me that usually controller does this kind of job. Should i try using some frameworks like angularjs?
You can have a look at this simple example app I've been working on, using just plain JS. It's not entirely finished but showcases the very basic principles of using Contentful to build a frontend only app with the contentful.js SDK: https://github.com/contentful/product-catalogue-js
Give that you added an angularjs tag I'm assuming you could also be interested in this: https://github.com/jvandemo/angular-contentful
Essentially you should just build an app as any other, using whatever framework (or not) you want, but get the data from Contentful instead of an AJAX endpoint or any other data library.
What you might want to think of as well is how you structure your Entries and Content Types in Contentful. A good strategy is to have some kind of Entry that corresponds to a page (for instance, in that example app there are Products and there are individual pages for each Product), and then have related Entries you can link to it (like say, Blog Posts and Images).
Ok so I've build a little php MVC framework. It basically has the following layers:
controllers: handling input, calling functions from the services based on that input and usually forwarding variables to the view (and rendering it)
domain-layer: split up into...
...models: domain entities, basically just setters and getters validating data and providing a consistent
data interface for the views
...mappers: loading/storing models
from/to the database
...services: encapsulating domain logic, like
"registerUser" or "sendMessage"
views: basically just html with some php.
Ok so far this works well. However now I would like to add some javascript functionality. I'm not sure how to do this properly. I know I'm supposed to send post-requests to my php scripts, but my controllers f.e. are not providing any return values, but instead just output views. So if I wanted to retrieve a list of friends for a user with js, would I..
a) provide a "javascript access service", which handles javascript requests with help from the domain services and outputs the results as json? What I wouldnt like about this, is that it leads to redundancy in some of my requests. I might have a regular controller action for viewFriends() and now I would have to add a javascriptService->viewFriends() as well.
b) have all my controllers return results? I don't even think this is really possible, cause javascript can only store whats being echoed, right?
Whats the way to go here?
Thanks.
If I was you I'd consider what a view is, and then make some minor changes to your controllers to enable them to output views that are not just HTML - so for example you might want to output some JSON data - and this could be considered a view.
This tutorial - http://www.paulund.co.uk/use-php-to-detect-an-ajax-request shows how to check if a request is Ajax - so you could use this method in the controller to decide how you want to deliver a view etc.
Here is what I intend to build:
There is a service providing data with RESTful JSON-only API. The server setup is Python + Flask.
There are several clients making use of this API, like a normal web app, mobile-compatible client and a Facebook App.
Now, my assumptions/decisions:
I decided on the server providing only data through JSON, thus handing over the presentation completely to the client-side.
I desire to make the web app mobile compatible, thus eliminating need of a separate mobile client.
Also, for Facebook app, I decided to use Facebook Canvas, which would render parts of the normal web app, thus reusing the code.
Feel free to correct me if anything is wrong in above assumptions. Though the above is theoretically possible, I would like to know if the practical implementation is feasible or not.
Now, the web app, after having fetched the base page/template from server, will have to handle the rendering dynamically after fetching data through JSON API. The data is quite simple: multiple-option questions, answering which user receives another question. At the end, user can share the result or invite other users.
With this setup, do I need a framework like angularjs or jQuery would suffice?
My main concern here is how do I handle internationalization? I initially intended to user Flask-Babel to internationalize HTML templates. But having zeroed in on JSON-only API, I don't have a clue as to how/where I handle it now: on client-side or server-side? What are the tools I use for it?
One approach I could think of was to have data in different languages on server itself, and send the JSON response with data in appropriate language, depending on some attribute the client sends in request.
Another approach is to let client do all the translation for a common dataset that server sends. I am not sure of this approach though.
You could find this plugin really helpful.
As far as the usage , it is quite simple to set it up for a single page application that is powered by a JSON API.
If we take a look at a sample usage :
HTML:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="[PATH]/jquery.js" /> // optional
<script type="text/javascript" src="[PATH]/i18next.js" />
</head>
<body>
<ul class="nav">
<li></li>
<li></li>
<li></li>
</ul>
</body>
Json (loaded resource):
{
"app": {
"name": "i18next"
},
"nav": {
"home": "Home",
"page1": "Page One",
"page2": "Page Two"
}
}
JS:
i18n.init(function(t) {
// translate nav
$(".nav").i18n();
// programatical access
var appName = t("app.name");
});
https://github.com/wikimedia/jquery.i18n may be close match. It can handle a lot of languages and messages are in json files and it is complete client side library.
If all of your interface code lives on the client side, so should your i18n. You would use a i18n library that works with the JavaScript framework you are using. For angular, that might be angular-gettext.
If you are developing several client you might use different i18n libraries in different client applications. Try to make sure they all compile gettext .po files – it will make it easier for your translators.
Using jQuery, Angular, etc. is a decision you should make based on your comfort with the technology, the needs of your application, and compatibility with the Facebook Canvas approach. Angular has powerful data binding, but it requires a mind shift compared to jQuery, for instance, so I suggest poking around with each to see if they meet your needs.
As for internationalization, you can use a plugin like jQuery.i18n, or you could roll your own, something I have done with jQuery and jQuery.Mustache for templating. The short version is that you use HTML templates to store your layout, then render them from inside jQuery like so:
var data = {myLabel: 'Some label', myOtherLabel: 'Some Other Label'};
$("#myDiv")
.html( $.Mustache.render( "MyTemplateId", data ) );
in html template:
<script type="text/html" id="MyTemplateId">
<div>
<label for="myInput">{{MyLabel}}</label> <input name="myInput" id="myInput type="text"/>
<label for="myOtherInput">{{MyOtherLabel}}</label> <input name="myOtherInput" id="myOtherInput type="text"/>
</div>
and on your page layout:
<div id="myDiv>
<!-- dynamic content inserted here -->
</div>
You use a loader command with jQuery.Mustache (https://github.com/jonnyreeves/jquery-Mustache) to load your templates from the server, and since you are using templates, you can fill in your values based on user language selection. How you store your internationalized data is dependent on your app. As Michael suggested, if it is a small amount of static content, maybe you just store it all in your JS files as constants and load into your Mustache render() methods as needed. If you have a larger amount/dynamic multilingual content, you should probably store it on the server and load it dynamically. One consideration is the number of languages you plan to support. If you go beyond a handful of languages, consider storing it on the server and loading language data on demand.
I like this approach because it gives you granular, runtime control over your layout and over internationalization. It also stores the data on the server but loads programatically from the client, maintaining a clean separation of concerns for your application layers.
As for responsive/mobile friendly design, using templating (Mustache) and checking the viewport at load time allows you to determine browser capabilities and serve the approrpriate layout without having to prompt the user to select a mobile/desktop experience.
If you go this route, you should also research script loaders like RequireJS and StealJS to handle dependency loading for your scripts, and to handle the initial browser check and layout generation.
Your question is too broad. I can only answer part of it and here are some of the answers:
I desire to make the web app mobile compatible, thus eliminating need of a separate mobile client.
In order to make sure that things are working fine you need to handle
Also, for Facebook app, I decided to use Facebook Canvas, which would render parts of the normal web app, thus reusing the code.
I am not sure.
With this setup, do I need a framework like angularjs or jQuery would suffice?
As you tagged that you are targeting this as a single page application. Therefore, I would recommend you to go for single page frameworks like Anglarjs, knockout.js or Node.js. A quick and good comparison between these frameworks can be found from here
Also this post shares how to implement Internationalization in Angularjs
My main concern here is how do I handle internationalization?
some of these frameworks provide support for handling internationalization and localization natively. For other you can find some links that will help you achieve internationalization.
Whereas if you use jQuery you will to define your own framework for handling single-page-application and apart for that you will need a huge bunch of add-on's to accomplish your objective.
Hope this helps!!!
Steps to implement i18n via js & json:
define css class for i18n tag, e.g. <span class="i18n" id="i18n_username"></span>
define i18n values for different language in different .properties file, e.g. in userhome_en_US.properties, there is a key value: username = Username
write backend API to load .properties file by language, and return in json key-value format, e.g. send param: lang=en_US, page=userhome to I18nAction -> loadI18n(), then it will return json value via ajax: {"username":"Username"},
write js function to load i18n key-value by lang & page param,
update i18n text on web page, by get the tag via css class, and replace content, e.g. use jquery to get all span tag that has class="i18n", then remove the i18n_ prefix of the id, then use it as key to get the value from returned json, then replace the content of span,
I did write util programs like this, it's quite flexible & easy to use. The basic concept is come from struts2 framework's i18n feature.
Although I don't know your technical constraints in detail, I believe it all depends on your volume of data :
If you have few "questions / answers" that probably won't evolve much over time, you can treat I18N as constants. Putting everything on the client side makes sense.
If you have a big amount of "questions / answers" that will probably evolve, I believe you have to treat I18N as data.
Since you have made a JSON API, the odds are that your Q/A is your data, and it already belongs to your server side.
The real question is : do you want to deliver a new version of your client app everytime you add or correct a question?
That's why I would do this :
One approach I could think of was to have data in different languages on server itself, and send the JSON response with data in appropriate language, depending on some attribute the client sends in request.
edit (precision) : I'm talking about the questions and answers. For the application messages (menus, text, help messages, etc), you should use your client framework's i18n components. The other answers provide a lot of good tools.
I've been getting into Pylons lately and was wondering how I could go about easily integrating AJAX functionality into my websites.
Basically, lets say I had a login form that usually gets accessed via site.com/user/login. Now, generally, this will be handled via something like:
class UserController(BaseController):
def login(self):
render('/login.html')
login.html would be a template that inherits the base, has a header, footer and navigation sidebar. A plani, simple website.
How could I AJAXify this? I would need to create two login.html templates, right? What would be a good way to handle the controller's login() method? Should I set a GET variable of something like &ajax=true then check for that when issuing render()?
I want a nice and clean way to choose how my controllers render content instead of some ugly hack (like the GET method above).
Thoughts?
All modern Javascript libraries set an "X-Requested-With: XMLHttpRequest" header in their AJAX wrappers. As a convenience, Pylons sets the request.is_xhr boolean if it finds this header.
Conditional inheritance is a little tricky in Mako because of how <%inherit> is handled, but here's what you do:
Change the render() call in your controller to render('/login.html', {'ajax': request.is_xhr})
In your template, separate out anything you don't want in your AJAX template using template inheritance.
Use an <%inherit> something like this:
<%inherit file="${None if context.get('ajax') else 'login_base.html'}"/>
(Note: There's nothing special about the render() syntax used. You could just as easily use c.ajax = request.is_xhr and context.get('c').ajax instead)
I'm not sure why your AJAX code would want to do a GET on that login page -- GET is only for getting information, and what info would the JS code client-side want to obtain from a login form?
Anyway, assuming there are pages that you want AJAX code to be able to GET in order to obtain useful info, I recommend a query string such as ?format=json to allow such requests to explicitly ask for "useful JSON-format info only, no decoration please".
Not only does this approach allow your app to know that this is an automated request (AJAX or otherwise, who cares? point is, no cosmetics are to be sent in response, just useful info!) but specifically that the requested format is JSON (so, should you ever want to supply XML or whatever as an alternative, there's an obvious growth path -- ?format=xml and the like).
There is nothing particularly Python-specific, much less Pylons-specific, in this -- it's the approach I would recommend for any "mixed" site (able, at least in some pages, to respond in more than one format, e.g. HTML with decorations or JSON, at clients' choice) no matter what sever-side language it was planning on using.
If your rendering is always of a form such as somefunction(sometemplate, somecontext), though, you may tweak things to ensure that the somefunction also gets the crucial bit about requested format -- if the requested format is JSON (or, who knows, in the future maybe XML or whatever) then somefunction knows it can ignore the template (which after all is or should be a purely view related functionality, and therefore should have presentation contents only) and just proceed to render the info that's in the context as JSON or whatever.
The author of Mako himself wrote a blog post that you might find interesting.
The main point is a function to render a single "def" of a template:
def render_def(template_name, name, **kwargs):
from pylons.templating import pylons_globals
globs = pylons_globals()
if kwargs:
globs = globs.copy()
globs.update(kwargs)
template = globs['app_globals'].mako_lookup.get_template(template_name).get_def(name)
return template.render(**globs)
I'm working on an AJAXy project (Dojo and Rails, if the particulars matter). There are several places where the user should be able to sort, group, and filter results. There are also places where a user fills out a short form and the resulting item gets added to a list on the same page.
The non-AJAXy implementation works fine -- the view layer server-side already knows how to render this stuff, so it can just do it again in a different order or with an extra element. This, however, adds lots of burden to the server.
So we switched to sending JSON from the server and doing lots of (re-)rendering client-side. The downside is that now we have duplicate code for rendering every page: once in Rails, which was built for this, and once in Dojo, which was not. The latter is basically just string concatenation.
So question part one: is there a good Javascript MVC framework we could use to make the rendering on the client-side more maintainable?
And question part two: is there a way to generate the client-side views in Javascript and the server-side views in ERB from the same template? I think that's what the Pragmatic Programmers would do.
Alternatively, question part three: am I completely missing another angle? Perhaps send JSON from the server but also include the HTML snippet as an attribute so the Javascript can do the filtering, sorting, etc. and then just insert the given fragment?
Well, every time you generate HTML snippets on the client and on the server you may end up with duplicated code. There is no good way around it generally. But you can do two things:
Generate everything on the server. Use AHAH when you need to generate HTML snippets dynamically. Basically you ask server to generate an HTML fragment, receive it asynchronously, and plug it in place using innerHTML or any other similar mechanism.
Generate everything on the client (AKA the thick client paradigm). In this case even for the initial rendering you pass data instead of pre-rendered HTML, and process the data client-side using JavaScript to make HTML. Depending on the situation you can use the data island technique, or request data asynchronously. Variant: include it as <script> using JSONP so the browser will make a request for you while loading the page.
Both approaches are very simple and have different set of pros and cons. Sometimes it is possible to combine both techniques within one web application for different parts of data.
Of course you can go for exotic solutions, like using some JavaScript-based server-side framework. In this case you can share the code between the server and the client.
I don't have a complete answer for you; I too have struggled with this on a recent project. But, here is a thought:
Ajax call to Rails
Rails composes the entire grid again, with the new row.
Rails serializes HTML, which is returned to the browser.
Javascript replaces the entire grid element with the new HTML.
Note: I'm not a Rails person, so I'm not sure if those bits fit.
Has anyone tried something like the following? There's redundant data now, but all the rendering is done server-side and all the interaction is done client-side.
Server Side:
render_table_initially:
if nojs:
render big_html_table
else:
render empty_table_with_callback_to_load_table
load_table:
render '{ rows: [
{ foo: "a", bar: "b", renderedHTML: "<tr><td>...</td></tr>" },
{ foo: "c", bar: "d", renderedHTML: "<tr><td>...</td></tr>" },
...
]}'
Client side:
dojo.xhrGet({
url: '/load_table',
handleAs: 'json',
load: function(response) {
dojo.global.all_available_data = response;
dojo.each(response.rows, function(row) {
insert_row(row.renderedHTML);
}
}
});
Storing the all_available_data lets you do sorting, filtering, grouping, etc. without hitting the server.
I'm only cautious because I've never heard of it being done. It seems like there's an anti-pattern lurking in there...
"Perhaps send JSON from the server but also include the HTML snippet as an attribute so the Javascript can do the filtering, sorting, etc. and then just insert the given fragment?"
I recommend keeping the presentation layer on the client and simply downloading data as needed.
For a rudimentary templating engine, you can extend Prototype's Template construct:
http://www.prototypejs.org/api/template
As your client scales and you need a rich and flexible MVC, try PureMVC.
http://puremvc.org/content/view/102/181/
As in regular server side programming you should strive to encapsulate your entities with controls, in your case client side controls that has data properties and also render methods + events.
So for example lets say you have on the page an are that shows tree of employees, effectively you should encapsulate it behavior in a client side class that can get JSON object of the employee list / by default connect to the service and a render method to render the output, events and so on.
In ExtJS its is relatively easy to create these kind of controls - look at this article.
Maybe I'm not fully understanding your problem but this is how I would solve your requirements:
Sort, Filter
It can be done all in JavaScript, without hitting the server. It's a problem of manipulating the table rows, move rows for sorting, hide rows for filtering, there is no need for re-rendering. You will need to mark columns with the data type with custom attributes or extra class names in order to be able to parse numbers or dates.
If your reports are paginated I think it's easier and better to refresh the whole table or page.
Group
I can't help here as I don't understand how will you enable grouping. Are you switching columns to show accumulates? How do you show the data that doesn't support accumulates like text or dates?
New item
This time I would use AJAX with a JSON response to confirm that the new item was correctly saved and possibly with calculated data.
In order to add the new item to the results table I would clone a row and alter the values. Again we don't need to render anything in client-side. The last time I needed something like this I was adding an empty hidden row at the end of the results, this way you will always have a row to clone no matter if the results are empty.
Number 5 in my list of five AJAX styles tends to work pretty well.