Thứ Ba, 30 tháng 12, 2008

Dot Net Interview Questions - Part 3

1.What is a stack? What is a heap?

Ans : Stack is a place in the memory where value types are stored. Heap is a place in the memory where the reference types are stored.

2.What is Boxing/Unboxing?

Ans : Boxing is used to convert value types to object.
E.g. int x = 1;
object obj = x ;
Unboxing is used to convert the object back to the value type.
E.g. int y = (int)obj;

3.What is globalization?

Ans : Globalization is the process of customizing applications that support multiple cultures and regions.

4.What is localization?

Ans : Localization is the process of customizing applications that support a given culture and regions.

5.What is Ilasm.exe used for?

Ans : Ilasm.exe is a tool that generates PE files from MSIL code. You can run the resulting executable to determine whether the MSIL code performs as expected.

6.What is Ildasm.exe used for?

Ans : Ildasm.exe is a tool that takes a PE file containing the MSIL code as a parameter and creates a text file that contains managed code.

7.What is the ResGen.exe tool used for?

Ans : ResGen.exe is a tool that is used to convert resource files in the form of .txt or .resx files to common language runtime binary .resources files that can be compiled into satellite assemblies.

8.What happens when you change the web.config file at run time?

Ans : ASP.NET invalidates the existing cache and assembles a new cache. Then ASP.NET automatically restarts the application to apply the changes.

9.Explain the AutoPostBack feature in ASP.NET?

Ans : AutoPostBack allows a control to automatically postback when an event is fired. For eg: If we have a Button control and want the event to be posted to the server for processing, we can set AutoPostBack = True on the button.

10.What are Master Pages?

Ans : Master pages is a template that is used to create web pages with a consistent layout throughout your application. Master Pages contains content placeholders to hold page specific content. When a page is requested, the contents of a Master page are merged with the content page, thereby giving a consistent layout.

11.What are the types of Caching?

Ans : 1.Application Cache 2.Page Output Cache 3.Variable Cache




12.Method Parameters in C#?

Ans : 1. REF,2. OUT,3.PARAMS




13.What’s the .NET datatype that allows the retrieval of data by a unique key?

Ans : HashTable.

14.How do you debug an ASP.NET Web application?

Ans : Attach the aspnet_wp.exe process to the DbgClr debugger.

15.What is the syntax to inherit from a class in C#?

Ans : Place a colon and then the name of the base class.

Example: class MyNewClass : MyBaseClass

16.What’s a bubbled event?

Ans : When you have a complex control, like DataGrid, writing an event processing routine for each object (cell, button, row, etc.) is quite tedious. The controls can bubble up their eventhandlers, allowing the main DataGrid event handler to take care of its constituents.

17.What does WSDL stand for?

Ans : Web Services Description Language.

18.Can you override private virtual methods?

Ans : No, moreover, you cannot access private methods in inherited classes, have to be protected in the base class to allow any sort of access.

19.What is an out parameter?

Ans : An out parameter allows an instance of a parameter object to be made inside a method. Reference parameters must be initialised but out gives a reference to an uninstanciated object.

20.What is recursion?

Ans : Recursion is when a method calls itself.

21.Name 10 C# keywords.

Ans : abstract, event, new, struct, explicit, null, base, extern, object, this

22.What is a DLL?

Ans : A set of callable functions, which can be dynamically loaded.

23.What is unsafe code?

Ans : Unsafe code bypasses type safety and memory management.

24.How would you read and write using the console?

Ans : Console.Write, Console.WriteLine, Console.Readline

25.What’s the difference between // comments, /* */ comments and /// comments?

Ans : Single-line comments, multi-line comments, and XML documentation comments.

Dot Net Interview Questions - Part 2



1.What are server controls?

Ans : ASP.NET server controls are components that run on the server and encapsulate user-interface and other related functionality. They are used in ASP.NET pages and in ASP.NET code-behind classes.

2.What are Sealed Classes in C#?

Ans : The sealed modifier is used to prevent derivation from a class. A compile-time error occurs if a sealed class is specified as the base class of another class. (A sealed class cannot also be an abstract class) .

3.What is the difference between Array and Arraylist?

Ans : As elements are added to an ArrayList, the capacity is automatically increased as required through reallocation. The capacity can be decreased by calling TrimToSize or by setting the Capacity property explicitly.

4.What is Jagged Arrays?

Ans : A jagged array is an array whose elements are arrays. The elements of a jagged array can be of different dimensions and sizes. A jagged array is sometimes called an “array-of-arrays.”

5.Which method is used to redirect the user to another page without performing a round trip to the client?

Ans : Server.Transfer method.

6.Is it possible to debug java-script in .NET IDE? If yes, how?

Ans : Yes, simply write “debugger” statement at the point where the breakpoint needs to be set within the javascript code and also enable javascript debugging in the browser property settings.

7.How many ways can we maintain the state of a page?

Ans : Client Side - Query string, hidden variables, viewstate, cookies

Server side - application , cache, context, session, database.

8.Will the finally block be executed if an exception has not occurred?

Ans : Yes it will execute.

9.What is the base class of all web forms?

Ans : System.Web.UI.Page .

10.Can we force the garbage collector to run?

Ans : Yes, using the System.GC.Collect(), the garbage collector is forced to run in case required to do so.

11.What does the virtual keyword in C# mean?

Ans : The virtual keyword signifies that the method and property may be overridden.

12.Whats the difference between web.config and app.config?

Ans : Web.config is used for web based asp.net applications whereas app.config is used for windows based applications.

13.What is the difference between a session object and an application object?

Ans : A session object can persist information between HTTP requests for a particular user, whereas an application object can be used globally for all the users.

14.Is it possible to perform forms authentication with cookies disabled on a browser?

Ans : No, it is not possible.

15.Which control has a faster performance, Repeater or Datalist?

Ans : Repeater.

16.What technique is used to figure out that the page request is a postback?

Ans : The IsPostBack property of the page object may be used to check whether the page request is a postback or not. IsPostBack property is of the type Boolean.

17.How can we force a thread to sleep for an infinite period?

Ans : Call the Thread.Interupt() method.

18.What’s the difference between Response.Write() andResponse.Output.Write()?

Ans : Response.Output.Write() allows you to write formatted output.




19.Describe the difference between inline and code behind.

Ans : Inline code written along side the html in a page. Code-behind is code written in a separate file and referenced by the .aspx page.

20.What is the lifespan for items stored in ViewState?

Ans : Item stored in ViewState exist for the life of the current page. This includes postbacks (to the same page).

21.What is PostBack & Callback?

Ans : One technique that current ASP.NET 1.0/1.1 developers use to overcome this postback problem is to use the Microsoft XMLHTTP ActiveX object to send requests to server-side methods from client-side JavaScript. In ASP.NET 2.0, this process has been simplified and encapsulated within the function known as the Callback Manager. The ASP.NET 2.0 Callback Manager uses XMLHTTP behind the scenes to encapsulate the complexities in sending data to and from the servers and clients. And so, in order for the Callback Manager to work, you need a web browser that supports XMLHTTP. Microsoft Internet Explorer is, obviously, one of them.

22.What is singlecall and singleton ?

Ans : Differneces between Single Call & Singleton. Single Call objects service one and only one request coming in. SingleCall objects are useful in scenarios where the objects are required to do afinite amount of work. Single Call objects areusually not required to store state information, and they cannot hold state information between method calls. However, SingleCall objects can be configured in aload-balanced fashion.

Singleton objects are those objects that service multiple clients and hence share data by storing state information between client invocations. They are useful in cases in which data needs tobe shared explicitly between clients and also in which the overhead of creating and maintaining objects is substantial.

23.What is Machine.config File ?

Ans : As web.config file is used to configure one asp .net web application, same way Machine.config file is usedto configure application according to a particular machine. That is, configuration done in machine.configfile is affected on any application that runs on a particular machine. Usually, this file is not alteredand only web.config is used which configuring applications.

24.What debugging tools come with the .NET SDK?

Ans : 1. CorDBG – command-line debugger. To use CorDbg, you must compile the original C# file using the /debug switch.

2. DbgCLR – graphic debugger. Visual Studio .NET uses the DbgCLR.

25.What does assert() method do?

Ans : In debug compilation, assert takes in a Boolean condition as a parameter, and shows the errordialog if the condition is false. The program proceeds without any interruption if the conditionis true.

Dot Net Interview Questions part 1

1.What method do you use to explicitly kill a users session?

Ans : Syntax: Session.Abandon()

Note : The Abandon method destroys all the objects stored in a Session object and releases their resources.If you do not call the Abandon method explicitly, the server destroys these objects when the session times out.

2.What methods are fired during the page load?

Ans : Init() ,Load(),PreRender(),Unload().

3.What data type does the RangeValidator control support?

Ans : Integer,String and Date.

4.Which method do you invoke on the DataAdapter control to load your generated dataset with data?

Ans : Fill() method.




5.Which control would you use if you needed to make sure the values in two different controls matched?

Ans : CompareValidator Control




6.What base class do all Web Forms inherit from?

Ans : The Page class.

7.Explain the differences between Server-side and Client-side code?

Ans : Server-side code executes on the server. Client-side code executes in the context of the clients’ browser.
8.do you store the information about the user’s locale?

Ans : System.Web.UI.Page.Culture

9.Can you edit data in the Repeater control?

Ans : No, it just reads the information from its data source.

10.Which template must you provide, in order to display data in a Repeater control?

Ans : ItemTemplate.

11.How can you provide an alternating color scheme in a Repeater control?

Ans : AlternatingItemTemplate.

12.Name two properties common in every validation control?

Ans : ControlToValidate property and Text property.

13.Is String is Value Type or Reference Type in C#?

Ans : String is an object (Reference Type).

14.What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other?

Ans : Server.Transfer transfers page processing from one page directly to the next page without making a round-trip back to the client’s browser. This provides a faster response with a little less overhead on the server. Server.Transfer does not update the clients url history list or current url. Response.Redirect is used to redirect the user’s browser to another page or site. This performas a trip back to the client where the client’s browser is redirected to the new page. The user’s browser history list is updated to reflect the new address.

15.What is the Global.asax used for?

Ans : The Global.asax (including the Global.asax.cs file) is used to implement application and session level events.

16.How many classes can a single .NET DLL contain?

Ans : It can contain many classes.




17.What is portable executable (PE)?

Ans : The file format defining the structure that all executable files (EXE) and Dynamic Link Libraries (DLL) must use to allow them to be loaded and executed by Windows. PE is derived from the Microsoft Common Object File Format (COFF). The EXE and DLL files created using the .NET Framework obey the PE/COFF formats and also add additional header and data sections to the files that are only used by the CLR.





18.What is strong name?

Ans : A name that consists of an assembly’s identity—its simple text name, version number, and culture information (if provided)—strengthened by a public key and a digital signature generated over the assembly.





19.What is Code Access Security (CAS)?

Ans : CAS is the part of the .NET security model that determines whether or not a piece of code is allowed to run, and what resources it can use when it is running. For example, it is CAS that will prevent a .NET web applet from formatting your hard disk.

20.What are the different types of assemblies?

Ans : Private, Public/Shared, Satellite

21.Which namespace is the base class for .net Class library?

Ans : system.object

22.How do you create threading in .NET? What is the namespace for that?

Ans : System.Threading.Thread .




23.What is the difference between ref & out parameters?

Ans : An argument passed to a ref parameter must first be initialized. Compare this to an out parameter, whose argument does not have to be explicitly initialized before being passed to an out parameter.





24.What are indexers?

Ans : Indexers are similar to properties, except that the get and set accessors of indexers take parameters, while property accessors do not.

25.What are the access-specifiers available in c#?

Ans : Private, Protected, Public, Internal, Protected Internal.

Chôm từ : fordevs.com

Thứ Hai, 29 tháng 12, 2008

Cakephp 1.2 final ra lò

Cakephp 1.2 final ra lò



Today, the history of the CakePHP grows stronger. December 25, 2008 will be remembered as one of the most important points in this history. After exactly 2 yrs from the first development release, we can happily say we have the most stable and powerful web framework available. Please enjoy our big present to you, CakePHP 1.2 stable [1]. For this release, we have removed the test files from the build, and created a tag in SVN.

Through the last two years, we have been blessed by a dedicated, talented, and opinionated community[2]. We have shared disagreements[3] and triumphs. We have won popularity contests[4] and been hated on. We have seen CakePHP grow into a truly international community[5]. All of these events have generated an immense amount of passion for CakePHP.

No one is more passionate about CakePHP than the developers[6] who close tickets and fix bugs. We started out two years ago with a small team that dedicated countless hours to implementing new features into 1.2 and maintaining 1.1 stable. This team ensured the integrity of code and vision of the project. When we needed to grow, we found members of the community who showed the same amount of dedication and passion for CakePHP. And with the launch of CakeBOOK, on http://book.cakephp.org, we have seen the dedication and passion further extend to all the contributors and translators[7] of the fantastic documentation that makes learning about the power of CakePHP a bit easier.

We have seen CakePHP adopted by large projects[8] and the growth of dedicated service companies[9]. We have held a workshop[10] to spread the knowledge and passion of CakePHP. And ultimately, we implemented a huge list of features...

  • - Tests!



    • - All classes are test-covered, with good code coverage

    • - Test suite now integrated into the framework

    • - test generation

    • - support for coverage analysis



  • - Command-line infrastructure



    • - with more shell scripts and ability to write custom ones easily



  • - Plugin architecture



    • - Plugins are now distributable as packaged collections of files

    • - Can be loaded from your main app with a dot syntax



  • - Internationalization and Localization support



    • - i18n and l10n classes

    • - Support for unicode strings



  • - Auth component



    • - automatically handles sessions for authenticated users

    • - ties into ACL for automatic denial of protected content or actions



  • - Email component



    • - for generation of text and html email



  • - Security component



    • - HTTP auth support, great for web services

    • - CSRF protection



  • - Cookie component



    • - for secure cookie handling



  • - Custom model finders



    • - simplified syntax



  • - powerful and extensible



  • - Join models



    • - for modeling and accessing HABTM join tables



  • - Behaviors, new way to extend models



    • - Supports "mixing in" new functionality



  • - Containable behavior



    • - simplified query optimization



  • - Validation system extended



    • - with new Validation class, lots of rules



  • - multiple rules and messages



  • - Database drivers



    • - support for many more databases including DB2 and Oracle



  • - Caching



    • - Adapter-driven caching, with support for APC/XCache/Memcache



  • - Set class,



    • - for magical array hacking



  • - Socket and HttpSocket classes



    • - for dealing with remote data and services



  • - Debugger class, for detailed introspection of errors



    • - Get stack traces anywhere in your code

    • - Introspected help on errors, with context information



  • - Pagination



    • - one of the first additions to the new version

    • - one of the simplest systems known



  • - Proper Routing



    • - mapResources() method for exposing controllers via REST

    • - Reverse routing support

    • - Named arguments

    • - Magic variables for common regexes

    • - Support for file extensions with custom content type mappings



  • - View stuff



    • - Separate templates for different content types

    • - automatic switching with RequestHandler

    • - New helper callbacks

    • - renderElement() replaced with element(), added built-in caching support



  • - FormHelper



    • - All form-related methods moved here

    • - New dot notation

    • - Support for associations and multiple records

    • - Huge automation and introspection support; form creation requires very little code



  • - Configure and App classes



    • - for configuration and loading



  • - Replaces defines and global functions


We hope that was a fun read. The changes since 1.1 have been dramatic, but to us this was the minimum set of features needed to a truly powerful framework and realize our vision for maintainability, flexibility, and extensibility.

Almost as dramatic as the feature set, was the growth of the community over this time, especially with its adoption of testing. We are proud of the fact that Cake is one of the most test covered frameworks. Test coverage allows us to fix more bugs and produce the most stable framework available. We believe that a feature is not truly a feature if there is even one known bug. With that in mind, each release comes with the expectation that no bugs are known at the time.

Many of you may remember the first release of 1.2. Back on Dec 25, 2006 we released at revision 4206. Many features had not been implemented or finalized, but we had a taste of what was to come. With this release at [7958], we have come a long way. But possibly the most exciting aspect of being where we are on Dec 25, 2008, is what we expect to see in the future.

CakePHP helps build amazingly powerful applications. We have a running list of examples[11]. Many of these applications were built with earlier versions of 1.2. With the release of CakePHP 1.2 stable, we expect these applications to enjoy a long history, just like the CakePHP project itself.

If you have made it this far, we would like to pass on a few extra goodies we have been working on. First is the all new Cake 1.2 cheatsheet. The old CakeSheet has proved to be a simple, quick reference to some of the power of CakePHP. This new version is the start of several more to come. Second, the gorgeous DebugKit plugin. This plugin helps you develop your application faster by providing quick, easy access to a lot of valuable debugging information. DebugKit also provides and excellent example of how you can build plugins to extend the functionality of you application. Finally, for all the TextMate users out there we have an updated CakePHP TextMate bundle. Joel Perras has put in a great amount of work and coding CakePHP in TextMate just got a lot easier thanks to him. For all these great resources and more, head on over to the downloads[12] page.

We hope you enjoy the big present and the few goodies. Have a great holiday season.
- Gwoo, Nate, PhpNut and the rest of the CakePHP team

download bản final ở đây

Thứ Năm, 25 tháng 12, 2008

Mẹo vặt với Apache 2

1. Để thêm một module vào apache (trên linux - win thì không biết )
a2enmod tên_mod
ví dụ
a2enmod rewrite
để thêm mod rewrite
2. Xem các module đã cài đặt
apache2ctl -l

Thứ Tư, 24 tháng 12, 2008

method chaining php

Trong một số thư viện của PHP người ta thường dùng method chaining để viết code ngắn gọn và đẹp hơn .

Doctrine là một ORM framework tận dụng triệt để cách viết này , một số khác có thể thấy trong các thư viện của Zend Framework .

Doctrine :


$users = Doctrine_Query::create()
->from('User u')
->leftJoin('u.Phonenumber p')
->execute();
?>

Zend Framework :


$mail = new Zend_Mail();
$mail->setBodyText('This is the text of the mail.')
->setFrom('somebody@example.com', 'Some Sender')
->addTo('somebody_else@example.com', 'Some Recipient')
->setSubject('TestSubject')
->send();


Trong khi cách viết thông thường là :


$mail = new Zend_Mail();
$mail->setBodyText('This is the text of the mail.');
$mail->setFrom('somebody@example.com', 'Some Sender');
$mail->addTo('somebody_else@example.com', 'Some Recipient');
$mail->setSubject('TestSubject');
$mail->send();


Rõ ràng sử dụng method chaining đẹp và ngắn gọn hơn nhiều .

để làm được điều này , rất đơn giản . Ở các phương thức cho phép tiếp tục gọi tiếp sẽ return về đối tượng $this .



public function foo() {
... do something ...
return $this;
}


lúc này có thể gọi như sau $myobject->foo()->bar()->baz()->bat();

Thứ Năm, 18 tháng 12, 2008

Hướng dẫn cài đặt flex sdk trong Ubuntu

Để có thể làm việc được với Flex, về cơ bản chúng ta sẽ cần cài đặt 2 chương trình sau:
- Flex SDK: là một chương trình biên dịch và gỡ lỗi command line. Đây là một chương trình miễn phí của Adobe. Bạn có thể download miễn phí tại đây.

- Flash Flayer 10: là một chương trình để chạy các flex đã được biên dịch (hay đúng hơn là thực thi các mã script). Đây cũng là một chương trình miễn phí của Adobe. Bạn có thể download tại đây.

Cài đặt Flex SDK:

- Sau khi download về tôi được một file zip sau: flex_sdk_3.zip. Giải nén file zip ta có được folder flex_sdk_3, ta sẽ chuyển thư mục này vào một thư mục nào đó. Tôi sẽ chuyển thư mục này theo đường dẫn: "/home/tendangnhap/flex_sdk_3". Vậy là ta đã cài đặt xong.

- Để chạy flex sdk, chúng ta sẽ vào thư mục "flex_sdk-3/bin". Trong thư mục này sẽ chứa các file chạy, với windown thì file chạy sdk sẽ là mxmlc.exe. Còn trong linux thì file chạy chỉ là mxmlc. Bây giờ ta test bằng cách chạy một đoạn flex helloword nhé.

+ Đầu tiên ta sẽ tạo ra một file có tên là helloworld.mxml ngay trong thư mục flex_sdk_3/bin có nội dung như sau:

helloword.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Panel title="Hello World" width="200" height="100">
<mx:Label text="Wellcome to Flex" fontSize="20" color="blue"
mouseDownEffect="WipeRight" />
</mx:Panel>
</mx:Application>

+Tiếp đến ta sẽ dúng sdk để dịch, ta vào chương trình Terminal, gọi đến đường dẫ chứa chương trình flex_sdk_3. Ở đây đường dẫ của tôi sẽ là: "/home/hoantocxoan/flex_sdk_3/bin/" ta sẽ gõ như sau:
sudo cd /home/hoantocxoan/flex_sdk_3/bin

sudo mxmlc helloworld.mxml

+ Sau 2 câu lệnh trên thì chương trình sẽ dịch ra file helloworld.swf. Như vậy là bạn đã cài đặt và biên dịch thành công flex_sdk.

- Công việc tiếp theo là ta sẽ thiết lập lại biến môi trường để ta có thể gọi chương được ở bất cứ nơi đâu thay vì cứ phải vào trong /home/hoantocxoan/flex_sdk_3/bin. Ta sẽ xét lại biến môi trường như sau:
sudo gedit ~/.bashrc

+ Ta sẽ mở được file bashrc bằng chương trình gedit trong ubuntu ra. Ta chỉ việc thêm vào 2 dòng sau:
export PATH=$PATH:/home/hoantocxoan/flex_sdk_3/bin

vào trước dòng "export HISTCONTROL=ignoreboth" là được.

Thứ Hai, 1 tháng 12, 2008

chơi với RIA

RIA là gì?

RIA - Rich Internet Application là một dạng ứng dụng web (web application) cố gắng thể hiện những chức năng truyền thống của phần mềm chạy trên desktop. Ở mức nào đó, RIA xóa nhòa lý thuyết phi trạng thái của giao thức HTTP.

RIA có đặc điểm gì?

  • ứng dụng RIA chạy hoàn toàn trên trình duyệt (web browser) hỗ trợ flash mà không cần cài đặt ứng dụng.

  • quan hệ khá gần với javascript


  • dung lượng tải về khá lớn nên phụ thuộc vào đường truyền mạng

  • không thân thiện với các máy tìm kiếm

  • nguy cơ bảo mật là có thật, dù flash & javascript bị rất hạn chế trong việc can thiệp vào hoạt động của máy tính.


Vậy lợi ích của RIA?

  • không cần cài đặt hay triển khai, đơn giản như là chạy ứng dụng flash.

  • cung cấp cho người dùng những chức năng vô cùng đa dạng, nâng cao lên rất nhiều khả năng tương tác so với mã HTML/DHTML/javascript truyền thống.

  • giao diện sử dụng rất ấn tượng với nhiều hiệu ứng hấp dẫn.

  • tương tác không đồng bộ (Asynchronous communication) với server, làm giảm tài nguyên mạng sử dụng cũng như tiết kiệm hoạt động của server. Bên cạnh đó lại dễ dàng dịch chuyển dữ liệu giữa client/server mà không cần người dùng phải thao tác nhiều và liên tục.


Xây dựng ứng dụng RIA?

bạn có thể sử dụng DHTML/css/javascript kết hợp với kỹ thuật ajax theo kiểu truyền thống hoặc sử dụng 2 dạng tiếp cận mới hơn là Flex & Silverlight.

cách đơn giản và dễ dàng nhất, bạn hãy tìm và download những cuốn sách về chủ đề & công cụ này để tìm hiểu thêm.

nếu bạn tự hỏi giữa flex & silverlight thì bạn nên học cái nào? thế này nhé, trong câu chuyện với một người bạn cách đây ít hôm, chúng tôi nói đến việc flash được cài trên hầu hết (>90%) trình duyệt web hiện nay, trong khi silverlight chỉ được cài trên ~ 6.3% số lượng. Điều đó có nghĩa là bạn học flex sẽ có tương lai hơn, bạn nghĩ vậy phải không? thế nhưng hôm đó bạn tôi đặt lại một vấn đề, nếu như Microsoft cài đặt mặc định silverlight vào tất cả các bản IE trong các phiên bản Windows sắp tới, thị phần trình duyệt cài silverlight sẽ tăng đến mức nào? có lẽ vào khoảng > 80% như thị phần của IE hiện nay.

ngoài ra, có một bài so sánh khá thú vị giữa flex vs silverlight của  ở đây

happy coding!

tham khảo: http://en.wikipedia.org/wiki/Rich_Internet_application,

(nguồn: http://www.hoang188.net/?p=91)

Chủ Nhật, 30 tháng 11, 2008

Sử dụng Helper TinyMCE trong Cakephp 1.2

Sử dụng tinyMCE trong cakephp đã được chaubl hướng dẫn ở bài trước (http://i-php.net/2008/10/cakephp-tinymce-ibrowser/). Tuy nhiên ở đây tôi sẽ hướng dẫn các bạn sử dụng TinyMCE thông qua một helper TinyMCE của cakephp.
Cài đặt TinyMCE

Bạn có thể download bản tinymce mới nhất tại địa chỉ http://tinymce.moxiecode.com/download.php và copy thư mục /tinymce/jscripts/tiny_mce vào thư mục /app/webroot/js.
Tạo ra helper TinyMCE

Bạn tạo một helper tinymce theo đường dẫn : app/views/helpers/tinymce.php . Bạn vào  http://i-php.net/2008/11/helper-tinymce/ để lấy source nhé.
Sử dụng trong controller

Bạn khai báo sử dụng helper tinymce trong controller như sau:
var $helpers = Array('Form', 'Tinymce'); 

Sử dụng trong view

Sử dụng tinymce hepler trong view sẽ tương tự như sử dụng các hepler form, html trong cakephp. Để khai báo một ô textarea sử dụng tinymce bạn chỉ việc thêm đoạn code sau vào:
<?php echo $tinymce->input('content') ?>

Sau đây là 2 trang view code mẫu để các bạn tham khảo:

đoạn code 1:
<div class="form-container">
<?php echo $form->create('Page'); ?>
<fieldset>
<legend>Page</legend>
<?php
echo $form->input('title');
echo $tinymce->input('content');
?>
</fieldset>
<?php echo $form->end('Save'); ?>
</div>

đoạn code 2: ở đây sẽ cấu hình một vài option của tinyMCE
<div class="form-container">
<?php echo $form->create('Page'); ?>
<fieldset>
<legend>Page</legend>
<?php
echo $form->input('title');
echo $tinymce->input('content', null, array(
'theme' => 'advanced',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_statusbar_location' => 'bottom',
));
?>
</fieldset>
<?php echo $form->end('Save'); ?>
</div>

Sự tiện ích khi sử dụng helper TinyMCE này là các bạn có thể tuỳ ý chọn ô textarea nào sử dụng tinyMCE cũng được, ta có thể tuỳ ý cấu hình từng ô nhập textarea cho phù hợp với ý đồ của mình. Good luck.

Helper TinyMCE

Bạn có thể tham khảo hướng dẫn sử dụng tại: http://i-php.net/2008/11/sử-dụng-helper-tinymce-trong-cakephp-12/

Tạo file app/views/helpers/tinymce.php.
<?php
class TinyMceHelper extends AppHelper
{

// Take advantage of other helpers
var $helpers = array('Javascript', 'Form');
// Check if the tiny_mce.js file has been added or not
var $_script = false;

/**
* Adds the tiny_mce.js file and constructs the options
*
* @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* @param array $tinyoptions Array of TinyMCE attributes for this textarea
* @return string JavaScript code to initialise the TinyMCE area
*/
function _build($fieldName, $tinyoptions = array())
{
if(!$this->_script)
{
// We don't want to add this every time, it's only needed once
$this->_script = true;
$this->Javascript->link('tiny_mce/tiny_mce.js', false);
}
// Ties the options to the field
$tinyoptions['mode'] = 'exact';
$tinyoptions['elements'] = $this->domId($fieldName);
return $this->Javascript->codeBlock('tinyMCE.init(' . $this->Javascript->object($tinyoptions) . ');');
}

/**
* Creates a TinyMCE textarea.
*
* @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* @param array $options Array of HTML attributes.
* @param array $tinyoptions Array of TinyMCE attributes for this textarea
* @return string An HTML textarea element with TinyMCE
*/
function textarea($fieldName, $options = array(), $tinyoptions = array(), $preset = null)
{
// If a preset is defined
if(!empty($preset))
{
$preset_options = $this->preset($preset);

// If $preset_options && $tinyoptions are an array
if(is_array($preset_options) && is_array($tinyoptions))
{
$tinyoptions = array_merge($preset_options, $tinyoptions);
}
else
{
$tinyoptions = $preset_options;
}
}

return $this->Form->textarea($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}

/**
* Creates a TinyMCE textarea.
*
* @param string $fieldName Name of a field, like this "Modelname.fieldname", "Modelname/fieldname" is deprecated
* @param array $options Array of HTML attributes.
* @param array $tinyoptions Array of TinyMCE attributes for this textarea
* @return string An HTML textarea element with TinyMCE
*/
function input($fieldName, $options = array(), $tinyoptions = array(), $preset = null)
{
// If a preset is defined
if(!empty($preset))
{
$preset_options = $this->preset($preset);

// If $preset_options && $tinyoptions are an array
if(is_array($preset_options) && is_array($tinyoptions))
{
$tinyoptions = array_merge($preset_options, $tinyoptions);
}
else
{
$tinyoptions = $preset_options;
}
}

$options['type'] = 'textarea';
return $this->Form->input($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}

/**
* Creates a preset for TinyOptions
*
* @param string $name
* @return array
*/
private function preset($name)
{
// Full Feature
if($name == 'full')
{
return array(
'theme' => 'advanced',
'plugins' => 'safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template',
'theme_advanced_buttons1' => 'save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect',
'theme_advanced_buttons2' => 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor',
'theme_advanced_buttons3' => 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen',
'theme_advanced_buttons4' => 'insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_statusbar_location' => 'bottom',
'theme_advanced_resizing' => true,
'theme_advanced_resize_horizontal' => false,
'convert_fonts_to_spans' => true
);
}

// Basic
if($name == 'basic')
{
return array(
'theme' => 'advanced',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_statusbar_location' => 'bottom',
'theme_advanced_resizing' => true,
'theme_advanced_resize_horizontal' => false,
'convert_fonts_to_spans' => true
);
}

// BBCode
if($name == 'bbcode')
{
return array(
'theme' => 'advanced',
'plugins' => 'bbcode',
'theme_advanced_buttons1' => 'bold,italic,underline,undo,redo,link,unlink,image,forecolor,styleselect,removeformat,cleanup,code',
'theme_advanced_buttons2' => '',
'theme_advanced_buttons3' => '',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_styles' => 'Code=codeStyle;Quote=quoteStyle',
'theme_advanced_statusbar_location' => 'bottom',
'theme_advanced_resizing' => true,
'theme_advanced_resize_horizontal' => false,
'entity_encoding' => 'raw',
'add_unload_trigger' => false,
'remove_linebreaks' => false,
'inline_styles' => false
);
}

return null;
}
}
?>

Thứ Bảy, 29 tháng 11, 2008

So sánh PHP vs Python

Bài viết này được tổng hợp từ nhiều nguồn khác nhau (bằng tiếng anh) cộng với kinh nghiệm viết PHP trong 5 năm và Python trong 5 tháng của tôi :D .

I.Giống nhau :

  • Là ngôn ngữ cao cấp , thông dịch và định kiểu động

  • Mã nguồn mở

  • Cộng đồng lập trình viên rộng lớn

  • Dễ học (so với Java , C hay Perl)

  • Dễ mở rộng (so với Java C++)

  • Rất khả chuyển , chạy được trên nhiều nền tảng mã không phải biên dịch lại (taats nhiên rồi) hay sửa code


II.Khác nhau :

1.PHP hơn

  • PHP kế thừa các curly braces để đánh dấu code block của C và dấu $ của Perl

  • Các câu lệnh switch và vòng lặp do..while

  • Toán tử gán , increment và decrement (++ và --)

  • Toán tử ternary operator/statement (... ? ... : ...)


    • Trong Python 2.5 có câu lệnh if .. else có tác dụng tương tự ("X if C else Y")





  • array rất mạnh ,đùng cho cả list và dict


  • tham chiếu ('$a =& $b' tức là khi biến  $b thay đổi, thì biến $a cũng thay đổi)





  • Có cả private, protected và public access modifiers cho cả phương thức và thuộc tính

  • Dùng cả abstract và final modifiers cho cả classes và methods

  • Có interfaces

  • $this là đối tượng mặc định , và không cần truyền ngược self để định nghĩa method như Python ( với Python chỗ này hơi chuối để định nghĩa test là method của một lớp cần định nghĩa :                                 def test(self)

  • Hỗ trợ code trên nhiều dòng (với Python phải thêm dấu \ vào cuối dòng nếu muốn)

  • Comment sướng hơn Python (# /* //)


(Các bạn đọc có đóng góp gì cứ comment nhét)

2.Python hơn

  • Ngôn ngữ sử dụng với các mục đích chung (Python có thể dùng để lập trình hầu hết mọi thứ , trong khi PHP chỉ dùng để lập trình web hay console . Tất nhiên có thể làm được việc khác nhưng không đáng kể )

  • Sử dụng indentation (thụt vào đầu dòng, và dòng mới) thay thế cho các dấu curly braces để đánh dấu các code block . (Tất nhiên là trông đẹp hơn , nhưng không thân thiện với HTML template cho Web )

  • Có namespaces và modules (PHP 5.3 mới có namespaces)

  • Truyền biến cho hàm hiệu quả hơn PHP nhờ cặp key=value pair , hỗ trợ tốt hơn cho giá trị mặc định của biến truyền vào hàm

  • Cho phép đa thừa kế (không biết là hay hay là dở nữa)

  • Introspection tốt hơn PHP Reflection

  • Mọi thứ từ biến tới đối tượng đều có kiểu tham chiếu

  • Có Threading

  • Document tốt hơn PHP  (nhưng chắc chắn là ít TUT ,Guide,comment,... hơn PHP)

  • Có thể lập trình GUI (Tất nhiên là PHP cũng có thể nhưng không thể bằng)

  • Có thể chạy trên .Net với IronPython hay nền Java với Jython (PHP cũng có thể chạy trên Java thậm chí trong cả các Application Server)

  • Có web server,Application server riêng , 100% viết bằng Python  .

  • lambdas và các hàm hỗ trợ để xây dựng hàm (PHP có create_function và closure)

  • cached byte-code (PHP cũng có nhưng không tốt bằng )

  • Unicode được hỗ trợ tốt hơn

  • Kiểm soát lỗi ngoại lệ tốt hơn

  • Chạy nhanh hơn PHP (Đúng là nhanh hơn nhưng ngốn CPU và Ram khủng khiếp :D )

Thứ Sáu, 28 tháng 11, 2008

generated list will be indexed

Sử dụng Element trong Cakephp

Element thật sự là cần thiết khi chúng ta muốn sử dụng một đoạn code nhiều lần trong view hoặc layout. Thay vì chúng ta viết đi viết lại nhiều lần trong các view với một đoạn source giống nhau thì chúng ta chỉ việc viết một lần trong element và sử dụng chúng nhiều lần. Việc tạo một element sử dụng nhiều lần trong cakephp sẽ rất dễ dàng khi chúng ta sử dụng hàm requestAction. Sau đây tôi sẽ hướng dẫn các bạn sử dụng element mà dùng được trong cả cakephp 1.1 lẫn cakephp 1.2.

Đầu tiên chúng ta sẽ tạo ra controller Post như sau:
<?php
class PostsController extends AppController {
var
$name = 'Posts';


function index() {
$posts = $this->Post->findAll();

//Kiểm tra xem hàm requestAction có được gọi hay không
if(isset(
$this->params['requested'])) {
return
$posts;
}
$this->set('posts', $posts);
}
}
?>

Trong hàm index trên ta sẽ kiểm tra xem nó có được gọi bằng hàm requestAciton hay không. Nếu có thì hàm sẽ trả về một mảng $posts. Bây giờ chúng ta sẽ tạo ra một element post.ctp (hay post.thml trong cakephp 1.1) có đường dẫn như sau: /app/elements/posts.ctp.
<?php

$posts = $this->requestAction('posts/index');
foreach($posts as $post):
echo $post['Post']['title'];
endforeach;


?>

Để sử dụng element trên, chúng ta chỉ việc thêm đoạn code sau vào các view hoặc layout là xong.
<?php echo $this->renderElement('posts');?>

Vậy là xong.

Thứ Năm, 27 tháng 11, 2008

Hàm tạo alias từ title


/**
*Hàm thay này có tác dụng thay thế các kí tự tiếng việt  và dấu cách bằng các ký tự không dấu và
*dấu '-'
*
*@author : không rõ
*@param string
*@return string
*/
function convert2Alias($cs)
{

$marTViet=array("à","á","ạ","ả","ã","â","ầ","ấ","ậ","ẩ","ẫ","ă",
"ằ","ắ","ặ","ẳ","ẵ","è","é","ẹ","ẻ","ẽ","ê","ề"
,"ế","ệ","ể","ễ",
"ì","í","ị","ỉ","ĩ",
"ò","ó","ọ","ỏ","õ","ô","ồ","ố","ộ","ổ","ỗ","ơ"
,"ờ","ớ","ợ","ở","ỡ",
"ù","ú","ụ","ủ","ũ","ư","ừ","ứ","ự","ử","ữ",
"ỳ","ý","ỵ","ỷ","ỹ",
"đ",
"À","Á","Ạ","Ả","Ã","Â","Ầ","Ấ","Ậ","Ẩ","Ẫ","Ă"
,"Ằ","Ắ","Ặ","Ẳ","Ẵ",
"È","É","Ẹ","Ẻ","Ẽ","Ê","Ề","Ế","Ệ","Ể","Ễ",
"Ì","Í","Ị","Ỉ","Ĩ",
"Ò","Ó","Ọ","Ỏ","Õ","Ô","Ồ","Ố","Ộ","Ổ","Ỗ","Ơ"
,"Ờ","Ớ","Ợ","Ở","Ỡ",
"Ù","Ú","Ụ","Ủ","Ũ","Ư","Ừ","Ứ","Ự","Ử","Ữ",
"Ỳ","Ý","Ỵ","Ỷ","Ỹ",
"Đ"," ");

$marKoDau=array("a","a","a","a","a","a","a","a","a","a","a"
,"a","a","a","a","a","a",
"e","e","e","e","e","e","e","e","e","e","e",
"i","i","i","i","i",
"o","o","o","o","o","o","o","o","o","o","o","o"
,"o","o","o","o","o",
"u","u","u","u","u","u","u","u","u","u","u",
"y","y","y","y","y",
"d",
"A","A","A","A","A","A","A","A","A","A","A","A"
,"A","A","A","A","A",
"E","E","E","E","E","E","E","E","E","E","E",
"I","I","I","I","I",
"O","O","O","O","O","O","O","O","O","O","O","O"
,"O","O","O","O","O",
"U","U","U","U","U","U","U","U","U","U","U",
"Y","Y","Y","Y","Y",
"D","_");
return str_replace($marTViet,$marKoDau,$cs);
}

tuan cho

Thứ Ba, 25 tháng 11, 2008

Cake bake - cake console toàn tập

Đã có bài viết của chaubl về việc sử dụng cake bake tuy nhiên bài viết này đề cập tới một vài kỹ thuật nhanh gọn khác .

Bình thường bạn sẽ phải gõ :

$cake bake

rồi sau đó trả lời từng câu hỏi cả cake bake như gen cái gì D/M/V/C/P/Q ... rồi gen thế nào ...?


  1. Muốn gen trực tiếp models :                    $cake bake model



  2. Muốn gen trực tiếp controller :                $cake bake controller



  3. Muốn gen trực tiếp view :                        $cake bake view



  4. Muốn gen trực tiếp models với tên :        $cake bake model tên_model



  5. Muốn gen trực tiếp controller với tên :    $cake bake controller tên_controller



  6. Muốn gen trực tiếp view với tên :            $cake bake view tên_controller tên_view



  7. Muốn gen view với tên với template :      $cake bake view tên_controller tên_template tên_view các template đặt ở đây : /cake/console/libs/templates/views và có thể viết thêm hoặc viết đè vào đây : /app/vendors/shells/templates/views


  8. Muốn gen controller giống kết quả của scaffold
    $cake bake controller Users scaffold


  9. Muốn gen controller thêm các action dành cho admin (cùng là add hay view nhưng admin sẽ có thể khác user thường , layout khác xử lý khác )
    $cake bake controller Users scaffold admin


  10. Muốn gen controller chỉ có các action dành cho admin
    $cake bake controller Users null admin


  11. Có cả help nữa nhé
    $cake bake model help


  12. Danh sách các Model
    $cake bake all


  13. Làm một phát sinh tất model -> controller -> views
    $cake bake all Tên_Model



Định viết tiếp vài kỹ thuật nữa nhưng số 13 là số đẹp đấy chứ ?

Thứ Hai, 24 tháng 11, 2008

auto counterCache và SEO url trong cakePHP

CakePHP Console

Hướng dẫn cách gencode bằng CakePHP console:


1. Start > Run > cmd [enter]

2. cd C:\AppServ\www\cake_1.2.0.7692-rc3\cake\console

3. cake -app C:\AppServ\www\cake_1.2.0.7692-rc3\app bake

( tham số -app để chỉ định đường dẫn đến thư mục app C:\AppServ\www\cake_1.2.0.7692-rc3\app )

4. Welcome to CakePHP v1.2.0.7296 RC2 Console

Thứ Tư, 19 tháng 11, 2008

happy teacher day!

I would like to send very special greetings for all my teachers & professor.

Happily, our BIT's CTO, mr. Ngoc performs somewhat as a very friendly instructor. Wish you health, smile & all the best on your day

Ill think bout you at every step I face to
greetings! :)

happy teacher's day

I would like to send very special greetings for all my teachers & professor.

Happily, our BIT's CTO, mr. Ngoc performs somewhat as a very friendly instructor. Wish you health, smile & all the best on your day

Thứ Ba, 18 tháng 11, 2008

code PHP ngắn thôi nhé!

trước nay hoangnd mới chỉ quen lập trình với các ngôn ngữ strongly-typed language như C#, Java, C/C++ (không tính javascript :P ). Sau trận benmark PHP với đại ca Ngọc (hiz hiz, thảm bại mất chầu bia :(( ) thì đã đầu tư một chút vào các dynamic language (PHP, Python).

PHP quả là linh động và thú vị, các đồng nghiệp ở BIT đang viết code khá nhanh và dễ dang. Thế nhưng, khi mà các bạn đang nghe đại ca Ngọc đang phàn nàn nhiều về việc viết comment trong quá trình code :P thì sao không thư giãn bằng cách viết code ngắn gọn hơn :).

ví dụ 1
// A lot of code
$status = fwrite($h, 'some text');
if (!
$status) {
log('Writing failed');
}


// Less code
${0} = fwrite($h, 'some text');
if (!${
0}) log('Writing failed');

// Even less code
fwrite($h, 'some text') or log('Writing failed');

ví dụ 2
// A lot of code
if ($age < 16) {
$message = 'Welcome!';
} else {
$message = 'You are too old!';
}


// Less code
$message = 'You are too old!';
if (
$age < 16) {
$message = 'Welcome!';
}


// Even less code
$message = ($age < 16) ? 'Welcome!' : 'You are too old!';

ví dụ 3
// A lot of code
$i = 0;
while (
$i < 100) {
$source[] = $target[$i];
$i += 2;
}


// less code
for ($i = 0; $i < 100; $source[] = $target[$i+=2]);

hi hi, trông hay chưa :P, sự thực là hầu hết các ngôn ngữ lập trình đều có khả năng viết code ngắn gọn như thế này. Thế nhưng, các đồng nghiệp sẽ có điều kiện thấy một ngôn ngữ mạnh mẽ hơn nhiều, đó là python :)

nhân đây các đồng nghiệp viết lại bài toán in ra các số từ 1 -> 20 với các điều kiện chia hết cho 3, 5, 15 đi :)

tham khảo:Arnold Daniels's blog

Thứ Ba, 11 tháng 11, 2008

Thế mạnh của PHP



Thứ nhất PHP có một kiến trúc độc nhất vô nhị , dựa trên triết lý "share nothing" mỗi luồng chạy php được webserver và ZendEngine thực hiện độc lập , giải phóng tài nguyên hoàn toàn sau khi kết thúc tác vụ .Điều này giúp cho PHP tuy và ngôn ngữ động và thông dịch nhưng lại có tốc độ thực thi rất nhanh và đặc biết là tiêu tốn rất ít tài nguyên. Một điểm nữa là giao thức HTTP (giao thức giao tiếp của web) cũng hoạt động tương tự như vậy "HTTP, each request is distinct"


Thứ 2  PHP được sinh ra để làm web (xem thêm)  . Nên thiết kết của PHP chắc chắn hơn hẳn các ngôn ngữ khác trong công nghệ web . Bản thân PHP cũng là một template engine rất mạnh thân thiện với web (HTML-CSS-Javascript).


Thứ 3 PHP là ngôn ngữ được dùng cho web phổ biến nhất thế giới , gần như tất cả các máy chủ web đều hỗ trợ PHP . PHP cũng có số lượng các lập trình viên web đông đảo nhất thế giới qua đó đã xây dựngđược một cộng đồng rộng lớn , lớn hơn rất nhiều các cộng đồng khác .




[caption id="" align="alignnone" width="480" caption="thống kê của netcraft"]thống kê của netcraft[/caption]

Xem thêm đánh giá của cộng đồng trên TIOBE , PHP đứng thứ 5 , quá cao so với một ngôn ngữ chỉ dùng làm Web - server side script .


Xem thống kê mới nhất của Nexen


Thứ 4 PHP là ngôn ngữ mà nguồn mở , nên với hàng triệu ứng dụng có sẵn , miễn phí , thư viện mã nguồn mở giúp cho việc lập trình trên ngôn ngữ này trở nên nhanh chóng và chất lượng .


Nếu như các ngôn ngữ khác có 1-2 sản phẩm ví dụ ASP.NET có một - hai sản phẩm diễn đàn thì PHP có vài chục sản phẩm có chất lượng tốt hơn nhiều .Có thể thấy điều tương tự qua các ứng dụng khác như : Blog , Shopping Cart , CMS .


Các thư viện của PHP nhiều hơn bất kì công nghệ lập trình web nào khác , được đóng góp bởi cả một cộng đồng rộng lớn , trong đó có các công ty IT hàng đầu như : Oracle , Yahoo ,IBM, Zend , FaceBook ..


Thứ 5 Với stack công nghệ mã nguồn mở LAMP bao gồm : hệ điều hành Linux , webserver Apache , Hệ quản trị cơ sở dữ liệu Mysql   và PHP . Đã làm nên một nền tảng mở mạnh mẽ với chi phí rất khiêm tốn . Nhưng dễ dàng mở rộng




[caption id="" align="alignnone" width="268" caption="Nguồn oracle"]Nguồn oracle[/caption]

Chính vì vậy các mạng xã hội 2.0 đã lựa chọn PHP thay vì các ngôn ngữ khác .


Kết luận : PHP là vô địch trên sân chơi web

Thứ Bảy, 8 tháng 11, 2008

Nhập môn RIA (Rich Internet Application)

Trước đây khi nhắc đến web người ta hiểu chúng là các nội dung tĩnh , qua một thời gian phát triển nội dung đã có thể được tùy biến và trở nên "động" và có tính tương tác cao hơn .  Ngày nay web đã có những sự thay đổi lớn lao , người ta nhắc đến các mạng xã hội tương tác giữa người với người , hay các "Ứng Dụng Web" phục vụ các công việc mà bình thường phải sử dụng các phần mềm độc lập .

RIA cũng là các ứng dụng web , cũng chạy trên các trình duyệt nhưng chúng khác ứng dụng web thông thường ở chỗ :

- Nhằm thay thế một phần hoặc hoàn toàn các ứng dụng desktop

- Thông thường sẽ hỗ trợ việc cộng tác , chia sẻ với các người dùng , nhóm người dùng

- (thông thường) Có thể chạy khi không có kết nối internet , và tiến hành cập nhật với server khi có kết nối trở lại

Có thể lấy ví dụ một vài RIA tiêu biểu :

googledocs,mindomo,splashup.com ..

Và ở việt nam hiện sắp xuất hiện phần mềm soạn bài giảng trực tuyến của fpt-visky-bachkim hay phần mềm soạn đề thi trực tuyến của bitjsc , phần mềm soạn thời khóa biểu trực tuyến của bit tech .

Công nghệ được sử dụng để tạo ra ứng dụng RIA thì có nhiều , nhưng thị phần chủ yếu thuộc về Flash-Flex của Adobe , Ajax-DHTML , và mới đây là SliverLight của M$ . Các nền tảng công nghệ này đủ mạnh để tạo các ứng dụng RIA lớn nhưng hiện các công ty việt nam còn chưa chú ý . Điều này cũng dễ hiểu vì việt nam chủ yếu làm outsource , hiện nay xuất hiện nhiều công ty làm các web 2.0 hay các mạng xã hội chứ các ứng dụng RIA thì chưa thấy nhiều . Về công nghệ thì chủ yếu là flash và DHTML , số các công ty đủ trình độ kỹ thuật để xây dựng các ứng dụng RIA cũng không nhiều , theo tôi biết thì có một vài công ty được thuê outsource các ứng dụng RIA với DHTML chủ yếu là webos (Hệ điều hành trên nền web) . Bachkim thì thực chất là online hóa sản phẩm violet (cũng được làm bằng flash là chủ yếu) . BIT jsc thì chủ yếu sử dụng Flex-Flash và một chút DHTML.

Thị trường RIA kể cả production và outsource hiện nay chủ yếu rơi vào các công ty Ấn Độ , Việt Nam muốn chen chân thì đầu tiên phải thay đổi cách tư duy của các nhà quản lý , rồi đến đội ngũ kỹ thuật ....

Thứ Sáu, 7 tháng 11, 2008

BIT FLV player 1.1

BIT FLV player 1.1

7/11/08 : Bit Flv player chính thức ra mắt .

Là một phần mềm chạy file flv (flash video) ,file này thường chạy khi download trên các trang chia sẻ video trực tuyến như Youtube.com về xem offline trên máy .

được viết trên nền tảng Adobe AIR có các tính năng :

  1. Chạy nhiều file flv cùng lúc

  2. Hỗ trợ kéo thả file Flv vào chương trình

  3. Seek trực tiếp vào file đang chạy


link download

Bản không kèm Adobe AIR (bạn phải cài Adobe AIR trước)

http://bitjsc.com/flvplayer/BitFLVPlayerV1.1.zip

có thể down Adobe AIR tại đây .

http://airdownload.adobe.com/air/win/download/latest/AdobeAIRInstaller.exe

Bản kèm Adobe AIR

http://bitjsc.com/flvplayer/BitFLVPlayerV1.1AIR.Include.zip

Thứ Ba, 28 tháng 10, 2008

Phân trang tìm kiếm trong cakephp 1.1

Việc phân trang trong cakephp 1.1 đã được tôi đề cập ở bài trước vì vậy tôi sẽ không hướng dẫn chi tiết các bạn cách làm phân trang trong cakephp 1.1 nữa. Các bạn có thể xem lại tại http://i-php.net/2008/10/pagination-phan-trang-trong-cakephp-11x/. Ở bài viết này tôi chỉ đi hướng dẫn cách phân trang khi tìm kiếm mà thôi. (Tất nhiên là dựa vào cách phân trang ở bài viết trước rồi).

Với các PaginationHelper và PaginationComponent ở bài trước chỉ có thể giúp chúng ta phân trang một cách bình thường mà thôi. Nhưng khi chúng ta thêm vào điều kiện tìm kiếm thì chức năng phân trang sẽ chạy sai. Nguyên nhân là do khi chúng ta thực hiện phân trang thì các biến của trang sẽ được truyền qua URL theo phương thức GET. Vì vậy mà các điều kiện lọc ở form sẽ không được truyền vào , và khi khởi tạo lại trang thì nó sẽ chỉ hiểu các điều kiện truyền từ phương thức GET, do vậy phân trang không còn chính xác nữa.

Đề giải quyết vấn đề trên có rất nhiều phương pháp, trong đó có 2 phương pháp mà tôi được biết đó là truyền các điều kiện còn lại lên trên URL theo phương thức GET hoặc là truyền điều kiện lọc theo phương thức POST đồng thời truyền các tham số phân trang lên URL theo phương thức GET. Cách đầu tiên có một nhược điểm rất lớn là do các tham số sẽ được truyền hết lên trên URL do đó URL trông sẽ rất xấu và dài, đồng thời nhược điểm lớn nhất khi truyền tham số trên URL là URL chỉ cho phép dài nhất là 256 ký tự mà thôi, do vậy khi tìm kiếm với khối lượng lớn dữ liệu điều kiện thì phương pháp này sẽ không khả thi. Do vậy tôi chọn phương pháp thứ 2 là truyền dữ liệu lọc theo phương thức POST đồng thời truyền các tham sô phân trang trên URL theo phương thức GET.
Cách thức thực hiện:

Trong phần phân trang ở trước, công việc phân trang sẽ thực hiện thông qua phương thức GET tức là các link sẽ chứa các tham số phân trang.và việc phân trang sẽ dựa hoàn toàn vào các tham số đó.

Giờ đây, khi ấn vào các link đó thay vì kích hoạt các link đó chúng ta sẽ gọi ra một hàm javascript thông qua sự kiện onclick. Chúng ta sẽ submit dữ liệu theo phương thức POST thay vì phương thức GET đồng thời truyền lên  URL các tham số phân trang. Như vậy sau khi submit chúng ta sẽ có cả dữ liệu lấy từ phương thức POST và phương thức GET.
Các bước thực hiện:

- Đầu tiên, chúng ta sẽ thêm sự kiện 'onclick' vào tất cả các link phân trang. Chúng ta mở file '/app/views/helpers/pagination.php', chúng ta tìm đến 'function _generateLink ()', di chuyển đến cuối hàm và thay đổi đoạn source code sau:
return $this->Html->link(
$title,
$url,
NULL,
NULL,
$escapeTitle)

thành
$options['onclick'] = "return paginator_number('form', '{$this->Html->url($url)}')";

return $this->Html->link(
$title,
$url,
$option,
NULL,
$escapeTitle

Ở trên, chúng ta đã gọi ra hàm javascript la 'paginator_number' với 2 tham số truyền và là tên form, mà cụ thể trong trường này tên form là 'form', tham số thứ 2 là url cần link đến và các tham số phân trang (giá trị này sẽ tự sinh ra, chúng ta không cần thay đổi). Điều đáng chú ý ở đây là để chạy được thì các bạn sẽ phải để tên form là 'form', nếu là tên form khác thì chương trình sẽ không chạy.

- Tiếp đến chúng ta sẽ thêm hàm sau:
function paginator_number(element, url )
{
$(element).attr("action",url);
$(element).submit();
return false;
}

Hàm javascript này sẽ được thêm vào layout. Các bạn chú ý các viết hàm javascipt trên là viết thông qua jquery. Nếu các bạn chưa có thì nhơ tải jquery về nhé. Chúc các bạn thành công.

Sử dụng bootstrap.php cấu hình các thư mục chứa source code trong cakephp

Như chúng ta đã biết, cakephp viết theo mô hình MVC, do vậy khi ta viết các đoạn lệnh của chương trình chủ yếu chúng ta chỉ viết ở các thư mục trong app như model, controller, views, component(trong controller) và helper (trong views). Các file source chủ yếu sẽ được viết trên các thư mục này.

Sau đây tôi xin hướng dẫn các bạn chuyển các file source của chúng ta ra một thư mục khác ngoài app. Việc chuyển code ra khỏi thư mục app trong cakephp sẽ có một số tiện ích sau đây:

- Quản lý các file code sẽ dễ dàng và sáng sủa hơn, dễ bảo trì hơn. Các file của chúng ta khi chuyển ra thư mục riêng thì việc tìm kiếm sẽ trở lên dễ dàng hơn so với việc ta tìm kiếm một file trong một mớ file hỗn độn bên trong app.

- Với các bạn hay sử dụng svn thì việc này sẽ tạo ra một sự tiện dụng vô cùng lớn. Thay vì chúng ta phải gửi rất nhiều code, bao gồm cả những file không cần thiết thì nay ta chỉ việc gửi một thư mục duy nhất mà ở đó chứa tất cả những gì chúng ta cần làm nên.

- Việc thay đổi các bản cakephp mới hơn sẽ trở lên dễ dàng hơn, vì giơ đây chương trình của chúng ta nằm ngoài các thư mục của cakephp. Thay vì trước khi khi update bản cakephp mới chúng ta phải nhọc công copy riêng từng thư mục ra thì nay ta chỉ việc copy đề lên thư mục cũ là được. Các file của chúng ta không hề bị ảnh hưởng gì cả.

Còn rất nhiều tiện ích nữa mà tôi chưa nhắc đến. Nhưng tôi nghĩ như vậy có lẽ là đủ để các bạn nên thử rồi đấy. Sau đây tôi sẽ thực hiện chuyển dữ liệu ở các thư mục sau ra bên ngoài: controllers, views và models (tất nhiên là sẽ bao gồm cả các thư mục con nằm bên trong các thư mục này như là helpers, components ...). Và thư mục mà chúng ta sẽ chuyển đến là thư mục bitjsc nằm cùng cấp với thư mục app.
Sau đây là các công việc cần làm:

- Đầu tiên: Chúng ta sẽ tạo các thư mục cần thiết bao gồm:

+ Thư mục bitjsc nằm cùng cấp với thư mục app và cake.

+ Các thư mục con nằm trong bitjsc bao gồm : controllers, views, models và config.

+ Các thư mục con nằm trong các thư mục controller, views, models và config như là: helpers, component ....

- Tiếp theo, chúng ta sẽ cấu hình lại file bootstrap.php theo đường dẫn /app/config/bootstrap.php. Chúng ta thêm vào cuối file dòng sau:
require_once(dirname(__FILE__) . DS . '..' . DS . '..' . DS . 'bitjsc' . DS . 'config' . DS . 'bootstrap.php');

Dòng trên sẽ thực hiện gọi file bootstrap.php trong theo đường dẫn 'bitjsc/config/', đây là các thư mục mà chúng ta vừa tạo ở phía trên. Trong thư mục 'bitjsc/config/' chúng ta sẽ tạo ra một file có tên là bootstrap.php, trong file này ta sẽ thực hiện bẫy để khi gọi các model, controller hay views thì chương trình sẽ tự động gọi các file tương ứng trong thư mục bitjsc thay vì gọi chúng trong app.

- Tạo file bootstrap.php theo đường dẫn '/bitjsc/config/bootstrap.php'.  Nội dung của file bootstap.php sẽ như sau:
<?php
/**
* Bitjsc bootstrap file
*
* This file should be included in app/bootsrap.php. It connect WF
* with your application.
*
* @package bitjsc
*/

// Bitjsc MVC paths
define('BITJSC_DIR', ROOT . DS . 'bitjsc');
define('SETTINGS_CACHE_FILE', TMP . 'settings' . DS . 'cache');

$modelPaths = array(BITJSC_DIR . DS . 'models' . DS);
$viewPaths = array(BITJSC_DIR . DS . 'views' . DS);
$controllerPaths = array(BITJSC_DIR . DS . 'controllers' . DS);
$behaviorPaths = array(BITJSC_DIR . DS . 'models' . DS . 'behaviors' . DS);
$helperPaths = array(BITJSC_DIR . DS . 'views' . DS . 'helpers' . DS);
$componentPaths = array(BITJSC_DIR . DS . 'controllers' . DS . 'components' . DS);
?>

Vậy là chúng ta đã xong việc cấu hình lại đường dẫn. Giờ khi thêm mới bất kỳ file controller, views hay model gì các bạn chỉ cần thêm vào các thư mục tương ứng trong bitjsc là xong. Chúc các bạn thành công.

convert mdyDate to YMDDate

Convert '23/12/1988' to '1988/12/23'
    function toYMDDate($mdyDate)
{
$mdyDate = explode("/",$mdyDate);
krsort($mdyDate);
return implode("/",$mdyDate);
}

Hướng dẫn sử dụng làm web với cakephp

1 Giới thiệu về cakePHP
2 Download framework
3 Cài đặt và cấu hình cakephp
3.1 Cài đặt
3.2 Cấu hình
4 Ví dụ sử dụng CakePHP để quản lý khách hàng trong web application "Quản lý phòng trọ"
4.1 Tạo bảng cơ sở dữ liệu
4.2 Viết Code
4.3 Mô hình hoạt động
4.4 Model
4.5 Controller
4.6 View
4.7 Hoàn chỉnh các chức năng của modul quản lý customer

Giới thiệu về cakePHP

CakePHP là một framework cho php, mục đích của nó là cung cấp một framework cho người sử dụng php phát triển những ứng dụng web nhanh, mạnh mà không mất tính linh hoạt của nó. Và điều quan trọng là CakePHP is free.Trang chủ cakephp: http://cakephp.org Để sử dụng nó, yêu cầu người làm phải biết những kiến thức cơ bản về PHP và HTML, ... Có thể đọc nội dung chi tiết về nội dung cũng như ví dụ của nó tại http://manual.cakephp.org Huypvt

Download framework

Click vào liên kết sau để tải về cakephp framework: http://cakephp.org/downloads (chọn stable release).

Cài đặt và cấu hình cakephp

Cài đặt

Để sử dụng nó, cần phải đáp ứng những yêu cầu sau: - Một HTTP Server (vd như Apache, IIS) - CakePHP chỉ support trong PHP ver 4 trở lên. - Database: cake hổ trợ các hệ cơ sở dữ liệu sau: MySql, PostgreSQL. Bài hướng dẫn này được viết dựa trên "AppServ Version 2.5.7 for Windows" gồm - Apache Web Server Version 2.2.3 - PHP Script Language Version 5.1.6 - MySQL Database Version 5.0.24a - phpMyAdmin Database Manager Version 2.9.0.2 Sau khi download cakephp về, bạn giải nén tập tin đó ra (.zip) và sao chép vào thư mục chứa Apache Server (vd: C:\AppServ\www\MyCake). VD:
/MyCake
/app
/cake
/vendors
.htaccess
index.php

Cấu hình

Để cake có thể làm việc được với database, cần cấu hình lại trang database.php, mặc định trang này không có, để cấu hình ta làm như sau: - Mở file database.php.default ở /app/config và Save As lại thành file database.php. - Điều chỉnh lại các thông số:
var $default = array('driver' => 'mysql',
'connect' => 'mysql_connect',
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'project_name',
'prefix' => );

Với user, password, database lần lượt là: tên user, password và database ở trong MySql. Quy ước về đặt tên bảng trong database
Tên bảng trong cake nên ở dạng tiếng Anh số nhiều (vd: users, customers, students, ... )
Bảng phải có primary key tên là 'id'
Nếu có sử dụng quan hệ trong các bảng vd: user_id (user không có s và dấu _ cộng id)

Ví dụ sử dụng CakePHP để quản lý khách hàng trong web application "Quản lý phòng trọ"

Tôi sẽ nói đến tính năng, cũng như mô hình hoạt động của CakePHP, cách viết một web application bằng cakephp tôi sẽ nói dần với các bạn qua ví dụ: Sau khi cài đặt và cấu hình CakePHP, kiểm tra CakePHP đã setup chưa, bạn test thử bằng cách mở webbrowserlên go http://localhost/MyCake/ bạn sẽ thấy giao diện như sau

Cần chú ý đến 2 dòng Your database configuration file is present. Cake is able to connect to the database. Xác định xem bạn đã kết nối được Cake với database của bạn hay chưa.

Tạo bảng cơ sở dữ liệu

Ta tạo bảng customers với những field như sau:
id: INT, AUTO_INCREMENT, PRIMARY KEY
name: NVARCHAR
age: INT
address: NVARCHAR

Viết Code

Mở trình soạn thảo và tạo các file và nội dung như sau lưu theo đường dẫn chỉ định File customer.php -> C:\AppServ\www\MyCake\app\models\
<?php
class Customer extends AppModel
{
var $name = 'Customer';
}
?>

File customers_controller.php -> C:\AppServ\www\MyCake\app\controllers
<?php
class CustomersController extends AppController
{
var $name = 'Customers';
function index()
{
$this->set('customers', $this->Customer->findAll());
}
}
?>

File index.thtml -> C:\AppServ\www\MyCake\app\views\customers\ Chú ý tạo thư mục customers trong /app/views

<h1>Customer Manager</h1>
<table>
<tr>
<th>Id</th><th>Name</th><th>Age</th><th>Address</th>
</tr>
<?php foreach ($customers as $cust): ?>
<tr>
<td><?php echo $cust['Customer']['id']; ?></td>
<td>
<?php echo $html->link($cust['Customer']['name'], '/customers/view/'.$cust['Customer']['id']);?>
<?php echo $html->link(
'Delete',
"/customers/delete/{$cust['Customer']['id']}",
null,
'Are you sure?'
)?>
<?php echo $html->link('Edit', '/customers/edit/'.$cust['Customer']['id']);?>
</td>
</td>
<td><?php echo $cust['Customer']['age']; ?></td>
<td><?php echo $cust['Customer']['address']; ?></td>
</tr>
<?php endforeach; ?>
</table>
<p><?php echo $html->link("Add Customer", "/customers/add"); ?>

Xong 3 trang đó, chúng ta test chạy thử , mở webbrowser http://localhost/MyCake/customers Bạn sẽ thấy giao diện trang chính như hình sau: Như vậy là bạn đã tạo được ứng dụng đơn giản đầu tiên về việc sử dụng cakephp để viết ứng dụng web. Tiếp theo tôi sẽ giải thích cho các bạn mô hình hoạt động của CakePHP, cách viết các trang,cũng như cách sử dụng biến, hàm ...

Mô hình hoạt động

Như tôi đã giới thiệu CakePHP là một framework, mô hình hoạt động của nó tương tự mô hình 3 lớp MVC trong lập trình hướng đối tượng. Với tầng trên cùng là view, tiếp theo là tầng controller và cuối cùng là tầng model. Tầng model sẽ giao tiếp với cơ sở dữ liệu của chúng ta.

Model

Trong ví dụ trên các bạn thấy trong file customer.php với cách viết code như trên, được Cake hiểu là ta muốn tạo một model tên là Customer để sử dụng trong CustomersController của chúng ta. Biến $name được chỉ định để tránh trường hợp model của chúng ta trùng với tên của các hàm của php. Và lớp Customer sẽ được kế thừa các thuộc tính và phưông thức từ lớp AppModel. Để có thể hiểu chi tiết về model và cách sử dụng các thuộc tính và hàm của model bạn có thể tham khảo tại http://manual.cakephp.org/chapter/models

Controller

Controller được sử dụng để quản lý việc giao tiếp với cơ sở dữ liệu, thiết lập các yêu cầu theo ý muốn của chúng ta để thể hiện lên view vidu như các hàm xử lý thêm, xóa, sữa và hiển thị, ..., là nơi mà tất cả các hoạt động của model ta sẽ quản lý nó được. Trong ví dụ trên (customers_controller.php)đoạn code trên được Cake hiểu rằng ta sẽ tạo một CustomersController dùng để quản lý việc sử dụng, các hoạt động của CustomerModel. Tương tự lớp CustomersController sẽ kế thừa từ lớp AppController. Hàm index() sẽ được xử lý khi ta gọi trang index.thtml. Trong đó có phương thức set() được sử dụng để gán giá trị là một mảng được trả về từ phương thức findAll() tại của model Customer. Trong ví dụ trên thì biến $customers sẽ mang giá trị là mảng các customer được lấy từ bảng customers từ database. Để xem chi tiết về controller các bạn có thể tham khảo tại: http://manual.cakephp.org/chapter/controllers

View

View là nơi thể hiện dữ liệu đã được xử lý của chúng ta. Một view được xem như một trang template. Chúng ta có thể lấy dữ liệu từ model tương ứng. Dữ liệu được truyền qua một mãng $data. Trong ví dụ trên thì index.thtml là một view. Phần tiếp theo tôi sẽ nói đến chi tiết view thông qua ví dụ trên. Tiếp theo ta tìm hiểu đến các thuộc tính và phương thức trong index.thtml <?php foreach ($customers as $cust): ?> Biến $customers chính là biến mà ta đã thiết lập bằng phương thức set() ở CustomersController của ví dụ. Nó mang giá trị là một mãng như tôi đã nói. $html là một đối tượng của lớp helpers sẽ được đề cập trong phần tới. Phương thức link() được sử dụng để xuất ra một liên kết giống href trong HTML với tham số đầu tiên là tựa để của liên kết, tham số thứ 2 là url.

Hoàn chỉnh các chức năng của modul quản lý customer

Ta sẽ thêm các chức năng thêm, sữa, xóa, hiển thị trong view của chúng ta. Ta thêm các hàm trong customers_controller như sau:
<?php
class CustomersController extends AppController
{
var $name = 'Customers';
function index()
{
$this->set('customers', $this->Customer->findAll());
}
function view($id)
{
$this->Customer->id = $id;
$this->set('customers', $this->Customer->read());
}
function add()
{
if (!empty($this->data))
{
if ($this->Customer->save($this->data))
{
$this->flash('Your customer has been saved.','/customers');
}
}
}
function delete($id)
{
$this->Customer->del($id);
$this->flash('The customer with id: '.$id.' has been deleted.', '/customers');
}
function edit($id = null)
{
if (empty($this->data))
{
$this->Customer->id = $id;
$this->data = $this->Customer->read();
}
else
{
if ($this->Customer->save($this->data['Customer']))
{
$this->flash('Your customer has been updated.','/customers');
}
}
}
}
?>

Như vậy ta đã thêm 4 function trong CustomersController của chúng ta. Function sẽ được gọi ở view. Ví dụ trên ta click vào link Add Customer thì function sẽ được thực hiện và thể hiện lên view add của chúng ta. Bạn tạo file add.thtml với nội dung như sau:

<h1>Add Customer</h1>
<form method="post" action="<?php echo $html->url('/customers/add')?>">
<p>
Name:
<?php echo $html->input('Customer/name', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/name', 'Name is required.') ?>
</p>
<p>
Age:
<?php echo $html->input('Customer/age', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/age', 'Age is required.') ?>
</p>
<p>
Address:
<?php echo $html->input('Customer/address', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/address', 'Address is required.') ?>
</p>
<p>
<?php echo $html->submit('Save') ?>
</p>
</form>

Trong view add trên dòng <?php echo $html->input('Customer/name', array('size' => '40'))?> sẽ xuất ra một thẻ input text. Với dòng lệnh trên thì Cake sẽ hiểu rằng ta sẽ sử dụng trường name trong model Customer.Tham số thứ 2 là thuộc tính của thẻ input trong HTML. Tương tự với thẻ submit. Hàm tagErrorMsg() sẽ thông báo lỗi ở view trong trường hợp dữ liệu nhập của ta bị lỗi. Việc xử lý lỗi sẽ được nói trong phần sau. Tương tự ta tạo các file edit.thtml, view.thtml như sau:
edit.thtml

<h3>Edit Your Customer</h3>
<form method="post" action="<?php echo $html->url('/customers/edit')?>">
<?php echo $html->hidden('Customer/id'); ?>
<p>
Name:
<?php echo $html->input('Customer/name', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/name', 'Name is required.') ?>
</p>
<p>
Age:
<?php echo $html->input('Customer/age', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/age', 'Age is required.') ?>
</p>
<p>
Address:
<?php echo $html->input('Customer/address', array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Customer/address', 'Address is required.') ?>
</p>
<p>
<?php echo $html->submit('Save') ?>
</p>
</form>

view.thtml

<h3>Your Customer</h3>
<h1>Name :<?php echo $customers['Customer']['name']?></h1>
<h1>Age :<?php echo $customers['Customer']['age']?></h1>
<h1>Address:<?php echo $customers['Customer']['address']?></h1>