Happy New Year!

I thought I would start off the new year with a tutorial on a tricky process I’ve had to do a few times for various projects using Symfony, Sonata Admin, and PHP’s magic method __call.

If you’re creating a basic project in Symfony 2, the Sonata Admin Generator is a great tool to use. It’s highly configurable, and easy to extend and modify for your own needs, like most Symfony bundles. It does have one flaw for use in my projects, and that is if you are using the __call magic method for getters/setters, the list view will show blank fields, because it relies on method_exists to find a getter method. (It currently checks for get{Property} and is{Name}).

Sonata __call before

For example, here is a very simple base model with a __call() method to capture get{Property} requests. This is useful if your getter methods are just returning the property with no other logic. I personally prefer not to have all those extra methods as they are basically cruft, when I can accomplish the same thing with magic methods.

The code that uses the method_exists function is in Sonata\AdminBundle\Admin\BaseFieldDescription::getFieldValue. In order to override this one function, we must:

  • Create custom FieldDescription class to override one method
  • Create custom ModelManager in our bundle, to use the new FieldDescription class
  • Make the new ModelManager available as a service
  • Update our admin services to use this ModelManager

Now I will walk you through these steps.

Custom FieldDescription Class

This one is pretty simple. I copied this code directly from the existing FieldDescription::getFieldValue and changed just a few lines. After adding the check to is_callable, I check that the result returned is not null – this is because is_callable will return true if __call exists, so even if you’re not processing that particular function call, it will still be callable.

You can however simplify this if you know you will always rely on get{Property} for your getters.

Custom ModelManager

The custom ModelManager is also easy, just copy the code from the current ModelManager and update the use statement to use your FieldDescription class. You’ll also want to alias the original ModelManager for your extend statement. The function is in fact exactly the same as the original, but since I have added the use statement for my new FieldDescription class before the class, it will use mine now.

ModelManager as Service

Update your services file to create a service for the new ModelManager. I prefer to use yml for my config files, but you can do this in XML or Annotations as well.

Update Admin Services to use ModelManager Service

Last step is to update your admin services to use the new ModelManager’s service. Again, you can use YML, XML or PHP for this.

Result

Sonata __call after

I hope this will help anyone out there trying to accomplish the same goal!

, , , ,

Is there a topic you’d love to see a tutorial on? Are you stuck on a bug you just can’t work out? Ask The Web Mason is your chance to get answers to all your burning questions – all of the web development related ones anyway! If your question is picked, the answer or tutorial will be posted on the blog. This is your chance to get a professional consultant to help with your programming challenges – for free!

To submit a question, problem, tutorial request, etc, simply comment on the Ask The Web Mason page. If your problem is fairly long and/or requires significant code for review, please submit a small comment asking for an email, and I’ll reply to the email you used for the comment. Remember to remove database connection information and any other personal details before sending your code over!

This was a task that took me a few hours to work out the solution, so I wanted to share it for other people to benefit from. I’m building a complicated form in Symfony 2.2.1 and I have many collections within it. I want to dynamically add rows to the collections. One is a collection of phone numbers, and I wanted to style it differently than every other row. I’m using Bootstrap.js to style the project, and wanted to apply some specific formatting to one row. See: Forms, Grid Sizing

Here’s how my page started out.
client-1

When you click on the “Add” buttons, you get the fields to add a new row. (The javascript and specific code you’ll need to make that work is in the Symfony Cookbook, under “How to Embed a Collection of Forms“)
client-2

Now, that’s ok, but here’s how I really wanted it to look:
client-3

Original Code

Here’s the original code to generate the Phone form. I’m going to try to limit this to showing only the code you need to make the specific change. You should be able to get everything else you need from the Symfony Cookbook if you don’t have it already.

First Changes

Okay, to get the dropdown and the input on the same row, we’ll first need to remove their labels, then set the class for each one. We can simply not render the label by using form_widget instead of form_row, and we can provide the class as an argument in form_widget. Don’t forget you need the ‘controls’ and ‘controls-row’ classes on the parent div.

It looks great now!
phone-1

Or does it?
phone-2

Final Solution

The problem is that when we use the add button, the generated code comes from that prototype definition. We’ll have to make some changes to the Type definition to fix this. Set the labels to false, and add the CSS class as well.

Beautiful!
phone-3

Note: At this point, you could revert the edit.html.twig template back to using form_row, but then you’ll run into a slight spacing issue with the bootstrap style and extra form_row divs, so I left it as is. If you’re using a different CSS framework to do this trick, you may want those divs.

, , , , , , , , , , , , , , ,

This tutorial will teach you a basic method for adding zebra-striping to your tables using PHP. Zebra-Striping is a visual technique that colors every other row of a table a different color. It’s a very effective way to make your tables more readable. It’s also very easy to accomplish in PHP.

First, let’s get some sample data and use PHP to output the table. I’ve generated some basic data to use for our table. Thanks to GenerateData.

Then we’ll use some basic PHP/HTML to print out a table with the data.

Here’s what your page should look like now:
zebra-1

Not very easy to read is it? Let’s add the stripes, it’s very simple. Add two CSS styles to your HTML:

Then add some logic to your PHP loop. Using the numeric array key and modulo, we can create a the ternary statement which says if the counter is evenly divisible by 2, then set $class to ‘even’. Otherwise set it to ‘odd’. Finally, assign that class to the table row.

Now it should look like this:
zebra-2
Much better! You can now apply more styles to make your table use whatever colors you want, having nicer spacing and borders, etc. Enjoy!

, , , , , , , , , , ,

I’m using Symfony for a project, and styling the application with Bootstrap.js. I wanted to dynamically create the menu using KnpMenuBundle, and still have the Bootstrap.js style. It was important that the active link be highlighted. It took a little fiddling, here is how I did it.

Here’s our goal (This is the example nav list from bootstrap.js):
menu_end_result

Obviously, you’ll need to have installed and configured both Symfony and KnpMenuBundle, and installed Bootstrap.js into your project.

For this demo we’ll just be using one template with some very basic content. If you already have all your controllers, routes and pages ready, skip down to the “Generating the Menu” Section. Otherwise, here are some basic demo files you’ll need.

Routes

Setup routes for the demo.

Demo Controller

Here’s a basic demo controller that will put some basic content in each page, and render the base twig template.

Twig Template

Setup a the base.html.twig for this demo, using bootstrap.js – make sure you have the bootstrap files in the web folder. Below is a basic base.html.twig file which has already been setup to use Twig syntax to load the bootstrap assets. Feel free to use this version and follow along, or use your own existing base html.

Your page should look like this now:
menu_setup

Generating the Menu

This is where you should start if you already have your routes, controllers, etc. For KnpMenuBundle, you need to create a file called Builder.php in /src/Acme/DemoBundle/Menu

Next we’ll create a multi-dimensional array to hold the section headers, routes and link text. The first dimension will be the section headers – if we don’t provide text we’ll use the horizontal rule. (Refer to the graphic in the beginning of this tutorial if you’re confused). The second dimension will be the routes and link texts.

Next, add the processing to create the menu object. We’ll first create a menu item, and start at the root to give the ul element the classes it needs for bootstrap. We’ll add each section to the menu, again giving it the proper class for bootstrap. Finally, add each item to the sections.
(Refer to the KnpMenuBundle Documenation if needed.)

Rendering The Menu

Now, go back to your base.html.twig file, and add the KnpMenuBundle rendering where you want your menu. Make sure you have the appropriate bootstrap scaffolding around it.

And now we are halfway there!
demo-1

Horizontal Rule / Divider

Let’s add some code to turn a numeric array key into the horizontal rule, as in the original bootstrap example.

Now the horizontal rule should be working.
demo-hr

Active Page

The last thing to do is make it so the route that is currently being used is displayed as the active page in the nav list. This part is sort of a hack, but Symfony does not have another other documented way to get the current route.

Add some code to get the current route, and then compare that route to each one being printed.

Now the page you’re viewing should be selected in the menu. See these examples:
demo-home demo-library demo-help

Conclusion

I hope this tutorial helps you understand how to utilize the KnpMenuBundle better and integrate it with your Bootstrapped layout.

, , , , , , , , , ,

This is Part 4 of a tutorial designed to teach you how to create a basic CRUD (Create, Read, Update & Delete) interface for a MySQL table using PHP. Part 4 covers Delete.

Part 1: Create (Add)
Part 2: Read
Part 3: Update (Edit)

Create a file called delete.php, which will be very similar to edit.php. Include the config file as before. Our delete page will have a confirmation screen, we want the user to be sure this is the data they meant to delete. Before we display the confirmation form, we’ll need to select the relevant information, based off the unique ID we submitted in the URL. So we’ll check to see that it was submitted and that it’s a valid ID, just like we did with edit.php

Processing Data

The processing for delete.php will be much simpler than edit.php.

HTML Form

Finally, the HTML form. This one will also be simpler than the edit one, we only need to show the data, now allow changes. We will however want to make a change so we don’t show the form again after it’s deleted, since we already deleted it!

Conclusion

So now you should understand the basics of using basic queries and prepared statements in PDO to insert, select (read), update and delete data while keeping your database safe from SQL Injection, as well as processing form data in PHP. You could try adding some more validation rules, or try something harder like adding profile photos for your contacts, or e-mail addresses to send emails.

There will be a follow-up to this tutorial with information on ways to improve this basic tutorial, such as creating functions or even converting this application to OOP. If you’ve had any questions or comments, please post them, and I’ll be happy to respond as quickly as possible.

, , , , , , ,

This is Part 3 of a tutorial designed to teach you how to create a basic CRUD (Create, Read, Update & Delete) interface for a MySQL table using PHP. Part 3 covers Update (Edit).

Part 1: Create (Add)
Part 2: Read

Create a file called edit.php, similar to our add.php. Include the config file. Before we display the edit form, we’ll need to select the relevant information, based off the unique ID we submitted in the URL. So we’ll check to see that it was submitted and that it’s a valid ID.

Data Validation

Next, we’ll validate the submitted data for when the form is submitted. We’ll only want to update fields that are actually changed, so we’ll compare the new value to the old value, then build an UPDATE query.

HTML Form

Now, the HTML Form. We’ll use the same basic code from add.php (make sure you change the action parameter and all “add” and “insert” to “edit” and “update”), and add the hidden input for the contact id, so we know which ID we are editing when we process it.

One important change is we will now wrap the entire edit form in a check to see if the ID was submitted and valid – if not, we don’t want to display the form at all.

Part 4: Delete

, , , , , , ,

This is Part 2 of a tutorial designed to teach you how to create a basic CRUD (Create, Read, Update & Delete) interface for a MySQL table using PHP. Part 2 covers the Read page. This part is super simple, don’t worry.

Part 1: Create (Add)

Adding a Menu

Before we create our second page, let’s add a menu so we can easily access our pages. Save this code as menu.php

Now in your add.php file, before the HTML form, add this line:

Creating a config file

The database connection is something we will want to use on every page, so at this point it’d be a good idea to move it into a separate file which we can include in the others. We can also put the array of fields in there, since we can use that same array for our table on the View All Entries page. Replace the code in your add.php file with a require as well.

Reading Entries

For our index page of our contacts CRUD application we’ll list all the entries in the database. This part is fairly simple, we’ll just select all the rows, and echo out an HTML table. Don’t forget to include the config file and the menu.

Adding Edit/Delete Links

The only thing we have left to do is add some links to the HTML table to let you edit or delete a row. For this part we’ll need to add the unique id for the MySQL table to our fields we select, and add two columns to the HTML table for the actions. (Check the line numbers if you’re confused about where to put this code)

Select the ID

Add the Edit/Delete Columns

Add the columns to the table headers…

…and to each row

Part 3: Update (Edit)

, , , , , , ,

This tutorial will teach you how to create a basic CRUD (Create, Read, Update & Delete) interface for a MySQL table using PHP. We’ll be using the PDO extension to handle the database interaction, so this tutorial will allow you to create an interface that is safe from SQL injection.

MySQL Table

We’ll create a basic table to store our data. For this tutorial, we’ll store some simple data, a contacts list to store our friends and family’s names, addresses and phone numbers. I’ll be using http://www.generatedata.com to generate random data, this is a great website to use for generating random sets of data.

Create (Adding) Entries

Create a new php file called add.php – this will be our form for adding new contacts.

PHP/HTML Form

First, let’s create an array of the fields we want to capture, along with their labels.

Then, we’ll use PHP to generate an HTML form with an input element for each field. Using PHP to generate the HTML form allows us to easily add new fields later, and add in error messages, without a lot of repetitive code. I’ve also added some styling. We’ll use the error class later.

Form Processing/Validation

Now we need to add the PHP code to process the data. For this tutorial we will only do some basic validation, making the first and last name required. After we validate those fields, we can check if it’s okay to insert. If it is, first we will prepare a statement (using positional placeholders), then insert the values. We’ll store the result of the insert (a boolean) in a variable to check later.

First, let’s add the validation. This code should go before your form HTML, but after the array that has the fields in it.

Now we’ll add the error messages to the form, as well as filling in the previously submitted data if any exists, so if there was an error the user doesn’t have to retype everything. Replace your previous PHP for generating the form with this:

Test the form out by entering a phone number or address, but leaving one or both name fields blank. You should be able to see your error messages on the first and last name fields, and keep the data you already entered.

Inserting Data to MySQL

At this point we are ready to insert the data. Add your database connection to the top of the file. We’ll be using PDO.

Then go to the end of your form validation code. If there are any errors, we don’t want to insert, so we want to check if there are no errors. If there are no errors, we’ll create a prepared statement and insert our values.

Success/Error Message for Insert

Finally, we’ll use the $result variable to display a success message if the form was submitted, or an error message including DB error info if not. Remember to remove the database error message code before using your code on a production server.

Final Code

Here’s what the final code looks like altogether.

Next Steps

Go ahead and add a few rows worth of data. We’ll work on the Read step next, so you’ll want to have at least one or two rows.

Part 2: Read

, , , , , , ,

Update: The software update has been completed. We’ve switched to using Crayon for syntax highlighting and so far it looks perfect. Thanks!

I haven’t been able to post any new tutorials lately because the plugin I use to do the syntax highlighting has been really buggy. I am looking into getting a new one. If the existing posts don’t look right, please check back in a little bit. Thanks!