...

Hi! I’m Starx

experienced Software Developer. And this is my blog
Start Reading About me
Blog Page
March 7, 2012

RegEx pattern to get the YouTube video ID from any YouTube URL

Question by Shackrock

Let’s take these URLs as an example:

  1. http://www.youtube.com/watch?v=8GqqjVXhfMU&feature=youtube_gdata_player
  2. http://www.youtube.com/watch?v=8GqqjVXhfMU

This PHP function will NOT properly obtain the ID in case 1, but will in case 2. Case 1 is very common, where ANYTHING can come behind the YouTube ID.

/**
 * get YouTube video ID from URL
 *
 * @param string $url
 * @return string YouTube video id or FALSE if none found. 
 */
function youtube_id_from_url($url) {
    $pattern = 
        '%^# Match any YouTube URL
        (?:https?://)?  # Optional scheme. Either http or https
        (?:www.)?      # Optional www subdomain
        (?:             # Group host alternatives
          youtu.be/    # Either youtu.be,
        | youtube.com  # or youtube.com
          (?:           # Group path alternatives
            /embed/     # Either /embed/
          | /v/         # or /v/
          | /watch?v=  # or /watch?v=
          )             # End path alternatives.
        )               # End host alternatives.
        ([w-]{10,12})  # Allow 10-12 for 11 char YouTube id.
        $%x'
        ;
    $result = preg_match($pattern, $url, $matches);
    if (false !== $result) {
        return $matches[1];
    }
    return false;
}

What I’m thinking is that there must be a way where I can just look for the “v=”, no matter where it lies in the URL, and take the characters after that. In this manner, no complex RegEx will be needed. Is this off base? Any ideas for starting points?

Answer by Starx

Instead of regex. I hightly recommend parse_url() and parse_str():

$url = "http://www.youtube.com/watch?v=8GqqjVXhfMU&feature=youtube_gdata_player";
parse_str(parse_url( $url, PHP_URL_QUERY ), $vars );
echo $vars['v'];    

Done

Read more

FInding duplicates in db values

Question by santa

I have a table with the following fields:

id
project
projectName

There are two different way when I display this data:

  1. Before I store it into a database I place projectName values into text fields. In this case I need to be able to somehow mark when there are duplicated with some sort of jQuery code, and

  2. I output the values from db into a list. Again, I need to somehow catch duplicates and mark them somehow, perhaps changing text color.

There could be multiple duplicate sets.

How can I do that?

Answer by Starx

Ok, you can send an ajax request to the server and see if is actually duplicate. I will give a simple example of how we can get something like this to work.

HTML

<a id="check"> check availabilty</a>

JQuery

$("#check").click(function() {
    $.post("checkname.php", 
           { name : $("#textboxname").val() },
           function(data) {
             //data will contain the output from the file `checkname.php`
             if(data=="ok") { //imagine the case it output ok if not duplicate is found
                alert('ok');
             else { 
                alert('duplicate name exists');
             }
    );
});

PHP checkname.php

$name = $_POST['name'];
//now confirm this with a query or just use your own logic
//
//

if($resultfound) { echo "ok"; } else { echo "no"; }

Note: This is a very basic example to illustrate the process.

Read more

@font face only displaying in demo html

Question by indrago

Ok so I downloaded a @font-face kit from fontsquirell, it works fine in the demo html file included in the download, but fails to render when I put it in any other file or sub folder.

I have checked the file structure and linked accordingly, i am still having this problem. Any suggestions on what I should do?

@font-face {
font-family: 'BreeSerifRegular';
src: url('..assets/fonts/BreeSerif-Regular-webfont.eot');
src: local("☺")
     url('..assets/fonts/BreeSerif-Regular-webfont.eot?#iefix') format('embedded-    opentype'),
     url('..assets/fonts/BreeSerif-Regular-webfont.woff') format('woff'),
     url('..assets/fonts/BreeSerif-Regular-webfont.ttf') format('truetype'),
     url('..assets/fonts/BreeSerif-Regular-webfont.svg#BreeSerifRegular') format('svg');
font-weight: normal;
font-style: normal;
}

The same format works for other fonts, dunno why its not working for this.

Answer by Starx

Its the basic problem with paths

Copy the fonts you receive and into a folder at the root lets say a font.

Then point your css to read the file in a relative pattern like

@font-face {
font-family: 'BreeSerifRegular';
src: url('fonts/BreeSerif-Regular-webfont.eot');
src: local("☺")
     url('fonts/BreeSerif-Regular-webfont.eot?#iefix') format('embedded-    opentype'),
     url('fonts/BreeSerif-Regular-webfont.woff') format('woff'),
     url('fonts/BreeSerif-Regular-webfont.ttf') format('truetype'),
     url('fonts/BreeSerif-Regular-webfont.svg#BreeSerifRegular') format('svg');
font-weight: normal;
font-style: normal;
}

UPDATE

The way you are defining relative path is wrong

Change ..assets to ../assets

Read more

jquery .serialize()

Question by Cjueden

I can’t get jquery .serialize() to work correctly. I have a form of dynamically generated checkboxes. The page wont submit the check boxes. Can you please tell me where I went wrong.

     $('#prof_take_attendance_submit').live("click",function(){
            var current_class = $('#class_choice :selected').attr('name');// GET CURRENT CLASS
            var prof_id = $('#prof_id').text();// GET PROFFESSOR ID NUMBER
                $("#prof_take_attendance_form").trigger('submit',function(){
                var query_string = $(this).serialize(); 
                        });

                $("#take_attendance_prof")// CALL TO FORM  
                .html(ajax_load)  
                .load(loadUrl, "form_being_submitted=prof_save_attendance&class="+current_class+"&prof_id="+prof_id+""+query_string);
        $('#take_attendance_prof').fadeIn(200);

     });

Answer by charlietfl

Based on assumption that $('#prof_take_attendance_submit') is a submit button you are trying to serialize just the button

Try:

   var query_string = $(this).closest('form').serialize(); 

Without more info about form is pretty hard to see what elese may not be working

EDIT: Get rid of trigger, bind submit to form not button

 $("#prof_take_attendance_form").live('submit', function(){
      var query_string = $(this).serialize(); 

       /* other code and ajax*/

 })

Answer by Starx

Serialize the form not the button

$("#prof_take_attendance_form").serialize();
Read more

Nested lists using PHP's iterator?

Question by thelolcat

I’m trying to display this kind of array:

$nodes = array(

  1 => array(
         'title'    => 'NodeLvl1',
         'children' => array(),
       ),    
  2 => array(
         'title'    => 'NodeLvl1',
         'children' => array(        
                         1 => array(
                                'title'    => 'NodeLvl2',
                                'children' => array(),
                             ),    
                         2 => array(
                                'title'    => 'NodeLvl2',
                                'children' => array(


                                   1 => array(
                                          'title'    => 'NodeLvl3',
                                          'children' => array(),
                                       ),


                                   2 => array(
                                          'title'    => 'NodeLvl3',
                                          'children' => array(),
                                       ),    
                                ),
                              ),    

                       ),
       ),

  3 => array(
         'title'    => 'NodeLvl1',
         'children' => array(),
       ),    
);

like this:

<ul>
  <li>
    NodeLvl1
  </li>
  <li>
    NodeLvl1
      <ul>
        <li>NodeLv2</li>
         ...

      </ul>
  </li>
  ...

Basically a nested list taking into account the “children” property. So far I’ve come up with this:

class It extends RecursiveIteratorIterator{

  protected
    $tab    = "t";

  public function beginChildren(){

    if(count($this->getInnerIterator()) == 0)
      return;

    echo str_repeat($this->tab, $this->getDepth())."<ul>n";
  }

  public function endChildren(){


    if(count($this->getInnerIterator()) == 0)
      return;

    echo str_repeat($this->tab, $this->getDepth())."n</ul>";
  }

  public function nextElement(){
    echo str_repeat($this->tab, $this->getDepth() + 1).'<li>';
  }

}

$it = new It(new RecursiveArrayIterator($nodes));

foreach($it as $key => $item)
  echo $item;

Which doesn’t work quite right: I get each item wrapped between <ul>s and I don’t know how can I close <li>s…

Any ideas on how to make this work? Also is it possible to get all the array properties (the actual element), instead of just the “title” property inside my foreach() loop? And can this be done with objects instead of arrays?

Answer by satrun77

You can use RecursiveCachingIterator to do what you want. Here is an example, (source: https://github.com/cballou/PHP-SPL-Iterator-Interface-Examples/blob/master/recursive-caching-iterator.php)

<?php
// example navigation array
$nav = array(
    'Home' => '/home',
    'Fake' => array(
        'Double Fake' => array(
            'Nested Double Fake' => '/fake/double/nested',
            'Doubly Nested Double Fake' => '/fake/double/doubly'
        ),
        'Triple Fake' => '/fake/tripe'
    ),
    'Products' => array(
        'Product 1' => '/products/1',
        'Product 2' => '/products/2',
        'Product 3' => '/products/3',
        'Nested Product' => array(
            'Nested 1' => '/products/nested/1',
            'Nested 2' => '/products/nested/2'
        )
    ),
    'Company' => '/company',
    'Privacy Policy' => '/privacy-policy'
);

class NavBuilder extends RecursiveIteratorIterator {

    // stores the previous depth
    private $_depth = 0;

    // stores the current iteration's depth
    private $_curDepth = 0;

    // store the iterator
    protected $_it;

    /**
     * Constructor.
     *
     * @access  public
     * @param   Traversable $it
     * @param   int         $mode
     * @param   int         $flags
     */
    public function __construct(Traversable $it, $mode = RecursiveIteratorIterator::SELF_FIRST, $flags = 0)
    {
        parent::__construct($it, $mode, $flags);

        // store the caching iterator
        $this->_it = $it;
    }

    /**
     * Override the return values.
     *
     * @access  public
     */
    public function current()
    {
        // the return output string
        $output = '';

        // set the current depth
        $this->_curDepth = parent::getDepth();

        // store the difference in depths
        $diff = abs($this->_curDepth - $this->_depth);

        // get the name and url of the nav item
        $name = parent::key();
        $url = parent::current();

        // close previous nested levels
        if ($this->_curDepth < $this->_depth) {
            $output .= str_repeat('</ul></li>', $diff);
        }

        // check if we have the last nav item
        if ($this->hasNext()) {
            $output .= '<li><a href="' . $url . '">' . $name . '</a>';
        } else {
            $output .= '<li class="last"><a href="' . $url . '">' . $name . '</a>';
        }

        // either add a subnav or close the list item
        if ($this->hasChildren()) {
            $output .= '<ul>';
        } else {
            $output .= '</li>';
        }

        // cache the depth
        $this->_depth = $this->_curDepth;

        // return the output ( we could've also overridden current())
        return $output;
    }

}
?>

Usage

<?php

try {

    // generate the recursive caching iterator
    $it = new RecursiveCachingIterator(new RecursiveArrayIterator($nav));

    // build the navigation with the iterator
    $it = new NavBuilder($it, RecursiveIteratorIterator::SELF_FIRST);

    // display the resulting navigation
    echo '<ul id="nav">' . PHP_EOL;
    foreach ($it as $value) {
        echo $value . "n";
    }
    echo '</ul>' . PHP_EOL;

} catch (Exception $e) {
    var_dump($e); die;
}
?>

Answer by Starx

First let me explain few things to you. Your array has two pattens

  1. One with numeric indexes
  2. One with string indexes, with title and children which has be parsed differently

I think a recursive function plays very nice role on this part, rather than complex logics. And our recursive function has to be able to handle both patterns separately.

Here is my version of the function you could use with explanation

function arraytolist(Array $array) { //ensure what you receive is array
  if(count($array)) { //only if it has some items
    //In case the array has `title` index we encountered out PATTERN 2
    if(isset($array['title'])) {
        $o = "<li>";
        $o .= $array['title']; //simply add the title
        $o .= arraytolist($array['children']); //and pass the children to this function to verify again
        $o .= "</li>";
    } else { //if its a normal array, //PATTERN 1
        $o = "<ul>";
        foreach($array as $value) {
            $n = "";
            if(is_array($value)) {  //in case its an array again, 
                //send it to this very same function so that it will return as output again
                $n .= arraytolist($value);
            } else {
                $n .= "<li>$value</li>";
            }
            $o .= strlen($n) ? $n : ""; //if $n has something use it otherwise not
        }
        $o .= "</ul>"; //lets close the ul
    }
    return $o;
  }
}

Some Advantage of this function

  • No iteration level
  • As long as its an array and has item, keeps on building them
  • Power of simple logic in PHP
Read more

PHP MVC natural URL schema

Question by Banago

I would like to specify my routing tables such that they would feel much more “natural”. The accent is at the “Books” – I need to have the “s” at the end for the index/archive book page.

  • /Books
  • /Book/17
  • /Book/Edit/17
  • /Book/Create

How can I achieve this in PHP?

PS: I’m not asking about routing in general. I just need some insight on how to add an “s” to the index/archive controller.

Answer by Banago

Here goes the solution. Since the controllers accepts a singular name, and I want to use a plural name on the Index/Archie views, singulerizing the plural name is the solution:

Inflect::singularize( $request[0] );

Making use of this class: http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/

Answer by Starx

In order to postfix additional text to the url a simplest version would be something like

RewriteEngine on
RewriteRule ^(.*)$ /${lc:$1}s [R=301,L]

But since you want to redirect only index and archive

RewriteEngine on
RewriteCond %{REQUEST_URI} !(index|archive)/$
RewriteRule ^(.*)$ http://yoursite.com/$1s [L,R=301]
Read more
March 6, 2012

Combining two columns on a id

Question by Snowflow

this is my database

database schema

What i want to do, is, for a given userid, show the total times he has been reported.
I have read various other questions on the matter, but I’m still stumped.

The latest query i tried was

select
   sum(posts.timesreported + comments.timesreported) AS total_reports
FROM 
  posts 
  INNER JOIN comments ON (posts.userid = comments.userid) 
WHERE posts.userid=5 AND comments.userid=5;

But this must be wrong as the number i get is much too high

Thanks!

Answer by SOaddict

SELECT 
 CASE WHEN NULL
      THEN 0
      ELSE (select sum(posts.timesreported) AS total_posts_reports
            FROM  posts  INNER JOIN users ON (posts.userid = users.id) 
            WHERE posts.userid=5) 
      END 
 +
 CASE WHEN NULL
      THEN 0
      ELSE (select sum(comments.timesreported) AS total_comments_reports
            FROM  comments  INNER JOIN users ON (comments.userid = users.id) 
            WHERE comments.userid=5) 
      END
FROM DUAL; 

Answer by Starx

WHERE posts.userid=5 AND comments.userid=5; is unnecessary since the tables are joined.

And sum operator is not correct logically

Use this query

select
   sum(posts.timesreported) + sum(comments.timesreported) AS total_reports
FROM 
  posts 
  INNER JOIN comments ON (posts.userid = comments.userid) 
WHERE posts.userid=5
Read more

3 div liquid design

Question by a Learner

I making 3 div (col) design with left and right divs with fixed size , centered div as liquid (in %) as:

.left{
width:10px;
float:left;
}

.right{
width:10px;
float:left;
}
.center{
width:100%;
float:left;
}

HTML CODE:

<div class="left">  LEFT   </div>
<div class="center">CENTER</div>
<div class="right"> RIGHT     </div>

But it is showing the divs vertically (in separate lines) as:

left div
centered div (occupying whole page)
right div

How to dispaly them in horizontal manner as:

left div      centered div       Right div

THanks…

Answer by Starx

Its logically impossible.

If the center div is 100% width, there is no room for .left and .right

Its better you specify all the width in %. to make them coincide perfectly.

.left{
width:1%;
float:left;
}

.right{
width:1%;
float:left;
}
.center{
width:98%;
float:left;
}

Update: Since, the target is to get a fluid container in the .center. Here is the solution.

Read more

Float over iframes html

Question by Ma9ic

Is it possible to float a nav bar over a iframe here is the code that i have so far?

the nav bar as you will be is in the html page and contains buttons that trigger the iframe to go to the next page etc.

Any ideas?

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Fraud Protection - Course</title>
<style>
    .backbutton[type="button"] {
        border: 0;
        background: url("back.png") no-repeat;
        text-indent: -9999em;
        line-height:3000;
        width: 100px;
        height: 35px;
        cursor:pointer;
    }
        .nextbutton[type="button"] {
        border: 0;
        background: url("next.png") no-repeat;
        text-indent: -9999em;
        line-height:3000;
        width: 100px;
        height: 35px;
        cursor:pointer;
    }
            .savebutton[type="button"] {
        border: 0;
        background: url("save.png") no-repeat;
        text-indent: -9999em;
        line-height:3000;
        width: 100px;
        height: 35px;
        cursor:pointer;
    }
</style>
</head>
<body>

    <iframe src="" width="100%" class="naviframe" id="contentFrame" hieght="100%"></iframe>
    <div id="navDiv">
     <input type="button" class="backbutton" id="butPrevious" onclick="doPrevious();" value="<- Previous"/>
        <input type="button" class="nextbutton" value="Next ->" img src="/images/Btn.PNG" id="butNext" onclick="doNext();"/>
        <input type="button" class="savebutton" value="Save Progress"  img src="/images/Btn.PNG" id="butExit" onclick="doExit();"/>
    </div>

</body>
</html>

Answer by Starx

It is possible. You have to position the element to be floated, as absolute with negative margin.

Demo

Read more
...

Please fill the form - I will response as fast as I can!