learning halo

1 view
Skip to first unread message

aek

unread,
Aug 17, 2010, 4:55:00 PM8/17/10
to Halo General Discussion
Hi all,
I am a Java developer that for a while has been worked with
IMHO the best frameworks that you can check out in Java world. I
created a software architecture around Spring Framework, Hibernate,
ExtJS and so many other cool frameworks that is domain object centric
and very productive. I want to do the port to PHP because the my
software architecture is simply a way to do things quickly using the
frameworks more productive to me. I just want to have a good MVC, a
good ORM and some other things that can be created or integrated for
the task. I like the way of halo works but I just start to play with
it.
There are some question in my head.
Actually I have a good setup Halo, Substrate, Skittle and Repose for
my task but there are some parts that is not correctly working and I
think that maybe Im doing something wrong. I have my own proyect
structure similar to a Java Web Proyect (Im from Java world) and the
frameworks are all in the folder /WebContent/WEB-INF/lib. When I tried
to use hc_core_ClassLoader::load() or hc_core_FileLocator::find()
there are errors due to the paths that are configured in hc-
bootstrap.php and following the setup proposal from Halo sample
proyect. How I can load or find any class or file in my classpath?, It
this possible?. I need to configure something else?

Congratulations for this great work, I want offers my colaboration,
for my software architecture proyect, I need especial features of
Spring MVC, that Halo don't have like InternalResourceViewResolver and
MultiactionController. I begin to develop my halo solution for this
tasks. I will share when they are finish, or more stables

Beau Simensen

unread,
Aug 18, 2010, 2:54:24 PM8/18/10
to halo...@googlegroups.com
Hi again!

You sure are eating these projects up. :) I'm going to have to start putting more focus on them if you are actually trying to use them. I think I am going to spend some time on Halo and Substrate and move them to git hosting very soon.

As for the class loading...

Did you try:

hc_core_ClassLoader::appendPaths('/WebContent/WEB-INF/lib');

... that should hopefully work. (assuming that /WebContent/WEB-INF/lib is an absolute path)

That would also need to be executed before anything tried to load that class.

--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/


[blog] http://not-invented-here.com/
[flickr] http://flickr.com/photos/kirkryyn
[facebook] http://facebook.com/simensen



--
You received this message because you are subscribed to the Google Groups "Halo General Discussion" group.
To post to this group, send email to halo...@googlegroups.com.
To unsubscribe from this group, send email to halo-php+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/halo-php?hl=en.


aek

unread,
Aug 25, 2010, 11:22:47 AM8/25/10
to Halo General Discussion
check repose discusion group for more topics about all of this greats
frameworks.
My MultiActionController is finish, the only need is some changes in
the halo_HttpRequest to get the relative url because Im not going to
use url rewrite yet. halo_SimpleUrlHandlerMapping need to resolve url
patterns like MultiActionController using Apache Ant style pattern,
like in Spring MVC. I found an util library for the task in http://www.php-pop.org
specifically the pur proyect. So I am testing that in
MultiActionController to add to SimpleUrlHandlerMapping.

Beau Simensen

unread,
Aug 25, 2010, 2:21:43 PM8/25/10
to halo...@googlegroups.com
Sounds good, looking forward to seeing your code.

How has the overall experience been building the application? Having come from a Java background, I Imagine it probably felt close to what you were used to. I'm still not decided on how to balance the PHP and Java worlds with these projects. Would love to get some additional feedback!


--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/


[blog] http://not-invented-here.com/
[flickr] http://flickr.com/photos/kirkryyn
[facebook] http://facebook.com/simensen



--

Beau D. Simensen

unread,
Aug 27, 2010, 4:41:28 PM8/27/10
to Halo General Discussion
> I have now an stable version of MultiActionController and the
> PropertiesMethodNameResolver that is my prefered MethodNameResolver
> strategy, the others that ship with Spring MVC are implemented but not
> tested, yet.
> How can I share those source code with you?

You could try attaching a patch to a group message. Please try to keep
the Halo related stuff in the Halo group, especially if you are going
to be submitting Halo patches.

Are you keeping your own modifications and additions in your own
repository? If so, is that repository available? If so, I could take a
look that way, too.

Are you familiar with git?

aek

unread,
Sep 2, 2010, 2:10:51 PM9/2/10
to Halo General Discussion
> Are you keeping your own modifications and additions in your own
> repository? If so, is that repository available? If so, I could take a
> look that way, too.
>

I have a svn repository but it's not available from internet, its
behind so many proxies.

> Are you familiar with git?

not very familiar, only for download.

Beau Simensen

unread,
Sep 2, 2010, 2:25:47 PM9/2/10
to halo...@googlegroups.com
Alright, I am sure we can work something out. :) Thanks again for your
help and feedback!

Since you are actively using Substrate and Halo I am going to start
trying to pay more attention to these projects again. Substrate first,
of course. :) I'll keep you in the loop as I start to make decisions
on how it may change. You've brought up a few issues I'd like to
address, like the class loader and file locator issues... I want to
make sure that I am doing something consistent across all three major
projects.


--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/

aek

unread,
Sep 2, 2010, 2:54:54 PM9/2/10
to Halo General Discussion
Here is my halo usage examples and classes, at the end there is a
balance of the use of this classes

<?php

class halo_MultiActionController implements halo_IController {
private $methodNameResolver;
private $delegate;

public function __construct() {
$this->methodNameResolver = new
halo_InternalPathMethodNameResolver();
$this->delegate = $this;
}

public function handleRequest(halo_HttpRequest $request,
halo_HttpResponse $response){
$methodName = $this->methodNameResolver-
>getHandlerMethodName($request);
return $this->invokeNamedMethod($methodName, $request, $response);
}

public function setDelegate($delegate) {
$this->delegate = $delegate;
}
public function setMethodNameResolver(halo_IMethodNameResolver
$methodNameResolver) {
$this->methodNameResolver = $methodNameResolver;
}
public function getMethodNameResolver() {
return $this->methodNameResolver;
}

public function bind(halo_HttpRequest $request, $object){
$reflectionClass = new ReflectionClass(get_class($object));

foreach ($request->getParameterNames() as $param) {
if($reflectionClass->hasProperty($param)){
LoggerReflectionUtils::setter($object, $param, $request-
>getParameter($param));
/*$reflectionProperty = $reflectionClass->getProperty($param);
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($object, $request-
>getParameter($param));*/
}
}
}

/*private function isHandlerMethod(Method $method) {
Class returnType = $method.getReturnType();
if (ModelAndView.class.equals(returnType) ||
Map.class.equals(returnType) || String.class.equals(returnType) ||
void.class.equals(returnType)) {
Class[] parameterTypes = method.getParameterTypes();
return (parameterTypes.length >= 2 &&
HttpServletRequest.class.equals(parameterTypes[0]) &&
HttpServletResponse.class.equals(parameterTypes[1]) &&
!("handleRequest".equals(method.getName()) &&
parameterTypes.length == 2));
}
return false;
}*/

protected function invokeNamedMethod($methodName, halo_HttpRequest
$request, halo_HttpResponse $response){

$method = new ReflectionMethod(get_class($this->delegate),
$methodName);
$parameters = $method->getParameters();
$params = Array();
$params[] = $request;
$params[] = $response;

if ($method->getNumberOfParameters() >= 3) {
$commandReflectionClass = new ReflectionClass($parameters[2]-
>getClass());
$class = $parameters[2]->getClass()->getName();
$command = new $class;
//$commandReflectionClass->newInstanceArgs();

$this->bind($request, $command);
$params[] = $command;
}

$returnValue = $method->invokeArgs($this->delegate, $params);
return $returnValue;
}

}
?>

<?php

interface halo_IMethodNameResolver {

public function getHandlerMethodName(halo_HttpRequest $request);
}

?>

<?php

class halo_InternalPathMethodNameResolver implements
halo_IMethodNameResolver {

private $prefix = "";
private $suffix = "";

public function setPrefix($prefix) {
$this->prefix = ($prefix !== null ? $prefix : "");
}
protected function getPrefix() {
return $this->prefix;
}
public function setSuffix($suffix) {
$this->suffix = ($suffix !== null ? $suffix : "");
}
protected function getSuffix() {
return $this->suffix;
}

public function getHandlerMethodName(halo_HttpRequest $request){
$urlPath = $request->getRequestedUrl();
$methodName = basename($urlPath, ".php");
$methodName = $this->prefix. $methodName. $this->suffix;
return $methodName;
}

}
?>

<?php

class halo_ParameterMethodNameResolver implements
halo_IMethodNameResolver {

private $paramName = 'action';
private $methodParamNames;

public function setParamName($paramName) {
$this->paramName = $paramName;
}

public function setMethodParamNames(Array $methodParamNames) {
$this->methodParamNames = $methodParamNames;
}

public function getHandlerMethodName(halo_HttpRequest $request){
$methodName = '';

// Check parameter names where the very existence of each parameter
// means that a method of the same name should be invoked, if any.
if ($this->methodParamNames !== null) {
foreach ($this->methodParamNames as $variable) {
if($request->getParameter($variable) !== null){
$methodName = $request->getParameter($variable);
break;
}
}
}

// Check parameter whose value identifies the method to invoke, if
any.
if ($methodName === null && $this->paramName !== null) {
$methodName = $request->getParameter($this->paramName);
}

if ($methodName !== null && $methodName === "") {
$methodName = null;
}

if ($methodName === null) {
if ($this->defaultMethodName !== null) {
// No specific method resolved: use default method.
$methodName = $this->defaultMethodName;
}
else {
//throw new NoSuchRequestHandlingMethodException(request);
}
}

return $methodName;
}
}
?>

<?php

interface halo_IPathMatcher {
public function match($pattern, $path);
}
?>

/** Pur is available in http://www.php-pop.org as an utility project
library. It's used here for perform an Url match using Ant Style like
in Spring.
<?php

class halo_AntPathMatcher implements halo_IPathMatcher {

public function match($pattern, $path){
return PurSelector::match($pattern, $path, true);
}
}
?>

<?php

class halo_PropertiesMethodNameResolver implements
halo_IMethodNameResolver {

private $mappings;
private $pathMatcher;

public function __construct() {
$this->pathMatcher = new halo_AntPathMatcher();
}

public function setMappings(Array $mappings) {
$this->mappings = $mappings;
}

/**
* Set the PathMatcher implementation to use for matching URL paths
* against registered URL patterns. Default is halo_AntPathMatcher.
* @see halo_AntPathMatcher
*/
public function setPathMatcher(halo_IPathMatcher $pathMatcher) {
$this->pathMatcher = $pathMatcher;
}


public function getHandlerMethodName(halo_HttpRequest $request){
$urlPath = $request->getRequestedUrl();
if(array_key_exists($urlPath, $this->mappings)){
return $this->mappings[$urlPath];
}

foreach ($this->mappings as $key => $value) {
if ($this->pathMatcher->match($key, $urlPath)) {
return $value;
}
}
return null;
}
}
?>

/****
To validate the url patterns in a consistent way, I tweek
halo_HttpRequest for construct a relative url to the script, changing
the way that halo construct the url using __haloUrl parameter. here is
the tweeks
****/

<?php

class halo_HttpRequest {

protected $method;

protected $queryParams;

protected $parameters;

protected $postParams;

protected $postData;

protected $fileData;

protected $env;

protected $attributes = array();

protected $urlParams = array();

protected $scriptPathRoot;

protected $requestedUrl;

public function __construct($method, array $queryParams = null,
array $postParams = null, array $fileData = null, array $env = null) {

if ( isset($queryParams['__haloUrl']) ) {
$this->requestedUrl = $queryParams['__haloUrl'];
unset($queryParams['__haloUrl']);
}

$this->method = $method;

$this->queryParams = $queryParams;
$this->postParams = $postParams;

$this->parameters = array_merge($this->postParams, $this-
>queryParams);

$this->fileData = $fileData;

if ( $env === null ) {
$env = array();
}

if ( isset($env['REQUEST_URI']) ) {
$requestUri = $env['REQUEST_URI'];

if($this->requestedUrl === null){
$expl = explode("/",$requestUri);
$first = array_shift($expl);
array_shift($expl);
array_unshift($expl,$first);
$expl = implode("/", $expl);

$expl = explode("?",$expl);
$expl = array_shift($expl);

$this->requestedUrl = $expl;
}

//$this->scriptPathRoot = $env['SCRIPT_PATH_ROOT'] =
substr($requestUri, 0, strpos($requestUri, $this->requestedUrl));
} else {
$this->scriptPathRoot = $env['SCRIPT_PATH_ROOT'] = null;
}

$this->env = $env;

$_SERVER = $this->env;

}
public function getQueryParams() {
return $this->queryParams;
}
public function getQueryParam($paramName) {
return $this->queryParamExists($paramName) ? $this-
>queryParams[$paramName] : null;
}
public function queryParamExists($paramName) {
return array_key_exists($paramName, $this->queryParams) ?
true : false;
}
public function getPostParams() {
return $this->postParams;
}
public function getPostParam($paramName) {
return $this->postParamExists($paramName) ? $this-
>postParams[$paramName] : null;
}
public function postParamExists($paramName) {
return array_key_exists($paramName, $this->postParams) ?
true : false;
}
public function getAttributeKeys() {
return array_keys($this->attributes);
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
}
public function getAttribute($key) {
return array_key_exists($key, $this->attributes) ? $this-
>attributes[$key] : null;
}
public function unsetAttribute($key) {
unset($this->attributes[$key]);
}
protected function isMethod($methodName) {
return strtoupper($methodName) == strtoupper($this->method);
}
public function isGetMethod() {
return $this->isMethod('GET');
}
public function isPostMethod() {
return $this->isMethod('POST');
}
public function getUrlParams() {
return $this->urlParams;
}
public function getUrlParamNames() {
return array_keys($this->urlParams);
}
public function setUrlParam($paramName, $paramValue = null) {
$this->urlParams[$paramName] = $paramValue;
}
public function getUrlParam($paramName) {
return array_key_exists($paramName, $this->urlParams) ? $this-
>urlParams[$paramName] : null;
}
public function urlParamExists($paramName) {
return array_key_exists($paramName, $this->urlParams);
}
public function getRequestedUrl() {
return $this->requestedUrl;
}
public function getScriptPathRoot() {
return $this->scriptPathRoot;
}
public function getEnv($key) {
return $this->env[$key];
}
public function getParameter($paramName) {
return array_key_exists($paramName, $this->parameters) ? $this-
>parameters[$paramName] : null;
}
public function getParameterNames() {
return array_keys($this->parameters);
}

}

?>

To work with this kind of urls I need that
halo_SimpleUrlHandlerMapping do the same url pattern match that is
perform in halo_MultiActionController so I change it a little:

<?php
hc_core_ClassLoader::load('halo_AbstractUrlHandlerMapping');
class halo_SimpleUrlHandlerMapping extends
halo_AbstractUrlHandlerMapping {
protected $mappings;
protected $useDefault;
private $pathMatcher;

public function __construct(array $mappings, $default = null) {
$this->mappings = $mappings;
$this->default = $default;
if ( $default !== null ) {
$this->useDefault = true;
} else {
$this->useDefault = false;
}
}
protected function getHandlerInternal(halo_HttpRequest
$httpRequest) {
$url = $httpRequest->getRequestedUrl();

if ( $this->useDefault and ( $url === null or $url === '' )
and $this->default !== null ) {
return $this->context->get($this->default);
}
if ( isset($this->registeredHandlers[$url]) ) {
return $this->context->get($this-
>registeredHandlers[$url]);
} else {
foreach ($this->registeredHandlers as $key => $value) {
if ($this->pathMatcher->match($key, $url)) {
return $this->context->get($value);
}
}
}

return null;
}

protected function registerHandlers() {
foreach ( $this->mappings as $url => $objectName ) {
$this->registerHandler($url, $objectName);
}
}

public function setPathMatcher(halo_IPathMatcher $pathMatcher) {
$this->pathMatcher = $pathMatcher;
}
}
?>

All of this is working perfectly and save me a lot of code using the
sustrate parent "bean" (what is the name here) to referr to a
CommonController that is a class that extends from
halo_MultiActionController to bring CRUD and other things
automagically. The regular expressions allow a bunch of urls that
match a pattern to be attended by a single controller
"bean" (seriously sustrate need a name for this).
My architecture know need to resolve just a few problems.
1- View Resolver (the Implementation of my
halo_InternalResourceViewResolver is not tested yet, and have some
bugs due to the lack of time to work on this).
2- Security (I will take a look at http://www.tomsick.net/projects/spf
because it said that it is like Spring Security formely Acegi, I know
very well boths and I can decide if spf fit my needs)
3- Reports (there are a couple of ideas around here but nothing
robust).
4- In a future Web Service like Apache CXF formely XFire
5- Auditing and Statistics (I need a robust AOP framework that work
with proxies, I will see how repose do the magic)

Beau Simensen

unread,
Sep 2, 2010, 3:02:04 PM9/2/10
to halo...@googlegroups.com
Wow, thanks for the info. I'll dig into this a bit more later.

I went with the generic term "object" instead of "bean" in Substrate
as I do not think anyone in the PHP world really knows what a bean is.
:) They really are just objects, right? Anyway, after I used it for
awhile I had a similar problem to you... object is just too generic
and can be confusing to wrap your head around.

Do you think they should be called beans? Or would it make more sense
to create another name for them specific to Substrate? (phean might be
too weird. :))


--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/

aek

unread,
Sep 3, 2010, 9:04:54 AM9/3/10
to Halo General Discussion
Yesterday, I finish and tested the halo_InternalResourceViewResolver
that is designed to resolve views taken a base path as a preffix and a
file extension as a suffix, letting the ability to the controller to
specify the rest of the path of the file and the filename to use as a
view. It can be configure it with a view classname to use for render
the model.
The is a concern here, I think that the view class don't need to
resolve the real path of the file, that role correspond to the view
resolver so in skittle_Skittle the line:

$realPath = $this->fileLocator->find($path);

that I mentioned before related to that this line can be replaced
with:

$realPath = classLoader::getClassPath($path);

can be omitted at all using the $path resolved by the ViewResolver as
a $realPath. With this tweek here is the code and a base configuration
for InternalResourceViewResolver:

<?php

class halo_InternalResourceViewResolver implements halo_IViewResolver
{

private $viewClass;
private $preffix;
private $suffix;

public function resolve($viewName, halo_HttpRequest $httpRequest,
halo_HttpResponse $httpResponse) {
$viewUrl = $this->preffix.$viewName.$this->suffix;
$view = new $this->viewClass($viewName, $viewUrl);
return $view;
}

public function setViewClass($viewClass) {
$this->viewClass = $viewClass;
}
public function setPreffix($preffix) {
$this->preffix = $preffix;
}
public function setSuffix($suffix) {
$this->suffix = $suffix;
}
}

?>

the example configuration in a sustrate context:

$context->set(array('className' =>
'halo_InternalResourceViewResolver', 'lazyLoad' => false,
'properties' => array(
'preffix' => './WebContent/WEB-INF/views',
'suffix' => '.php',
'viewClass' => 'halo_SkittleView',
),
));

Now a controller can return as a viewName something like this examples
in ArcheType-PHP (my architecture port to PHP):

/common/index
/common/json
/common/error
/admin/login
/admin/logout
/admin/manage

there is no need to register and maintain the urls of the view files
in a property file even when you could do it this way by default using
halo_PropertiesConfigurationViewResolver
hope this would be helpful

Beau Simensen

unread,
Sep 21, 2010, 1:06:39 AM9/21/10
to halo...@googlegroups.com
I am considering switching the terminology for Substrate from "object" to something else. I am thinking that "bean" might be the best bet since it would be consistent with the Java world. My other ideas are "brick" and "stone."

"Brick" really seems too heavy to me but conceptually connected to substrate and what the the object represents. "Stone" sounds more friendly to me and does not have a powerful visual associated with it. Stones can be smaller, like beans.

Aek, what are your thoughts on this? Stick with "object," move to "bean" for consistency or choose "brick" or "stone" to both differentiate from Java and not overload the core idea of an object?




--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/


[blog] http://not-invented-here.com/
[flickr] http://flickr.com/photos/kirkryyn
[facebook] http://facebook.com/simensen


aek

unread,
Sep 21, 2010, 1:44:24 PM9/21/10
to Halo General Discussion
I like stone, but could be piece or chunk too...

Beau Simensen

unread,
Sep 21, 2010, 2:07:36 PM9/21/10
to halo...@googlegroups.com
Thanks for your input! I'll think about it a bit longer, but I think I'm leaning in the direction of stone. Piece could work, too... I think I'll probably choose one of those two.



--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/


[blog] http://not-invented-here.com/
[flickr] http://flickr.com/photos/kirkryyn
[facebook] http://facebook.com/simensen


On Tue, Sep 21, 2010 at 10:44 AM, aek <aek...@gmail.com> wrote:
piece

Reply all
Reply to author
Forward
0 new messages