?
Solved

duplication does not work when namespaces are involved

Posted on 2014-04-21
7
Medium Priority
?
148 Views
Last Modified: 2014-04-22
I added code to matt zandstra php book

$classname2= "L520";
require_once("tasks/{$classname2}.php");
$classname2="tasks\\$classname2";

$myObj2= new $classname2();
$myObj2->doSpeak();
$myObj2->replicate();

listing 5.20
<?php
// TaskRunner.php
$classname = "Task";
require_once( "tasks/{$classname}.php" );
$classname = "tasks\\$classname";

$myObj = new $classname();
$myObj->doSpeak();
$myObj->replicate();
echo $myObj->property;

$classname2= "L520";
require_once("tasks/{$classname2}.php");
$classname2="tasks\\$classname2";

$myObj2= new $classname2();
$myObj2->doSpeak();
$myObj2->replicate();
?>

Open in new window


hello repeatproperty
Fatal error: Class 'tasks\L520' not found in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_05_Code\listing5.20.php on line 16


\tasks\Task.php
<?php
// Task.php
namespace tasks;

class Task {
  public $property='property';
    function doSpeak() {
        print "hello\n";
    }
    function replicate(){
      print "repeat";
    }
}
?>

Open in new window


so I added this file
\tasks\L520.php
<?php
  namespace L520;
    class L520{
      function dospeak(){
        
      }
      function replicate(){
        
      }
  }
?>

Open in new window



the way I learn is I create variables and classes and methods which I think do the exact same output

but with namespaces, this gets confusing and I get errors

maybe I have to declare
use new namespace
0
Comment
Question by:rgb192
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 58

Expert Comment

by:Julian Hansen
ID: 40014274
Your problem is on line 14

$classname2="tasks\\$classname2";

Open in new window


Should be

$classname2="L520\\$classname2";

Open in new window


You are trying to instantiate the L520 class in the tasks namespace but you have declared the L520 class in the L520 namespace.

So either you need to change your class L520 to be in the tasks namespace

OR

Change your reference to the class to be the L520 namespace.
0
 

Author Comment

by:rgb192
ID: 40014741
I moved L520.php to new L520 folder


Code now works

<?php
// TaskRunner.php
$classname = "Task";
require_once( "tasks/{$classname}.php" );
$classname = "tasks\\$classname";

$myObj = new $classname();
$myObj->doSpeak();
$myObj->replicate();
echo $myObj->property;

$classname2= "L520";
require_once("L520/{$classname2}.php");
$classname2="L520\\$classname2";

$myObj2= new $classname2();
$myObj2->doSpeak();
$myObj2->replicate();
?>

Open in new window



but I do not understand the difference between
namespace
and
folder
0
 
LVL 58

Expert Comment

by:Julian Hansen
ID: 40014853
A folder is where the file is actually stored and is at the filesystem level - not the PHP level.

A namespace is defined inside the php file to group classes, functions and variables under a common grouping.

Consider this example
<?php
require_once('tasks/person.php');
$x = new john\Person('Mary');
$y = new bob\Person('Jane');
?>

Open in new window

tasks/person.php
<?php
namespace john {
  class Person
  {
    function __construct($who)
    {
      echo "Hello $who, I am a John Person";
    }
  }
}
namespace bob {
  class Person 
  {
    function __construct($who)
    {
      echo "Hello $who, I am a Bob Person";
    }
  }
}
?>

Open in new window

Can you see that in the same file I have two namespaces (John and Bob)

Each of them has a class called person that do different things.

To avoid these two classes conflicting with each other I put them in different namespaces - that way I can differentiate between them without changing the underlying code of either of them.

Now consider this example
<?php
namespace john;
require_once('tasks/person.php');
$x = new Person('Mary');
?>

Open in new window

By declaring the namespace as john as the first line (it must be the first line) of the script the interpreter now looks for Person as John\Person by default.
Now look at the next example
<?php
namespace john;
require_once('tasks/person.php');
class People
{
  function __construct($who)
  {
    echo "Hullo $who I are a people";
  }
}
$x = new Person('Mary');
$y = new People('Frank');
?>

Open in new window

People also resolves correctly because it is part of the default namespace in which it is instantiated.

However the following will fail
<?php
namespace john;
require_once('tasks/person.php');
$x = new bob\Person('Mary');
?>

Open in new window

Why? Because the interpreter will attempt to find the class as
john\bob\Person - because we declared that the namespace we were using was John.
0
7 Extremely Useful Linux Commands for Beginners

Just getting started with Linux? Here's a quick start guide that has 7 commands that we believe will come in handy.

 

Author Comment

by:rgb192
ID: 40015182
A folder is where the file is actually stored and is at the filesystem level - not the PHP level.

is this like html browser view source and I see all the css/javascript files


and I can keep adding classes to namespace john whenever I call namespace john
<?php
namespace john;
require_once('tasks/person.php');
class People
{
  function __construct($who)
  {
    echo "Hullo $who I are a people";
  }
}
class another{
  function __construct($who){
    echo '<br>in class: '.__CLASS__.'<br>';
  }
}
$x = new Person('Mary');
$y = new People('Frank');
$z= new another('Richy');
?>

Open in new window




calling namespace bob works when namespace bob; is declared
<?php
namespace john;
require_once('tasks/person.php');
namespace bob;
$x = new Person('Mary');
?>

Open in new window


but is there a way to call with one line
$x = new ../bob/Person('Mary');
0
 
LVL 58

Accepted Solution

by:
Julian Hansen earned 2000 total points
ID: 40015219
and I can keep adding classes to namespace john whenever I call namespace john
Slight correction - you don't call a namespace. A namespace is used by the interpreter to locate the correct code to run. You group all code you want together in a namespace that you optionally give a name. If you don't declare a namespace one is implied - the default namespace.
Think of a namespace as a packet of groceries. You put in the packet all the items you want to group to gether. To locate the item again you need to know what packet you put it in.

calling namespace bob works when namespace bob; is declared
That is because you overrode the previous namespace declaration.

but is there a way to call with one line
Not sure what you are asking - you can always find the namespace relative to the root
i.e
<?php
namespace john;
require_once('tasks/person.php');
$z = new Person('Mary'); // John person in the specified namespace so does not need John in front
$x = new \bob\Person('Jane'); // Bob person - found by referencing from the root.

Open in new window

0
 

Author Closing Comment

by:rgb192
ID: 40016191
$x = new \bob\Person('Jane'); // Bob person - found by referencing from the root.

now I know how to call a namespace from root
and where namespaces are located.

thanks
0
 
LVL 58

Expert Comment

by:Julian Hansen
ID: 40016280
You are welcome - thanks for the points.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question