1
votes

I have just started rebuilding my app i made to use namespaces to make future development easier and so we can reuse class names.

basically my code is as follows.

<?php
session_start();

error_reporting(E_ALL);
ini_set('display_errors', 1);

use core\marketing as marketing;
use core\security as security;
use core\structure as structure;
use core\data as data;

include 'marketing\cleanurl.php';
?>

As soon as I run this I get the following error:

Warning: include(marketing\cleanurl.php): failed to open stream: No such file or directory in /var/www/index.php on line 27 Warning: include(): Failed opening 'marketing\cleanurl.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/index.php on line 27

My directory structure matches the namespaces as that is what I read on the net.

Now if I change the include to match the directory i.e.

include 'core/marketing/cleanurl.php';

I get the following error

Parse error: syntax error, unexpected T_CLASS, expecting T_NS_SEPARATOR or ';' or '{' in /var/www/twiggled/core/marketing/cleanurl.php on line 4

This all worked when I was just using require_once to call all the classes but found this limited expansion of the system and made changes more time consuming and wanted to use namespaces as they have always been great in other languages I have used.

1
can u post content of cleanurl.php - robert
The first error is what happens when you design the namespace separator to look like the path separator from the wrong plattform. (You are on a Unix filesystem requiring the forward slash, but used the Windows backslash.) - mario
@mario the namespace separator is correct per PHP documentation. The problem appears to be with how you are including the cleanurl file. That seems to be where the slash might be the problem. Change to "marketing/cleanurl.php" if you are on a unix system and make sure that you have not omitted a semicolon somewhere. - Scott Harwell
Namespaces and file paths are entirely separate, they do not work together. The first error is a regular problem with wrong file paths. The second is a normal syntax error, for which we'd have to see the file it occurs in. - deceze
Your cleanurl.php probably misses a semicolon right after the namespace core\marketing declaration. - Ja͢ck

1 Answers

2
votes

Since OP asked for it, here's an updated answer using autoload.

Note: Such a complex construct wouldn't be needed for the ease of task, of course. However, This is just an example how things play together (autoloading, requires, static methods etc).

Bootstrap / Autoload

/var/www/somedir/Twiggled/bootstrap.php

<?php
namespace Twiggled;

require_once __DIR__ . '\Common\AutoLoader.php';

$autoloader = new \Twiggled\Common\AutoLoader(__NAMESPACE__, dirname(__DIR__));
$autoloader->register();

/var/www/somedir/Twiggled/Common/AutoLoader.php

<?php
namespace Twiggled\Common;

/**
 * PSR-0 Autoloader
 *
 * @package    Common
 */
class AutoLoader
{
    /**
     * @var string The namespace prefix for this instance.
     */
    protected $namespace = '';

    /**
     * @var string The filesystem prefix to use for this instance
     */
    protected $path = '';

    /**
     * Build the instance of the autoloader
     *
     * @param string $namespace The prefixed namespace this instance will load
     * @param string $path The filesystem path to the root of the namespace
     */
    public function __construct($namespace, $path)
    {
        $this->namespace = ltrim($namespace, '\\');
        $this->path      = rtrim($path, '/\\') . DIRECTORY_SEPARATOR;
    }

    /**
     * Try to load a class
     *
     * @param string $class The class name to load
     *
     * @return boolean If the loading was successful
     */
    public function load($class)
    {
        $class = ltrim($class, '\\');

        if (strpos($class, $this->namespace) === 0) {
            $nsparts   = explode('\\', $class);
            $class     = array_pop($nsparts);
            $nsparts[] = '';
            $path      = $this->path . implode(DIRECTORY_SEPARATOR, $nsparts);
            $path     .= str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';

            if (file_exists($path)) {
                require $path;
                return true;
            }
        }
        return false;
    }

    /**
     * Register the autoloader to PHP
     *
     * @return boolean The status of the registration
     */
    public function register()
    {
        return spl_autoload_register(array($this, 'load'));
    }

    /**
     * Unregister the autoloader to PHP
     *
     * @return boolean The status of the unregistration
     */
    public function unregister()
    {
        return spl_autoload_unregister(array($this, 'load'));
    }
}

Package files

/var/www/somedir/Twiggled/Core/Helper/Strings.php

<?php
namespace Twiggled\Core\Helper;

class Strings
{
    // Note: Eventhough the method use a global PHP function name,
    // there is no problem with it - thanks to namespace.
    public static function str_replace($str) 
    {
        $str = preg_replace('/\s/', '_', strtolower($str));
        return preg_replace('/[^a-zA-Z_]/', '', $str);
    }
}

/var/www/somedir/Twiggled/Core/Marketing/Cleanurl.php

<?php
namespace Twiggled\Core\Marketing;

use \Twiggled\Core\Helper\Strings as HelperStrings;

class Cleanurl 
{
    const BASE_URL = 'http://example.com/';
    public $cleanPath;

    public function __construct($str) 
    {
        $this->cleanPath= HelperStrings::str_replace($str);
    }
}

Load and use it..

/var/www/somedir/index.php

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('date.timezone', 'Europe/Berlin');

// Bootstrap the package / register autoloader
require_once __DIR__ . '\Twiggled\bootstrap.php';

use \Twiggled\Core\Marketing as Marketing;

try {
    $obj = new Marketing\Cleanurl('$This w-ork5s!');

    // prints 'http://example.com/this_works'.
    echo Marketing\Cleanurl::BASE_URL . $obj->cleanPath; 
} 
catch (\Exception $e) { }