PHP Environement with MacPorts

So I was happy with my native PHP setup.
Until I updated Snow Leopard to 10.6.3.
The problem with the update is that it also updates PHP from 5.3.0 to 5.3.1. This in itself would be fine, but it also enables zend-multibyte. And this causes problems with FLOW3, because FLOW3 uses declare(ENCODING = 'utf-8'); at the beginning of every file, which throws an error on 5.3.1 with enabled zend-multibyte because of a bug (see the FLOW3 mailing list for details). This bug is fixed in PHP 5.3.2, but Snow Leopard 10.6.3 includes only 5.3.1.

Still with me? Okay, let’s fix this mess. How? If we were to fix this in the default setup, we’re going to run into these kind of problems again and again. To me, the only reasonable solution is to have your own operating-system independent solution.

So here’s what I did (and you should do, too):
Start by installing MacPorts if you don’t have it already. Then, install the newest Apache and PHP with the following commands:

sudo port install apache2
sudo port install php5 +apache2 +pear

You’ll also need the PDO drivers and the mbstring extension, get them with:

sudo port install php5-sqlite
sudo port install php5-mysql
sudo port install php5-mbstring

And then you probably have to adjust the settings. Now, MacPorts installs everything under /opt/local, so that’s were you should be looking for the files:

hosts is still at /etc/hosts (of course)
httpd.conf is at /opt/local/apache2/conf/httpd.conf
httpd-vhosts.conf is at
/opt/local/apache2/conf/extra/httpd-vhosts.conf
[username].conf is at
/opt/local/apache2/conf/extra/[username].conf

Some important things to check:

  • Are [username].conf and httpd-vhosts.conf included in your httpd.conf? (Just do a quick search on both)
  • Does httpd.conf handle php files? If not, enable it at the end of the file with
    <IfModule php5_module>
    AddType application/x-httpd-php .php
    </IfModule>
    
  • Is overriding allowed? Search for <Directory /> and ensure
    AllowOverride is set to All

That’s it, restart Apache

sudo /opt/local/etc/LaunchDaemons/ »
org.macports.apache2/apache2.wrapper stop
sudo /opt/local/etc/LaunchDaemons/ »
org.macports.apache2/apache2.wrapper start

And of course you don’t want to do this everytime, so have it start on launch with:

sudo launchctl load -w »
/Library/LaunchDaemons/org.macports.apache2.plist

Hope this helps … if you have any questions or corrections, please let me know.

, , | April 5, 2010 | No Comments

Review: Crockford on JavaScript

As I mentioned in my blog post “Learning JavaScript” a couple of days ago, I decided to watch the series “Crockford on JavaScript”. And I did watch them!
So far, I listened to part 2-4 and will definitely watch part 5 once it’s out. Although the talks are a bit lengthy at times, I would say I learned more about JavaScript than in the last 2 years. And I also learned a couple of things I didn’t expect (like a little bit of background about how HTML came to be).
In this post, I want to share some points I noted down while watching:

  • I’m still unsure if the object model of JavaScript is really suited for large programs, I think I’m still favoring a classical model like one in Java or PHP. But more important is that I understand the “JavaScript way” of doing things (e.g. prototypal inheritance) better, because using a language as it was intended to be used will yield better results.
  • I fully agree with Crockfords position that numbers should be numbers in programming languages and not ints, floats, doubles and what-not. Wish that PHP would be like this.
  • Functions are really good in JavaScript, and I finally got what closures are all about. The whole concept sounds really nice, so, yes, JavaScript has good parts :)
  • Getting the introduction to DOM that Crockford gave was great to fill in gaps and to deepen my understanding on why things are how they are.
  • And finally, it was interesting to see what he thinks about HTML, CSS, DOM and the W3C. Pretty strong opinions here, but I think he is right to a certain extent. The standards we have today have a mostly crazy history and do several things wrong, but we have to use them. Unfortunately, the output of the groups like the W3C is much worse than what we get from Ajax libraries (or any other framework we have). Of course, this is not taking into account that you can just ditch a library, but you can’t work around JavaScript. And this is also why I disagree with Crockford that the good parts saved JavaScript, I would say JavaScript survived, because it is the only thing that all browsers support.

So that was my quick review of the talks. I highly recommend taking the time to watch them if you are interested in the web and want to understand things on a deeper level.

, | March 24, 2010 | No Comments

My TYPO3 default template

After setting up several TYPO3 websites, I thought it was time to build my own default template to start with for new projects. I’m sharing this with everyone in the hope it is useful, but be aware that the template is only my current way of doing things, and will probably change in the future. Also, I do not recommend to copy-and-paste it if you do not know what all these lines do. Look them up in the TSref.

######### PAGE #########
page = PAGE
page {
 typeNum = 0
 meta {
  language = de
  description = TYPO3TEST
  keywords =
 }
 includeCSS {
  file1 = {$css_file1}
 }
 includeJS {

 }
 shortcutIcon = {$favicon_file}
}

######### CONFIG #########
config {
 doctype = xhtml_strict
 xmlprologue = none
 xhtml_cleaning = all
 disablePrefixComment = 1
 removeDefaultJS = 1
}
lib {
 parseFunc_RTE.nonTypoTagStdWrap.encapsLines.addAttributes.P.class >
 stdheader.stdWrap.dataWrap >
 stdheader.3.headerClass >
}
tt_content {
 stdWrap.innerWrap.cObject.default {
  10 >
  15 >
  20 >
  30.value = |
 }
 stdWrap.dataWrap >
}
plugin {
 tx_cssstyledcontent._CSS_DEFAULT_STYLE >
}

######### MENU #########
lib.navigation = HMENU
lib.navigation {
 1 = TMENU
 1 {
  wrap = <ul>|</ul>
  expAll = 1
  NO {
   wrapItemAndSub = <li>|</li>
  }
  ACT = 1
  ACT {
   wrapItemAndSub = <li class="active">|</li>
  }
 }
 2 = TMENU
 2 {
  wrap = <ul>|</ul>
  NO {
   wrapItemAndSub = <li>|</li>
  }
  ACT = 1
  ACT {
   wrapItemAndSub = <li class="active">|</li>
  }
 }
}

######### REALURL #########
config {
 simulateStaticDocuments = 0
 baseURL = my.domain.tld
 tx_realurl_enable = 1
}

######### TEMPLATE #########
page.10 = USER
page.10.userFunc = tx_templavoila_pi1->main_page

, | March 16, 2010 | No Comments

New engine, new URL

Finally, I switched this blog to Wordpress. No more fiddling around and solving problems that don’t need to be solved ;). Unfortunately, this comes with a change of the url: michaelsauter.net/blog. Also, the feeds are now at michaelsauter.net/blog/feed/rss. And, last but not least: Expect a lot of errors. Thanks.

So much for the bad news, the good news are tags and comments ;) And the whole thing took me not even 3 hours. More to come!

March 14, 2010 | No Comments

Learning JavaScript

Okay, I give in. I’m going to learn JavaScript now.

Once again I realised I’m spending a lot of time of a project (and it’s only getting more and more) on the JavaScript part and don’t feel very comfortable with it. Yes, I’ve used JavaScript (more to the point, jQuery) for many years now, but I use it like PHP without the dollar sign. Which sucks  …

So, what am I going to do?

First, I’m going to listen to Douglas Crockford:

Second, I’ll have a look at another JavaScript framework: ExtJS. I chose ExtJS because it is focused more on web applications than jQuery (which I still love!), and TYPO3 v5 will use it. I haven’t decided yet which book to read, but am determined to pick one after I got the basics right.

, | March 14, 2010 | No Comments

FLOW3: Updating entities inside an aggregate

The manual explains how to update entities that are accessible via a repository, but it does not say explicitly how to update an entity within an aggregate. In this post, I’ll show which steps need to be taken to do that.

Assume you have the following to models: Foo and Bar, and Foo contains an SplObjectStorage of Bars. Foo is the aggregate root and has its own FooRepository. Bar should not be accessible from the outside but only through traversal via Foo. Now, how to update a Bar object? Obviously, you can’t do $this->barRepository->update($bar); because there is no bar repository!

So, let’s start by looking at the controller and the views. Create basic index, new, create, edit and save actions. All of these need a $foo as an argument (additonally to the $bar that you want to create/edit/update). So you need to give all links (or forms) in the views arguments={foo: foo}.

The controller then needs to set the < code >$bar in the $foo. When creating, this could be $foo->addBar($bar).
For updating, I suggest calling $foo->updateBar($bar).

Of course you need to implement these to methods in the model Foo. addBar() is easy, just attach the given $bar to the SplObjectStorage of Bars. updateBar() is a little more complicated, because you first need to find out which of the items in the SplObjectStorage needs to be replaced. This can be done with the following code:

$editedBarIdentifier = »
$this->persistenceManager->getIdentifierByObject($editedBar);
$originalBar =  $this->persistenceManager-> »
getObjectByIdentifier($editedBarIdentifier);
$this->bars->detach($originalBar);
$this->bars->attach($editedBar);

As you can see, that requires a persistence manager object, which can be injec ted via dependency injection in the model. Make sure to set the @transient annotation to tell the persistence framework that you don't want it to track the persistence manager object (of course!).

That's it. Happy updating!

, | March 8, 2010 | No Comments

Programmatic ViewHelpers for FLOW3

In the current version of FLOW3 (1.0.0 alpha7), there is no way to create Fluid ViewHelpers programmatically. But there is a workaround which is not that bad either. I got the inspiration from the admin package, so all kudos goes to the creator ;)

First off, why would you want something like this? I wanted to accomplish the following: I have a page entity which contains several page items. Every page item shares the same interface, e.g. all have a display method. Of course I don’t want to generate HTML code directly in there, but have Fluid ViewHelpers based on the properties of the page item.

The soultion is rather simple: Instead of generating Fluid ViewHelpers in the code, render a view! So for every page item, create a Fluid template, and the display method of the page item makes sure all necessary view variables are set.

Here is the code needed in the page item’s display method:

$view = $objectFactory->create('F3\Fluid\View\TemplateView');
$view->setControllerContext($controllerContext);
$view->setTemplatePathAndFilename('package:// »
Your-Package-Name/Private/Templates/PageItemName.html');
$view->assign('varName', $var);
return $view->render();

That’s it. Of course, you need to make sure you have an objectFactory at that place, as well as the controllerContext which you can get from the current controller via getControllerContext().

, | March 6, 2010 | 1 Comment

Templater

Everytime I start a new template, I look up some old files and copy stuff from there. And everytime I think I should finally generate a zip file containing all basic files and folders (HTML, CSS, JavaScript).

This time I did, and the result is Templater, which even allows some customization based on the current project. Check it out!

, | December 14, 2009 | No Comments

Mac, Apache and Virtual Hosts

And another round of setting up a development environment on Mac OS X 10.5 or 10.6 …

You can think of Virtual hosts as of domains on your machine.
First, open /private/etc/hosts (yes, with no file ending). In there, add the following line at the very end: 127.0.0.1/[name-of-your-virtual-host]. You can choose any name you like (and which is a URI), though I would recommend using something like myproject.local.

Then, open /private/etc/apache2/extra/httpd-vhosts.conf. At the end, insert:

<VirtualHost *:80>
DocumentRoot "/Users/[your-username]/Sites/[your-folder]"
ServerName [name-of-your-virtual-host]
</VirtualHost>

Make sure [name-of-your-host] is the same as the one you entered in the hosts-file.

Finally, open /private/etc/apache2/httpd.conf and uncomment the following line:
#Include /private/etc/apache2/extra/httpd-vhosts.conf

sudo apachectl restart and you’re done.

, | December 13, 2009 | No Comments

Mac, Apache and PHP 5.3

Okay, I should have written this post before writing about the symlinks problem, but anyway … Here is how to use PHP 5.3 on Mac OS X 10.5 or 10.6 with the default Apache.

First, check if Web Sharing is enabled in System Preferences. If it is, Apache should be running and accessing http://127.0.0.1/~[your-username]/ should give you Apples default index.html, located in /Users/[your-username]/Sites.

So far so good, let’s turn on PHP 5.3.
If you are on Leopard (10.5), you need to get PHP 5.3 first. I recommend downloading http://www.entropy.ch/software/macosx/php/, because it’s really easy to install.

If you are on Snow Leopad (10.6), you already have PHP 5.3! But, you need to enable it. Open /private/etc/apache2/httpd.conf and uncomment the line #LoadModule php5_module libexec/apache2/libphp5.so.

Now, restart Apache with sudo apachectl restart, and all PHP files in your Sites-folder should be processed by Apache!

, , | December 12, 2009 | No Comments