/tutorials/PHP/build-apps-with-kendo-ui-and-php.md

https://github.com/petar-raykov-telerik/kendo-docs · Markdown · 487 lines · 334 code · 153 blank · 0 comment · 0 complexity · 4620e590ef229fbe9e7b52c4f37186ca MD5 · raw file

  1. ---
  2. title: Intro to Building Apps with Kendo UI And PHP Part 1
  3. slug: tutorial-intro-building-apps-with-kendo-ui-and-php
  4. tags: Tutorial
  5. publish: true
  6. ---
  7. # Tutorial: Intro to Building Apps with Kendo UI And PHP - Part 1
  8. This tutorial will walk you through building your first Kendo UI PHP Application. It is a two part tutorial in which you will learn...
  9. - How to setup your PHP Development Environment, including selecting an IDE
  10. - How to connect to your database and return data
  11. - How to create a Kendo UI Grid bound to data
  12. - How to handle read, create, update and delete operations
  13. - How to filter data
  14. - How to use detail grids
  15. ### Setting Up To Develop In PHP
  16. The development environment that will be used for this consists of a MacBook Pro running Lion. Install MySQL, PHP and Apache by using [MAMP][3]
  17. (Macintosh Apache MySQL PHP). Once you do this, you will have a neat
  18. environment setup for running PHP applications with a MySQL database. MAMP
  19. will run by default on port 8888 for the webserver, and the root folder will
  20. be **htdocs** inside of the **Applications/MAMP** directory.
  21. The next step is to get an IDE. Its all text in the end, but a good PHP IDE
  22. is a must. The Eclipse PHP development environment is recommended for this. You can pick up
  23. their community tools contribution to Eclipse free [here][5].
  24. Once you download the IDE, you are all setup to start building PHP
  25. applications.
  26. ### We Need Some Data
  27. For this tutorial we will be using the Northwind database.
  28. Northwind comes in Microsoft Access and SQL Server flavors, but someone was
  29. nice enough to port it to just about every other database type out there. You
  30. can download the .sql script [here][7] and run it in to MySQL to create the
  31. database.
  32. ### Project Setup
  33. Below is a screenshot of how the project looks in Eclipse. Normally, you would
  34. put your publicly accessible files in a public folder and restrict access to
  35. ones that are server only. For the sake of simplicity, all the files are
  36. public.
  37. [![1][8]]
  38. Lets look a bit at the structure.
  39. The css files for Kendo UI and images are in the **css** folder. Additionally, the Metro theme for Kendo UI is being used. The Kendo UI JavaScript files and
  40. jQuery are in a **js** folder. The startup page for the site is **index.php**.
  41. A **data** folder has been manually added. In this folder is where all of the data access code will go. Each of these files will return a JSON formatted
  42. string of data from the MySQL database.
  43. The next thing to do is to add in the CSS and JavaScript files to the head of
  44. the** index.php **page.
  45. <!DOCTYPE html>
  46. <html>
  47. <head>
  48. <link href="css/kendo.metro.min.css" rel="stylesheet">
  49. <link href="css/kendo.common.min.css" rel="stylesheet">
  50. <script src="js/jquery.min.js"></script>
  51. <script src="js/kendo.all.min.js"></script> </head>
  52. So far this is probably all very familiar if you have done any PHP development
  53. in the past at all.
  54. ### Create The Grid
  55. Next, we are just going to add an empty **div** and then turn that div into a
  56. grid by selecting it with a jQuery selector and calling the **kendoGrid** function.
  57. For more information about the basics of working with the grid, see the
  58. [Getting Started With The Kendo UI Grid][10] Screencast, or the
  59. [Walkthrough][11].
  60. This is what the whole page looks like so far. The grid has no columns and no
  61. data. The next step is to create the .php file which will return the data
  62. from the MySQL database.
  63. <!DOCTYPE html>
  64. <html>
  65. <head>
  66. <link href="css/kendo.metro.min.css"rel="stylesheet">
  67. <link href="css/kendo.common.min.css" rel="stylesheet">
  68. <script src="js/jquery.min.js"></script>
  69. <script src="js/kendo.all.min.js"></script>
  70. </head>
  71. <body>
  72. <div id="grid"></div>
  73. <script>
  74. $(function() {
  75. $("#grid").kendoGrid();
  76. });
  77. </script>
  78. </body>
  79. </html>
  80. ### Connect To The Database
  81. We are going to create a file in the **data** folder called **employees.php**.
  82. This file will connect to the MySQL instance and return all of the employees.
  83. To do this, we need to connect to the database instance using the MySQL PHP
  84. commands.
  85. 1. <?php
  86. 2.
  87. 3. $link = mysql_pconnect("localhost", "root", "root") or die("Unable To Connect To Database Server");
  88. 4. mysql_select_db("northwind") or die("Unable To Connect To Northwind");
  89. 5.
  90. 6. $arr = array();
  91. 7.
  92. 8. $rs = mysql_query("SELECT EmployeeID, LastName, FirstName FROM Employees");
  93. 9.
  94. 10. while($obj = mysql_fetch_object($rs)) {
  95. 11. $arr[] = $obj;
  96. 12. }
  97. 13.
  98. 14. echo "{\"data\":" .json_encode($arr). "}";
  99. 15.
  100. 16. ?>
  101. **Line 3** connects to the MySQL server. The first parameter is the server
  102. name, the second is the username and the third is the password.
  103. **Line 4** selects the Northwind database.
  104. **Line 8** defines a SQL query and associates the results with the **rs**
  105. variable.
  106. **Lines 10 through 13** iterate over the **rs** variable, which holds a
  107. collection of records and stuffs each record into an array that was defined on
  108. line 5.
  109. **Line 14** returns back the results of the array using the **json_encode**
  110. PHP function which turns the array into formatted JSON. Additionally, I have
  111. prefixed the array of data with a top level **data** element. Its typically
  112. a good idea to not have an array as your top level JSON element.
  113. You could now hit that PHP page directly from your browser and see the
  114. results. Your URL might be something similar to the following depending on how your development environment is setup.
  115. [http://localhost:8888/KendoUI/data/employees.php][12]
  116. [![2][13]][14]
  117. ### Wire Up The Grid
  118. We define a data source for the grid and bind that data source to this URL
  119. which returns the JSON data. The **transport** defines how the grid will
  120. interact with remote endpoints, and the **read** method defines which URL will
  121. provide the data when the grid is loaded. Additionally, we are defining columns
  122. for the **LastName** and **FirstName**.
  123. <body>
  124. <div id="grid"></div>
  125. <script>
  126. $(function() {
  127. $("#grid").kendoGrid({
  128. dataSource: {
  129. transport: {
  130. read: "data/employees.php"
  131. },
  132. schema: {
  133. data: "data"
  134. }
  135. },
  136. columns: [{ field: "FirstName" }, { field: "LastName" }]
  137. });
  138. });
  139. </script>
  140. </body>
  141. Note that since we are not actually defining anything in the column but the
  142. field, we could have just specified the columns as:
  143. columns: [ FirstName, LastName ]
  144. Also notice that we only have to reference **data/employees.php** as the URL to
  145. read because the path is relative to the current application page being served
  146. up. I also set some **schema** information basically telling the grid that
  147. the repeating information that it needs to display is found in the top level
  148. **data** element. Lets save and have a look at it in the browser.
  149. [![3][15]][16]
  150. ## Theres No Data.
  151. This was done on purpose to demonstrate a rather important detail. If you look
  152. in the Developer Tools on Chrome you will see an error saying that length
  153. cannot be read off of undefined.
  154. [![4][17]][18]
  155. Thats a good indication that something is wrong with your JSON data. Either
  156. it isnt formatted correctly, or you have some other issue. In this case the
  157. data is formatted correctly, the problem is that when the PHP file gets read,
  158. its getting read as HTML and not as JSON.
  159. How do you know this?
  160. Have a look in the Network Activity tab in Chrome Developer Tools. You can
  161. examine the content type there.
  162. [![5][19]][20]
  163. Actually, it is JSON but the server is reporting that its HTML. How do we
  164. fix this? We just need to specify in our PHP file right before we echo back
  165. that the type is JSON. We do this by adding a header. The PHP file now looks
  166. like this
  167. <?php
  168. $link = mysql_pconnect("localhost", "root", "root") or die("Unable To Connect To Database Server");
  169. mysql_select_db("northwind") or die("Unable To Connect To Northwind");
  170. $arr = array();
  171. $rs = mysql_query("SELECT EmployeeID, LastName, FirstName FROM Employees");
  172. while($obj = mysql_fetch_object($rs)) {
  173. $arr[] = $obj;
  174. }
  175. // add the header line to specify that the content type is JSON
  176. header("Content-type: application/json");
  177. echo "{\"data\":" .json_encode($arr). "}";
  178. ?>
  179. Now we can refresh the page and there will be data in the grid.
  180. [![6][21]][22]
  181. ### More Complex Data
  182. Thats all well and good, but that data is really simple. Lets make it a bit
  183. more complex. Each of these employees is in sales. They all have territories
  184. that they are responsible for. Ideally, we need to be able to display 1 to
  185. many territories per each employee.
  186. With Kendo UI, you can define a detail template for each item in the grid. In
  187. other words, we are going to nest a grid within a grid.
  188. **The Detail Template**
  189. The detail template is very simple. Its just an empty **div**. We could do
  190. much more complex things here like adding in tab controls like we did in the
  191. detail template example on the [demos page][23].
  192. <script type="text/x-kendo-template" id="template">
  193. <div class="subgrid"></div>
  194. </script>
  195. For more information on Kendo UI Templates, refer to the [documentation][24]
  196. and [examples][25]. Now that we have a template defined, we need to specify
  197. in the grid that we do in fact want a detail template and a function to call
  198. each time a row is expanded to check the details.
  199. Our main grid function now looks like this. The last two lines define the
  200. template, and to call the **detailInit()** function when a grid row is
  201. expanded.
  202. $("#grid").kendoGrid({
  203. dataSource: {
  204. transport: {
  205. read: "data/employees.php"
  206. },
  207. schema: {
  208. data: "data"
  209. }
  210. },
  211. columns: [{ field: "FirstName" }, { field: "LastName" }],
  212. detailTemplate: kendo.template($("#template").html()),
  213. detailInit: detailInit
  214. });
  215. The **detailInit** function is fairly straightforward.
  216. function detailInit(e) {
  217. // get a reference to the current row being initialized
  218. var detailRow = e.detailRow;
  219. // create a subgrid for the current detail row, getting territory data for this employee
  220. detailRow.find(".subgrid").kendoGrid({
  221. dataSource: {
  222. transport: {
  223. read: "data/territories.php"
  224. },
  225. schema: {
  226. data: "data"
  227. },
  228. serverFiltering: true,
  229. filter: { field: "EmployeeID", operator: "eq", value:e.data.EmployeeID }
  230. },
  231. columns: [{ title: "Territories", field: "TerritoryDescription" }],
  232. });
  233. }
  234. It takes in an argument of **e** which will contain data about the row we
  235. expanded in the grid, and the data that was in that row.
  236. The **subgrid** has a class of **.subgrid**. The .**find()** is a jQuery
  237. method to search the children of the current row and find the grid. Again,
  238. having a full template here is unnecessary since all we have is a simple
  239. **div**, but it should give you a better idea of where you would start if you
  240. wanted to have a robust details section.
  241. The only other thing of note in the **subgrid** declaration is that we are
  242. going to pass the EmployeeID on which to filter the territories by using
  243. filtering. Filtering will pass a filter object with the request to the
  244. **data/territories.php** file.
  245. ### Create The Territories File
  246. We need a new file for querying territories. Make one exactly like the
  247. **employees.php** file and call it **territories.php**. You can copy the code
  248. inside verbatim. We do need to swap out the SQL. Its going to have to join
  249. several tables together to get from the Territories table back to the
  250. Employees Table.
  251. We can get the **EmployeeID** off the **filter** object which Kendo UI sends
  252. to the server as part of the request. Filter objects are complex in their
  253. structure because they can contain extensive filtering instructions. The
  254. filter we defined above will pass an object filter that is an array of
  255. filters. Each of these filters has a field to filter on, an operator (eq,
  256. greaterthan, ect.) and a value. We are only interested in the one value we
  257. are passing and we know the operator is always equals.
  258. 1: <?php
  259. 2: // DISCLAIMER: It is better to use prepared statements in PHP.
  260. 3. // This provides protection against sql injection.
  261. 4. // [http://php.net/manual/en/pdo.prepared-statements.php][26]
  262. 5: // get the employee id off the request. escape it to protect against sql injection
  263. 6: $employeeID = mysql_real_escape_string($_REQUEST["filter"]["filters"][0]["value"]);
  264. 7:
  265. 8: $link = mysql_pconnect("localhost", "root", "root") or die("Unable To Connect To Database Server");
  266. 9: mysql_select_db("northwind") or die("Unable To Connect To Northwind");
  267. 10:
  268. 11: $arr = array();
  269. 12: $rs = mysql_query("SELECT TRIM(t.TerritoryDescription) AS TerritoryDescription
  270. 13: FROM Territories t
  271. 14: INNER JOIN EmployeeTerritories et ON t.TerritoryID = et.TerritoryID
  272. 15: INNER JOIN Employees e ON et.EmployeeID = e.EmployeeID
  273. 16: WHERE e.EmployeeID = " .$employeeID);
  274. 17:
  275. 18: while($obj = mysql_fetch_object($rs)) {
  276. 19: $arr[] = $obj;
  277. 20: }
  278. 21:
  279. 22: // add the header line to specify that the content type is JSON
  280. 23: header("Content-type: application/json");
  281. 24:
  282. 25: echo "{\"data\":" .json_encode($arr). "}";
  283. 26:
  284. 27: ?>
  285. **Line 6** pulls the filter data of the PHP **$_REQUEST** object. This is not
  286. necessarily the best way to read the parameter, but for the sake of simplicity
  287. and the ability to see how the filter object is actually structured, I have
  288. done it this way.
  289. Now whenever a row is expanded, a query will be made to the**
  290. territories.php** file which will provide the territories that are associated
  291. with each employee.
  292. [![7][27]][28]
  293. And expanded
  294. [![8][29]][30]
  295. ### Wrap Up
  296. We walked through a lot of content here, but lets review. We accomplished
  297. the following things
  298. 1. Installed PHP, MySQL
  299. 2. Created A PHP Application
  300. 3. Wrote Endpoints For Returning Data
  301. 4. Wired Up A Kendo UI Grid For Displaying Parent-Child Data
  302. This has been an example of how to get rolling with PHP and [Kendo UI][32].
  303. [Proceed To Part 2](http://docs.kendoui.com/tutorials/PHP/build-apps-with-kendo-ui-and-php-2)
  304. [2]: http://en.wikipedia.org/wiki/Polyglot
  305. [3]: http://www.mamp.info/en/index.html
  306. [4]: http://framework.zend.com/
  307. [5]: http://www.zend.com/en/community/pdt
  308. [6]: http://www.microsoft.com/web/webmatrix/
  309. [7]: http://code.google.com/p/northwindextended/downloads/detail?name=Northwind.MySQL5.sql
  310. [8]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-1_thumb_1.png (1)
  311. [9]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-1_thumb_1.png (1)
  312. [10]: http://www.kendoui.com/videos.aspx
  313. [11]: http://www.kendoui.com/documentation/ui-widgets/grid/walkthrough.aspx
  314. [12]: http://localhost:8888/KendoUI/data/employees.php
  315. [13]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-2_thumb_2.png (2)
  316. [14]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-2_thumb_2.png (2)
  317. [15]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-3_thumb_2.png (3)
  318. [16]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-3_thumb_2.png (3)
  319. [17]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-4_thumb.png (4)
  320. [18]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-4_thumb.png (4)
  321. [19]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-5_thumb_1.png (5)
  322. [20]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-5_thumb_1.png (5)
  323. [21]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-6_thumb.png (6)
  324. [22]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-6_thumb.png (6)
  325. [23]: http://demos.kendoui.com/web/grid/detailtemplate.html
  326. [24]:http://www.kendoui.com/documentation/framework/templates/overview.aspx
  327. [25]: http://demos.kendoui.com/web/templates/index.html
  328. [26]: http://php.net/manual/en/pdo.prepared-statements.php
  329. [27]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-7_thumb_2.png (7)
  330. [28]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-7_thumb_2.png (7)
  331. [29]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-8_thumb_1.png (8)
  332. [30]: https://raw.github.com/telerik/kendo-docs/production/tutorials/PHP/images/ff819b019713_9A19-8_thumb_1.png (8)
  333. [31]: /Blogs_Libraries/Source_Code/KendoUI.sflb.ashx
  334. [32]: http://www.kendoui.com/get-kendo-ui.aspx